diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 00000000..667e97f3
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,8 @@
+{
+ "permissions": {
+ "allow": [
+ "Read(//workspaces/**)",
+ "Bash(find / -maxdepth 5 -type d \\\\\\( -name \"PandABlocks-FPGA\" -o -name \"PandABlocks-server\" -o -name \"PandABlocks-rootfs\" -o -name \"PandABlocks.github.io\" \\\\\\))"
+ ]
+ }
+}
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 00000000..e4b66da5
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,13 @@
+# Devcontainer for meta-panda Yocto/kas builds.
+# Unlike the other PandABlocks repos (which use ubuntu-devcontainer), this is
+# based on the kas image, matching KAS_IMAGE_VERSION in build.sh.
+FROM ghcr.io/siemens/kas/kas:4.8 AS developer
+
+USER root
+
+# Add any system dependencies for the developer environment here.
+# npm provides npx, used by `make docs` to run mystmd on demand for the docs build.
+RUN apt-get update -y && apt-get install -y --no-install-recommends \
+ make \
+ npm \
+ && apt-get clean
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 00000000..1aea043f
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,24 @@
+// For format details, see https://containers.dev/implementors/json_reference/
+{
+ "name": "meta-panda Developer Container",
+ "build": {
+ "dockerfile": "Dockerfile",
+ "target": "developer"
+ },
+ "customizations": {
+ "vscode": {
+ // Add the IDs of extensions you want installed when the container is created.
+ "extensions": [
+ "redhat.vscode-yaml"
+ ]
+ }
+ },
+ "runArgs": [
+ "--net=host",
+ // Make sure SELinux does not disable access to host filesystems like tmp
+ "--security-opt=label=disable"
+ ],
+ // Mount the parent as /workspaces so peer repos are visible alongside
+ // this one, and bitbake build output can live outside the repo
+ "workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind"
+}
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 00000000..3a0cec24
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1,18 @@
+# Contributing
+
+Contributions and issues are most welcome! All issues and pull requests are handled
+through [GitHub](https://github.com/PandABlocks/meta-panda/issues). Please check for any
+existing issues before filing a new one.
+
+## Issue or Pull Request?
+
+Raise an issue if you want to report a bug or request a feature. Open a pull request if
+you already have a change ready to propose. If you are unsure, raise an issue first to
+discuss the change.
+
+## Documentation
+
+Documentation is built with [MyST](https://mystmd.org) and published to GitHub Pages.
+The docs follow the [Diátaxis](https://diataxis.fr) framework — tutorials, how-to
+guides, reference and explanations. See `how-to/contribute` for the documentation
+authoring conventions and the cross-repository link setup.
diff --git a/.github/pages/index.html b/.github/pages/index.html
deleted file mode 100644
index 30a217c8..00000000
--- a/.github/pages/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- Redirecting to master branch
-
-
-
-
-
diff --git a/.github/workflows/_make_boot.yml b/.github/workflows/_make_boot.yml
deleted file mode 100644
index d5786c6f..00000000
--- a/.github/workflows/_make_boot.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-on:
- workflow_call:
- inputs:
- machine:
- required: true
- type: string
-env:
- KAS_MACHINE: ${{ inputs.machine }}
-jobs:
- make_boot:
- runs-on:
- group: iris_runners
- container:
- image: ghcr.io/siemens/kas/kas:4.8
- steps:
- - name: Checkout Source
- uses: actions/checkout@v6
- with:
- fetch-depth: 0
-
- - name: Build and gather
- run: |
- kas build kas.yml
- mkdir boot
- cp -Lf build/tmp/deploy/images/${{ inputs.machine }}/fitImage-petalinux-initramfs-image-${{ inputs.machine }}-${{ inputs.machine }} boot/image.ub
- cp -f build/tmp/deploy/images/${{ inputs.machine }}/rootfs.squashfs boot/
- cp -f build/tmp/deploy/images/${{ inputs.machine }}/boot.bin boot/
- cp -f build/tmp/deploy/images/${{ inputs.machine }}/boot.scr boot/
- cp -f build/tmp/deploy/images/${{ inputs.machine }}/target-defs boot/
- cd boot
- tar cvzf ../boot-${{ inputs.machine }}-${{ github.ref_name }}.tar.gz *
-
- - name: Upload boot
- uses: actions/upload-artifact@v7
- with:
- name: boot
- path: ${{ github.workspace }}/boot-${{ inputs.machine }}-${{ github.ref_name }}.tar.gz
- if-no-files-found: error
diff --git a/.github/workflows/_make_image.yml b/.github/workflows/_make_image.yml
deleted file mode 100644
index c509106b..00000000
--- a/.github/workflows/_make_image.yml
+++ /dev/null
@@ -1,63 +0,0 @@
-on:
- workflow_call:
- inputs:
- machine:
- required: true
- type: string
-jobs:
- make_image:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout Source
- uses: actions/checkout@v5
- with:
- path: meta-panda
- fetch-depth: 0
-
- - name: Download sdk
- uses: actions/download-artifact@v5
- with:
- name: pandablocks-sdk-${{ inputs.machine }}
- path: pandablocks-sdk-${{ inputs.machine }}.sh
-
- - name: Cache Docker layers
- uses: actions/cache@v4
- with:
- path: /tmp/.buildx-cache
- key: ${{ runner.os }}-buildx-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-buildx-
-
- - name: Log in to GitHub Docker Registry
- if: github.event_name != 'pull_request'
- uses: docker/login-action@v1
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@v4
- with:
- images: ghcr.io/pandablocks/pandablocks-sdk-${{ inputs.machine }}
- tags: |
- type=ref,event=branch
- type=ref,event=tag
- type=raw,value=latest
-
- - name: Set up Docker Buildx
- id: buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Rebuild and release CI image
- uses: docker/build-push-action@v5
- with:
- context: .
- file: ./meta-panda/Dockerfile
- build-args: |
- MACHINE=${{ inputs.machine }}
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
- cache-from: type=gha
- push: ${{ github.event_name != 'pull_request' }}
diff --git a/.github/workflows/_make_sdk.yml b/.github/workflows/_make_sdk.yml
deleted file mode 100644
index 4436349b..00000000
--- a/.github/workflows/_make_sdk.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-on:
- workflow_call:
- inputs:
- machine:
- required: true
- type: string
-jobs:
- make_sdk:
- runs-on:
- group: iris_runners
- container:
- image: ghcr.io/siemens/kas/kas:4.8
- env:
- KAS_WORK_DIR: ${{ github.workspace }}
- KAS_MACHINE: ${{ inputs.machine }}
- steps:
- - name: Remove old build
- run: |
- rm -rf ${KAS_WORK_DIR}/*
- mkdir ${KAS_WORK_DIR}/build
-
- - name: Checkout Source
- uses: actions/checkout@v5
- with:
- path: meta-panda
- fetch-depth: 0
-
- - name: Check cash
- uses: actions/cache@v4
- with:
- path: |
- ${{ env.KAS_WORK_DIR }}/build/sstate-cache
- key: kas-sdk-${{ inputs.machine }}-${{ hashFiles('meta-panda/kas.yml') }}
- restore-keys: |
- kas-sdk-${{ inputs.machine }}
-
- - name: build sdk
- run: |
- kas build -c populate_sdk meta-panda/kas.yml
-
- - name: Upload sdk
- uses: actions/upload-artifact@v4
- with:
- name: pandablocks-sdk-${{ inputs.machine }}
- path: ${{ env.KAS_WORK_DIR }}/build/tmp/deploy/sdk/pandablocks-sdk-${{ inputs.machine }}.sh
- if-no-files-found: error
diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml
deleted file mode 100644
index 122108f6..00000000
--- a/.github/workflows/_release.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-on:
- workflow_call:
-
-jobs:
- release:
- runs-on: ubuntu-latest
- if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
- steps:
- - uses: actions/download-artifact@v4
- with:
- name: boot
- path: boot
-
- - name: Github Release
- # We pin to the SHA, not the tag, for security reasons.
- # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
- uses: softprops/action-gh-release@2d72d869af3bf23602f9593a1e3fd739b80ac1eb # v0.1.12
- with:
- prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
- files: boot/*.tar.gz
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..75efa594
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,66 @@
+name: CI
+
+# Single entry point for this repo's GitHub Actions CI: the versioned MyST docs
+# build/publish and the GitHub Release (on a tag) that carries the docs.zip
+# asset. There is no Python package here (meta-panda is a Yocto layer), so
+# there is no pyproject/lint job — and no boot-image build here either: that
+# (and the GitLab Release with the boot/zpg assets) is `.gitlab-ci.yml`'s job
+# now, on Diamond's `pollux-dev` runners. The `docs` and `rel-*` branches are
+# gone (docs merged into main; releases are tag-only), so main + tags is the
+# only trigger surface.
+#
+# The docs half consumes the shared version-switcher reusable workflows
+# (DiamondLightSource/myst-version-switcher-plugin) pinned at a tag, following
+# the same pattern as PandABlocks-server/FPGA:
+#
+# docs -> docs.yml@ versioned MyST docs build (build-command input)
+# release -> release.yml@ GitHub Release on a tag (attaches docs.zip)
+# publish -> publish-dispatch.yml deploy the assembled docs site (the shim that
+# pins publish.yml@; it branches internally)
+#
+# Every job runs on the same events — a pull request, a push to main, or a tag — so
+# no per-job `if:` event guards are needed. publish runs once for every event in the
+# canonical repo and publish.yml branches internally (deploy / tag re-dispatch /
+# fork-PR warn), so there is no fork guard here.
+on:
+ pull_request:
+ push:
+ branches: [main]
+ tags: ['*'] # '*' never matches '/'
+
+jobs:
+ # --- Docs build (never publishes) --------------------------------------------
+ docs:
+ uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/docs.yml@v0.23.0
+ with:
+ # `make docs` reads build settings (incl. MYSTMD_VERSION) from CONFIG; docs.yml
+ # sets BASE_URL and packs/uploads the docs.zip artifact. meta-panda's docs are
+ # pure MyST (no python directives), so no extra apt packages are needed.
+ build-command: cp CONFIG.example CONFIG && make docs
+
+ # Tag-only: create the GitHub Release and attach this run's docs.zip (the `docs`
+ # artifact) so `assemble` can reconstruct that released version later. Boot images
+ # and app packages are released from GitLab now (`.gitlab-ci.yml`'s `release-all`).
+ release:
+ needs: [docs]
+ if: github.ref_type == 'tag'
+ uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/release.yml@v0.23.0
+ permissions:
+ contents: write # create the GitHub Release + attach the docs.zip asset
+
+ # One publish job for every event in the canonical repo — publish.yml (via the
+ # publish-dispatch.yml shim) owns the branching (deploy / tag re-dispatch / fork-PR
+ # warn), so there's no fork or ref guard here. `actions: write` lets the re-dispatch
+ # job re-fire the shim; `version-name` injects this run's build inline.
+ publish:
+ needs: [docs]
+ if: github.repository == 'PandABlocks/meta-panda'
+ uses: ./.github/workflows/publish-dispatch.yml
+ with:
+ version-name: ${{ needs.docs.outputs.version-name }}
+ permissions:
+ contents: read
+ actions: write
+ pages: write
+ id-token: write
+ statuses: write
diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml
deleted file mode 100644
index 2fb011f5..00000000
--- a/.github/workflows/code.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-name: Code CI
-
-on:
- # Only run on changes to branches with open PRs
- pull_request:
- types: [opened, edited, synchronize]
- # Run after PR merged, on implicit push, and on tag pushes
- push:
- tags:
- - '*'
- branches: [rel-*]
-
-jobs:
- make_boot:
- strategy:
- fail-fast: false
- matrix:
- machine:
- - pandabox
- - pandabox2
- - pandabrick
- uses: ./.github/workflows/_make_boot.yml
- with:
- machine: ${{ matrix.machine }}
-
- release:
- needs: make_boot
- uses: ./.github/workflows/_release.yml
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
deleted file mode 100644
index 4b8387be..00000000
--- a/.github/workflows/docs.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-name: Docs CI
-
-on:
- push:
- pull_request:
-
-jobs:
- make_docs:
- runs-on: ubuntu-latest
- container:
- # TODO: use panda sdk image when available
- image: ghcr.io/pandablocks/pandablocks-dev-container:latest
- credentials:
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
- volumes:
- - ${{ github.workspace }}:/repos
- - ${{ github.workspace }}/build:/build
-
- steps:
- # Git repositories
- - name: Checkout Source
- uses: actions/checkout@v2
- with:
- path: meta-panda
- # require history to get back to last tag for version number of branches
- fetch-depth: 0
-
- # Build docs
- - name: Make docs
- run: |
- cd meta-panda
- python3 -m sphinx -M html docs /build/
-
- - name: Move to versioned directory
- # e.g. master or 0.1.2
- run: mv /build/html "meta-panda/.github/pages/${GITHUB_REF##*/}"
-
- - name: Publish Docs to gh-pages
- # Only master and tags are published
- if: "${{ github.repository_owner == 'PandABlocks' && (startsWith(github.ref, 'refs/heads/rel-') || startsWith(github.ref, 'refs/tags')) }}"
- # We pin to the SHA, not the tag, for security reasons.
- # https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
- uses: peaceiris/actions-gh-pages@bbdfb200618d235585ad98e965f4aafc39b4c501 # v3.7.3
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- publish_dir: meta-panda/.github/pages
- keep_files: true
diff --git a/.github/workflows/publish-dispatch.yml b/.github/workflows/publish-dispatch.yml
new file mode 100644
index 00000000..03ec6957
--- /dev/null
+++ b/.github/workflows/publish-dispatch.yml
@@ -0,0 +1,39 @@
+name: Publish (dispatch)
+
+# Thin shim — the one dispatchable file in this repo. It forwards to the shared
+# version-switcher engine (publish.yml), exposing it two ways:
+# workflow_call — ci.yml's `publish` job, for every event (publish.yml branches
+# into deploy / tag re-dispatch / fork warn).
+# workflow_dispatch — the tag re-dispatch, the fork-PR preview (`pr`), and manual
+# re-deploys.
+# A reusable workflow can't be workflow_dispatch'd cross-repo, so this shim must live
+# here; publish.yml's re-dispatch job re-fires it by name (`dispatch-workflow`). This
+# is the single place this repo pins publish.yml@.
+on:
+ workflow_call:
+ inputs:
+ version-name:
+ description: Version name of the in-run build to inject (passed by ci.yml's inline publish).
+ required: false
+ default: ""
+ type: string
+ workflow_dispatch:
+ inputs:
+ pr:
+ description: External fork PR number to approve (pins its head SHA) and preview. Leave empty to just re-deploy.
+ required: false
+ default: ""
+
+jobs:
+ publish:
+ uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/publish.yml@v0.23.0
+ with:
+ version-name: ${{ inputs.version-name }} # "" on dispatch → pure durable gather
+ pr: ${{ inputs.pr }} # set (dispatch only) → pin that fork head SHA
+ dispatch-workflow: publish-dispatch.yml # the file the tag re-dispatch re-fires
+ permissions:
+ contents: read
+ actions: write # publish.yml's re-dispatch job re-fires this shim via gh
+ pages: write
+ id-token: write
+ statuses: write
diff --git a/.gitignore b/.gitignore
index 640d2a27..e6a69fd0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,8 @@
build/
sources/
+
+# Local build settings (copy of CONFIG.example)
+CONFIG
+
+# MyST build output
+docs/_build/
diff --git a/CONFIG.example b/CONFIG.example
new file mode 100644
index 00000000..cc6e6135
--- /dev/null
+++ b/CONFIG.example
@@ -0,0 +1,13 @@
+# Example configuration file for building the meta-panda documentation.
+#
+# Copy this file to a file named CONFIG and edit as appropriate.
+#
+# Note that this file is used as part of github Continuous Integration (see
+# .github/workflows/_docs.yml), so the entries in this file must refer to valid
+# paths/values in the CI container.
+
+# Version of mystmd (https://mystmd.org) used to build the documentation with
+# `make docs` / `make docs-dev`. Run on demand via npx, so no global install is
+# needed.
+#
+MYSTMD_VERSION = 1.10.1
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..c4c27434
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,25 @@
+# meta-panda is a Yocto/kas layer with no compiled build of its own; this Makefile
+# exists only to drive the documentation build the same way as the other
+# PandABlocks repos (`make docs`).
+#
+# Docs are built with MyST (mystmd), run on demand through npx so no global install
+# is needed; pin the version with MYSTMD_VERSION (see CONFIG.example). MyST writes
+# its output into docs/_build/html. --strict exits non-zero on any error-severity
+# message (e.g. an unresolved cross-repo xref) so CI fails rather than publishing
+# broken links.
+
+# The CONFIG file is required. If not present, create by copying CONFIG.example.
+include CONFIG
+
+MYST = npx --yes --package mystmd@$(MYSTMD_VERSION) myst
+
+docs:
+ cd docs && $(MYST) build --html --strict
+
+docs-dev:
+ cd docs && $(MYST) start
+
+clean-docs:
+ rm -rf docs/_build
+
+.PHONY: docs docs-dev clean-docs
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..aa8fefca
--- /dev/null
+++ b/README.md
@@ -0,0 +1,34 @@
+# meta-panda
+
+PandA is a programmable logic box for synchronised triggering and position
+capture in scientific experiments. You configure it by wiring together
+functional blocks in its FPGA — from a web browser or over a simple TCP
+protocol — and capture timestamped position data from it at high speed.
+
+This site is the root of the PandABlocks documentation: it covers getting a
+PandA on the network, using the Web Control, capturing data, administering and
+upgrading a PandA, and building its firmware and software. Documentation for
+the individual components (FPGA framework, TCP server, Python client, EPICS /
+Tango integration) is linked throughout.
+
+This repository itself is the `meta-panda` layer: the Yocto recipes and
+configuration for building the Linux system that runs on a PandA.
+
+- Machines provided: `pandabox`, `pandabox2`, `pandabrick`
+- Distro provided: `panda-petalinux`
+- Image provided: `panda-image`
+
+The Linux system brings up the network from a `config.txt` file on the SD card, runs an
+SSH server for debugging access, programs the FPGA and runs services such as the TCP
+server and Web Control, and serves a Web Admin interface on port 80 for installing and
+removing packages and adding SSH keys.
+
+
+
+## Where to find things
+
+| | |
+|---|---|
+| Source code | |
+| Documentation | |
+| Releases | |
diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md
new file mode 100644
index 00000000..ce949770
--- /dev/null
+++ b/docs/PROGRESS.md
@@ -0,0 +1,94 @@
+# Docs Rewrite Progress — meta-panda
+
+Tracks every target page for this repo. Update the relevant line **in the same commit** as the file
+it refers to. Statuses: ☐ todo · ◐ stub · ✅ converted · 🔍 needs-review · ⛔ blocked (→ issue #).
+Page list expanded from `06-source-provenance-map.md`.
+
+## Stage A — scaffold
+- ✅ skeleton instantiated (title/github/logo swapped, apidoc + pip-tutorial + run-container removed)
+- ✅ TOC + stubs for every target page present (33 stubs + 4 landing + index + decisions)
+- ✅ `index.md` README-include + `how-to/contribute` CONTRIBUTING-include resolve
+- ✅ xref/intersphinx wired + cross-link probe resolves in built output
+- ☐ (FPGA only) — N/A for meta-panda
+- ✅ `myst build` green (exit 0, no warnings/errors)
+- ✅ Pages deploy wired — `.github/workflows/docs.yml` switched from Sphinx to `myst build` (see Notes)
+
+## Tutorials
+- ✅ tutorials/tutorial0_connecting_to_web_control — source: webcontrol/userguide/quick-start.rst — converted
+- ✅ tutorials/tutorial1_blinking_leds — source: tutorials/tutorial1_blinking_leds.rst — converted
+- ✅ tutorials/tutorial2_position_capture — source: tutorials/tutorial2_position_capture.rst — converted
+- ⛔ tutorials/tutorial3_position_compare — source: tutorials/tutorial3_position_compare.rst (stub) — blocked: capture
+- ⛔ tutorials/tutorial4_snake_scan — source: tutorials/tutorial4_snake_scan.rst (stub) — blocked: capture
+
+## How-to
+- ✅ how-to/quickstart — source: how-to/quickstart.rst + rootfs quickstart.md — merged; boot.txt→config.txt fixed; FAQ moved to reference/troubleshooting
+- ✅ how-to/build — source: how-to/build.rst + run-container.rst (KAS) — merged; KAS_IMAGE_VERSION verify note added
+- ✅ how-to/manual-build — source: tutorials/manual-build.rst — manifest URL fixed (Xilinx/yocto-manifests); post-5.0 branch verify noted
+- ✅ how-to/make-release — source: how-to/make-release.rst — releases link fixed → meta-panda
+- ✅ how-to/packages — source: how-to/packages.rst — converted
+- ✅ how-to/upgrade-via-ssh — source: how-to/remote.rst — pre-5.0 + post-5.0 covered; 24V EEPROM DLS-only noted; gap audit verify noted
+- ✅ how-to/upgrade-via-web-admin — source: how-to/web-interface.rst — pre-5.0 zpg path + fresh SD card install added; zpg filename verify noted
+- ✅ how-to/use-web-control-to-set-up-a-panda — source: webcontrol/userguide/working_with_a_design.rst — converted (Prompt E); attribute widgets folded in; 4 widget subsections (View/Edit, Dropdown, Text Input, Checkbox) + trailing sentence kept as blocked: capture stub w/ issue link
+- ✅ how-to/save-restore-design — source: working_with_a_design.rst (Saving/Opening) — split out (Prompt E); Saving a Design + Opening an Existing Design
+- ✅ how-to/monitor-attribute-values — source: webcontrol/userguide/monitoring_attribute_values.rst — converted
+- ✅ how-to/integrate-with-a-panda — source: NEW (Interview5; client + fastcs) — skeleton written; xref probe preserved
+- ✅ how-to/test-firmware-changes — source: NEW (Interview5 §1-2) — authored
+- ✅ how-to/choose-fpga-bitstream — source: NEW (Interview5 §10; Interview3 §4) — authored
+- ✅ how-to/contribute — content merge from github.io + xref/intersphinx setup documented
+
+## Reference
+- ✅ reference/opkg — converted from reference/opkg.rst
+- ⛔ reference/changes — source: github.io migration_guide.rst + release_compatibility.rst — blocked: verify (3.0->4.0)
+- ✅ reference/machine-targets — NEW from Interview6 §A; PandABrick verify noted
+- ✅ reference/glossary — canonical merge of webcontrol + FPGA glossaries; MyST {glossary} directive
+- ✅ reference/troubleshooting — seeded from quickstart.rst FAQ (7 Qs); boot.txt→config.txt fixed
+
+## Explanations
+- ✅ explanations/boot-process — converted from explanations/boot-process.rst
+- ✅ explanations/architecture — skeleton authored from Interview1; TCP/client/EPICS/data flow
+- ⛔ explanations/hardware-targets — blocked: author
+- ✅ explanations/web-control-ui-overview — converted from user_interface_overview.rst; screenshots reused
+- ✅ explanations/understanding-attribute-state — 8 states described; all 8 state icons recreated as standalone SVGs in `images/attribute-state/` (material-style glyphs in the colour spec) and wired in (Prompt C done; no malcolm reference in docs)
+- ✅ explanations/decisions + decisions/0001,0002,COPYME — kept from scaffold (no change)
+
+## Blocked (issues raised)
+Issues not yet created — Stage B (Prompt B) will create and link them. Blocked pages:
+- ⛔ tutorials/tutorial3_position_compare — issue #12 — human-capture
+- ⛔ tutorials/tutorial4_snake_scan — issue #12 — human-capture
+- ⛔ reference/changes — issue #14 — verify (3.0->4.0)
+- ⛔ explanations/hardware-targets — issue #19 — author
+- ⛔ how-to/use-web-control-to-set-up-a-panda (widget screenshots + trailing sentence) — issue #13 — human-capture
+
+- ⛔ reference/machine-targets (hardware details) — issue #15 — verify
+
+- ⛔ how-to/build (KAS_IMAGE_VERSION) — issue #16 — verify
+
+- ⛔ how-to/upgrade-via-web-admin (zpg filename) — issue #17 — verify
+
+- ⛔ how-to/manual-build (Xilinx branch post-5.0) — issue #18 — verify
+
+- ⛔ infrastructure: versioned docs / version switcher (R5) — issue #20 — infrastructure
+
+## Notes
+- **Legacy sources preserved.** The original Sphinx/RST tree was moved to `docs/_legacy_rst/`
+ (not in the TOC, ignored by `myst build`) so Stage D/E conversion can read the cited source
+ files in-tree at their `06` paths (under `docs/_legacy_rst/...`). They also remain on
+ `origin/main` / `origin/rel-v2023.2`. Screenshots stay reusable in place there; tutorial
+ screenshots also live at `docs/images/`. Delete `_legacy_rst/` once conversion is complete.
+- **Logo / icon swap** already done upstream in the skeleton: `images/PandA-logo-for-black-background.svg`.
+- **xref/intersphinx prototype.** `myst.yml project.references` currently activates only
+ `PandABlocks-client` (deployed). The probe link in `how-to/integrate-with-a-panda` resolves in
+ built output to `.../PandABlocks-client/main/reference/api.html#pandablocks.blocking.blockingclient`.
+ The other core repos + devcontainer + fastcs are kept commented (their docs aren't published yet);
+ uncomment in Stage F and upstream the block into python-copier-template.
+- **Pages workflow.** `.github/workflows/docs.yml` is modelled on the python-copier-template-example
+ `_docs.yml` (checkout@v5, sanitized `DOCS_VERSION`, `upload-artifact@v4` of `docs/_build` as `docs`,
+ move to versioned `.github/pages//`, `make_switcher.py` → `switcher.json`, publish via
+ peaceiris v4.0.0 pinned SHA with `keep_files: true`). Adaptations from the template: (1) build uses
+ npm + mystmd (`myst build --html`) instead of `uv run tox -e docs` since meta-panda is a Yocto layer,
+ not a Python/uv project; (2) `BASE_URL=/meta-panda/` is set so assets resolve under the
+ versioned Pages sub-path (the template's in-progress mystmd migration doesn't set it yet). Root
+ branch is now **`main`**: publish is gated to `github.ref_name == 'main' || ref_type == 'tag'`, and
+ `.github/pages/index.html` redirects to `./main/index.html`. Validated locally end-to-end with
+ `DOCS_VERSION=main`. The version switcher is generated but wiring it into the theme is the deferred
+ R5 (versioned docs) item.
diff --git a/docs/_static/css/custom.css b/docs/_legacy_rst/_static/css/custom.css
similarity index 100%
rename from docs/_static/css/custom.css
rename to docs/_legacy_rst/_static/css/custom.css
diff --git a/docs/conf.py b/docs/_legacy_rst/conf.py
similarity index 100%
rename from docs/conf.py
rename to docs/_legacy_rst/conf.py
diff --git a/docs/explanations.rst b/docs/_legacy_rst/explanations.rst
similarity index 100%
rename from docs/explanations.rst
rename to docs/_legacy_rst/explanations.rst
diff --git a/docs/explanations/boot-process.rst b/docs/_legacy_rst/explanations/boot-process.rst
similarity index 100%
rename from docs/explanations/boot-process.rst
rename to docs/_legacy_rst/explanations/boot-process.rst
diff --git a/docs/how-to.rst b/docs/_legacy_rst/how-to.rst
similarity index 100%
rename from docs/how-to.rst
rename to docs/_legacy_rst/how-to.rst
diff --git a/docs/how-to/build.rst b/docs/_legacy_rst/how-to/build.rst
similarity index 100%
rename from docs/how-to/build.rst
rename to docs/_legacy_rst/how-to/build.rst
diff --git a/docs/how-to/make-release.rst b/docs/_legacy_rst/how-to/make-release.rst
similarity index 100%
rename from docs/how-to/make-release.rst
rename to docs/_legacy_rst/how-to/make-release.rst
diff --git a/docs/how-to/packages.rst b/docs/_legacy_rst/how-to/packages.rst
similarity index 100%
rename from docs/how-to/packages.rst
rename to docs/_legacy_rst/how-to/packages.rst
diff --git a/docs/how-to/pandablocks-sdk.rst b/docs/_legacy_rst/how-to/pandablocks-sdk.rst
similarity index 100%
rename from docs/how-to/pandablocks-sdk.rst
rename to docs/_legacy_rst/how-to/pandablocks-sdk.rst
diff --git a/docs/how-to/quickstart.rst b/docs/_legacy_rst/how-to/quickstart.rst
similarity index 100%
rename from docs/how-to/quickstart.rst
rename to docs/_legacy_rst/how-to/quickstart.rst
diff --git a/docs/how-to/remote.rst b/docs/_legacy_rst/how-to/remote.rst
similarity index 100%
rename from docs/how-to/remote.rst
rename to docs/_legacy_rst/how-to/remote.rst
diff --git a/docs/how-to/run-container.rst b/docs/_legacy_rst/how-to/run-container.rst
similarity index 100%
rename from docs/how-to/run-container.rst
rename to docs/_legacy_rst/how-to/run-container.rst
diff --git a/docs/how-to/web-interface.rst b/docs/_legacy_rst/how-to/web-interface.rst
similarity index 100%
rename from docs/how-to/web-interface.rst
rename to docs/_legacy_rst/how-to/web-interface.rst
diff --git a/docs/index.rst b/docs/_legacy_rst/index.rst
similarity index 100%
rename from docs/index.rst
rename to docs/_legacy_rst/index.rst
diff --git a/docs/reference.rst b/docs/_legacy_rst/reference.rst
similarity index 100%
rename from docs/reference.rst
rename to docs/_legacy_rst/reference.rst
diff --git a/docs/reference/opkg.rst b/docs/_legacy_rst/reference/opkg.rst
similarity index 100%
rename from docs/reference/opkg.rst
rename to docs/_legacy_rst/reference/opkg.rst
diff --git a/docs/tutorials.rst b/docs/_legacy_rst/tutorials.rst
similarity index 100%
rename from docs/tutorials.rst
rename to docs/_legacy_rst/tutorials.rst
diff --git a/docs/tutorials/manual-build.rst b/docs/_legacy_rst/tutorials/manual-build.rst
similarity index 100%
rename from docs/tutorials/manual-build.rst
rename to docs/_legacy_rst/tutorials/manual-build.rst
diff --git a/docs/tutorials/template_tutorial1_leds.json b/docs/_legacy_rst/tutorials/template_tutorial1_leds.json
similarity index 100%
rename from docs/tutorials/template_tutorial1_leds.json
rename to docs/_legacy_rst/tutorials/template_tutorial1_leds.json
diff --git a/docs/tutorials/template_tutorial2_pcap.json b/docs/_legacy_rst/tutorials/template_tutorial2_pcap.json
similarity index 100%
rename from docs/tutorials/template_tutorial2_pcap.json
rename to docs/_legacy_rst/tutorials/template_tutorial2_pcap.json
diff --git a/docs/tutorials/tutorial1_blinking_leds.rst b/docs/_legacy_rst/tutorials/tutorial1_blinking_leds.rst
similarity index 100%
rename from docs/tutorials/tutorial1_blinking_leds.rst
rename to docs/_legacy_rst/tutorials/tutorial1_blinking_leds.rst
diff --git a/docs/tutorials/tutorial2.timing.ini b/docs/_legacy_rst/tutorials/tutorial2.timing.ini
similarity index 100%
rename from docs/tutorials/tutorial2.timing.ini
rename to docs/_legacy_rst/tutorials/tutorial2.timing.ini
diff --git a/docs/tutorials/tutorial2_position_capture.rst b/docs/_legacy_rst/tutorials/tutorial2_position_capture.rst
similarity index 100%
rename from docs/tutorials/tutorial2_position_capture.rst
rename to docs/_legacy_rst/tutorials/tutorial2_position_capture.rst
diff --git a/docs/tutorials/tutorial3_position_compare.rst b/docs/_legacy_rst/tutorials/tutorial3_position_compare.rst
similarity index 100%
rename from docs/tutorials/tutorial3_position_compare.rst
rename to docs/_legacy_rst/tutorials/tutorial3_position_compare.rst
diff --git a/docs/tutorials/tutorial4_snake_scan.rst b/docs/_legacy_rst/tutorials/tutorial4_snake_scan.rst
similarity index 100%
rename from docs/tutorials/tutorial4_snake_scan.rst
rename to docs/_legacy_rst/tutorials/tutorial4_snake_scan.rst
diff --git a/docs/webcontrol/_static/theme_overrides.css b/docs/_legacy_rst/webcontrol/_static/theme_overrides.css
similarity index 100%
rename from docs/webcontrol/_static/theme_overrides.css
rename to docs/_legacy_rst/webcontrol/_static/theme_overrides.css
diff --git a/docs/webcontrol/_templates/layout.html b/docs/_legacy_rst/webcontrol/_templates/layout.html
similarity index 100%
rename from docs/webcontrol/_templates/layout.html
rename to docs/_legacy_rst/webcontrol/_templates/layout.html
diff --git a/docs/webcontrol/_templates/page.html b/docs/_legacy_rst/webcontrol/_templates/page.html
similarity index 100%
rename from docs/webcontrol/_templates/page.html
rename to docs/_legacy_rst/webcontrol/_templates/page.html
diff --git a/docs/webcontrol/build_popping_screenshot.js b/docs/_legacy_rst/webcontrol/build_popping_screenshot.js
similarity index 100%
rename from docs/webcontrol/build_popping_screenshot.js
rename to docs/_legacy_rst/webcontrol/build_popping_screenshot.js
diff --git a/docs/webcontrol/conf.py b/docs/_legacy_rst/webcontrol/conf.py
similarity index 100%
rename from docs/webcontrol/conf.py
rename to docs/_legacy_rst/webcontrol/conf.py
diff --git a/docs/webcontrol/contents.rst b/docs/_legacy_rst/webcontrol/contents.rst
similarity index 100%
rename from docs/webcontrol/contents.rst
rename to docs/_legacy_rst/webcontrol/contents.rst
diff --git a/docs/webcontrol/copy_screenshots_from_e2e.js b/docs/_legacy_rst/webcontrol/copy_screenshots_from_e2e.js
similarity index 100%
rename from docs/webcontrol/copy_screenshots_from_e2e.js
rename to docs/_legacy_rst/webcontrol/copy_screenshots_from_e2e.js
diff --git a/docs/webcontrol/index.rst b/docs/_legacy_rst/webcontrol/index.rst
similarity index 100%
rename from docs/webcontrol/index.rst
rename to docs/_legacy_rst/webcontrol/index.rst
diff --git a/docs/webcontrol/malcolm-logo.ico b/docs/_legacy_rst/webcontrol/malcolm-logo.ico
similarity index 100%
rename from docs/webcontrol/malcolm-logo.ico
rename to docs/_legacy_rst/webcontrol/malcolm-logo.ico
diff --git a/docs/webcontrol/malcolm-logo.png b/docs/_legacy_rst/webcontrol/malcolm-logo.png
similarity index 100%
rename from docs/webcontrol/malcolm-logo.png
rename to docs/_legacy_rst/webcontrol/malcolm-logo.png
diff --git a/docs/webcontrol/malcolm-logo.svg b/docs/_legacy_rst/webcontrol/malcolm-logo.svg
similarity index 100%
rename from docs/webcontrol/malcolm-logo.svg
rename to docs/_legacy_rst/webcontrol/malcolm-logo.svg
diff --git a/docs/webcontrol/requirements.txt b/docs/_legacy_rst/webcontrol/requirements.txt
similarity index 100%
rename from docs/webcontrol/requirements.txt
rename to docs/_legacy_rst/webcontrol/requirements.txt
diff --git a/docs/webcontrol/userguide/contents.rst b/docs/_legacy_rst/webcontrol/userguide/contents.rst
similarity index 100%
rename from docs/webcontrol/userguide/contents.rst
rename to docs/_legacy_rst/webcontrol/userguide/contents.rst
diff --git a/docs/webcontrol/userguide/glossary.rst b/docs/_legacy_rst/webcontrol/userguide/glossary.rst
similarity index 100%
rename from docs/webcontrol/userguide/glossary.rst
rename to docs/_legacy_rst/webcontrol/userguide/glossary.rst
diff --git a/docs/webcontrol/userguide/images/attribute_lifecycle.svg b/docs/_legacy_rst/webcontrol/userguide/images/attribute_lifecycle.svg
similarity index 100%
rename from docs/webcontrol/userguide/images/attribute_lifecycle.svg
rename to docs/_legacy_rst/webcontrol/userguide/images/attribute_lifecycle.svg
diff --git a/docs/webcontrol/userguide/images/design_context.png b/docs/_legacy_rst/webcontrol/userguide/images/design_context.png
similarity index 100%
rename from docs/webcontrol/userguide/images/design_context.png
rename to docs/_legacy_rst/webcontrol/userguide/images/design_context.png
diff --git a/docs/webcontrol/userguide/images/disconnected_icon.png b/docs/_legacy_rst/webcontrol/userguide/images/disconnected_icon.png
similarity index 100%
rename from docs/webcontrol/userguide/images/disconnected_icon.png
rename to docs/_legacy_rst/webcontrol/userguide/images/disconnected_icon.png
diff --git a/docs/webcontrol/userguide/images/error_icon.png b/docs/_legacy_rst/webcontrol/userguide/images/error_icon.png
similarity index 100%
rename from docs/webcontrol/userguide/images/error_icon.png
rename to docs/_legacy_rst/webcontrol/userguide/images/error_icon.png
diff --git a/docs/webcontrol/userguide/images/information_icon.png b/docs/_legacy_rst/webcontrol/userguide/images/information_icon.png
similarity index 100%
rename from docs/webcontrol/userguide/images/information_icon.png
rename to docs/_legacy_rst/webcontrol/userguide/images/information_icon.png
diff --git a/docs/webcontrol/userguide/images/locally_edited_icon.png b/docs/_legacy_rst/webcontrol/userguide/images/locally_edited_icon.png
similarity index 100%
rename from docs/webcontrol/userguide/images/locally_edited_icon.png
rename to docs/_legacy_rst/webcontrol/userguide/images/locally_edited_icon.png
diff --git a/docs/webcontrol/userguide/images/put_process.svg b/docs/_legacy_rst/webcontrol/userguide/images/put_process.svg
similarity index 100%
rename from docs/webcontrol/userguide/images/put_process.svg
rename to docs/_legacy_rst/webcontrol/userguide/images/put_process.svg
diff --git a/docs/webcontrol/userguide/images/system_context.svg b/docs/_legacy_rst/webcontrol/userguide/images/system_context.svg
similarity index 100%
rename from docs/webcontrol/userguide/images/system_context.svg
rename to docs/_legacy_rst/webcontrol/userguide/images/system_context.svg
diff --git a/docs/webcontrol/userguide/images/ui_schematic.png b/docs/_legacy_rst/webcontrol/userguide/images/ui_schematic.png
similarity index 100%
rename from docs/webcontrol/userguide/images/ui_schematic.png
rename to docs/_legacy_rst/webcontrol/userguide/images/ui_schematic.png
diff --git a/docs/webcontrol/userguide/images/warning_icon.png b/docs/_legacy_rst/webcontrol/userguide/images/warning_icon.png
similarity index 100%
rename from docs/webcontrol/userguide/images/warning_icon.png
rename to docs/_legacy_rst/webcontrol/userguide/images/warning_icon.png
diff --git a/docs/webcontrol/userguide/index.rst b/docs/_legacy_rst/webcontrol/userguide/index.rst
similarity index 100%
rename from docs/webcontrol/userguide/index.rst
rename to docs/_legacy_rst/webcontrol/userguide/index.rst
diff --git a/docs/webcontrol/userguide/monitoring_attribute_values.rst b/docs/_legacy_rst/webcontrol/userguide/monitoring_attribute_values.rst
similarity index 100%
rename from docs/webcontrol/userguide/monitoring_attribute_values.rst
rename to docs/_legacy_rst/webcontrol/userguide/monitoring_attribute_values.rst
diff --git a/docs/webcontrol/userguide/quick-start.rst b/docs/_legacy_rst/webcontrol/userguide/quick-start.rst
similarity index 100%
rename from docs/webcontrol/userguide/quick-start.rst
rename to docs/_legacy_rst/webcontrol/userguide/quick-start.rst
diff --git a/docs/webcontrol/userguide/screenshots/PANDA-block-details.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/PANDA-block-details.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/PANDA-block-details.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/PANDA-block-details.png
diff --git a/docs/webcontrol/userguide/screenshots/PANDA-layout-spread-out.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/PANDA-layout-spread-out.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/PANDA-layout-spread-out.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/PANDA-layout-spread-out.png
diff --git a/docs/webcontrol/userguide/screenshots/PANDA-layout.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/PANDA-layout.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/PANDA-layout.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/PANDA-layout.png
diff --git a/docs/webcontrol/userguide/screenshots/PANDA-new-link.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/PANDA-new-link.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/PANDA-new-link.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/PANDA-new-link.png
diff --git a/docs/webcontrol/userguide/screenshots/attribute_table.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/attribute_table.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/attribute_table.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/attribute_table.png
diff --git a/docs/webcontrol/userguide/screenshots/attribute_value_table.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/attribute_value_table.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/attribute_value_table.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/attribute_value_table.png
diff --git a/docs/webcontrol/userguide/screenshots/attribute_view_chart.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/attribute_view_chart.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/attribute_view_chart.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/attribute_view_chart.png
diff --git a/docs/webcontrol/userguide/screenshots/block-list.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/block-list.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/block-list.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/block-list.png
diff --git a/docs/webcontrol/userguide/screenshots/chart_options.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/chart_options.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/chart_options.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/chart_options.png
diff --git a/docs/webcontrol/userguide/screenshots/continuous_plot.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/continuous_plot.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/continuous_plot.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/continuous_plot.png
diff --git a/docs/webcontrol/userguide/screenshots/example-ui.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/example-ui.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/example-ui.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/example-ui.png
diff --git a/docs/webcontrol/userguide/screenshots/layout-button.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/layout-button.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/layout-button.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/layout-button.png
diff --git a/docs/webcontrol/userguide/screenshots/panel_popping.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/panel_popping.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/panel_popping.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/panel_popping.png
diff --git a/docs/webcontrol/userguide/screenshots/popping-1.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/popping-1.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/popping-1.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/popping-1.png
diff --git a/docs/webcontrol/userguide/screenshots/popping-2.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/popping-2.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/popping-2.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/popping-2.png
diff --git a/docs/webcontrol/userguide/screenshots/popping-3.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/popping-3.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/popping-3.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/popping-3.png
diff --git a/docs/webcontrol/userguide/screenshots/popping-4.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/popping-4.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/popping-4.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/popping-4.png
diff --git a/docs/webcontrol/userguide/screenshots/starting-ui.png b/docs/_legacy_rst/webcontrol/userguide/screenshots/starting-ui.png
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/starting-ui.png
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/starting-ui.png
diff --git a/docs/webcontrol/userguide/screenshots/window_popping_output.svg b/docs/_legacy_rst/webcontrol/userguide/screenshots/window_popping_output.svg
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/window_popping_output.svg
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/window_popping_output.svg
diff --git a/docs/webcontrol/userguide/screenshots/window_popping_template.svg b/docs/_legacy_rst/webcontrol/userguide/screenshots/window_popping_template.svg
similarity index 100%
rename from docs/webcontrol/userguide/screenshots/window_popping_template.svg
rename to docs/_legacy_rst/webcontrol/userguide/screenshots/window_popping_template.svg
diff --git a/docs/webcontrol/userguide/understanding_attribute_state.rst b/docs/_legacy_rst/webcontrol/userguide/understanding_attribute_state.rst
similarity index 100%
rename from docs/webcontrol/userguide/understanding_attribute_state.rst
rename to docs/_legacy_rst/webcontrol/userguide/understanding_attribute_state.rst
diff --git a/docs/webcontrol/userguide/user_interface_overview.rst b/docs/_legacy_rst/webcontrol/userguide/user_interface_overview.rst
similarity index 100%
rename from docs/webcontrol/userguide/user_interface_overview.rst
rename to docs/_legacy_rst/webcontrol/userguide/user_interface_overview.rst
diff --git a/docs/webcontrol/userguide/working_with_a_design.rst b/docs/_legacy_rst/webcontrol/userguide/working_with_a_design.rst
similarity index 100%
rename from docs/webcontrol/userguide/working_with_a_design.rst
rename to docs/_legacy_rst/webcontrol/userguide/working_with_a_design.rst
diff --git a/docs/explanations.md b/docs/explanations.md
new file mode 100644
index 00000000..a1dca5ac
--- /dev/null
+++ b/docs/explanations.md
@@ -0,0 +1,7 @@
+# Explanations
+
+Explanations of how it works and why it works that way.
+
+```{toc}
+:context: children
+```
diff --git a/docs/explanations/architecture.md b/docs/explanations/architecture.md
new file mode 100644
index 00000000..7bb1c350
--- /dev/null
+++ b/docs/explanations/architecture.md
@@ -0,0 +1,67 @@
+# Architecture
+
+PandABlocks is a framework for building real-time signal processing and data
+capture systems on Zynq FPGA hardware. The system has four main layers:
+
+## Layers
+
+### FPGA firmware (PandABlocks-FPGA)
+
+The FPGA runs a set of functional **blocks** — clock generators, counters,
+pulse stretchers, position capture, lookup tables and more. Each block
+has typed input and output ports (bit bus, position bus) and a set of
+configurable fields. Block definitions live in the
+[PandABlocks-FPGA](https://github.com/PandABlocks/PandABlocks-FPGA) repository.
+
+### Server (PandABlocks-server)
+
+The PandABlocks server runs on the Zynq ARM and exposes all block fields over
+a plain TCP interface on port 8888 (control) and port 8889 (data capture).
+The server is the sole point of contact for clients — it translates TCP
+commands into register reads/writes to the FPGA. The server lives in
+[PandABlocks-server](https://github.com/PandABlocks/PandABlocks-server).
+
+### Client libraries
+
+Several client layers build on the TCP interface:
+
+| Layer | Repo | Use case |
+|---|---|---|
+| Direct TCP | — | Low-level scripting, quick checks |
+| Python client | [PandABlocks-client](xref:PandABlocks-client) | Python applications; preferred for new integrations |
+| EPICS / Tango | [fastcs-PandABlocks](https://github.com/DiamondLightSource/fastcs-PandABlocks) | Control-system integrations |
+
+See [](../how-to/integrate-with-a-panda.md) for step-by-step instructions.
+
+### Firmware build (meta-panda)
+
+The Yocto layer in this repository assembles the firmware image: it pulls the
+rootfs, server, FPGA bitstreams and web-control packages together into a
+bootable SD card image (see [](../how-to/build.md)).
+
+## Data flow
+
+```
+ Detector / instrument hardware
+ │
+ ▼
+ ┌──────────────┐
+ │ FPGA blocks │ ← bit bus / position bus connections
+ │ (Zynq PL) │ configured via TCP server
+ └──────┬───────┘
+ │
+ ┌──────▼───────┐ port 8888 (control)
+ │ PandA server│ ─────────────────────────► clients
+ │ (Zynq PS) │ port 8889 (data stream)
+ └──────────────┘
+```
+
+At trigger the server streams captured data over port 8889 in ASCII or binary
+format. Binary frames can be decoded to numpy arrays or written to HDF5 by
+PandABlocks-client.
+
+## Hardware targets
+
+PandABlocks firmware runs on several Zynq-based hardware platforms — see
+[](hardware-targets.md) for per-target descriptions and
+[](../reference/machine-targets.md) for the `MACHINE` build strings.
diff --git a/docs/explanations/boot-process.md b/docs/explanations/boot-process.md
new file mode 100644
index 00000000..776b8a6a
--- /dev/null
+++ b/docs/explanations/boot-process.md
@@ -0,0 +1,39 @@
+# The boot process
+
+The boot process on a Zynq-based PandA proceeds through five stages:
+
+0. **Stage-0 boot loader (hard-wired in Zynq)**
+ Reads `boot.bin` from the SD card into memory and passes control to the
+ stage-1 loader.
+
+1. **Stage-1 boot loader (inside `boot.bin`)**
+ Loads U-Boot from `boot.bin`.
+
+2. **Stage-2 boot loader: U-Boot**
+ Runs the boot script (`boot.scr`) which locates the FIT image (`image.ub`),
+ checks its integrity, and boots the Linux kernel.
+
+3. **Kernel initialisation**
+ The kernel initialises hardware resources and then unpacks the initramfs
+ image contained inside the FIT image. The `init` script within the
+ initramfs is executed.
+
+4. **Initramfs init script**
+ Checks the configuration (including network settings from `config.txt`),
+ prompts for a MAC address if one has not been set, and mounts the main
+ rootfs image (`rootfs.squashfs`).
+
+5. **Rootfs init system**
+ The target system starts by running the init system inside the mounted
+ rootfs image. PandA services (TCP server, web interface) are started here.
+
+## Key files on the SD card
+
+| File | Role |
+|---|---|
+| `boot.bin` | Stage-0/1 boot loader + U-Boot |
+| `boot.scr` | U-Boot boot script |
+| `image.ub` | FIT image: kernel + device tree + initramfs |
+| `rootfs.squashfs` | Main Linux rootfs |
+| `config.txt` | Network and boot configuration (user-editable) |
+| `target-defs` | Target-specific configuration functions |
diff --git a/docs/explanations/decisions.md b/docs/explanations/decisions.md
new file mode 100644
index 00000000..44e42668
--- /dev/null
+++ b/docs/explanations/decisions.md
@@ -0,0 +1,5 @@
+# Architectural Decision Records
+
+Architectural decisions are made throughout a project's lifetime. As a way of keeping track of these decisions, we record these decisions in Architecture Decision Records (ADRs) listed below.
+
+For more information on ADRs see this [blog by Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions).
diff --git a/docs/explanations/decisions/0001-record-architecture-decisions.md b/docs/explanations/decisions/0001-record-architecture-decisions.md
new file mode 100644
index 00000000..44d234ef
--- /dev/null
+++ b/docs/explanations/decisions/0001-record-architecture-decisions.md
@@ -0,0 +1,18 @@
+# 1. Record architecture decisions
+
+## Status
+
+Accepted
+
+## Context
+
+We need to record the architectural decisions made on this project.
+
+## Decision
+
+We will use Architecture Decision Records, as [described by Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions).
+
+## Consequences
+
+See Michael Nygard's article, linked above. To create new ADRs we will copy and
+paste from existing ones.
diff --git a/docs/explanations/decisions/0002-switched-to-python-copier-template.md b/docs/explanations/decisions/0002-switched-to-python-copier-template.md
new file mode 100644
index 00000000..66fe5d8b
--- /dev/null
+++ b/docs/explanations/decisions/0002-switched-to-python-copier-template.md
@@ -0,0 +1,28 @@
+# 2. Adopt python-copier-template for project structure
+
+## Status
+
+Accepted
+
+## Context
+
+We should use the following [python-copier-template](https://github.com/DiamondLightSource/python-copier-template).
+The template will ensure consistency in developer
+environments and package management.
+
+## Decision
+
+We have switched to using the template.
+
+## Consequences
+
+This module will use a fixed set of tools as developed in `python-copier-template`
+and can pull from this template to update the packaging to the latest techniques.
+
+As such, the developer environment may have changed, the following could be
+different:
+
+- linting
+- formatting
+- pip venv setup
+- CI/CD
diff --git a/docs/explanations/decisions/COPYME b/docs/explanations/decisions/COPYME
new file mode 100644
index 00000000..b466c792
--- /dev/null
+++ b/docs/explanations/decisions/COPYME
@@ -0,0 +1,19 @@
+# 3. Short descriptive title
+
+Date: Today's date
+
+## Status
+
+Accepted
+
+## Context
+
+Background to allow us to make the decision, to show how we arrived at our conclusions.
+
+## Decision
+
+What decision we made.
+
+## Consequences
+
+What we will do as a result of this decision.
diff --git a/docs/explanations/hardware-targets.md b/docs/explanations/hardware-targets.md
new file mode 100644
index 00000000..7c83448e
--- /dev/null
+++ b/docs/explanations/hardware-targets.md
@@ -0,0 +1,13 @@
+# Hardware targets
+
+:::{admonition} 🚧 TODO — documentation stub
+:class: warning
+
+This page is a Stage A scaffold stub and has not yet been written.
+
+**Status:** blocked: author
+
+**Source:** NEW (Interview6 §A) — per-target hardware (SoC/module, features)
+
+**Blocked:** [PandABlocks/meta-panda#19](https://github.com/PandABlocks/meta-panda/issues/19)
+:::
diff --git a/docs/explanations/understanding-attribute-state.md b/docs/explanations/understanding-attribute-state.md
new file mode 100644
index 00000000..720827fd
--- /dev/null
+++ b/docs/explanations/understanding-attribute-state.md
@@ -0,0 +1,132 @@
+# Understanding attribute state
+
+At any given time an attribute can be in one of eight states. State depends on:
+
+- The current value of the attribute.
+- The pre-defined permissible operating range or threshold for that attribute.
+- The workflow the attribute is currently involved in.
+- The overall context of the control system.
+
+State is shown as an icon to the left of the attribute name in the
+{term}`Block Information Panel`.
+
+## State reference
+
+### Normal
+
+Data is within an acceptable operating threshold or range. For a
+{term}`Parameter Attribute` this also means the value has been successfully
+committed to the server.
+
+```{figure} ../images/attribute-state/normal.svg
+:align: center
+:width: 32px
+
+Normal state icon
+```
+
+### Processing
+
+Data has been submitted to the server or a retrieval request has been made.
+A response is being awaited.
+
+```{figure} ../images/attribute-state/processing.svg
+:align: center
+:width: 32px
+
+Processing state icon
+```
+
+### Locally Edited
+
+The value has been changed in the UI but not yet committed to the server.
+The local edit has no effect on the running system and will not be saved as
+part of the {term}`Design` until it is submitted.
+
+```{figure} ../images/attribute-state/locally-edited.svg
+:align: center
+:width: 32px
+
+Locally Edited state icon
+```
+
+### Update Error
+
+The value submitted to the server was not accepted — typically because it
+failed the validation defined in the Block specification.
+
+```{figure} ../images/attribute-state/update-error.svg
+:align: center
+:width: 32px
+
+Update Error state icon
+```
+
+### Warning
+
+An issue has been detected that requires investigation. Data is outside
+normal operating parameters but is still considered acceptable.
+
+```{figure} ../images/attribute-state/warning.svg
+:align: center
+:width: 32px
+
+Warning state icon
+```
+
+### Error
+
+An issue has been detected and an error has been reported by the server.
+Data is outside acceptable operating conditions; immediate action is
+recommended.
+
+```{figure} ../images/attribute-state/error.svg
+:align: center
+:width: 32px
+
+Error state icon
+```
+
+### Invalid
+
+The overall block context has changed since the UI was last accessed.
+Displayed data may no longer be accurate or consistent with the current
+{term}`Design`.
+
+```{figure} ../images/attribute-state/invalid.svg
+:align: center
+:width: 32px
+
+Invalid state icon
+```
+
+### Disconnected
+
+Communication with the block hosting the attribute has been lost by the
+server. Immediate investigation is recommended.
+
+```{figure} ../images/attribute-state/disconnected.svg
+:align: center
+:width: 32px
+
+Disconnected state icon
+```
+
+## Presenting status information
+
+Within Block Information Panels, the state icon appears to the left of each
+attribute name.
+
+When viewing historical data in the
+[attribute value table](../how-to/monitor-attribute-values.md),
+the corresponding icon is shown against each row.
+
+When viewing historical data in the
+[attribute chart](../how-to/monitor-attribute-values.md),
+the line colour reflects the alarm state.
+
+:::{note}
+Operating ranges and threshold values are not defined in the UI — they are
+configured in the underlying Block specification and reflected into the UI.
+Refer to the specific block documentation for details.
+:::
diff --git a/docs/explanations/web-control-ui-overview.md b/docs/explanations/web-control-ui-overview.md
new file mode 100644
index 00000000..95a488a6
--- /dev/null
+++ b/docs/explanations/web-control-ui-overview.md
@@ -0,0 +1,92 @@
+# Web control UI overview
+
+The web control provides a fully interactive environment for designing,
+configuring and managing PandA block connections.
+
+## Components
+
+The interface has four core components whose content changes dynamically
+depending on the current activity:
+
+```{figure} ../images/webcontrol/ui_schematic.png
+:align: center
+
+Web control UI components
+```
+
+| Component | Description |
+|---|---|
+| **Navigation bar** | Breadcrumb trail showing your current position within the Design, starting from the selected {term}`Root Block`. Use it to move between nested levels. |
+| **Left-hand panel** | Information about the {term}`Parent Block` currently in focus. |
+| **Central panel** | Details of the selected {term}`Attribute` or the {term}`Layout` view if **Layout** is selected. |
+| **Right-hand panel** | Detailed information about the {term}`Block`, {term}`Attribute` or {term}`Link` currently in focus. |
+
+:::{tip}
+- A Block is *always* displayed in the left-hand panel (Parent or Child).
+- Attribute metadata is always shown in the right-hand panel.
+- Link information is always shown in the right-hand panel.
+:::
+
+## Views
+
+### Layout view
+
+The Layout view lets you create, modify and manage the overall {term}`Design`.
+Open it by clicking **View** or **Edit** next to the *Layout* attribute on any
+Parent Block.
+
+```{figure} ../images/webcontrol/PANDA-layout-spread-out.png
+:align: center
+
+Example Layout view — PANDA system with CLOCKS block selected
+```
+
+In this view:
+
+- Drag blocks to rearrange them; links are re-routed automatically.
+- Click **Auto Layout** in the central panel to optimise the arrangement.
+- Click a block to load its details in the right-hand panel.
+
+### Attribute view
+
+The interface transitions to Attribute view when you select an attribute from
+either panel:
+
+- Selecting from the **left-hand panel** shows more detail about that attribute
+ in the right-hand panel.
+- Selecting from the **right-hand panel** moves the corresponding block to the
+ left-hand panel as the new focus.
+
+The **central panel** shows the attribute's value over time as either:
+
+- **Plot** — an interactive line chart (pan, zoom, export). See
+ [](../how-to/monitor-attribute-values.md) for chart controls.
+- **Table** — a time-ordered list of value changes.
+
+```{figure} ../images/webcontrol/attribute_view_chart.png
+:align: center
+
+Attribute view — example plot for a continuously updated attribute
+```
+
+:::{note}
+In Attribute view the left-hand panel shows the selected block (e.g. "Input
+Encoder 1"), not the top-level Parent Block.
+:::
+
+## Panel popping
+
+In complex designs you may want to monitor several blocks at once. Click the
+pop icon in the top-left corner of any Block Information Panel to open it in
+its own independent window. Multiple panels can be popped simultaneously.
+
+```{figure} ../images/webcontrol/window_popping_output.svg
+:align: center
+
+Three Child Blocks (CLOCKS, COUNTER1, BITS) popped into independent windows
+alongside the PANDA Layout
+```
+
+Each independent window stays live — attribute updates are reflected in real
+time, and any edits you make are sent back to the PandA just as they would be
+from the integrated panel.
diff --git a/docs/how-to.md b/docs/how-to.md
new file mode 100644
index 00000000..ba801fd7
--- /dev/null
+++ b/docs/how-to.md
@@ -0,0 +1,7 @@
+# How-to Guides
+
+Practical step-by-step guides for the more experienced user.
+
+```{toc}
+:context: children
+```
diff --git a/docs/how-to/build.md b/docs/how-to/build.md
new file mode 100644
index 00000000..139d4924
--- /dev/null
+++ b/docs/how-to/build.md
@@ -0,0 +1,83 @@
+# How to build the PandA boot image
+
+## Prerequisites
+
+- [kas](https://kas.readthedocs.io/) installed, or Docker / Podman available
+ so that `kas-container` can pull and run the build container automatically.
+- A clone of the `meta-panda` repository.
+
+## Build steps
+
+1. Clone the repository:
+
+ ```bash
+ git clone https://github.com/PandABlocks/meta-panda
+ cd meta-panda
+ ```
+
+2. If `kas` is not already installed, create a virtual environment and install
+ it:
+
+ ```bash
+ python3 -m venv venv && . venv/bin/activate && pip install kas
+ ```
+
+3. Build the image. `kas-container` pulls the required build container image
+ automatically — no manual Docker setup is needed:
+
+ ```bash
+ export KAS_IMAGE_VERSION="4.8"
+ kas-container build ./kas.yml
+ ```
+
+ :::{note}
+ `KAS_IMAGE_VERSION` pins the version of the build container. Check the
+ `meta-panda` release notes or the `kas.yml` file for the value appropriate
+ to the version you are building.
+ :::
+
+ To target a different machine set `KAS_MACHINE`, e.g.:
+
+ ```bash
+ KAS_MACHINE=xu5-st1 kas-container build ./kas.yml
+ ```
+
+ The default machine is `pandabox`. Output lands under
+ `build/tmp/deploy/images/`.
+
+4. (Optional) Collect the output files, for example for pandabox:
+
+ ```bash
+ mkdir boot
+ cp -Lf build/tmp/deploy/images/pandabox/fitImage-petalinux-initramfs-image-pandabox-pandabox \
+ boot/image.ub
+ cp -f build/tmp/deploy/images/pandabox/{rootfs.squashfs,boot.bin,boot.scr,target-defs} boot/
+ zip boot-pandabox.zip boot/*
+ ```
+
+ Alternatively, the `build.sh` helper script builds and collects everything
+ for a specific machine in one step:
+
+ ```bash
+ ./build.sh
+ ```
+
+ A `boot-.zip` file is created in the current directory.
+
+
+## Output files
+
+| File | Description |
+|---|---|
+| `boot.bin` | Zynq stage-0 boot loader + U-Boot (stage-2) |
+| `boot.scr` | U-Boot script that locates and loads `image.ub` |
+| `image.ub` | FIT image: Linux kernel + device tree + initramfs |
+| `rootfs.squashfs` | Full Linux rootfs with all packages installed |
+| `config.txt` | User-editable network and boot configuration |
+| `target-defs` | Target-specific configuration functions |
+
+Copy these files to the SD card and insert it in the target; the system will
+boot normally. On the first boot of a pandabox you will be prompted for a MAC
+address.
+
+To build the FPGA bitstream that can be used to make the firmware, see [PandABlocks-FPGA documentation](https://pandablocks.github.io/PandABlocks-FPGA/docs/)
\ No newline at end of file
diff --git a/docs/how-to/choose-fpga-bitstream.md b/docs/how-to/choose-fpga-bitstream.md
new file mode 100644
index 00000000..f6b3ae24
--- /dev/null
+++ b/docs/how-to/choose-fpga-bitstream.md
@@ -0,0 +1,52 @@
+# Choose the FPGA bitstream
+
+Each PandABlocks-FPGA `.ipk` package ships an FPGA bitstream and declares
+which FMC hardware it requires. On boot, meta-panda selects the bitstream
+to load as follows:
+
+1. If the `APP` variable is set in `config.txt`, that bitstream is used.
+2. Otherwise the PandA reads the FMC EEPROM and auto-selects the bitstream
+ whose FMC requirements match.
+3. If more than one installed bitstream would satisfy the EEPROM check, the
+ PandA reports an error.
+
+## Automatic selection
+
+Leave `APP` unset in `config.txt`. The PandA will select the bitstream that
+matches the FMC card detected at boot. If no FMC EEPROM is found, the
+`no-fmc` variant is used.
+
+## Manual override via `APP`
+
+To force a specific bitstream, add `APP=` to `config.txt` on the SD
+card:
+
+```ini
+APP = pandabox-fmc-acq430
+```
+
+The `APP` variable takes effect only if the corresponding FPGA variant package
+is installed. Available variant names are listed in the package names visible
+in the web admin (**Packages → List Installed Packages**).
+
+### USB override (no SD card access needed)
+
+To override without opening the PandA, add `APP=` to
+`panda-config.txt` on a USB stick and plug it in while the PandA boots:
+
+```ini
+APP = pandabox-fmc-acq430
+```
+
+See [](setup-without-dhcp.md) for full details of the USB override mechanism.
+
+## Installing a new bitstream package
+
+```bash
+scp panda-fpga-_.ipk root@:/tmp/
+ssh root@ opkg install /tmp/panda-fpga-_.ipk
+ssh root@ reboot
+```
+
+To build a custom bitstream package from source, see the
+[PandABlocks-FPGA documentation](https://github.com/PandABlocks/PandABlocks-FPGA).
diff --git a/docs/how-to/contribute.md b/docs/how-to/contribute.md
new file mode 100644
index 00000000..415f7582
--- /dev/null
+++ b/docs/how-to/contribute.md
@@ -0,0 +1,17 @@
+```{include} ../../.github/CONTRIBUTING.md
+```
+
+## Cross-repository references
+
+PandABlocks docs cross-link to the other repos with MyST `xref:` links,
+configured in `docs/myst.yml` under `project.references`. For the link syntax,
+when to use each target type, and the list of available reference targets, see
+the [documentation standards reference](/reference/documentation-standards.md).
+
+### Upstreaming to the copier template
+
+The `project.references` block in `docs/myst.yml` is a prototype intended for
+upstreaming into the
+[python-copier-template](https://github.com/DiamondLightSource/python-copier-template).
+When upstreaming, verify that the URL format and key names are consistent with
+any MyST version changes since Stage A.
diff --git a/docs/how-to/integrate-with-a-panda.md b/docs/how-to/integrate-with-a-panda.md
new file mode 100644
index 00000000..d8edb1e7
--- /dev/null
+++ b/docs/how-to/integrate-with-a-panda.md
@@ -0,0 +1,72 @@
+# Integrate with a PandA
+
+A PandA exposes a plain TCP server on port 8888 (control) and port 8889
+(data capture). Several client libraries build on this interface:
+
+| Approach | When to use |
+|---|---|
+| Direct TCP | Low-level scripting; quick one-off checks |
+| PandABlocks-client (Python) | Python applications; preferred for new integrations |
+| fastcs-PandABlocks (EPICS / Tango) | Control-system integrations via EPICS or Tango |
+
+## Direct TCP
+
+Connect to port 8888 to send commands and read responses:
+
+```bash
+nc 8888
+```
+
+See the
+[PandABlocks-server commands reference](xref:PandABlocks-server/reference/commands)
+for the command syntax.
+
+Connect to port 8889 for the data capture stream:
+
+```bash
+nc 8889
+```
+
+Press Return; you will see `OK`. After arming PCAP (in the web control or
+via port 8888), data streams until you disarm. See
+[Tutorial 2](../tutorials/position_capture.md) for a worked example.
+
+## Python client (`PandABlocks-client`)
+
+[PandABlocks-client](xref:PandABlocks-client)
+provides both a blocking and an asyncio client.
+
+Install:
+
+```bash
+pip install pandablocks
+```
+
+### Blocking client
+
+The [`BlockingClient`](xref:PandABlocks-client#pandablocks.blocking.BlockingClient)
+is the simplest entry point:
+
+```python
+from pandablocks.blocking import BlockingClient
+
+with BlockingClient("my-panda") as client:
+ responses = client.send(["PCAP.ARM=1"])
+```
+
+### Data capture to HDF5 / numpy
+
+PandABlocks-client includes helpers to read the binary capture stream and
+write it to HDF5 or convert it to numpy arrays. See the
+[PandABlocks-client documentation](xref:PandABlocks-client)
+for the `PcapHdf5Writer` and related utilities.
+
+## EPICS and Tango via `fastcs-PandABlocks`
+
+[fastcs-PandABlocks](https://github.com/DiamondLightSource/fastcs-PandABlocks)
+wraps PandABlocks-client and exposes all PandA attributes as EPICS PVs or
+Tango attributes via the [FastCS](https://github.com/DiamondLightSource/FastCS)
+framework.
+
+Refer to the fastcs-PandABlocks repository for installation and configuration
+instructions.
diff --git a/docs/how-to/make-release.md b/docs/how-to/make-release.md
new file mode 100644
index 00000000..55f76320
--- /dev/null
+++ b/docs/how-to/make-release.md
@@ -0,0 +1,18 @@
+# Make a firmware release
+
+To make a new release, follow this checklist:
+
+1. Choose a new [PEP 440](https://peps.python.org/pep-0440/) compliant version
+ number.
+2. Go to the [GitHub releases page](https://github.com/PandABlocks/meta-panda/releases).
+3. Click **Draft a New Release**.
+4. Click **Choose a tag** and type the new version tag (select **Create new
+ tag** when prompted).
+5. Click **Generate release notes**, review and edit the auto-generated notes.
+6. Add a title and click **Publish Release**.
+
+:::{note}
+Pushing a tag to the `main` branch triggers the same release workflow, but you
+will not have the opportunity to edit the release notes before they are
+published.
+:::
diff --git a/docs/how-to/manual-build.md b/docs/how-to/manual-build.md
new file mode 100644
index 00000000..ccdba8d5
--- /dev/null
+++ b/docs/how-to/manual-build.md
@@ -0,0 +1,62 @@
+# Manually build the PandA image
+
+:::{note}
+This page describes a manual Yocto build without `kas-container`. For the
+recommended approach see [](build.md).
+:::
+
+The steps below can be run inside a Docker container (e.g. the `kas` image) if
+the Yocto host dependencies are not available on your system.
+
+## Steps
+
+1. Initialise the Yocto source tree using `repo` and the Xilinx manifest:
+
+ ```bash
+ BRANCH="rel-v2023.2"
+ repo init -u https://github.com/Xilinx/yocto-manifests.git -b $BRANCH
+ repo sync
+ ```
+
+ :::{note}
+ `rel-v2023.2` is the manifest branch used for current PandA 5.x builds.
+
+ :::
+
+2. Load the Yocto build environment, passing the build directory as argument:
+
+ ```bash
+ . setupsdk build
+ ```
+
+3. Add the `meta-panda` layer:
+
+ ```bash
+ git clone https://github.com/PandABlocks/meta-panda ../sources/meta-panda
+ bitbake-layers add-layer ../sources/meta-panda
+ ```
+
+4. In `conf/local.conf` set:
+
+ ```makefile
+ MACHINE = "pandabox" # or e.g. "xu5
+ DISTRO = "panda-petalinux"
+ ```
+
+5. Build the image:
+
+ ```bash
+ bitbake panda-image
+ ```
+
+6. Collect the output files:
+
+ ```bash
+ mkdir boot
+ cp -Lf tmp/deploy/images/pandabox/fitImage-petalinux-initramfs-image-pandabox-pandabox \
+ boot/image.ub
+ cp -f tmp/deploy/images/pandabox/{rootfs.squashfs,boot.bin,boot.scr,target-defs} boot/
+ zip boot-pandabox.zip boot/*
+ ```
+
+See [](build.md) for a description of each output file.
diff --git a/docs/how-to/monitor-attribute-values.md b/docs/how-to/monitor-attribute-values.md
new file mode 100644
index 00000000..4749d488
--- /dev/null
+++ b/docs/how-to/monitor-attribute-values.md
@@ -0,0 +1,93 @@
+# Monitor attribute values
+
+The web control provides a near-real-time graphical and numerical view of block
+attribute values over time. Each attribute can be displayed as a **chart** or a
+**table**.
+
+## Working with charts
+
+A chart starts recording when you open it by clicking the information icon next
+to an attribute in its block's detail panel. Data is "for information only" —
+it represents the attribute's behaviour over the time the chart is open.
+
+The web control renders every attribute type as a chart:
+
+| Attribute format | Plot type |
+|---|---|
+| Numerical | Continuous scatter plot; attribute value on Y axis, time on X axis |
+| Text | Discrete scatter plot; each unique text string on Y axis |
+| Boolean | On/off state plot on Y axis |
+
+### Chart controls
+
+Hover over the chart to reveal the menu bar:
+
+```{figure} ../images/webcontrol/chart_options.png
+:align: center
+
+Chart controls toolbar
+```
+
+| Control | Description |
+|---|---|
+| Download Plot as PNG | Save a snapshot of the current chart |
+| Edit in Chart Studio | Export data to the [Chart Studio](https://chart-studio.plotly.com/) online tool |
+| Zoom | Draw a bounding box to zoom; smaller box = higher zoom; updates pause while zoomed |
+| Pan | Pan horizontally or vertically; updates continue while panning |
+| Zoom in / out | Auto-zoom centred on the most recent data; updates pause while zoomed |
+| Autoscale | Scale the plot to show all data since the chart was opened |
+| Home (Reset Axes) | Return to the default scale and resume live updates |
+| Toggle Spike Lines | Overlay crosshair guide lines on hover |
+| Show closest data on hover | Display the value of the nearest data point to the cursor |
+| Compare data on hover | Display all attribute values at the time point under the cursor |
+
+:::{note}
+The **Edit in Chart Studio** option is provided by a third-party service
+(Plotly). The PandABlocks project is not responsible for its availability or
+support.
+:::
+
+### Chart update behaviour
+
+- Data is supplied at up to **20 Hz**.
+- The on-screen chart updates at **1 Hz**; each update plots all 20 Hz samples
+ collected in the preceding second.
+- Zooming **pauses** automatic chart updates so you can inspect a snapshot.
+ Automatic updates resume when you return to the default view (Home / Reset
+ Axes).
+
+### Exporting a chart
+
+Click **Download Plot as PNG** in the chart menu bar at any time. The snapshot
+is saved to your browser's default downloads folder.
+
+### Advanced analysis with Chart Studio
+
+Click **Edit in Chart Studio** to export the current on-screen data to the
+Plotly Chart Studio web application. See the
+[Chart Studio documentation](https://help.plot.ly/) for its full feature set.
+
+## Working with numerical tables
+
+A table presents attribute values in numerical form. Each row records a value
+change and shows:
+
+- The time of the change
+- The new attribute value
+- The attribute alarm status
+
+```{figure} ../images/webcontrol/attribute_value_table.png
+:align: center
+
+Attribute values presented in a numerical table
+```
+
+The data shown is "for information only" and covers only the time the table has
+been open.
+
+### Table update behaviour
+
+- Data is supplied at up to **20 Hz**.
+- The table updates at **1 Hz**; each update appends all 20 Hz samples from the
+ preceding second.
+- New rows are added at the **bottom** of the table.
diff --git a/docs/how-to/packages.md b/docs/how-to/packages.md
new file mode 100644
index 00000000..ad7889c0
--- /dev/null
+++ b/docs/how-to/packages.md
@@ -0,0 +1,24 @@
+# Install packages via opkg
+
+PandA uses [opkg](https://openwrt.org/docs/guide-user/additional-software/opkg)
+to manage application software. Packages are distributed as `.ipk` files whose
+names follow the convention `_.ipk`.
+
+## Install via the web admin interface
+
+1. Place the `.ipk` file(s) on a USB stick.
+2. Insert the USB stick into the PandA.
+3. Open the web admin interface at `http:///admin/`.
+4. Navigate to **Packages → Install Packages from USB**.
+5. Browse to the `.ipk` file and click **Install Selected**.
+
+## Install over SSH
+
+Copy the `.ipk` to the PandA and install it with `opkg`:
+
+```bash
+scp panda-fpga_.ipk root@:/tmp
+ssh root@ opkg install /tmp/panda-fpga_.ipk
+```
+
+Replace `panda-fpga_.ipk` with the actual filename.
diff --git a/docs/how-to/save-restore-design.md b/docs/how-to/save-restore-design.md
new file mode 100644
index 00000000..5dc89ac3
--- /dev/null
+++ b/docs/how-to/save-restore-design.md
@@ -0,0 +1,62 @@
+# Save and restore a design
+
+A {term}`Design` can be saved to a {term}`Parent Block` and reopened later. This
+page covers saving the current design and opening an existing one. To build or
+edit a design, see
+[](use-web-control-to-set-up-a-panda.md).
+
+:::{tip}
+Saving a design saves only attributes already in the **server** state — locally
+modified fields are not saved. See
+[Local vs. server attribute state](use-web-control-to-set-up-a-panda.md#local-vs-server-attribute-state).
+:::
+
+## Save a design
+
+You can save your design at any time during creation or modification, and we
+recommend you do so regularly.
+
+1. Navigate to the {term}`Root Block` representing the highest level of the
+ design you wish to save.
+2. Navigate to the *Save* attribute group at the bottom of the left-hand panel.
+ Expand it if necessary.
+3. Enter a descriptive name for the design in the *Design Name* field. This
+ name is used later to identify the design.
+
+ :::{tip}
+ To save the design with the same name as the currently open design, leave the
+ *Design Name* field blank.
+ :::
+
+4. Select the **Save** button. The information icon to the left of the button
+ spins while the save is in progress, returning to the information icon when
+ the design is saved.
+
+:::{note}
+If an error is detected during the save, a red warning icon is displayed next to
+the button.
+:::
+
+## Open an existing design
+
+A {term}`Parent Block` may hold multiple {term}`Design`s, each reflecting
+operation of that block in a different scenario. Only one design can be in use at
+any given time; by default this is the design open at the time of system
+execution.
+
+When a parent block is opened, a list of all its designs is available via the
+*Design* attribute in the left-hand panel. Selecting an existing design presents
+it in the central Layout panel.
+
+To open an existing design:
+
+1. Navigate to the {term}`Parent Block` representing the highest level of the
+ system you wish to use.
+2. Navigate to the *Design* attribute and select the dropdown arrow to display
+ the list of available designs.
+3. Select the design you wish to use.
+4. Select the **View/Edit** button on the *Layout* attribute.
+
+:::{tip}
+If no previously saved designs exist, the *Design* attribute list is empty.
+:::
diff --git a/docs/how-to/setup-without-dhcp.md b/docs/how-to/setup-without-dhcp.md
new file mode 100644
index 00000000..b9ff2d31
--- /dev/null
+++ b/docs/how-to/setup-without-dhcp.md
@@ -0,0 +1,77 @@
+# How to get a PandA on the network without DHCP
+
+> **No configuration needed for DHCP** — just plug in and boot.
+
+The SD card inside a PandA contains a `config.txt` file that controls networking
+and other boot-time settings. Below is the default file with all options
+commented out:
+
+```ini
+# This file contains configuration settings. In this file network and other
+# settings can be adjusted.
+
+# If ADDRESS and NETMASK are not both specified DHCP will be used instead.
+# The ADDRESS field can be set to a four part dotted IP address followed by a
+# network mask specification thus:
+#
+# ADDRESS = 172.23.252.202
+# NETMASK = 255.255.240.0
+
+# If the ADDRESS field has been set then the GATEWAY and DNS fields should be
+# set:
+#
+# GATEWAY = 172.23.240.254
+# DNS = 172.23.5.13 172.23.4.1 130.246.8.13
+
+# Optionally the DNS search domain can be set:
+#
+# DNS_SEARCH = diamond.ac.uk
+
+# The NTP server or servers can be specified here:
+#
+# NTP = 172.23.240.2 172.23.199.1
+
+# The machine hostname can be specified here:
+#
+# HOSTNAME = panda
+
+# To skip loading any zpackages at startup, either for testing or as an
+# override to recover from a faulty zpkg install:
+#
+# NO_ZPKG
+```
+
+During startup the network is configured as follows:
+
+- If `ADDRESS` and `NETMASK` are both set, a static IP is assigned.
+ Set `GATEWAY` and `DNS` too; `NTP` is optional.
+- Otherwise DHCP is attempted. On success it sets IP, gateway, DNS and may
+ set hostname. If the DHCP server advertises NTP servers those take priority
+ over the `NTP` key.
+- If DHCP fails, ZeroConf is attempted. If that also fails the PandA will not
+ be reachable on the network.
+
+In the default (all-commented) configuration the PandA contacts
+`0.pool.ntp.org` and pool peers for time.
+
+## Override file
+
+If a static IP needs to be set without opening the SD card, use the USB
+override mechanism:
+
+Place a file named `panda-config.txt` on a USB drive and plug the drive into
+the PandA **while it is booting**. The PandA will read `panda-config.txt` from
+the USB drive instead of `config.txt` from the SD card.
+
+The override file uses the same format as `config.txt`, for example:
+
+```ini
+ADDRESS = 192.168.0.2
+NETMASK = 255.255.255.0
+GATEWAY = 192.168.0.254
+HOSTNAME = mypanda
+```
+
+To make the USB settings permanent, use the **Show Network Configuration**
+function in the Web Admin interface (described below), which writes the settings
+back to `config.txt` on the SD card.
diff --git a/docs/how-to/test-firmware-changes.md b/docs/how-to/test-firmware-changes.md
new file mode 100644
index 00000000..26324fa1
--- /dev/null
+++ b/docs/how-to/test-firmware-changes.md
@@ -0,0 +1,81 @@
+# Test firmware changes on a PandA
+
+This guide covers the workflow for building and deploying server or FPGA
+firmware changes to a live PandA for manual testing.
+
+## Simulation-mode testing (server)
+
+Server changes can be unit-tested natively in **simulation mode** — no PandA
+required. The only dependencies are `make` and `gcc`.
+
+```bash
+cd PandABlocks-server
+make sim
+```
+
+Simulation mode runs the server against a software model of the block
+hardware. See the
+[PandABlocks-server documentation](https://github.com/PandABlocks/PandABlocks-server)
+for the full test flow.
+
+## Live testing with `devtool` (server and FPGA)
+
+To test changes against real hardware, use the Yocto `devtool` workflow inside
+the `kas` build container:
+
+1. Open a shell in the `kas` container:
+
+ ```bash
+ KAS_MACHINE= kas-container --ssh-agent shell kas.yml
+ ```
+
+:::{note}
+Make sure there is disk space for the build files, an alternative build path
+can be specified with the environment variable KAS\_WORK\_DIR.
+:::
+
+2. Use `devtool` to build an updated package in the Yocto workspace:
+
+ ```bash
+ devtool modify
+ # make your changes in the workspace source tree
+ devtool build
+ ```
+
+3. Deploy the built `.ipk` to the PandA:
+
+ ```bash
+ devtool deploy-target root@
+ ```
+
+4. Restart the relevant service on the PandA:
+
+ ```bash
+ ssh root@ systemctl daemon-reload
+ ssh root@ systemctl restart
+ ```
+
+5. Test your changes on the live hardware.
+
+## Deploying a custom FPGA bitstream
+
+To test a custom FPGA bitstream:
+
+1. Build the `.ipk` containing the bitstream in
+ [PandABlocks-FPGA](https://github.com/PandABlocks/PandABlocks-FPGA)
+ (see the FPGA repo docs).
+
+2. Install it on the PandA:
+
+ ```bash
+ scp panda-fpga_.ipk root@:/tmp/
+ ssh root@ opkg install --force-reinstall /tmp/panda-fpga_.ipk
+ ```
+
+3. Override the active bitstream if needed — see [](choose-fpga-bitstream.md).
+
+4. Restart the relevant service:
+
+ ```bash
+ ssh root@ systemctl restart panda-fpga
+ ```
diff --git a/docs/how-to/upgrade-via-ssh.md b/docs/how-to/upgrade-via-ssh.md
new file mode 100644
index 00000000..fa20d5de
--- /dev/null
+++ b/docs/how-to/upgrade-via-ssh.md
@@ -0,0 +1,79 @@
+# Upgrading a PandA over SSH
+
+SSH access lets you upgrade a PandA without physical access, and is
+particularly useful for upgrading multiple PandAs in one scripted pass.
+
+## Prerequisites
+
+SSH must be authorised on the PandA. You can either:
+
+- Place an `authorized_keys` file on the SD card before first boot, or
+- Load SSH keys from `authorized_keys` file on a USB stick via the Web Admin interface
+ (**SSH Keys → Append SSH keys from USB**).
+
+:::{warning}
+A PandA has only a single `root` user. Remote operations run as root and can
+break the system if commands are wrong — take care.
+:::
+
+## 5.0 or later to 5.x (opkg / `.ipk`)
+
+1. Download the `boot-{MACHINE}.tar.gz` release archive from
+[GitHub Releases](https://github.com/PandABlocks/meta-panda/releases) and
+extract it locally.
+2. Then copy the files to the PandA and reboot:
+
+```bash
+ssh root@ rm -f /boot/rootfs.squashfs
+scp boot-{MACHINE}/* root@:/boot
+ssh root@ 'sync; reboot'
+```
+
+The `/boot` directory on the PandA should contain:
+
+- `boot.bin`
+- `boot.scr`
+- `image.ub`
+- `rootfs.squashfs`
+- `target-defs`
+
+3. Under **Admin Commands → System → Reboot/Restart**, click **Reboot Now** to restart the PandA; it will apply the new rootfs on next boot.
+
+## Pre-5.0 to 5.x (zpkg → opkg)
+
+1. Delete old conflicting files:
+ ```bash
+ ssh root@
+ rm -f /boot/uImage /boot/uinitramfs /boot/devicetree.db
+ ```
+2. Follow the instructions under **5.0 or later to 5.x**
+
+## Update the 24V FMC EEPROM (DLS-specific, one-time)
+
+:::{note}
+This step applies **only to users of the 24V FMC card produced by Diamond
+Light Source**. If you do not have this card you can skip this section
+entirely.
+:::
+
+From PandA 3.0 onwards the 24V FMC EEPROM must be populated once with
+hardware metadata. This is a permanent, one-time write:
+
+1. Find the `ipmi_definition.ini` for your 24V FMC card
+ (in the
+ [`modules/fmc_24vio/`](https://github.com/PandABlocks/PandABlocks-FPGA/blob/master/modules/fmc_24vio/ipmi_definition.ini)
+ directory of the FPGA repo).
+2. Copy it to the PandA:
+
+ ```bash
+ scp ipmi_definition.ini root@:/tmp/
+ ```
+
+3. Write the EEPROM:
+
+ ```bash
+ ssh root@ pandai2c-cli write /tmp/ipmi_definition.ini
+ ```
+
+ The script reads back the EEPROM after writing to confirm the content
+ matches.
diff --git a/docs/how-to/upgrade-via-web-admin.md b/docs/how-to/upgrade-via-web-admin.md
new file mode 100644
index 00000000..f44aa65c
--- /dev/null
+++ b/docs/how-to/upgrade-via-web-admin.md
@@ -0,0 +1,59 @@
+# Upgrading a PandA via the web admin interface
+
+The Web Admin interface lets you upgrade a PandA using only a browser and a
+USB stick — no SSH or network file transfer required.
+
+## Prerequisites
+
+- Physical access to the PandA (to insert a USB stick).
+- The new firmware archive downloaded from
+ [GitHub Releases](https://github.com/PandABlocks/meta-panda/releases).
+
+## 5.0 or later to 5.x (opkg / `.ipk`)
+
+1. Download the `boot-{MACHINE}.tar.gz` archive for your machine type.
+ There is no need to unzip it.
+2. Copy the archive to a USB stick.
+3. Insert the USB stick into the USB port on the back of the PandA.
+4. Open a browser and navigate to `http:///`.
+5. Click **Admin** in the bottom banner.
+6. Note the current version shown in the Version section.
+7. Under **Admin Commands → Packages**, click **Install Rootfs from USB**.
+8. Select your `boot-{MACHINE}.tar.gz` file from the list and follow the
+ on-screen instructions.
+
+:::{note}
+If you are installing a major rootfs upgrade it is recommended to uninstall
+all installed zpkgs/ipkgs **before** upgrading. An option to do this is offered
+as part of the rootfs install flow.
+:::
+
+9. Under **Admin Commands → System → Reboot/Restart**, click **Reboot Now** to restart the PandA; it will apply the new rootfs on next boot.
+
+## Pre-5.0 to 5.x upgrade (zpkg → opkg)
+
+Pre-5.0 PandAs use a legacy zpkg-based firmware format. To upgrade to a
+5.x release:
+
+1. Download the legacy-updater package.
+2. Copy the updater package `legacyupgrader@pandabox-{VERSION}.zpg`to a USB stick.
+3. Insert the USB stick into the USB port on the back of the PandA.
+4. Open a browser and navigate to `http:///`.
+5. Click **Admin** in the bottom banner.
+6. Note the current version shown in the Admin tab landing page.
+7. Under **Admin Commands → Packages**, click **Install Packages from USB**.
+8. Select the `legacyupgrader@pandabox-{VERSION}.zpg` file from the list, click install, and wait for the installaton to finish.
+9. Under **Admin Commands → System → Reboot/Restart**, click **Reboot Now** to restart the PandA; it will apply the new firmware on next boot.
+
+## Fresh SD card install
+
+If the PandA cannot be reached over the network or the rootfs is corrupted,
+install from a fresh SD card:
+
+1. Download the `boot-{MACHINE}.tar.gz` archive from
+ [GitHub Releases](https://github.com/PandABlocks/meta-panda/releases).
+2. Extract the archive and copy all files to a freshly formatted SD card
+ (FAT32).
+3. Optionally add a `config.txt` with network settings
+ (see [](setup-without-dhcp.md)).
+4. Insert the SD card into the PandA and power on.
diff --git a/docs/how-to/use-web-control-to-set-up-a-panda.md b/docs/how-to/use-web-control-to-set-up-a-panda.md
new file mode 100644
index 00000000..b790a791
--- /dev/null
+++ b/docs/how-to/use-web-control-to-set-up-a-panda.md
@@ -0,0 +1,417 @@
+# Use Web Control to set up a PandA
+
+A {term}`Design` is the heart of your system implementation. It is an
+interactive graphical representation of your system that helps you build and
+manage:
+
+- {term}`Block`s representing hardware components, logic gates, etc.
+- The {term}`Link` connectivity between blocks, in terms of input
+ ({term}`Sink Port`) and output ({term}`Source Port`) ports.
+- The {term}`Attribute`s associated with blocks and links.
+- The {term}`Method`s available to influence behaviour within blocks.
+
+A Design is created in the Web Control **Layout** view.
+
+## Add a block to a design
+
+A block is added to a design by dragging it from the Block Palette into the
+Layout view:
+
+1. Select the **Palette** icon at the bottom of the Layout panel. The Block
+ Palette opens, containing the set of blocks currently available to you.
+2. Identify the block you wish to add. Hovering over it changes the mouse
+ pointer from an arrow to a hand.
+3. Press and hold the left mouse button to select the block, then drag it into
+ the Layout panel.
+4. Release the mouse button at the desired location.
+
+The Block Palette icon is replaced by a full representation of the selected
+block, showing:
+
+- The block name (shown relative to its {term}`Parent Block`).
+- An optional, configurable descriptive label (initially default text).
+- {term}`Source Port`s that transmit output from the block, including their
+ type.
+- {term}`Sink Port`s that receive input to the block, including their type.
+
+After adding a block, select it by hovering over it and clicking the left mouse
+button. On selection, the {term}`Block Information Panel` listing every
+attribute and method available to that block is shown in the right-hand panel.
+
+:::{note}
+On initially adding a new block to your design it is configured according to
+its pre-defined default settings, retrieved from the underlying design
+specification of that block.
+:::
+
+## Remove a block from a design
+
+A block can be removed in one of two ways:
+
+- **By dragging it to the Bin:**
+ 1. Select the block by hovering over it and clicking the left mouse button. A
+ **Bin** icon appears at the bottom of the Layout panel.
+ 2. Holding down the left mouse button, drag the block over the **Bin** icon.
+ The icon is highlighted.
+ 3. Release the left mouse button.
+- **By pressing Delete or Backspace:**
+ 1. Select the block by hovering over it and clicking the left mouse button.
+ The selected block is highlighted.
+ 2. Press the *Delete* or *Backspace* key.
+
+:::{note}
+Removing a block automatically removes all {term}`Source Port` and
+{term}`Sink Port` links associated with it.
+:::
+
+## Work with the Block Palette
+
+The Block Palette lists each block available to a design, based on the
+constraints imposed by the underlying hardware.
+
+When a block is selected from the palette for inclusion in a design it is
+removed from the palette, so it cannot be included more than once. If all blocks
+of a particular type have been added to a design, no more can be added because
+the underlying hardware cannot represent them.
+
+If a block is removed from a design it immediately becomes available again in
+the Block Palette.
+
+## Specify block attributes
+
+The behaviour of a block is defined via its {term}`Attribute`s. Attributes are
+pre-defined based on the function of the block and may carry default values as a
+starting point for later customisation. A full list of the attributes for each
+block is given in the documentation for that block.
+
+### Types of attribute
+
+Four types of attribute are available; a block may support zero or more
+depending on its purpose:
+
+| Type | Description |
+|---|---|
+| {term}`Input Attribute` | Identifies the source of data received into a block via a {term}`Sink Port` of the same name. |
+| {term}`Output Attribute` | Identifies the value (or stream of values) transmitted out of a block via a {term}`Source Port` of the same name. |
+| {term}`Parameter Attribute` | Can be set by a user while configuring a block, influencing the block's behaviour. |
+| {term}`Readback Attribute` | Set automatically by a process in the execution environment. Cannot be set manually via the UI. |
+
+Attributes whose value can be set at design time are denoted by a highlight
+below the attribute value field.
+
+### Obtain information about an attribute
+
+Select the information icon next to an attribute in the
+{term}`Block Information Panel` to open the Attribute Information Panel in the
+right-hand panel. It displays:
+
+- The fully qualified path to the attribute, uniquely identifying it within the
+ design.
+- Basic metadata: its type, a brief description, and whether it is writeable.
+- The [attribute state](../explanations/understanding-attribute-state.md),
+ including the severity of any issue and any corresponding message.
+- Timestamp details showing when the attribute was last updated.
+
+Attribute metadata and alarm-state information is derived from the underlying
+block specification.
+
+### Set a block attribute
+
+Parameter, Input and Output attributes are set via the
+{term}`Block Information Panel` of the block you wish to configure. The way an
+attribute is set reflects its definition in the underlying block specification,
+and this also hints at whether the attribute is editable. The UI provides four
+input widgets — View/Edit button, Dropdown list, Text input, and Checkbox.
+
+:::{admonition} 🚧 TODO — attribute input widgets (blocked: capture)
+:class: warning
+
+The four attribute input widgets (**View/Edit button**, **Dropdown list**,
+**Text input** and **Checkbox**) need fresh screenshots before this subsection
+can be written, and the source text for *Text input* is truncated mid-sentence
+in the original. Tracked in [PandABlocks/meta-panda#13](https://github.com/PandABlocks/meta-panda/issues/13).
+
+In brief, until then:
+
+- **View/Edit button** — opens a {ref}`complex attribute `
+ in the central panel; reads *Edit* if modifiable, *View* otherwise.
+- **Dropdown list** — select a value from a list of pre-defined options valid
+ for the attribute in its current block context.
+- **Text input** — a free-text field accepting any alphanumeric string; press
+ *Enter* to submit.
+- **Checkbox** — switches the attribute's action on or off; an empty checkbox
+ means *off*.
+:::
+
+:::{tip}
+An attribute may hold a value that cannot be modified in the context of the
+current design. Such attributes are shown greyed out.
+:::
+
+To configure an attribute:
+
+1. Select the block by clicking it in the Layout panel. The block is highlighted
+ and its {term}`Block Information Panel` opens on the right.
+2. Find the attribute you wish to configure.
+3. Edit the attribute value field as appropriate for the widget described above.
+
+:::{note}
+No data-type validation is performed on manually entered values in the UI.
+Validation is performed by the backend server on receipt. If an invalid format
+is detected, a [Warning](../explanations/understanding-attribute-state.md) icon
+is shown.
+:::
+
+While a new value is being submitted, a
+[Processing](../explanations/understanding-attribute-state.md) (spinning) icon
+is displayed to the left of the modified attribute — see
+[Attribute change lifecycle](#attribute-change-lifecycle). On success the icon
+reverts to the information icon; on failure an
+[Update Error](../explanations/understanding-attribute-state.md) icon is shown.
+
+### Export attributes
+
+The UI presents a hierarchical view of the system, with one or more
+{term}`Parent Block`s encapsulating deeper levels of your design. By default,
+at the top level you see only attributes of parent blocks — but an underlying
+attribute in a {term}`Child Block` may influence its parent's behaviour. Every
+parent block can therefore **Export** one or more attributes from its children
+so they are displayed within the parent.
+
+To specify an attribute for export:
+
+1. Identify the attribute you wish to monitor outside the current layout level.
+ Note its source, in the form `BlockName.Attribute`.
+2. In the parent block, select the **View** option on the *Exports* attribute.
+3. In the Export Table, select the first blank row (or add a new row).
+4. In the **Source** column, use the dropdown to find the attribute to export.
+5. In the **Export** column, enter the name to display when exported. Leave it
+ blank to use the attribute's default name. User-specified display names must
+ be in `camelCase`, e.g. *myAttribute*.
+
+:::{note}
+The `camelCase` convention is required so an appropriate attribute label can be
+generated in the parent {term}`Block Information Panel`.
+:::
+
+Once exported, the attribute appears in the *Exported Attributes* section of the
+parent's {term}`Block Information Panel`. Any number of attributes can be
+exported from child blocks. Their order mirrors the order in which they were
+added; to reorder, or to insert above/below an existing entry, use the
+**Insert row above**, **Insert row below**, **Move Up** and **Move Down**
+options in the Export Table.
+
+To remove an exported attribute, open the parent's *Export* attribute,
+select the information icon for the relevant row, and choose **Delete** on the
+**Delete row** field.
+
+To apply your changes, select **Submit** at the bottom of the Export Table, then
+refresh the parent block to confirm the attributes have been promoted (or
+removed). Select **Discard Changes** at any time to abandon edits without
+affecting the recorded specification.
+
+### Local vs. server attribute state
+
+The physical hardware is configured from the design specification behind the
+graphical representation. A change takes effect in hardware only when it is
+submitted and recorded. It is therefore important to understand the difference
+between *local* and *server* attribute state, particularly for
+{term}`Parameter Attribute`s that can be modified directly in the UI.
+
+- **Local** state is a parameter attribute that has been modified in the UI but
+ not yet submitted. It has no effect on hardware. Locally modified attributes
+ show the *edit* icon next to the attribute name. An attribute enters local
+ state as soon as its value is changed and remains there until *Enter* is
+ pressed to submit. If the server reports an error, the attribute stays in
+ local state until the issue is resolved.
+- **Server** state means the value has been recorded to the information server
+ hosting the design specification. Server-state attributes are reflected in
+ hardware and show the *information* icon.
+
+:::{tip}
+Do not confuse local/server attribute state with a *saved* design.
+[Saving a design](save-restore-design.md) saves only attributes already in the
+**server** state; locally modified fields are not saved. Equally, a
+server-state attribute is not stored permanently until the overall design is
+saved.
+:::
+
+(attribute-change-lifecycle)=
+### Attribute change lifecycle
+
+Recording a modified attribute value is referred to as a *put* action. Once the
+put completes, the value takes immediate effect on any executing processes. If
+an error is detected during the put it is abandoned and reported back to the UI.
+
+The round trip from submission to use takes a small but non-deterministic time
+while data is transferred, validated and recorded, so attribute modification is
+not atomic. During this time the
+[Processing](../explanations/understanding-attribute-state.md) (spinning) icon
+replaces the information icon; its reversion is the only reliable indication
+that the value has been recorded and is now in use.
+
+```{figure} ../images/webcontrol/attribute_lifecycle.svg
+:align: center
+
+Attribute change lifecycle workflow
+```
+
+:::{tip}
+Remember the three rules of attribute change:
+
+- Changing an attribute value in the UI has no effect on the physical system
+ until it has been *put*.
+- Once the put completes, the change takes immediate effect.
+- Changes are not stored permanently unless the design is
+ [saved](save-restore-design.md); only *put* values are recorded in the saved
+ design.
+:::
+
+(complex-attributes)=
+## Complex attributes
+
+An attribute may itself represent a collection of values that together define
+the overall attribute. For example, the Sequencer block contains a single
+attribute defining the sequence of steps performed by hardware when controlling
+motor motion.
+
+These values are presented as an Attribute Table, generated dynamically from the
+attribute's specification within its block. For details of a specific table,
+refer to the technical documentation of its block.
+
+```{figure} ../images/webcontrol/attribute_table.png
+:align: center
+
+Example Attribute Table associated with a complex attribute
+```
+
+### Identify table attributes
+
+A table attribute is identified by the **View/Edit** button associated with it.
+Selecting the button opens the Attribute Table in the central panel.
+
+### Specify attribute table content
+
+On opening an Attribute Table you can define values, which (like attributes
+themselves) may be selected from a list, enable/disable options, or text and
+numerical inputs. After adding values, select **Submit** at the bottom of the
+table to record them, or **Discard Changes** to abandon edits.
+
+### Static vs. dynamic attribute tables
+
+- **Static** tables have a fixed number of columns and rows; all fields must be
+ completed to fully define the attribute.
+- **Dynamic** tables have a fixed number of columns but a varying number of
+ rows. At least one row must be present.
+
+New rows are added in one of two ways:
+
+- Select **Add** below the last row to append a new row.
+- If row order matters (for example, a sequence of activities), select the edit
+ icon on an existing row (or the information icon on a new row) and use
+ **Insert row above**, **Insert row below**, **Move Up** or **Move Down**.
+
+To remove a row, select the information icon on the row and choose **Delete** on
+the **Delete row** field.
+
+## Work with block methods
+
+While {term}`Attribute`s define a block's *behaviour*, {term}`Method`s define
+the *actions* it can perform. A method is represented as a button labelled with
+the action it performs, executed only when the button is pressed.
+
+There is currently a single method: *Save* on the {term}`Parent Block`, which
+requires the name of the file to save the design to as its input parameter.
+Method parameters:
+
+- Can be edited directly in the {term}`Block Information Panel`.
+- Exist in *local* state until the method's button is pressed.
+- Are properties of their method rather than entities in their own right; they
+ are never recorded on the server or saved in the persistent design.
+
+### Obtain information about method execution
+
+Selecting the information icon on a method displays two sources of information:
+
+- The right-hand panel describes the method's purpose and required parameters.
+- The central panel shows a log of each method execution in the current session,
+ including submission and completion times, the completion status (e.g. success
+ or failure), and any alarms. Selecting a parameter name in the table header
+ opens information about that parameter in the right-hand panel.
+
+## Block ports
+
+Blocks may *receive* input via one or more {term}`Sink Port`s and *transmit*
+output via one or more {term}`Source Port`s. A block's ports are listed in its
+documentation. Ports are colour-coded by the type of information they carry:
+
+| Port type | Key |
+|---|---|
+| Boolean | Blue |
+| Int32 | Orange |
+
+Information is transferred from a source port to a sink port via a
+{term}`Link` — see [Linking blocks](#linking-blocks) below.
+
+(linking-blocks)=
+## Link blocks
+
+Blocks are connected via {term}`Link`s. A link joins a {term}`Source Port` on
+one block to a {term}`Sink Port` on another; both ports must be of the same
+type. A block's ports and their specification are defined in its documentation.
+
+### Create a block link
+
+1. Hover over the {term}`Source Port` or {term}`Sink Port` at one terminus of
+ the link. The port is temporarily highlighted.
+2. Press and hold the left mouse button and drag the link to the port at the
+ other terminus. The target port is temporarily highlighted.
+3. Release the mouse button. If the link constraints below are respected, the
+ link is displayed in the Layout.
+
+```{figure} ../images/webcontrol/PANDA-new-link.png
+:align: center
+
+Creating a link between two blocks
+```
+
+:::{note}
+If an error occurs during creation, details are displayed at the bottom of the
+Layout panel.
+:::
+
+:::{tip}
+To confirm a link was created correctly, click it. The link is highlighted and
+the Link Information Panel opens, showing the {term}`Source Port` and
+{term}`Sink Port` names.
+:::
+
+### Interrogate link attributes
+
+A link has no attributes of its own, but selecting it shows information about its
+{term}`Source Port` origin and {term}`Sink Port` target in the right-hand panel:
+
+1. Hover over the link. It changes colour to denote it may be selected.
+2. Click the left mouse button. The Link Information Panel opens on the right.
+
+:::{caution}
+You can modify the source and sink of a link from the Link Information Panel. Do
+so cautiously — this changes how blocks are connected without any acknowledgement
+that a change has occurred.
+:::
+
+### Remove a link
+
+- **By pressing Delete or Backspace:** hover over the link, click to select it,
+ then press *Delete* or *Backspace*.
+- **Via the Link Information Panel:** select the link, then choose **Delete** in
+ the Link Information Panel.
+
+### Constraints when using links
+
+- A {term}`Sink Port` can accept only a single link.
+- Multiple links can originate from a {term}`Source Port`, connecting it to
+ multiple blocks.
+- Links can connect only a {term}`Source Port` and {term}`Sink Port` of the same
+ logical type (e.g. boolean, int32). Port types are colour-coded in the Layout
+ to aid identification.
diff --git a/docs/images/attribute-state/disconnected.svg b/docs/images/attribute-state/disconnected.svg
new file mode 100644
index 00000000..911c8ec0
--- /dev/null
+++ b/docs/images/attribute-state/disconnected.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/images/attribute-state/error.svg b/docs/images/attribute-state/error.svg
new file mode 100644
index 00000000..8719b7a9
--- /dev/null
+++ b/docs/images/attribute-state/error.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/images/attribute-state/invalid.svg b/docs/images/attribute-state/invalid.svg
new file mode 100644
index 00000000..14753b8f
--- /dev/null
+++ b/docs/images/attribute-state/invalid.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/images/attribute-state/locally-edited.svg b/docs/images/attribute-state/locally-edited.svg
new file mode 100644
index 00000000..658e543d
--- /dev/null
+++ b/docs/images/attribute-state/locally-edited.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/images/attribute-state/normal.svg b/docs/images/attribute-state/normal.svg
new file mode 100644
index 00000000..3f972813
--- /dev/null
+++ b/docs/images/attribute-state/normal.svg
@@ -0,0 +1,4 @@
+
diff --git a/docs/images/attribute-state/processing.svg b/docs/images/attribute-state/processing.svg
new file mode 100644
index 00000000..2932aad5
--- /dev/null
+++ b/docs/images/attribute-state/processing.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/images/attribute-state/update-error.svg b/docs/images/attribute-state/update-error.svg
new file mode 100644
index 00000000..e6b32dd8
--- /dev/null
+++ b/docs/images/attribute-state/update-error.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/images/attribute-state/warning.svg b/docs/images/attribute-state/warning.svg
new file mode 100644
index 00000000..353079e8
--- /dev/null
+++ b/docs/images/attribute-state/warning.svg
@@ -0,0 +1,3 @@
+
diff --git a/docs/images/webcontrol/PANDA-block-details.png b/docs/images/webcontrol/PANDA-block-details.png
new file mode 100644
index 00000000..dda584cc
Binary files /dev/null and b/docs/images/webcontrol/PANDA-block-details.png differ
diff --git a/docs/images/webcontrol/PANDA-layout-spread-out.png b/docs/images/webcontrol/PANDA-layout-spread-out.png
new file mode 100644
index 00000000..432ca1f9
Binary files /dev/null and b/docs/images/webcontrol/PANDA-layout-spread-out.png differ
diff --git a/docs/images/webcontrol/PANDA-layout.png b/docs/images/webcontrol/PANDA-layout.png
new file mode 100644
index 00000000..b8bf4d57
Binary files /dev/null and b/docs/images/webcontrol/PANDA-layout.png differ
diff --git a/docs/images/webcontrol/PANDA-new-link.png b/docs/images/webcontrol/PANDA-new-link.png
new file mode 100644
index 00000000..9039e8ee
Binary files /dev/null and b/docs/images/webcontrol/PANDA-new-link.png differ
diff --git a/docs/images/webcontrol/attribute_lifecycle.svg b/docs/images/webcontrol/attribute_lifecycle.svg
new file mode 100644
index 00000000..2faed034
--- /dev/null
+++ b/docs/images/webcontrol/attribute_lifecycle.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/docs/images/webcontrol/attribute_table.png b/docs/images/webcontrol/attribute_table.png
new file mode 100644
index 00000000..da55436d
Binary files /dev/null and b/docs/images/webcontrol/attribute_table.png differ
diff --git a/docs/images/webcontrol/attribute_value_table.png b/docs/images/webcontrol/attribute_value_table.png
new file mode 100644
index 00000000..1e94358b
Binary files /dev/null and b/docs/images/webcontrol/attribute_value_table.png differ
diff --git a/docs/images/webcontrol/attribute_view_chart.png b/docs/images/webcontrol/attribute_view_chart.png
new file mode 100644
index 00000000..2f2b2f06
Binary files /dev/null and b/docs/images/webcontrol/attribute_view_chart.png differ
diff --git a/docs/images/webcontrol/block-list.png b/docs/images/webcontrol/block-list.png
new file mode 100644
index 00000000..85fb72d0
Binary files /dev/null and b/docs/images/webcontrol/block-list.png differ
diff --git a/docs/images/webcontrol/chart_options.png b/docs/images/webcontrol/chart_options.png
new file mode 100644
index 00000000..d52026bc
Binary files /dev/null and b/docs/images/webcontrol/chart_options.png differ
diff --git a/docs/images/webcontrol/disconnected_icon.png b/docs/images/webcontrol/disconnected_icon.png
new file mode 100644
index 00000000..63ce41be
Binary files /dev/null and b/docs/images/webcontrol/disconnected_icon.png differ
diff --git a/docs/images/webcontrol/error_icon.png b/docs/images/webcontrol/error_icon.png
new file mode 100644
index 00000000..8061541c
Binary files /dev/null and b/docs/images/webcontrol/error_icon.png differ
diff --git a/docs/images/webcontrol/information_icon.png b/docs/images/webcontrol/information_icon.png
new file mode 100644
index 00000000..c43f2c25
Binary files /dev/null and b/docs/images/webcontrol/information_icon.png differ
diff --git a/docs/images/webcontrol/layout-button.png b/docs/images/webcontrol/layout-button.png
new file mode 100644
index 00000000..624cc3e2
Binary files /dev/null and b/docs/images/webcontrol/layout-button.png differ
diff --git a/docs/images/webcontrol/locally_edited_icon.png b/docs/images/webcontrol/locally_edited_icon.png
new file mode 100644
index 00000000..acf3e004
Binary files /dev/null and b/docs/images/webcontrol/locally_edited_icon.png differ
diff --git a/docs/images/webcontrol/starting-ui.png b/docs/images/webcontrol/starting-ui.png
new file mode 100644
index 00000000..83f9ad07
Binary files /dev/null and b/docs/images/webcontrol/starting-ui.png differ
diff --git a/docs/images/webcontrol/ui_schematic.png b/docs/images/webcontrol/ui_schematic.png
new file mode 100644
index 00000000..ee855ff7
Binary files /dev/null and b/docs/images/webcontrol/ui_schematic.png differ
diff --git a/docs/images/webcontrol/warning_icon.png b/docs/images/webcontrol/warning_icon.png
new file mode 100644
index 00000000..313b7207
Binary files /dev/null and b/docs/images/webcontrol/warning_icon.png differ
diff --git a/docs/images/webcontrol/window_popping_output.svg b/docs/images/webcontrol/window_popping_output.svg
new file mode 100644
index 00000000..9dc5d477
--- /dev/null
+++ b/docs/images/webcontrol/window_popping_output.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..6c00c2f8
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,42 @@
+---
+site:
+ hide_outline: true
+---
+
+```{include} ../README.md
+:end-before: |
+| `xu5` | XU5 SoM on the ST1 board | Development only |
+| `zedboard` | Zedboard | Development/testing platform |
+
+The generally supported machines are `pandabox`, `pandabox2` and `pandabrick`;
+`xu5-st1` and `zedboard` are development-only targets.
+
+:::{note}
+`pandabox` is the default machine built when `KAS_MACHINE` is not set.
+:::
+
+Per-target hardware descriptions (SoC, expansion connectors, FMC slots,
+notable capabilities) are in [](../explanations/hardware-targets.md).
diff --git a/docs/reference/opkg.md b/docs/reference/opkg.md
new file mode 100644
index 00000000..f9ce8c8f
--- /dev/null
+++ b/docs/reference/opkg.md
@@ -0,0 +1,14 @@
+# opkg quick reference
+
+[opkg](https://openwrt.org/docs/guide-user/additional-software/opkg) is the
+package manager used on PandA.
+
+| Command | Description |
+|---|---|
+| `opkg list-installed` | List all installed packages |
+| `opkg install ...` | Install or replace named packages |
+| `opkg remove ...` | Remove named packages |
+| `opkg files ...` | Show files belonging to named packages |
+| `opkg help` | Show all available options |
+
+For a step-by-step guide to installing packages see [](../how-to/packages.md).
diff --git a/docs/reference/troubleshooting.md b/docs/reference/troubleshooting.md
new file mode 100644
index 00000000..c6f48611
--- /dev/null
+++ b/docs/reference/troubleshooting.md
@@ -0,0 +1,67 @@
+# Troubleshooting
+
+## Networking
+
+### How do I configure a static IP address?
+
+By default PandA uses DHCP. To set a static address, edit `config.txt` on the
+SD card and uncomment or add the relevant lines:
+
+```ini
+ADDRESS = 192.168.0.2
+NETMASK = 255.255.255.0
+GATEWAY = 192.168.0.254
+HOSTNAME = mypanda
+```
+
+See [](../how-to/setup-without-dhcp.md) for the full `config.txt` format and the USB
+override mechanism (no SD card access required).
+
+### How do I disable subnet validation in the web control?
+
+Create an empty file called `no-subnet-validation` under `state/options/` on
+the SD card.
+
+### How do I authorise a public SSH key?
+
+Add the public key to a file named `authorized_keys` on the SD card, or load
+it from a USB stick via **Web Admin → SSH Keys → Append SSH keys from USB**.
+
+## Boot and recovery
+
+### How do I recover from a catastrophic configuration change?
+
+Remove the file `changes.ext4` from the SD card. This discards all
+configuration changes and resets the PandA to factory defaults.
+
+### How do I load the full rootfs to RAM at boot?
+
+Create an empty file called `to-ram` on the SD card.
+
+:::{warning}
+On some targets (such as ZedBoard) loading to RAM may cause the server to fail
+because the driver cannot allocate sufficient DMA buffers.
+:::
+
+### What do I do if the system freezes after loading the FPGA?
+
+Create an empty file called `no-fpga` on the SD card. The FPGA loader will
+skip loading the bitstream, which lets you try alternative bitstreams manually.
+
+## FPGA bitstream
+
+### How do I override the FPGA bitstream variant used?
+
+By default PandA reads the FMC EEPROM and selects the bitstream whose FMC
+requirements are satisfied. If no EEPROM is found the `no-fmc` variant is
+used.
+
+To force a specific bitstream, set `APP` in `config.txt`:
+
+```ini
+APP = pandabox-fmc-acq430
+```
+
+This takes effect only if the corresponding FPGA variant package is installed.
+See [](../how-to/choose-fpga-bitstream.md) for the full bitstream selection
+mechanism.
diff --git a/docs/tutorials.md b/docs/tutorials.md
new file mode 100644
index 00000000..528b288e
--- /dev/null
+++ b/docs/tutorials.md
@@ -0,0 +1,10 @@
+# Tutorials
+
+Tutorials for installation and typical usage. New users start here.
+
+If your PandA is not yet on the network, follow
+[](how-to/setup-without-dhcp.md) first, then begin with Tutorial 0.
+
+```{toc}
+:context: children
+```
diff --git a/docs/tutorials/blinking_leds.md b/docs/tutorials/blinking_leds.md
new file mode 100644
index 00000000..3ca78c80
--- /dev/null
+++ b/docs/tutorials/blinking_leds.md
@@ -0,0 +1,82 @@
+# Tutorial 2: Blinking LEDs
+
+This tutorial introduces the basics of PandABlocks: how to wire blocks together
+so that different LEDs flash at different rates.
+
+## Prerequisites
+
+- A PandA powered on and reachable in your browser
+ (see [](connecting_to_web_control.md)).
+- The `template_tutorial1_leds` design saved on your PandA (pre-loaded on all
+ standard PandA images).
+
+## Opening the web control
+
+Navigate to `http:///` in your browser.
+The welcome page has links for **Docs**, **Control** and **Admin** at the bottom.
+Click **Control** to open the web control.
+
+## Loading the tutorial design
+
+The **Design** drop-down lists saved designs stored on the PandA.
+Selecting one replaces the current block settings with the saved ones.
+
+Select **template_tutorial1_leds** from the drop-down.
+The blocks and wiring will change to:
+
+```{image} ../images/tutorial1_layout.png
+```
+
+If you look at the front panel of the PandA you should see the first four TTL
+output LEDs turn on sequentially, then turn off in reverse order.
+
+## How the design works
+
+The **CLOCK1** block generates a 50% duty-cycle pulse train with a 1 s period.
+**PULSE1–4** each take this as an input trigger and produce a pulse with a
+different width and delay. The PULSE blocks act as a delay line, queuing pulses
+until each delay expires.
+
+Click on any PULSE block to see its settings:
+
+```{image} ../images/tutorial1_pulse.png
+```
+
+:::{tip}
+Increase a PULSE delay beyond 1 s and the **Queued** field will grow — the block
+continues producing pulses at the correct delay. If you increase the **Width**
+beyond the period the block drops the pulse instead of merging it, reporting the
+drop in the **Dropped** field.
+:::
+
+You can also click the **CLOCK1** block to adjust the input pulse period.
+
+To explore further, try wiring pulse outputs to different TTLOUT blocks:
+click the Palette icon, drag a **TTLOUT** block onto the canvas, then connect a
+PULSE out port to the TTLOUT val port by dragging between them.
+
+## The bit bus
+
+All visible block ports are blue — they carry single boolean (bit) values.
+You can view all bit values at once by clicking **Bits** in the left-hand panel:
+
+```{image} ../images/tutorial1_bits.png
+```
+
+Scroll to the PULSE section to see the same flashing pattern as on the PandA
+front panel.
+
+:::{note}
+The web control polls the PandA at 10 Hz, receiving the current value of each
+bit and whether it has changed. It displays the current value for signals
+toggling below 5 Hz and a 5 Hz pulsing indicator for faster signals — so even
+short pulses are visible. Front-panel LEDs behave similarly, capped at 10 Hz.
+:::
+
+## Summary and next steps
+
+You have loaded a saved design, inspected block parameters, and seen bit outputs
+connected to hardware TTL outputs via TTLOUT blocks.
+
+Continue with [](position_capture.md) to learn about position outputs
+and data capture.
diff --git a/docs/tutorials/connecting_to_web_control.md b/docs/tutorials/connecting_to_web_control.md
new file mode 100644
index 00000000..89bf056b
--- /dev/null
+++ b/docs/tutorials/connecting_to_web_control.md
@@ -0,0 +1,104 @@
+# Tutorial 1: Connecting to the PandA Web Control
+
+In this tutorial you will navigate to the PandA web control interface,
+explore the block list, view block details, and open the layout panel.
+By the end you will know how the main areas of the UI fit together and
+be ready for the hands-on tutorials that follow.
+
+## Prerequisites
+
+- PandA is setup and have completed [](getting_started.md).
+- Its IP address or hostname (e.g. `192.168.0.100` or `my-panda`).
+
+### 1. Open the web control
+
+In a browser navigate to:
+
+```
+http:///
+```
+
+where `` is the IP address or hostname of your PandA.
+You will see the initial screen:
+
+```{figure} ../images/webcontrol/starting-ui.png
+:align: center
+
+The initial web control screen
+```
+
+### 2. Select the PANDA block
+
+The drop-down at the top of the page lists the root blocks available on
+your PandA. Click it and choose **PANDA**:
+
+```{figure} ../images/webcontrol/block-list.png
+:align: center
+
+Selecting the PANDA root block
+```
+
+### 3. View the block details
+
+After selecting PANDA, the left-hand panel loads that block's details —
+attributes, groups, and methods:
+
+```{figure} ../images/webcontrol/PANDA-block-details.png
+:align: center
+
+Details for the PANDA block
+```
+
+### 4. Open the layout
+
+Scroll down in the left-hand panel until you see the **Layout** attribute.
+Click **Edit** to open the block layout in the centre panel:
+
+```{figure} ../images/webcontrol/layout-button.png
+:align: center
+
+Click **Edit** in the Layout attribute row to open the layout panel
+```
+
+```{figure} ../images/webcontrol/PANDA-layout.png
+:align: center
+
+The layout panel showing the functional blocks of the PandA
+```
+
+### 5. Rearrange blocks
+
+Drag blocks to new positions to suit your preference.
+A brief spinner indicates that the updated position is being saved to the
+hardware:
+
+```{figure} ../images/webcontrol/PANDA-layout-spread-out.png
+:align: center
+
+Blocks dragged to new positions; clicking a block loads its details in the right-hand panel
+```
+
+Clicking any block in the layout loads its details in the right-hand panel
+(the *child block* view).
+
+### 6. Wire two blocks together
+
+Click a port on one block and drag to a compatible port on another block
+to create a signal link:
+
+```{figure} ../images/webcontrol/PANDA-new-link.png
+:align: center
+
+Dragging between two ports to create a new link
+```
+
+Blocks can be wired in any combination to build up more complex
+signal-processing designs.
+
+## Next steps
+
+You now know how to reach the web control, inspect block attributes, and
+connect blocks together in the layout view. Continue with:
+
+- [](blinking_leds.md) — drive some output bits and see real
+ hardware changes.
\ No newline at end of file
diff --git a/docs/tutorials/getting_started.md b/docs/tutorials/getting_started.md
new file mode 100644
index 00000000..50f62730
--- /dev/null
+++ b/docs/tutorials/getting_started.md
@@ -0,0 +1,62 @@
+# Tutorial 0: Getting Started
+
+In this tutorial you will setup your PandA; configure it so you can find it on the network, understand the web interface, and upgrade to the latest firmware.
+
+## Prerequisites
+
+- A PandA that is powered on and connected to your network.
+
+## Getting on the network
+
+By default the PandA uses DHCP — no configuration needed. Simply connect it
+to your network and power it on.
+
+If you need a static IP instead, see [](../how-to/setup-without-dhcp.md).
+
+Once it has an address, confirm it's reachable by navigating to:
+
+```
+http:///
+```
+
+where `` is the IP address or hostname of your PandA, you should see the PandA web interface home page.
+
+## Web interface overview
+
+The home page has four sections:
+
+- **Home** — summary of the web interface sections
+- **Docs** — hardware, firmware and software documentation
+- **Control** — the web control; wire functional blocks together, set parameters,
+ save and load designs (requires the web-control package to be installed)
+- **Admin** — install packages from USB, manage SSH keys, and other remote
+ administration
+
+```{figure} ../images/webcontrol/starting-ui.png
+:align: center
+
+The initial web control screen
+```
+
+## Upgrading the firmware
+
+Make sure your PandA has the latest firmware. From the web admin page:
+
+1. Click **Admin** in the bottom banner.
+2. Check your current version under **Version Information**.
+3. If your PandA needs upgrading you can do so with one of the following guides. Make sure to check whether you are need to follow instructions under **pre-5.0 to 5.x** or **5.0 or later to 5.x**:
+ - If you want to upgrade via the web admin interface — see [](../how-to/upgrade-via-web-admin.md).
+ - If you want to upgrade via SSH — see [](../how-to/upgrade-via-ssh.md).
+
+## Troubleshooting
+
+See [](../reference/troubleshooting.md) for answers to common questions such as
+configuring a static IP, disabling subnet validation, recovering from a
+corrupted SD card, and overriding the FPGA bitstream variant.
+
+## Next steps
+
+You have now setup your PandA and upgraded to the latest firmware. Continue with:
+
+- [](connecting_to_web_control.md) — drive some output bits and see real
+ hardware changes.
diff --git a/docs/tutorials/position_capture.md b/docs/tutorials/position_capture.md
new file mode 100644
index 00000000..5a007295
--- /dev/null
+++ b/docs/tutorials/position_capture.md
@@ -0,0 +1,225 @@
+# Tutorial 3: Position Capture
+
+This tutorial introduces the Position Capture (PCAP) interface of PandABlocks:
+how to provide trigger and gate signals that control when data is captured, and
+how to receive and interpret the captured stream.
+
+## Prerequisites
+
+- Completed [](blinking_leds.md) or comfortable with the web control
+ layout view.
+- `nc` (netcat) or any TCP client available on your workstation.
+
+## Loading the tutorial design
+
+Select **template_tutorial2_pcap** from the Design drop-down.
+The block wiring will change to:
+
+```{image} ../images/tutorial2_layout.png
+```
+
+## How the design works
+
+The design has two CLOCK blocks, both enabled as soon as the PCAP block becomes
+active:
+
+- **CLOCK1** is wired to PCAP trigger *and* gate.
+ - **Gate** is a level-driven signal defining the capture window.
+ - **Trigger** is an edge-driven signal that captures data.
+ `PCAP.TRIG_EDGE="Falling"` so capture fires on the falling edge of the
+ trigger.
+- **CLOCK2** is wired to a COUNTER, incrementing its value on each rising edge.
+
+With both CLOCKs set to a 1 s period, each second the COUNTER increments by one
+and the PCAP trigger fires half a second later.
+
+**Timing diagram — Trigger Only (1 s clock):**
+
+```
+ Gate: _____|‾‾‾‾‾‾|________|‾‾‾‾‾‾|___
+ Trig: _________|__|_____________|__|___
+ Capture: ↑ ↑
+```
+
+The `PCAP` block settings and the Bits/Positions tables determine what is
+captured on each trigger:
+
+| Capture mode | Description |
+|---|---|
+| No | Don't capture |
+| Value | Instantaneous value at time of trigger |
+| Diff | Difference in value while gate was high |
+| Sum | Sum of all samples while gate was high |
+| Min | Smallest value seen while gate was high |
+| Max | Largest value seen while gate was high |
+| Mean | Average value seen while gate was high |
+| Min Max | Capture both Min and Max |
+| Min Max Mean | Capture Min, Max and Mean |
+
+For Bits you can toggle instantaneous capture on or off for each bit signal.
+Additional PCAP outputs (start-of-frame, end-of-frame, trigger time) can be
+enabled on the PCAP block itself.
+
+If you click the PCAP block you can see the Outputs section:
+
+```{image} ../images/tutorial2_pcap.png
+```
+
+### Input delays
+
+In the Inputs section you will see a delay of **1** on both Trig and Gate.
+Delays on bit inputs are measured in FPGA clock ticks and compensate for
+different-length data paths. In this design both COUNTER1 and PCAP are
+triggered by CLOCK1 in the same clock tick; the 1-tick delay on PCAP inputs
+ensures PCAP sees the updated COUNTER1 value *after* the corresponding rising
+edge.
+
+:::{note}
+Delay values also appear as small badges on the input ports of the PCAP block in
+the layout view.
+:::
+
+## Capturing data
+
+### Set up Value capture
+
+Open the Positions table and set **COUNTER1.OUT** to capture **Value**, then
+press Submit:
+
+```{image} ../images/tutorial2_positions.png
+```
+
+### Connect a client
+
+Open a TCP connection to port 8889 of your PandA:
+
+```
+$ nc 8889
+```
+
+Press Return; you should see:
+
+```
+OK
+```
+
+### Arm and collect
+
+Go back to the PandA layout, click the PCAP block, and press **ARM**.
+The Active indicator lights and data streams to the terminal until you press
+**Disarm**:
+
+```
+missed: 0
+process: Scaled
+format: ASCII
+fields:
+ COUNTER1.OUT double Value scale: 1 offset: 0 units:
+
+ 1
+ 2
+ 3
+ 4
+END 4 Disarmed
+```
+
+The captured values match the instantaneous COUNTER1.OUT value at each
+PCAP.TRIG falling edge — consistent with the 1 s timing above.
+
+### Speed up the counter
+
+Set **CLOCK2.PERIOD** to `0.2s`, then ARM again:
+
+```
+missed: 0
+process: Scaled
+format: ASCII
+fields:
+ COUNTER1.OUT double Value scale: 1 offset: 0 units:
+
+ 3
+ 8
+ 13
+ 18
+END 4 Disarmed
+```
+
+**Timing diagram — Counter 5× faster:**
+
+```
+ Counter: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...
+ Gate: __|‾‾‾‾‾‾‾‾‾‾‾|___|‾‾‾‾‾‾‾‾‾‾‾|__________________
+ Capture: ↑ ↑
+```
+
+The value is captured mid-way through each increment of 5.
+
+### Diff capture
+
+Change **COUNTER1.OUT** to capture **Diff** and ARM:
+
+```
+missed: 0
+process: Scaled
+format: ASCII
+fields:
+ COUNTER1.OUT double Diff scale: 1 offset: 0 units:
+
+ 2
+ 2
+ 2
+ 2
+END 4 Disarmed
+```
+
+`Diff` returns the difference between the value at the gate rising edge and the
+gate falling edge. Gate rises when COUNTER was at 1 and falls at 3 → diff = 2.
+
+:::{note}
+Without the 1-tick input delays, the gate would rise at 0 and fall at 3,
+giving a diff of 3.
+:::
+
+This capture mode is commonly used with a COUNTER connected to a
+[V2F](https://hal.archives-ouvertes.fr/hal-01573024/document) (voltage-to-
+frequency converter) to record the total counts within a gate window.
+
+### Min / Max / Mean capture
+
+Change **COUNTER1.OUT** to **Min Max Mean** and ARM:
+
+```
+missed: 0
+process: Scaled
+format: ASCII
+fields:
+ COUNTER1.OUT double Min scale: 1 offset: 0 units:
+ COUNTER1.OUT double Max scale: 1 offset: 0 units:
+ COUNTER1.OUT double Mean scale: 1 offset: 0 units:
+
+ 1 3 1.8
+ 6 8 6.8
+ 11 13 11.8
+ 16 18 16.8
+END 4 Disarmed
+```
+
+The Mean is the time-weighted average of the counter value over the gate window:
+
+```
+# (sum of counter_value × time_at_value) / gate_time = mean
+(1×0.2 + 2×0.2 + 3×0.1) / 0.5 = 1.8
+(6×0.2 + 7×0.2 + 8×0.1) / 0.5 = 6.8
+```
+
+This mode is useful with encoder inputs to record the min, max and mean encoder
+position over a detector frame.
+
+## Summary and next steps
+
+You have used the PCAP interface to capture position data with different capture
+modes (Value, Diff, Min/Max/Mean), and received the ASCII stream over TCP.
+
+The next tutorial ([](position_compare.md)) covers position compare —
+generating triggers automatically when an encoder reaches a set of target
+positions.
diff --git a/docs/tutorials/position_compare.md b/docs/tutorials/position_compare.md
new file mode 100644
index 00000000..c113f01f
--- /dev/null
+++ b/docs/tutorials/position_compare.md
@@ -0,0 +1,13 @@
+# Tutorial 4: Position Compare
+
+:::{admonition} 🚧 TODO — documentation stub
+:class: warning
+
+This page is a Stage A scaffold stub and has not yet been written.
+
+**Status:** blocked: capture
+
+**Source:** tutorials/tutorial3_position_compare.rst (41w stub) — author from human screenshots+bullets
+
+**Blocked:** [PandABlocks/meta-panda#12](https://github.com/PandABlocks/meta-panda/issues/12)
+:::
diff --git a/docs/tutorials/snake_scan.md b/docs/tutorials/snake_scan.md
new file mode 100644
index 00000000..66de2f12
--- /dev/null
+++ b/docs/tutorials/snake_scan.md
@@ -0,0 +1,13 @@
+# Tutorial 5: Snake Scan
+
+:::{admonition} 🚧 TODO — documentation stub
+:class: warning
+
+This page is a Stage A scaffold stub and has not yet been written.
+
+**Status:** blocked: capture
+
+**Source:** tutorials/tutorial4_snake_scan.rst (52w stub) — author from human screenshots+bullets
+
+**Blocked:** [PandABlocks/meta-panda#12](https://github.com/PandABlocks/meta-panda/issues/12)
+:::
diff --git a/knowledge/00-plan.md b/knowledge/00-plan.md
new file mode 100644
index 00000000..74fdeeab
--- /dev/null
+++ b/knowledge/00-plan.md
@@ -0,0 +1,434 @@
+# PandABlocks Documentation Project — Step by Step Plan
+
+This document covers all four phases: repo trawl, interview, planning, and output.
+Each step specifies which tool to use, which model, and why.
+
+---
+
+## Guiding principles
+
+**Git is the state store, not the context window.** Every artefact produced in
+each phase is committed before moving on. Any session can be resumed cold.
+
+**Dumb inputs, smart outputs.** Claude reads raw source and produces structured
+summaries. Those summaries — not the raw source — are the inputs to every
+subsequent phase. Context stays manageable throughout.
+
+**Phases are independent.** You can pause between any two phases, hand the work
+to a colleague, or resume weeks later. Each phase produces a well-defined set of
+committed files that the next phase reads.
+
+---
+
+## Phase 1 — Repo trawl (automated reading)
+
+**Goal:** Produce a structured inventory of everything that currently exists
+across all five repos, without you doing any work.
+
+**Tool:** Claude Code
+**Model:** Sonnet 4.6 (fast, cheap — this is mechanical reading, not deep reasoning)
+**Why not web:** The repos are on disk. Fetching files via web would be 100× slower
+and require you to ferry content manually.
+
+### What Claude Code does
+
+1. Finds every `.rst` and `.md` file under `docs/` in each repo.
+2. For each file, records: path, word count, last git commit date, and a
+ two-sentence summary of what the page covers.
+3. Identifies any doc pages that reference external URLs or other repo docs
+ (potential cross-links that will need updating).
+4. Writes the results to `meta-panda/knowledge/01-inventory.md` in a structured
+ table, one section per repo.
+
+### The prompt you give Claude Code
+
+```
+Read every .rst and .md file under docs/ in each of these repos:
+PandABlocks-FPGA, PandABlocks-server, PandABlocks-rootfs,
+PandABlocks.github.io, meta-panda.
+
+For each file write a row in knowledge/01-inventory.md with:
+- repo name
+- file path relative to docs/
+- word count
+- date of last git commit on this file
+- one sentence: what does this page cover?
+- one sentence: what audience is it written for?
+- flag: does it look outdated, partial, or current?
+
+Commit when done.
+```
+
+### Output
+
+`knowledge/01-inventory.md` — a complete map of what exists. Commit it.
+
+---
+
+## Phase 2 — Repo trawl (gap pre-analysis)
+
+**Goal:** Have Claude read the inventory and the actual doc content to form a
+first-pass view of what is missing, duplicated, or contradictory — before you
+are involved at all.
+
+**Tool:** Claude Code
+**Model:** Sonnet 4.6 — see note below
+**Why not web:** Still reading files on disk.
+
+> **Pro plan limitation:** Opus is not available in Claude Code on Pro — it is
+> reserved for Max plans. Sonnet 4.6 will do a reasonable job of gap analysis
+> for a codebase of this size. If you find it too shallow, run a follow-up pass
+> in Claude web (Phase 2b below) where Opus 4.8 is available.
+
+### What Claude Code does
+
+1. Reads `01-inventory.md` plus the full content of every doc file flagged as
+ current or partial (skips ones it already flagged as clearly outdated).
+2. Produces `knowledge/02-gap-analysis-draft.md` with three sections:
+ - **Duplications** — the same content appearing in multiple repos
+ - **Apparent gaps** — topics mentioned in passing but never given a full page
+ (e.g. a how-to that says "see the build docs" but those docs don't exist)
+ - **Questions for the owner** — things Claude cannot determine from the files
+ alone, numbered Q1, Q2, Q3 etc. This becomes the interview agenda.
+
+### The prompt you give Claude Code
+
+```
+Read knowledge/01-inventory.md and the content of every doc file marked
+current or partial. Then write knowledge/02-gap-analysis-draft.md with:
+
+Section 1 — Duplications: list pages that cover the same topic across repos.
+Section 2 — Apparent gaps: topics referenced but never fully documented.
+Section 3 — Questions for the owner: numbered list of things you cannot
+determine from the files. Be specific — not "is this accurate?" but
+"the quickstart guide says to run build.sh but the rootfs docs say to use
+kas — which is correct for a new user in 2026?". Cap at 30 questions.
+
+Commit when done.
+```
+
+### Output
+
+`knowledge/02-gap-analysis-draft.md` — your interview agenda. Commit it.
+
+### Optional Phase 2b — deeper gap analysis in Claude web
+
+If the Sonnet output feels thin, start a new Claude web conversation with Opus 4.8,
+paste in `01-inventory.md` and the full content of the most important doc files,
+and ask it to deepen the gap analysis. Paste the result back into
+`02-gap-analysis-draft.md` and commit. This costs Opus quota but is a single
+focused session, not a long interview — it should stay well within one 5-hour window.
+
+---
+
+## Phase 3 — Interview (knowledge elicitation)
+
+**Goal:** Answer Claude's questions from Phase 2, capture your own knowledge
+about what the docs should cover, and produce a durable knowledge base that
+survives any crash.
+
+**Tool:** Claude web (this conversation)
+**Model:** Opus 4.8 (the current flagship, available on Pro)
+**Why not Claude Code:** This is a conversation, not a coding task. You are doing
+significant cognitive work. The web interface is comfortable for long answers,
+supports image uploads, works on mobile, and — critically — the conversation
+history is preserved in Claude's servers regardless of what happens to your
+container or machine. The container is not involved at all.
+
+> **Usage note:** Each interview session will likely run 20–30 exchanges on Opus
+> 4.8 with substantial context. Realistically, one or two heavy sessions per day
+> is your ceiling on Pro before the 5-hour window fills. With six sessions (A–F)
+> spread across two weeks this is comfortable — but do not try to run two
+> sessions back-to-back. Start each session in a fresh conversation, not as a
+> continuation of the previous one, to keep context lean.
+
+### Session structure
+
+Each session covers one subsystem. Do not try to cover everything in one
+conversation. Suggested split:
+
+| Session | Subsystem | Key files to paste in |
+|---|---|---|
+| A | Boot process and hardware overview | `02-gap-analysis-draft.md` questions about rootfs and meta-panda |
+| B | Server command interface | Questions about PandABlocks-server |
+| C | FPGA blocks and firmware | Questions about PandABlocks-FPGA |
+| D | Web control and user-facing features | Questions about webcontrol |
+| E | Tutorials — scope and accuracy | Cross-cutting questions about the four tutorials |
+| F | Audience and scope decisions | Which docs live where, who reads them |
+
+### How to start each session
+
+Paste `02-gap-analysis-draft.md` into a new Claude web conversation with this
+framing:
+
+```
+I am rewriting the documentation for the PandABlocks org. Here is a
+gap analysis produced by reading the existing docs. This session covers
+[subsystem]. Ask me the questions from Section 3 that relate to this
+subsystem, one at a time. After each answer, summarise what I said in
+2–4 bullet points. At the end of the session, compile all the bullet
+points into a single knowledge file I can copy into my repo.
+```
+
+The "one at a time" instruction prevents Claude from overwhelming you with a
+wall of questions. The "summarise after each answer" instruction means that
+even if you give a rambling answer, the important information is extracted
+cleanly.
+
+### After each session
+
+At the end, ask:
+
+```
+Write the full contents of knowledge/03-[subsystem].md based on
+everything we discussed. Format it as structured markdown with clear
+headings. Include: what this subsystem does, who the audiences are,
+what currently exists, what is missing, and any specific facts I gave
+you that aren't in the existing docs.
+```
+
+Copy the output into `knowledge/03-[subsystem].md` in your repo and commit it.
+This is the crash-recovery checkpoint. You lose at most one session's work if
+something goes wrong.
+
+### Output
+
+`knowledge/03-boot-process.md`
+`knowledge/03-server.md`
+`knowledge/03-fpga.md`
+`knowledge/03-webcontrol.md`
+`knowledge/03-tutorials.md`
+`knowledge/03-scope-decisions.md`
+
+All committed to `meta-panda/knowledge/`.
+
+---
+
+## Phase 4 — Planning (doc structure design)
+
+**Goal:** Decide which documents exist, what they contain, which repo they live
+in, and what the MyST-MD structure for each repo looks like. Produce a plan that
+can be handed directly to the output phase.
+
+**Tool:** Claude web
+**Model:** Opus 4.8
+**Why not Claude Code:** This is design work, not file work. You want to be able
+to push back, ask "what if we merged these two pages", and have a real
+conversation. The output is a plan document, not code.
+
+> **Usage note:** This is likely one or two long sessions. Paste all the
+> `knowledge/03-*.md` files in one go at the start — this is a large context
+> load, but prompt caching means subsequent turns are much cheaper than the
+> first. Start a fresh conversation; do not continue from a Phase 3 session.
+
+### How to run this session
+
+Start a new conversation and paste in all the `knowledge/03-*.md` files plus
+`02-gap-analysis-draft.md`. Then:
+
+```
+Based on this knowledge base, design the full documentation structure for the
+PandABlocks organisation. Each repo should have its own MyST-MD based doc
+structure. Apply Diátaxis strictly: tutorials, how-to guides, explanations,
+and reference. Follow the target structure from this GitHub issue [paste
+the issue text].
+
+For each document produce:
+- repo it lives in
+- Diátaxis category
+- filename
+- one-paragraph description of what it covers
+- audience (new user / developer / operator)
+- whether it can be written from the knowledge base alone, or needs
+ more input from me
+
+Output this as knowledge/04-doc-plan.md.
+```
+
+Review the plan carefully. This is the last moment to change your mind about
+scope. When you are happy, copy `04-doc-plan.md` into the repo and commit it.
+
+### MyST-MD structure in the plan
+
+Ask Claude to also produce, for each repo, the skeleton `myst.yml` /
+`_toc.yml` entries so the output phase has a template to fill, e.g.:
+
+```yaml
+# meta-panda/_toc.yml
+format: jb-book
+root: index
+chapters:
+ - file: tutorials/tutorial1_blinking_leds
+ - file: how-to/quickstart
+ - file: how-to/build
+ ...
+```
+
+### Output
+
+`knowledge/04-doc-plan.md` — full doc inventory with repo assignments
+`knowledge/04-toc-meta-panda.yml`
+`knowledge/04-toc-fpga.yml`
+`knowledge/04-toc-server.yml`
+
+All committed.
+
+---
+
+## Phase 5 — Output (writing the docs)
+
+**Goal:** Write each document. Use the knowledge base as the source of truth.
+Reference the existing docs only as inspiration, not as copy-paste material.
+
+**Tool:** Claude Code for file creation and structure; Claude web for any doc
+that needs significant back-and-forth with you
+**Model:** Opus 4.8 for the first draft of complex docs; Sonnet 4.6 for
+mechanical docs (reference tables, toc files, redirect pages)
+**Why Claude Code here:** The writing phase is now a defined coding task. Claude
+Code reads the plan file, knows exactly what to produce, and can write all the
+files, set up the MyST directory structure, and commit as it goes. You review
+PRs rather than driving each doc.
+
+> **Usage note:** Sonnet 4.6 is the right default for Claude Code sessions here.
+> Use the `/model opusplan` pattern — plan with Opus, execute with Sonnet —
+> for any doc that needs real architectural thinking before writing. Switching
+> models mid-session does not clear context, so Sonnet sees everything Opus
+> planned.
+
+### How to run this phase
+
+One Claude Code session per repo. Each session:
+
+```
+Read knowledge/04-doc-plan.md and knowledge/04-toc-[repo].yml.
+Write all the docs assigned to [repo] into docs/ using MyST markdown.
+Use knowledge/03-*.md as your primary source. Where you need content
+that isn't in the knowledge base, write a clearly marked placeholder:
+
+
+Create the _toc.yml, index.md, and conf.py for a MyST-MD build.
+Commit after writing each document, not at the end.
+```
+
+The "commit after each document" instruction means a crash loses at most one
+document.
+
+### Docs that need your input during writing
+
+Some docs — particularly the conceptual explanations and any tutorial that is
+being significantly rewritten — will hit TODOs that need answers. Handle these
+in Claude web, using the same session format as Phase 3:
+
+```
+Claude Code has written a draft of [doc] but flagged these TODOs.
+[Paste the TODOs]. Answer my questions one at a time, then revise the draft.
+```
+
+Paste the revised draft back into the file and commit.
+
+### Output
+
+All documentation files in their final target repos, committed as draft PRs
+for review.
+
+---
+
+## Summary table
+
+| Phase | Name | Tool | Model | Crash risk | Output |
+|---|---|---|---|---|---|
+| 1 | Repo trawl — inventory | Claude Code | Sonnet 4.6 | Low — pure file reading | `01-inventory.md` |
+| 2 | Repo trawl — gap analysis | Claude Code | Sonnet 4.6 | Low — produces one file | `02-gap-analysis-draft.md` |
+| 2b | Gap analysis deepening (optional) | Claude web | Opus 4.8 | None — chat history durable | updated `02-gap-analysis-draft.md` |
+| 3 | Interview | Claude web | Opus 4.8 | None — chat history is durable | `03-*.md` per subsystem |
+| 4 | Planning | Claude web | Opus 4.8 | None — chat history is durable | `04-doc-plan.md`, toc files |
+| 5 | Output | Claude Code | Sonnet 4.6 + Opus 4.8 via `/model opusplan` | Low — commits per document | Final doc files |
+
+---
+
+## Pro plan usage limits and model versions
+
+### What's available on Pro
+
+All three current Opus versions (4.6, 4.7, 4.8) are available on Pro in Claude
+web. **Opus 4.8 is the right default** — it is the current flagship with the
+best reasoning, and costs no more quota than 4.6 or 4.7. There is no reason to
+reach for an older Opus version.
+
+Sonnet 4.6 is the only Sonnet version currently on Pro. No version decision needed.
+
+**Opus is not available in Claude Code on Pro.** It is reserved for Max plans.
+Claude Code on Pro uses Sonnet 4.6 only. Plan accordingly: phases that need
+Opus reasoning (gap analysis deepening, planning, complex doc drafts) must happen
+in Claude web, not Claude Code.
+
+### How limits work
+
+Usage runs on a **5-hour rolling window**, not a daily reset. Approximate ceilings
+on Pro: ~45 Opus messages or ~100 Sonnet messages per window. These are for
+short, fresh conversations — a long interview session where Claude is re-processing
+20 previous exchanges may consume 5–10× the quota of a first message. One or two
+heavy Opus sessions per day is a realistic ceiling.
+
+**The single biggest lever is conversation length.** Every previous message is
+resent on every turn. Starting a fresh conversation for each interview session
+(rather than continuing one long thread) is the most effective way to preserve
+quota. Paste in only what that session needs — not the entire knowledge base.
+
+### Version-specific tokenizer note
+
+Opus 4.7 introduced a new tokenizer that encodes text 1.0–1.35× less efficiently
+than Opus 4.6. Opus 4.8 uses the same tokenizer as 4.7, so moving from 4.7 to
+4.8 has no token cost impact. For this project — mostly short RST/Markdown files
+and your own prose — the tokenizer difference is unlikely to materially affect
+how many sessions you get per window.
+
+### If you hit a limit mid-session
+
+- Switch to Sonnet 4.6 for the remainder of that session (non-reasoning turns
+ like "write the knowledge file from our discussion" are fine on Sonnet).
+- Or end the session, commit what you have, and resume in a new conversation
+ after the window resets (5 hours from your first message).
+- If limits are consistently blocking you by week 1, a one-month upgrade to
+ Max 5× (£80) removes the constraint entirely.
+
+---
+
+## What lives in `meta-panda/knowledge/` at each checkpoint
+
+After Phase 1: `01-inventory.md`
+After Phase 2: `01-inventory.md`, `02-gap-analysis-draft.md`
+After Phase 3: above + `03-boot-process.md`, `03-server.md`, `03-fpga.md`,
+`03-webcontrol.md`, `03-tutorials.md`, `03-scope-decisions.md`
+After Phase 4: above + `04-doc-plan.md`, `04-toc-*.yml`
+After Phase 5: above + all final doc files in their repos
+
+The `knowledge/` directory is the complete audit trail of the project. Anyone
+joining later can read it and understand every decision made.
+
+---
+
+## One thing to do before you start
+
+Add this to `meta-panda/CLAUDE.md`:
+
+```markdown
+## Doc project status
+
+Phase 1 — inventory: [ ]
+Phase 2 — gap analysis: [ ]
+Phase 3 — interviews:
+ - [ ] Boot process and hardware (Session A)
+ - [ ] Server command interface (Session B)
+ - [ ] FPGA blocks and firmware (Session C)
+ - [ ] Web control (Session D)
+ - [ ] Tutorials (Session E)
+ - [ ] Scope decisions (Session F)
+Phase 4 — planning: [ ]
+Phase 5 — output: [ ]
+
+To resume any Claude Code session: read this file and knowledge/04-doc-plan.md.
+```
+
+Tick boxes off as you go. Claude Code reads this at the start of every session
+and knows exactly where you are.
diff --git a/knowledge/01-inventory.md b/knowledge/01-inventory.md
new file mode 100644
index 00000000..905e27d3
--- /dev/null
+++ b/knowledge/01-inventory.md
@@ -0,0 +1,90 @@
+# Documentation Inventory
+
+| Repo | File path (relative to docs/) | Words | Last commit | Covers | Audience | Status |
+|------|-------------------------------|-------|-------------|--------|----------|--------|
+| PandABlocks-FPGA | blocks.rst | 41 | 2019-01-03 | Lists the available block types that can be built into a PandABlocks app, with content pulled from a generated build artifact. | Developers and system integrators selecting blocks for an app. | outdated |
+| PandABlocks-FPGA | index.rst | 257 | 2024-09-20 | Top-level documentation home page describing what PandABlocks does and routing different audiences to the relevant sections. | All users from end-users to core framework developers. | current |
+| PandABlocks-FPGA | reference/app.rst | 364 | 2020-03-06 | Explains how to assemble blocks into an app using an ini file and how to build and query it at runtime. | Developers creating or configuring a new PandABlocks app. | outdated |
+| PandABlocks-FPGA | reference/block.rst | 1610 | 2023-09-01 | Comprehensive reference for writing a new block, covering the ini file format, Python simulation, timing tests, and target ini. | FPGA firmware developers creating or extending blocks. | current |
+| PandABlocks-FPGA | reference/changelog.rst | 3 | 2018-08-02 | Stub that includes the top-level CHANGELOG.rst file. | All users tracking version history. | partial |
+| PandABlocks-FPGA | reference/cocotb.rst | 742 | 2025-11-27 | Documents how to run, interpret, and write VHDL timing tests using the cocotb-based test runner. | FPGA developers writing or debugging block timing tests. | current |
+| PandABlocks-FPGA | reference/contributing.rst | 3 | 2018-08-02 | Stub that includes the top-level CONTRIBUTING.rst file. | Contributors to the project. | partial |
+| PandABlocks-FPGA | reference/framework.rst | 500 | 2019-01-31 | Describes the internal autogeneration framework architecture, including how testbenches read timing data and compare signals. | Core framework developers working on the autogeneration pipeline. | outdated |
+| PandABlocks-FPGA | reference/glossary.rst | 245 | 2018-08-09 | Defines key PandABlocks terminology such as App, Block, Field, Module, and PandABox. | All users needing to understand project-specific vocabulary. | outdated |
+| PandABlocks-FPGA | reference/testing.rst | 274 | 2024-09-20 | Describes how to run the Python, simulation, and HDL testbench test suites via Makefile targets. | Developers running or debugging the project's test suite. | current |
+| PandABlocks-FPGA | tutorials/tutorial1_blinking_leds.rst | 648 | 2020-01-03 | Step-by-step walkthrough of wiring PULSE and CLOCK blocks together to blink LEDs at different rates using the web GUI. | End users new to PandABlocks learning the basics of the block wiring interface. | outdated |
+| PandABlocks-FPGA | tutorials/tutorial2_position_capture.rst | 1167 | 2020-01-27 | Hands-on guide to using the PCAP block to capture position bus values with various capture modes (Value, Diff, Min, Max, Mean). | End users learning how to set up and use position capture on a PandA device. | outdated |
+| PandABlocks-FPGA | tutorials/tutorial3_position_compare.rst | 41 | 2019-02-18 | Stub introduction to position compare for generating trigger pulses at regular positional intervals. | End users learning position compare functionality. | partial |
+| PandABlocks-FPGA | tutorials/tutorial4_snake_scan.rst | 52 | 2019-02-18 | Stub introduction to table-based position compare using the SEQ block for a 2D snake scan. | End users learning advanced scanning patterns. | partial |
+| PandABlocks-server | docs/building.rst | 493 | 2017-06-26 | Explains build dependencies, CONFIG file setup, make targets, and generated output files for the PandABlocks server. | Developers building the server from source for the first time. | outdated |
+| PandABlocks-server | docs/capture.rst | 1460 | 2024-02-16 | Documents the data capture port protocol, connection flow, capture options, data header format, transport modes, and completion codes. | Client developers integrating with the PandA data capture interface. | current |
+| PandABlocks-server | docs/commands.rst | 1984 | 2025-07-11 | Describes the full ASCII command interface on port 8888, including all configuration and system command forms and their responses. | Client developers and integrators communicating with the PandA socket server. | current |
+| PandABlocks-server | docs/config.rst | 1198 | 2025-09-03 | Specifies the syntax and semantics of the three server configuration files (config, registers, description) that define blocks, fields, and register mappings. | FPGA/firmware developers authoring or maintaining PandA configuration files. | current |
+| PandABlocks-server | docs/extension.rst | 739 | 2021-08-13 | Describes the extension server mechanism for implementing custom fields via Python modules with a remote procedure call interface. | Developers writing custom Python extension modules for the PandA server. | outdated |
+| PandABlocks-server | docs/fields.rst | 2671 | 2025-07-11 | Documents all block field types, sub-types, attributes, and their read/write/capture behaviours as exposed via the socket server. | Client developers and system integrators working with PandA block and field configuration. | current |
+| PandABlocks-server | docs/index.rst | 20 | 2021-09-22 | Acts as the documentation root, including the README and linking the toctree to all other doc pages. | All documentation readers navigating the site. | partial |
+| PandABlocks-server | docs/presentation-2016-05/building.rst | 341 | 2018-02-16 | Slide-deck instructions for building the PandABlocks-rootfs project and its boot image dependencies. | Developers or sysadmins attending the May 2016 PandA workshop. | outdated |
+| PandABlocks-server | docs/presentation-2016-05/panda.rst | 1362 | 2017-06-26 | May 2016 conference presentation covering PandA hardware/software architecture, installation, network configuration, and zpkg package management. | Engineers being introduced to the PandA system at the 2016 workshop. | outdated |
+| PandABlocks-server | docs/presentation-2016-05/server.rst | 649 | 2016-05-05 | May 2016 presentation slide set introducing the PandA socket server architecture, config file format, and field types. | Engineers attending the May 2016 PandA server overview talk. | outdated |
+| PandABlocks-server | docs/startup.rst | 501 | 2019-04-05 | Lists and explains all command-line arguments for starting the PandA socket server manually. | System administrators and developers launching or scripting the server. | outdated |
+| PandABlocks-server | docs/support.rst | 391 | 2016-09-19 | Covers supporting Python tools (sim_server, tcp_client, save/load-state) and the meaning of the PandA hardware status LEDs. | System operators and developers troubleshooting or interacting with a running PandA. | outdated |
+| PandABlocks-rootfs | explanations.md | 19 | 2024-12-11 | Navigation stub listing explanations sub-pages via a toctree glob with no substantive content. | Documentation maintainers/contributors. | partial |
+| PandABlocks-rootfs | how-to/building.md | 1302 | 2025-11-20 | Step-by-step instructions for building the PandABlocks root filesystem from source, including dependencies, configuration, output files, boot process, and zpkg package management. | Developers who need to compile and deploy the PandA rootfs image. | current |
+| PandABlocks-rootfs | how-to.md | 55 | 2024-12-11 | Navigation stub introducing the three how-to guides: getting PandA on the network, updating via SSH, and building the rootfs. | Documentation maintainers/contributors. | partial |
+| PandABlocks-rootfs | how-to/quickstart.md | 564 | 2024-12-11 | How to configure PandA networking via config.txt, use the USB override mechanism, and navigate the web interface and web admin panel. | Hardware operators and system administrators setting up a PandA device for the first time. | current |
+| PandABlocks-rootfs | index.md | 174 | 2024-12-11 | Landing page for the PandABlocks-rootfs documentation, describing what the rootfs does and linking to the three main how-to guides. | All users of the PandABlocks-rootfs project. | current |
+| PandABlocks-rootfs | reference.md | 20 | 2024-12-11 | Navigation stub listing reference sub-pages including APIs, release notes, and a generated index. | Documentation maintainers/contributors. | partial |
+| PandABlocks-rootfs | tutorials.md | 8 | 2024-12-11 | Navigation stub for the tutorials section with no content beyond a toctree glob. | Documentation maintainers/contributors. | partial |
+| PandABlocks.github.io | explanations/decisions/0001-record-architecture-decisions.rst | 57 | 2024-03-25 | ADR recording the decision to use Architecture Decision Records to document project architectural choices. | Project contributors and maintainers. | current |
+| PandABlocks.github.io | explanations/decisions/0002-switched-to-pip-skeleton.rst | 93 | 2024-03-25 | ADR recording the decision to adopt the DiamondLightSource python3-pip-skeleton for consistent project structure and tooling. | Project contributors and maintainers. | current |
+| PandABlocks.github.io | explanations/decisions.rst | 71 | 2024-03-25 | Index page listing all Architecture Decision Records for the project. | Project contributors and maintainers. | current |
+| PandABlocks.github.io | explanations.rst | 16 | 2024-03-25 | Navigation stub for the explanations section. | Documentation maintainers/contributors. | partial |
+| PandABlocks.github.io | how.rst | 19 | 2024-03-25 | Navigation stub for the how-to guides section. | Documentation maintainers/contributors. | partial |
+| PandABlocks.github.io | how-to/contribute.rst | 3 | 2024-03-25 | Stub that includes the project's CONTRIBUTING.rst file from the .github directory. | Potential contributors to the project. | partial |
+| PandABlocks.github.io | how-to/finedelay-test.rst | 183 | 2026-03-16 | Procedure for testing the fine delay functionality of LVDSOUT pins using an oscilloscope and a sweep script. | Hardware engineers and FPGA developers validating PandA timing outputs. | current |
+| PandABlocks.github.io | how-to/make-release.rst | 97 | 2024-03-25 | Checklist for creating a new GitHub release for the project. | Project maintainers responsible for publishing releases. | current |
+| PandABlocks.github.io | how-to/remote.rst | 471 | 2024-11-27 | Instructions for updating PandA rootfs and zpkg packages remotely over SSH, including an EEPROM update for 24V FMC cards. | System administrators and engineers managing PandA firmware deployments. | current |
+| PandABlocks.github.io | how-to/run-container.rst | 167 | 2025-07-08 | Instructions for pulling and running the PandA development Docker container with the required volume mounts. | Developers setting up a local PandA build environment using containers. | current |
+| PandABlocks.github.io | how-to/update-tools.rst | 84 | 2024-03-25 | Instructions for syncing the project with the latest DiamondLightSource python3-pip-skeleton via git rebase. | Project maintainers keeping developer tooling up to date. | current |
+| PandABlocks.github.io | how-to/web-interface.rst | 329 | 2024-11-27 | Step-by-step guide for updating PandA rootfs and zpkg packages using the web admin interface and a USB memory stick. | System administrators and operators performing PandA firmware updates in the field. | current |
+| PandABlocks.github.io | index.rst | 127 | 2024-03-25 | Top-level documentation landing page linking to all four documentation sections and listing the URLs for each PandABlocks sub-project. | All users and developers of the PandABlocks ecosystem. | current |
+| PandABlocks.github.io | reference/genindex.rst | 5 | 2024-03-25 | Minimal stub page providing a placeholder for the API index. | Documentation maintainers/contributors. | partial |
+| PandABlocks.github.io | reference/migration_guide.rst | 119 | 2024-03-25 | Guide for migrating PandA firmware between major versions, with API change tables for the 2.0-to-3.0 upgrade. | System administrators and developers upgrading PandA firmware between major releases. | current |
+| PandABlocks.github.io | reference/release_compatibility.rst | 32 | 2024-03-25 | Table showing which rootfs versions are compatible with which zpkg release versions. | System administrators ensuring compatible component versions when deploying PandA firmware. | current |
+| PandABlocks.github.io | reference.rst | 18 | 2024-03-25 | Navigation stub for the references section. | Documentation maintainers/contributors. | partial |
+| PandABlocks.github.io | reference/standards.rst | 17 | 2024-03-25 | Stub defining code and documentation standards for the repository with only a section header and no body content. | Project contributors writing or reviewing code and documentation. | partial |
+| PandABlocks.github.io | tutorial.rst | 18 | 2024-03-25 | Navigation stub for the tutorials section. | Documentation maintainers/contributors. | partial |
+| PandABlocks.github.io | tutorials/tutorial1_blinking_leds.rst | 648 | 2024-03-25 | Hands-on tutorial introducing PandABlocks basics by wiring CLOCK and PULSE blocks to blink TTL output LEDs at different rates. | New users learning the PandABlocks web GUI and block-wiring concepts for the first time. | current |
+| PandABlocks.github.io | tutorials/tutorial2_position_capture.rst | 1167 | 2024-03-25 | Tutorial explaining how to configure PCAP position capture with various capture modes and retrieve data via TCP. | Users learning to use PandA's position capture interface for data acquisition experiments. | current |
+| PandABlocks.github.io | tutorials/tutorial3_position_compare.rst | 41 | 2024-03-25 | Stub introduction to the Position Compare tutorial covering 1D encoder scanning and trigger generation at positional intervals. | New users progressing through the PandABlocks tutorial series. | partial |
+| PandABlocks.github.io | tutorials/tutorial4_snake_scan.rst | 52 | 2024-03-25 | Stub introduction to the Snake Scan tutorial covering table-based 2D position compare using the SEQ block. | New users progressing through the PandABlocks tutorial series. | partial |
+| meta-panda | explanations/boot-process.rst | 141 | 2025-10-08 | Describes the five-stage boot sequence of the PandA Zynq device from SD card to running Linux. | Developers and engineers building or debugging the PandA firmware. | current |
+| meta-panda | explanations.rst | 19 | 2025-10-08 | Top-level toctree wrapper for the Explanations section with no substantive content. | Navigation/structural page for documentation readers. | partial |
+| meta-panda | how-to/build.rst | 275 | 2026-02-02 | Step-by-step instructions for building the PandA Linux image using kas and collecting output files. | Developers who want to build the PandA firmware from source. | current |
+| meta-panda | how-to/make-release.rst | 97 | 2025-10-13 | Checklist for creating a new GitHub release of the project. | Project maintainers responsible for publishing releases. | current |
+| meta-panda | how-to/packages.rst | 137 | 2025-10-18 | How to install IPK/opkg packages onto a PandA via USB or SSH. | System administrators and developers deploying software to a PandA. | current |
+| meta-panda | how-to/pandablocks-sdk.rst | 161 | 2025-10-18 | How to use the PandABlocks Yocto SDK Docker image to cross-compile the PandABlocks-server outside of Yocto. | Developers needing to build and test PandABlocks-server binaries for the PandA target. | current |
+| meta-panda | how-to/quickstart.rst | 817 | 2025-10-08 | How to get a PandA on the network, configure networking, use the web admin interface, and answers to common operational FAQs. | Users setting up or administering a PandA device for the first time. | current |
+| meta-panda | how-to/remote.rst | 245 | 2025-10-13 | How to update PandA firmware and EEPROM remotely via SSH. | Administrators needing to update multiple PandAs or perform low-level maintenance without physical access. | current |
+| meta-panda | how-to.rst | 9 | 2025-10-08 | Top-level toctree wrapper for the How-to Guides section with no substantive content. | Navigation/structural page for documentation readers. | partial |
+| meta-panda | how-to/run-container.rst | 167 | 2025-10-13 | How to pull and run the PandABlocks development Docker container with the required volume mounts. | Developers setting up a containerised build environment for PandA FPGA work. | current |
+| meta-panda | how-to/web-interface.rst | 240 | 2025-10-13 | How to update PandA rootfs firmware using the web admin interface and a USB stick. | End users and administrators performing firmware upgrades via the browser-based admin panel. | current |
+| meta-panda | index.rst | 31 | 2025-10-08 | Top-level documentation index linking all Linux system and webcontrol documentation sections. | All readers navigating the meta-panda documentation. | partial |
+| meta-panda | reference/opkg.rst | 41 | 2025-10-08 | Quick-reference listing of common opkg package management commands available on the PandA. | System administrators and developers managing installed packages on a PandA. | current |
+| meta-panda | reference.rst | 16 | 2025-10-08 | Top-level toctree wrapper for the Reference section with no substantive content. | Navigation/structural page for documentation readers. | partial |
+| meta-panda | tutorials/manual-build.rst | 153 | 2025-10-08 | Alternative manual Yocto build procedure for the PandA image without the kas helper, intended for learning. | Developers wanting to understand the underlying Yocto build steps in detail. | current |
+| meta-panda | tutorials.rst | 8 | 2025-10-08 | Top-level toctree wrapper for the Tutorials section with no substantive content. | Navigation/structural page for documentation readers. | partial |
+| meta-panda | tutorials/tutorial1_blinking_leds.rst | 648 | 2025-10-13 | Guided tutorial using the web GUI to wire PULSE and CLOCK blocks together to flash PandA front-panel LEDs. | New users learning PandABlocks concepts through hands-on experimentation. | current |
+| meta-panda | tutorials/tutorial2_position_capture.rst | 1167 | 2025-10-13 | Guided tutorial on using the PCAP block to capture position bus values with various capture modes. | Users learning how to configure and use PandA position capture functionality. | current |
+| meta-panda | tutorials/tutorial3_position_compare.rst | 41 | 2025-10-13 | Stub introduction to a tutorial on generating trigger pulses at positional intervals using position compare. | Users progressing through the PandABlocks tutorial series. | partial |
+| meta-panda | tutorials/tutorial4_snake_scan.rst | 52 | 2025-10-13 | Stub introduction to a tutorial on using the SEQ block for table-based two-dimensional snake scans. | Users progressing through the PandABlocks tutorial series. | partial |
+| meta-panda | webcontrol/contents.rst | 22 | 2025-10-07 | Toctree contents page organising the webcontrol overview and user guide sections. | Navigation/structural page for the webcontrol documentation. | partial |
+| meta-panda | webcontrol/index.rst | 97 | 2025-10-07 | Introduction to the PandABlocks-webcontrol GUI, listing its capabilities and pointing to quick-start and detailed guides. | New users approaching the webcontrol documentation for the first time. | current |
+| meta-panda | webcontrol/userguide/contents.rst | 22 | 2025-10-07 | Toctree contents page organising the webcontrol user guide sub-pages. | Navigation/structural page for the webcontrol user guide. | partial |
+| meta-panda | webcontrol/userguide/glossary.rst | 732 | 2025-10-07 | Defines key terms used throughout the webcontrol documentation (Block, Attribute, Link, Port, Design, etc.). | Users who need precise definitions of webcontrol and MalcolmJS interface concepts. | current |
+| meta-panda | webcontrol/userguide/index.rst | 97 | 2025-10-07 | Introduction to the PandABlocks-webcontrol GUI (mirrors webcontrol/index.rst content). | New users approaching the webcontrol documentation for the first time. | current |
+| meta-panda | webcontrol/userguide/monitoring_attribute_values.rst | 991 | 2025-10-07 | Explains how to view attribute values as real-time charts or numerical tables within the webcontrol UI. | Users who want to monitor and inspect live or historical block attribute data. | current |
+| meta-panda | webcontrol/userguide/quick-start.rst | 376 | 2025-10-07 | Brief walkthrough of connecting to a Malcolm instance, selecting a root block, and creating a link between blocks. | New users wanting a fast introduction to the MalcolmJS web interface. | current |
+| meta-panda | webcontrol/userguide/understanding_attribute_state.rst | 535 | 2025-10-07 | Explains each attribute state (Normal, Processing, Locally Edited, Warning, Error, etc.) and how they are shown in the UI. | Users who need to interpret the status icons displayed next to attributes in the webcontrol UI. | partial |
+| meta-panda | webcontrol/userguide/user_interface_overview.rst | 1150 | 2025-10-07 | Describes the four UI panels, Layout View, and Attribute View of the MalcolmJS webcontrol interface. | Users learning how to navigate and use the webcontrol graphical interface. | current |
+| meta-panda | webcontrol/userguide/working_with_a_design.rst | 4882 | 2025-10-07 | Comprehensive reference for all design operations in the webcontrol UI including adding/removing blocks, setting attributes, linking, and saving/loading designs. | Users actively building and configuring PandA designs in the webcontrol interface. | partial |
diff --git a/knowledge/02-gap-analysis-draft.md b/knowledge/02-gap-analysis-draft.md
new file mode 100644
index 00000000..3da3dbfa
--- /dev/null
+++ b/knowledge/02-gap-analysis-draft.md
@@ -0,0 +1,330 @@
+# Documentation Gap Analysis (Draft)
+
+Scope: based on `knowledge/01-inventory.md` and a full read of every doc file
+marked **current** or **partial** across the five repos (PandABlocks-FPGA,
+PandABlocks-server, PandABlocks-rootfs, PandABlocks.github.io, meta-panda).
+Files marked *outdated* were not re-read and are referenced only where a current
+page points at them.
+
+---
+
+## Section 1 — Duplications
+
+Pages (or large sections) that cover the same topic in more than one place.
+
+1. **Tutorials 1–4 exist in triplicate.** `tutorials/tutorial1_blinking_leds`,
+ `tutorial2_position_capture`, `tutorial3_position_compare`,
+ `tutorial4_snake_scan` are present in **PandABlocks-FPGA**,
+ **PandABlocks.github.io**, and **meta-panda**. Tutorials 3 and 4 are the same
+ ~40/52-word stub in all three repos (identical wording). Tutorials 1 and 2
+ are the same 648/1167-word content in all three. Only the *status* differs
+ (FPGA's 1 & 2 are marked outdated; github.io and meta-panda are current).
+
+2. **"Make a release"** — `how-to/make-release.rst` is byte-for-byte identical
+ in **PandABlocks.github.io** and **meta-panda** (both 97 words). Notably
+ meta-panda's copy still links to
+ `github.com/PandABlocks/PandABlocks.github.io/releases` (see Q4).
+
+3. **"Run in a container"** — `how-to/run-container.rst` is identical in
+ **PandABlocks.github.io** and **meta-panda** (both 167 words, same REPO_DIR /
+ VIVADO_DIR / BUILD_DIR volume-mount instructions, same "reistry" typo).
+
+4. **"Updating a PandA via SSH"** — `how-to/remote.rst` in
+ **PandABlocks.github.io** (471 w) and **meta-panda** (245 w) cover the same
+ task (update rootfs, update packages, 24V EEPROM). They diverge on artifact
+ names and package tooling (zpkg/`boot-x.x.zip` vs opkg/`boot-{MACHINE}.tar.gz`).
+ The 24V-EEPROM section is duplicated almost verbatim between them.
+
+5. **"Updating a PandA via web interface"** — `how-to/web-interface.rst` in
+ **PandABlocks.github.io** (329 w) and **meta-panda** (240 w) duplicate the
+ same web-admin upgrade procedure, again diverging on zpkg vs opkg artifacts.
+
+6. **"Getting a PandA on the network" / quickstart** — the `config.txt`
+ network-configuration block, "Web Interface", and "Web Admin" sections are
+ duplicated between **PandABlocks-rootfs** `how-to/quickstart.md` (564 w) and
+ **meta-panda** `how-to/quickstart.rst` (817 w). meta-panda adds an FAQ
+ section; otherwise the shared content is near-identical.
+
+7. **Boot process** — the five-stage boot description appears in both
+ **PandABlocks-rootfs** `how-to/building.md` ("Boot Process" section) and
+ **meta-panda** `explanations/boot-process.rst`. Same five stages, but rootfs
+ describes `imagefile.cpio.gz` + SD repartitioning while meta-panda describes a
+ FIT image + `rootfs.squashfs`.
+
+8. **Building the image** — two overlapping-but-divergent build guides:
+ **PandABlocks-rootfs** `how-to/building.md` (Diamond rootfs builder + Xilinx
+ SDK + `CONFIG` + zpkg) vs **meta-panda** `how-to/build.rst` (kas/Yocto) and
+ **meta-panda** `tutorials/manual-build.rst` (manual Yocto/bitbake). Three
+ documents answer "how do I build the PandA image?" with different toolchains.
+
+9. **Package management** — **PandABlocks-rootfs** `how-to/building.md`
+ ("Installing zpkg Files" + "zpkg Command") vs **meta-panda**
+ `how-to/packages.rst` + `reference/opkg.rst`. Same concept (install via USB
+ admin page or scp+CLI; list/install/remove/show commands), zpkg vs opkg/ipk.
+
+10. **Capture-mode table** — the pos_out capture options
+ (No/Value/Diff/Sum/Mean/Min/Max/Min Max/Min Max Mean) appear three times:
+ **PandABlocks-server** `docs/capture.rst`, **PandABlocks-server**
+ `docs/fields.rst` (pos_out `CAPTURE` attribute), and **meta-panda**
+ `tutorials/tutorial2_position_capture.rst`. The three lists do not fully
+ agree (see Q21).
+
+11. **Webcontrol "Introduction"** — `webcontrol/index.rst` and
+ `webcontrol/userguide/index.rst` (both in meta-panda) are byte-for-byte
+ identical (97 w each).
+
+12. **Webcontrol "Contents"** — `webcontrol/contents.rst` and
+ `webcontrol/userguide/contents.rst` (both meta-panda) are byte-for-byte
+ identical toctree pages.
+
+13. **pip-skeleton / tooling** — **PandABlocks.github.io**
+ `how-to/update-tools.rst` and ADR `0002-switched-to-pip-skeleton.rst` both
+ document the python3-pip-skeleton relationship.
+
+14. **Version/compatibility** — **PandABlocks.github.io**
+ `reference/migration_guide.rst` and `reference/release_compatibility.rst`
+ both address "which versions go together", from different angles.
+
+15. **Navigation toctree stubs** — every repo carries near-identical empty
+ section wrappers: `explanations(.rst/.md)`, `how-to(.rst/.md)` / `how.rst`,
+ `reference(.rst/.md)`, `tutorials(.rst/.md)` / `tutorial.rst`. rootfs,
+ github.io and meta-panda each have their own set with the same boilerplate.
+
+---
+
+## Section 2 — Apparent gaps
+
+Topics referenced but never fully documented (in the current/partial set).
+
+1. **Tutorials 3 & 4 are never written.** Both are intro-paragraph stubs in all
+ three repos. tutorial2's conclusion explicitly promises "In the next tutorial
+ we will read about how to use position compare…", but position compare and
+ snake scan are never delivered.
+
+2. **`block.rst` placeholder sections.** "Writing docs" ("Two RST directives,
+ how to structure"), "Block VHDL entity" ("How to structure the VHDL entity"),
+ and "Tables will be defined here too" / `table` ("Tables are treated
+ specially") are stubs with no real content.
+
+3. **rootfs SSH-update guide is missing but linked.** `index.md` and `how-to.md`
+ in **PandABlocks-rootfs** describe and toctree-include an "Updating a PandA
+ via SSH" guide (`how-to/remote.md`), but no `remote.md` exists in the rootfs
+ docs — only `building.md` and `quickstart.md` do.
+
+4. **Webcontrol attribute-state icons missing.** `understanding_attribute_state.rst`
+ has `*GET IMAGE*` placeholders for Processing, Update Error, and Disconnected
+ states, and references a "table above" of icons that is not present on the
+ page.
+
+5. **Webcontrol design screenshots missing.** `working_with_a_design.rst` has
+ several `*GET SCREENSHOT*` / `*GET SCREENHOST*` placeholders (View/Edit,
+ Dropdown List, Text Input, Checkbox) and an unfinished sentence in the Text
+ Input section ("shown in the .").
+
+6. **Standards undocumented.** github.io `reference/standards.rst` has a "Code
+ Standards" heading with no body and no "Documentation Standards" section,
+ despite the intro promising both.
+
+7. **No API reference.** github.io `reference/genindex.rst` is an empty
+ placeholder, and rootfs `reference.md` toctrees a `genindex` and "APIs" that
+ do not exist. No actual API documentation is present anywhere in the set.
+
+8. **Per-block reference missing from the inventoried set.** Tutorials and
+ server docs constantly reference PULSE, CLOCK, PCAP, COUNTER, SEQ, TTLOUT,
+ ADDER, V2F, etc., but the only block listing (FPGA `blocks.rst`) is an
+ outdated generated artifact, and the `modules/*/*_doc.rst` files are not part
+ of the inventory. There is no current, authored "what each block does" page.
+
+9. **V2F block** is referenced (with an external paper link) in tutorial2 but is
+ never defined or documented.
+
+10. **Webcontrol install/launch is undocumented.** The webcontrol guide explains
+ the GUI thoroughly but never says how to install or start the webcontrol /
+ Malcolm server, nor what host/port to use (quick-start says
+ `http://{malcolm host}/gui/`, e.g. `localhost:3000`; the network/web-admin
+ docs imply the PandA's IP on port 80). See Q9.
+
+11. **Malcolm ↔ webcontrol relationship.** The glossary references `malcolm`,
+ `pymalcolm`, "MalcolmJS", "Web Control" and "PandABox User Interface"
+ interchangeably; the relationship between these is never explained.
+
+12. **Host SDK installer.** `pandablocks-sdk.rst` states "the sdk installer is
+ also provided to use it in the host directly" but never says where to get it
+ or how to run it.
+
+13. **Streaming tables.** server `fields.rst` documents the full `MODE`
+ transition matrix for streaming tables (`<<`, `<<|`) but no page explains
+ when or why a client would use streaming vs fixed tables.
+
+14. **Extension server.** server `config.rst` and FPGA `block.rst` reference the
+ extension mechanism (`:ref:`extension``, `extension_read`/`extension_write`,
+ extension `.py` files), but the only explainer (`extension.rst`) is marked
+ outdated.
+
+15. **Supported MACHINE values.** Build docs mention `pandabox` (default),
+ `xu5-s1`, `xu5-st1`, and ZedBoard, but no reference page enumerates the
+ supported targets or their differences.
+
+16. **kas image version ↔ firmware version.** `build.rst` sets
+ `KAS_IMAGE_VERSION="4.8"` with no explanation of how this relates to the
+ PandA firmware release a user is trying to build.
+
+17. **EEPROM / 24V FMC tooling.** The `write_eeprom` + `ipmi_definition.ini`
+ procedure appears in remote.rst but has no broader reference for which cards
+ need it or how the bitstream-variant selection (IPMI EEPROM) works end to end.
+
+18. **Pre-2.1 / legacy upgrade path.** github.io web-interface.rst carries a note
+ about rootfs "< 2.1" needing `imagefile.cpio.gz`; meta-panda's version drops
+ it. Whether legacy upgrades are still supported, and where that's documented,
+ is unclear.
+
+---
+
+## Section 3 — Questions for the owner
+
+Numbered, specific. Cap is 50; there are 34 below.
+
+1. The rootfs `building.md` describes building via the Diamond rootfs builder +
+ Xilinx SDK + `CONFIG` + zpkg, while meta-panda `build.rst` describes building
+ via kas/Yocto producing opkg/ipk packages. Which is the canonical build path
+ for a new user in 2026, and is `building.md` now obsolete (should it be
+ retired or marked legacy)?
+
+2. Package tooling: github.io `remote.rst`/`web-interface.rst` still reference
+ `panda-*.zpg` and `zpkg install`, while meta-panda `packages.rst`/`opkg.rst`
+ use `.ipk` and `opkg install`. Which is correct for current firmware, and at
+ which release did zpkg → opkg happen?
+
+3. Release artifacts: github.io `remote.rst` says download `boot-x.x.zip`
+ containing `imagefile.cpio.gz`/`uImage`; meta-panda `remote.rst` says
+ `boot-{MACHINE}.tar.gz` containing `rootfs.squashfs`/`Image`. What is the
+ current release artifact name and format?
+
+4. meta-panda `how-to/make-release.rst` links to
+ `github.com/PandABlocks/PandABlocks.github.io/releases`. Should this point at
+ the meta-panda releases page instead (copy-paste leftover)?
+
+5. Tutorials 1–4 exist in three repos (FPGA, github.io, meta-panda). Which repo
+ is meant to be the canonical home, and should the other copies be deleted or
+ replaced with cross-links?
+
+6. Tutorials 3 (position compare) and 4 (snake scan) are stubs everywhere. Are
+ these planned to be written, and which repo should host the finished versions?
+
+7. `webcontrol/index.rst` and `webcontrol/userguide/index.rst` are identical, as
+ are the two `contents.rst` files. Which is the intended source, and can the
+ duplicate be removed?
+
+8. quickstart.rst's FAQ says to write a static network config to a file called
+ `boot.txt` on the SD card, but the rest of that doc (and rootfs
+ `quickstart.md`) uses `config.txt` / `panda-config.txt`. Which filename is
+ correct? (`boot.txt` is mentioned nowhere else.)
+
+9. The webcontrol `quick-start.rst` says to connect at `http://{malcolm host}/gui/`
+ e.g. `localhost:3000`, but `quickstart.rst`/`web-interface.rst` say the web
+ interface is reached at the PandA's IP/hostname (implying port 80). What is
+ the correct URL and port for reaching the webcontrol GUI on a real PandA in
+ 2026?
+
+10. rootfs `index.md` and `how-to.md` describe and toctree-include an "Updating a
+ PandA via SSH" guide (`how-to/remote.md`), but that file does not exist in
+ the rootfs docs. Should it be created, or should the references be removed
+ because the SSH guide now lives only in github.io/meta-panda?
+
+11. `migration_guide.rst` only covers 2.0 → 3.0, but `web-interface.rst` already
+ mentions "From PandA v4.0". Are 3.0 → 4.0 (and later) migration notes needed,
+ and who maintains them?
+
+12. `release_compatibility.rst` stops at rootfs 3.0 / zpkg 3.0. With v4.x and the
+ zpkg → opkg switch, what is the current compatibility matrix?
+
+13. server `building.rst` (CONFIG/make standalone build) vs meta-panda
+ `pandablocks-sdk.rst` (Yocto SDK cross-compile): is the standalone build of
+ PandABlocks-server still supported, or is the SDK the only sanctioned path?
+
+14. `block.rst` has empty placeholder sections "Writing docs", "Block VHDL
+ entity", and "Tables will be defined here too". Do you have the intended
+ content, or should these be removed?
+
+15. `understanding_attribute_state.rst` has `*GET IMAGE*` placeholders
+ (Processing, Update Error, Disconnected) and references a "table above" that
+ isn't present. Are the missing icons / table available to drop in?
+
+16. `working_with_a_design.rst` has several `*GET SCREENSHOT*` placeholders and
+ an unfinished sentence in the Text Input section. Are the source screenshots
+ available, and what was the Text Input sentence meant to say?
+
+17. github.io `standards.rst` has a "Code Standards" heading with no body and no
+ "Documentation Standards" section. What standards should be documented here,
+ or should the page be dropped?
+
+18. FPGA `testing.rst` says the Python tests run "as part of the Travis tests".
+ Is CI still Travis (vs GitHub Actions), and is this page current?
+
+19. `pandablocks-sdk.rst` says "the sdk installer is also provided to use it in
+ the host directly" but gives no instructions. Where is the host installer and
+ what are the steps to use it?
+
+20. The `CONFIG` example in `pandablocks-sdk.rst` mixes `KERNEL_DIR=...` (no
+ spaces) with `PYTHON = python3` (spaces around `=`). Which syntax does the
+ server Makefile's `CONFIG` actually require?
+
+21. Capture options disagree across three pages: `capture.rst` lists
+ No/Value/Diff/Sum/Mean/Min/Max/Min Max/Min Max Mean; `commands.rst`
+ (`*CAPTURE.OPTIONS?`) lists Value/Diff/Sum/Mean/Min/Max/**StdDev** (no Min Max
+ combos); `fields.rst` lists the Min Max combos but not Sum or StdDev;
+ tutorial2 omits StdDev. What is the authoritative list for current firmware?
+
+22. `capture.rst` states FRAMED RAW mode sustains ~60 MByte/s "when
+ panda-webcontrol is not installed". Is this figure still accurate for current
+ hardware/firmware?
+
+23. `commands.rst` shows `*IDN?` returning `SW: 1.1 … rootfs: PandA 1.1`. Is the
+ identification string format (and the `rootfs:` field introduced in 1.1)
+ unchanged in v4.x?
+
+24. The webcontrol glossary uses `malcolm`, `pymalcolm`, "MalcolmJS", "Web
+ Control" and "PandABox User Interface" interchangeably. Is the GUI still
+ MalcolmJS/pymalcolm-based, and should the docs standardise on one name?
+
+25. meta-panda `index.rst` simply `.. include::`s `../README.rst`. Does the
+ README hold the intended landing-page content, or should index.rst have its
+ own introduction?
+
+26. FPGA `index.rst` routes block authors to `blocks.rst` (outdated, generated)
+ and `app.rst` (outdated). Are these being regenerated/rewritten, or should
+ the index point somewhere else?
+
+27. The 24V FMC EEPROM update is described as "PandA 3.0 requires…". Is it still
+ required for v4.x installs, and is it a one-time migration step or per-install?
+
+28. `manual-build.rst` uses Xilinx's internal `gitenterprise.xilinx.com` manifest
+ on branch `rel-v2023.2`. Is that URL reachable by external users; if not,
+ what is the public equivalent (and is `rel-v2023.2` still the target branch
+ in 2026)?
+
+29. meta-panda `boot-process.rst` describes a FIT image + `rootfs.squashfs`
+ boot, while rootfs `building.md` describes `imagefile.cpio.gz` + SD-card
+ repartitioning. Is the cpio.gz/repartition flow fully superseded; should
+ building.md's "Boot Process" section be retired?
+
+30. server `config.rst` says config files load from `/opt/share/panda/config_d`
+ on a PandA. With the move to Yocto/opkg, is that path still correct?
+
+31. github.io `web-interface.rst` notes that rootfs "< 2.1" needs
+ `imagefile.cpio.gz`; meta-panda's version drops this note. Are pre-2.1
+ upgrades still supported, and where is that documented now?
+
+32. `cocotb.rst` says "Modules using IP are currently unsupported" by the cocotb
+ runner. Is that still true, and does it block testing any production blocks
+ we should flag?
+
+33. Both `make-release.rst` files instruct maintainers to use PEP440 version
+ numbers and GitHub "Generate release notes". Given the firmware version
+ scheme (2.0/3.0/4.0), is PEP440 actually the intended scheme for
+ meta-panda/firmware releases, or only for the python (github.io) repo?
+
+34. Is there an intended single "documentation home" across the five repos
+ (e.g. PandABlocks.github.io aggregating the others), or should each repo's
+ docs remain standalone? This determines whether the duplications in Section 1
+ should be consolidated or deliberately mirrored.
diff --git a/knowledge/03-doc-rewrite-sessions.md b/knowledge/03-doc-rewrite-sessions.md
new file mode 100644
index 00000000..994485f8
--- /dev/null
+++ b/knowledge/03-doc-rewrite-sessions.md
@@ -0,0 +1,488 @@
+# PandABlocks Docs Rewrite — Interview Sessions
+
+This file splits the 34 owner questions from the gap analysis into **7 self-contained
+sessions**. Each session embeds everything a fresh chat needs — the agreed target
+architecture, the relevant duplications/gaps, and the questions — so you only ever
+copy from here.
+
+## How to use it
+
+1. Start a **new chat** for each session.
+2. Copy **everything under that session's "Paste into a fresh chat" heading** (from the
+ instruction line down through the last question) and paste it in.
+3. Answer one question at a time; you'll get a 2–4 bullet summary after each.
+4. At the end of the session you'll get a single Markdown knowledge file for your repo.
+
+## Session order
+
+Structural first, then most user-facing → least user-facing (developer-facing last):
+
+1. Documentation architecture & tutorials *(structural)*
+2. Web-control UI docs *(user-facing)*
+3. Deploy, upgrade & boot *(user-facing)*
+4. Versioning & compatibility *(user-facing / ops)*
+5. PandABlocks-server: interface, build & integration *(developer-facing)*
+6. Firmware build & release *(developer-facing)*
+7. FPGA repo: blocks, build, test & CI *(developer-facing)*
+
+> Q34 from the gap analysis ("is there a single documentation home?") is **already
+> resolved** by the target architecture below, so it is not re-asked.
+
+---
+
+## Session 1 — Documentation architecture & tutorials
+
+### Paste into a fresh chat
+
+I'm rewriting the documentation for the PandABlocks org. Work through the questions in
+this message **one at a time**: ask a question, wait for my answer, then summarise my
+answer in 2–4 bullet points before moving to the next. When all questions are answered,
+compile every bullet point into a single Markdown knowledge file I can copy into my repo.
+
+**Target documentation architecture (decided):**
+
+- **meta-panda** — the front door and primary home: tutorials, architecture,
+ hardware-target descriptions, web-control UI docs, most user-facing docs, plus
+ developer docs for the Yocto firmware build. It assembles the firmware and ships an
+ offline copy of the docs inside it, so it holds the majority.
+- **PandABlocks-FPGA** — block-specific and target-specific docs; how to build, test and
+ upgrade selected firmwares.
+- **PandABlocks-server** — the TCP server interface; how to build, test and integrate.
+- **PandABlocks-rootfs** — being archived; any still-valid content moves to meta-panda
+ (the build has migrated to Yocto).
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
+
+**This session covers:** the front-door/landing structure, where tutorials live,
+cross-repo duplication cleanup, contribution/standards pages, and navigation stubs.
+
+**Relevant findings from the gap analysis:**
+
+Duplications:
+- Tutorials 1–4 exist in triplicate across FPGA, github.io and meta-panda. Tutorials 3 & 4
+ are identical ~40/52-word stubs in all three; Tutorials 1 & 2 are full content
+ (648/1167 words) in all three. Only the *status* differs (FPGA's 1 & 2 are outdated;
+ github.io and meta-panda are current).
+- `webcontrol/index.rst` and `webcontrol/userguide/index.rst` (meta-panda) are
+ byte-identical (97 w each), as are the two `contents.rst` toctree files.
+- github.io `update-tools.rst` and ADR `0002-switched-to-pip-skeleton.rst` both document
+ the python3-pip-skeleton relationship. (github.io is being reduced to a redirect, so
+ this likely retires with it.)
+- Every repo carries near-identical empty section-wrapper / toctree stubs (`explanations`,
+ `how-to`, `reference`, `tutorials`).
+
+Gaps:
+- Tutorials 3 (position compare) and 4 (snake scan) are never written; tutorial2's
+ conclusion promises position compare "in the next tutorial", but it's never delivered.
+- github.io `standards.rst` has a "Code Standards" heading with no body and no
+ "Documentation Standards" section, despite the intro promising both.
+
+**Questions:**
+
+1. Tutorials 1–4 currently live in three repos. meta-panda is now the canonical home —
+ should the FPGA and github.io copies be deleted, replaced with cross-links/redirects,
+ or handled some other way?
+2. Tutorials 3 (position compare) and 4 (snake scan) are stubs everywhere. Are they
+ planned to be written? (They'll be hosted in meta-panda.)
+3. `webcontrol/index.rst` vs `webcontrol/userguide/index.rst` are identical, as are the
+ two `contents.rst` files. Which is the intended source, and can the duplicate be
+ removed?
+4. github.io `standards.rst` has an empty "Code Standards" heading and no "Documentation
+ Standards" section. What standards should be documented, and where should they live now
+ that github.io redirects to meta-panda — or should the page be dropped?
+5. meta-panda `index.rst` simply `.. include::`s `../README.rst`. Now that meta-panda is
+ the front door, should `index.rst` have its own landing-page introduction instead of
+ including the README?
+
+---
+
+## Session 2 — Web-control UI docs
+
+### Paste into a fresh chat
+
+I'm rewriting the documentation for the PandABlocks org. Work through the questions in
+this message **one at a time**: ask a question, wait for my answer, then summarise my
+answer in 2–4 bullet points before moving to the next. When all questions are answered,
+compile every bullet point into a single Markdown knowledge file I can copy into my repo.
+
+**Target documentation architecture (decided):**
+
+- **meta-panda** — the front door and primary home: tutorials, architecture,
+ hardware-target descriptions, web-control UI docs, most user-facing docs, plus
+ developer docs for the Yocto firmware build. It ships an offline copy of the docs inside
+ the firmware, so it holds the majority.
+- **PandABlocks-FPGA** — block- and target-specific docs; build, test, upgrade firmwares.
+- **PandABlocks-server** — the TCP server interface; build, test, integrate.
+- **PandABlocks-rootfs** — being archived; still-valid content moves to meta-panda.
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
+
+**This session covers:** the web-control / GUI documentation, which is destined for
+meta-panda.
+
+**Relevant findings from the gap analysis:**
+
+Gaps:
+- `understanding_attribute_state.rst` has `*GET IMAGE*` placeholders (Processing, Update
+ Error, Disconnected) and references a "table above" of icons that isn't present.
+- `working_with_a_design.rst` has several `*GET SCREENSHOT*` / `*GET SCREENHOST*`
+ placeholders (View/Edit, Dropdown List, Text Input, Checkbox) and an unfinished sentence
+ in the Text Input section ("shown in the .").
+- Webcontrol install/launch is undocumented: the guide explains the GUI but never says how
+ to install or start it, nor what host/port to use. Quick-start says
+ `http://{malcolm host}/gui/` (e.g. `localhost:3000`); the network/web-admin docs imply
+ the PandA's IP on port 80.
+- The glossary uses `malcolm`, `pymalcolm`, "MalcolmJS", "Web Control" and "PandABox User
+ Interface" interchangeably; the relationship is never explained.
+
+**Questions:**
+
+1. The web-control `quick-start.rst` says to connect at `http://{malcolm host}/gui/`
+ (e.g. `localhost:3000`), but `quickstart.rst`/`web-interface.rst` say the web interface
+ is reached at the PandA's IP/hostname (implying port 80). What is the correct URL and
+ port for reaching the web-control GUI on a real PandA in 2026?
+2. `understanding_attribute_state.rst` has `*GET IMAGE*` placeholders (Processing, Update
+ Error, Disconnected) and references a missing "table above" of icons. Are the icons /
+ table available to drop in?
+3. `working_with_a_design.rst` has several `*GET SCREENSHOT*` placeholders and an
+ unfinished sentence in the Text Input section. Are the source screenshots available,
+ and what was the Text Input sentence meant to say?
+4. The glossary uses `malcolm`, `pymalcolm`, "MalcolmJS", "Web Control" and "PandABox User
+ Interface" interchangeably. Is the GUI still MalcolmJS/pymalcolm-based, and should the
+ docs standardise on one name?
+
+---
+
+## Session 3 — Deploy, upgrade & boot
+
+### Paste into a fresh chat
+
+I'm rewriting the documentation for the PandABlocks org. Work through the questions in
+this message **one at a time**: ask a question, wait for my answer, then summarise my
+answer in 2–4 bullet points before moving to the next. When all questions are answered,
+compile every bullet point into a single Markdown knowledge file I can copy into my repo.
+
+**Target documentation architecture (decided):**
+
+- **meta-panda** — the front door and primary home: tutorials, architecture,
+ hardware-target descriptions, web-control UI docs, most user-facing docs, plus
+ developer docs for the Yocto firmware build. It ships an offline copy of the docs inside
+ the firmware, so it holds the majority.
+- **PandABlocks-FPGA** — block- and target-specific docs; build, test, upgrade firmwares.
+- **PandABlocks-server** — the TCP server interface; build, test, integrate.
+- **PandABlocks-rootfs** — being archived; any still-valid content moves to meta-panda
+ (the build has migrated to Yocto).
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
+
+**This session covers:** getting firmware and packages onto a PandA, network/boot
+configuration, and the boot process. The user-facing how-to and boot explanation are
+destined for meta-panda, which absorbs the rootfs upgrade/SSH material as rootfs is
+archived.
+
+**Relevant findings from the gap analysis:**
+
+Duplications:
+- `remote.rst` ("Updating a PandA via SSH") in github.io (471 w) and meta-panda (245 w)
+ cover the same task (update rootfs, update packages, 24V EEPROM) but diverge on artifact
+ names and tooling (zpkg / `boot-x.x.zip` vs opkg / `boot-{MACHINE}.tar.gz`). The
+ 24V-EEPROM section is near-verbatim in both.
+- `web-interface.rst` ("Updating a PandA via web interface") in github.io (329 w) and
+ meta-panda (240 w) duplicate the web-admin upgrade procedure, diverging on zpkg vs opkg
+ artifacts.
+- The `config.txt` network-config block plus "Web Interface" / "Web Admin" sections are
+ duplicated between rootfs `quickstart.md` (564 w) and meta-panda `quickstart.rst`
+ (817 w); meta-panda adds an FAQ.
+- Boot process: a five-stage description appears in both rootfs `building.md`
+ ("Boot Process") and meta-panda `boot-process.rst` — same five stages, but rootfs
+ describes `imagefile.cpio.gz` + SD repartitioning while meta-panda describes a FIT image
+ + `rootfs.squashfs`.
+- Package management: rootfs `building.md` (zpkg) vs meta-panda `packages.rst` +
+ `reference/opkg.rst` (opkg/ipk) — same concept (USB admin page or scp+CLI;
+ list/install/remove/show), different tooling.
+
+Gaps:
+- rootfs `index.md` and `how-to.md` describe and toctree-include an "Updating a PandA via
+ SSH" guide (`how-to/remote.md`) that does not exist in the rootfs docs.
+- EEPROM / 24V FMC tooling: the `write_eeprom` + `ipmi_definition.ini` procedure appears
+ in `remote.rst` but has no broader reference for which cards need it or how the
+ bitstream-variant selection (IPMI EEPROM) works end to end.
+- Pre-2.1 / legacy upgrade path: github.io `web-interface.rst` notes rootfs "< 2.1" needs
+ `imagefile.cpio.gz`; meta-panda's version drops this note. Whether legacy upgrades are
+ still supported, and where it's documented, is unclear.
+
+**Questions:**
+
+1. Package tooling: github.io `remote.rst`/`web-interface.rst` reference `panda-*.zpg` and
+ `zpkg install`, while meta-panda `packages.rst`/`opkg.rst` use `.ipk` and
+ `opkg install`. Which is correct for current firmware, and at which release did
+ zpkg → opkg happen?
+2. `quickstart.rst`'s FAQ says to write a static network config to a file called
+ `boot.txt` on the SD card, but the rest of that doc (and rootfs `quickstart.md`) use
+ `config.txt` / `panda-config.txt`. Which filename is correct? (`boot.txt` appears
+ nowhere else.)
+3. rootfs `index.md`/`how-to.md` toctree an "Updating a PandA via SSH" guide
+ (`how-to/remote.md`) that doesn't exist. Since rootfs is being archived, should the SSH
+ guide be (re)written in meta-panda and the rootfs references removed?
+4. The 24V FMC EEPROM update is described as "PandA 3.0 requires…". Is it still required
+ for v4.x installs, and is it a one-time migration step or per-install?
+5. meta-panda `boot-process.rst` describes a FIT image + `rootfs.squashfs` boot, while
+ rootfs `building.md` describes `imagefile.cpio.gz` + SD-card repartitioning. Is the
+ cpio.gz/repartition flow fully superseded, and should `building.md`'s "Boot Process"
+ section be retired, with the canonical boot explanation living in meta-panda?
+6. github.io `web-interface.rst` notes rootfs "< 2.1" needs `imagefile.cpio.gz`;
+ meta-panda drops this note. Are pre-2.1 upgrades still supported, and where should that
+ be documented?
+
+---
+
+## Session 4 — Versioning & compatibility
+
+### Paste into a fresh chat
+
+I'm rewriting the documentation for the PandABlocks org. Work through the questions in
+this message **one at a time**: ask a question, wait for my answer, then summarise my
+answer in 2–4 bullet points before moving to the next. When all questions are answered,
+compile every bullet point into a single Markdown knowledge file I can copy into my repo.
+
+**Target documentation architecture (decided):**
+
+- **meta-panda** — the front door and primary home: tutorials, architecture,
+ hardware-target descriptions, web-control UI docs, most user-facing docs, plus
+ developer docs for the Yocto firmware build.
+- **PandABlocks-FPGA** — block- and target-specific docs; build, test, upgrade firmwares.
+- **PandABlocks-server** — the TCP server interface; build, test, integrate.
+- **PandABlocks-rootfs** — being archived; still-valid content moves to meta-panda.
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
+
+**This session covers:** which releases go together, migration between releases, and the
+device identification string. This is cross-cutting reference material spanning meta-panda
+(compatibility/migration) and the server (the `*IDN?` string).
+
+**Relevant findings from the gap analysis:**
+
+Duplications:
+- github.io `migration_guide.rst` and `release_compatibility.rst` both address "which
+ versions go together", from different angles.
+
+**Questions:**
+
+1. `migration_guide.rst` only covers 2.0 → 3.0, but `web-interface.rst` already mentions
+ "From PandA v4.0". Are 3.0 → 4.0 (and later) migration notes needed, and who maintains
+ them?
+2. `release_compatibility.rst` stops at rootfs 3.0 / zpkg 3.0. With v4.x and the
+ zpkg → opkg switch, what is the current compatibility matrix?
+3. `commands.rst` shows `*IDN?` returning `SW: 1.1 … rootfs: PandA 1.1`. Is the
+ identification-string format (and the `rootfs:` field introduced in 1.1) unchanged in
+ v4.x?
+
+---
+
+## Session 5 — PandABlocks-server: interface, build & integration
+
+### Paste into a fresh chat
+
+I'm rewriting the documentation for the PandABlocks org. Work through the questions in
+this message **one at a time**: ask a question, wait for my answer, then summarise my
+answer in 2–4 bullet points before moving to the next. When all questions are answered,
+compile every bullet point into a single Markdown knowledge file I can copy into my repo.
+
+**Target documentation architecture (decided):**
+
+- **meta-panda** — the front door and primary home: tutorials, architecture,
+ hardware-target descriptions, web-control UI docs, most user-facing docs, plus
+ developer docs for the Yocto firmware build.
+- **PandABlocks-FPGA** — block- and target-specific docs; build, test, upgrade firmwares.
+- **PandABlocks-server** — the TCP server interface; how to build, test and integrate.
+- **PandABlocks-rootfs** — being archived; still-valid content moves to meta-panda.
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
+
+**This session covers:** the TCP server interface, building/integrating the server,
+data-capture semantics, and config paths — all living in the PandABlocks-server repo.
+Note: the host SDK used to build the server is produced by the meta-panda Yocto build
+(covered in the Firmware build & release session).
+
+**Relevant findings from the gap analysis:**
+
+Duplications:
+- Capture-mode table: the pos_out capture options appear in server `capture.rst`, server
+ `fields.rst` (pos_out `CAPTURE` attribute) and meta-panda `tutorial2`; the three lists
+ don't fully agree.
+
+Gaps:
+- No API reference: github.io `genindex.rst` is an empty placeholder and rootfs
+ `reference.md` toctrees a `genindex` and "APIs" that don't exist. No authored
+ API/interface reference exists anywhere in the current set.
+- Host SDK installer: `pandablocks-sdk.rst` says "the sdk installer is also provided to
+ use it in the host directly" but never says where to get it or how to run it.
+- Streaming tables: server `fields.rst` documents the full `MODE` transition matrix
+ (`<<`, `<<|`) but no page explains when or why a client would use streaming vs fixed
+ tables.
+- Extension server: server `config.rst` and FPGA `block.rst` reference the extension
+ mechanism (`extension_read`/`extension_write`, extension `.py` files), but the only
+ explainer (`extension.rst`) is marked outdated.
+
+**Questions:**
+
+1. server `building.rst` (CONFIG/make standalone build) vs meta-panda `pandablocks-sdk.rst`
+ (Yocto SDK cross-compile): is the standalone build of PandABlocks-server still
+ supported, or is the SDK the only sanctioned path?
+2. `pandablocks-sdk.rst` says "the sdk installer is also provided to use it in the host
+ directly" but gives no instructions. Where is the host installer and what are the steps
+ to use it?
+3. The `CONFIG` example in `pandablocks-sdk.rst` mixes `KERNEL_DIR=...` (no spaces) with
+ `PYTHON = python3` (spaces around `=`). Which syntax does the server Makefile's `CONFIG`
+ actually require?
+4. Capture options disagree across pages: `capture.rst` lists
+ No/Value/Diff/Sum/Mean/Min/Max/Min Max/Min Max Mean; `commands.rst` (`*CAPTURE.OPTIONS?`)
+ lists Value/Diff/Sum/Mean/Min/Max/**StdDev** (no Min Max combos); `fields.rst` lists the
+ Min Max combos but not Sum or StdDev; tutorial2 omits StdDev. What is the authoritative
+ list for current firmware?
+5. `capture.rst` states FRAMED RAW mode sustains ~60 MByte/s "when panda-webcontrol is not
+ installed". Is this figure still accurate for current hardware/firmware?
+6. server `config.rst` says config files load from `/opt/share/panda/config_d` on a PandA.
+ With the move to Yocto/opkg, is that path still correct?
+
+> While you're in this repo, three known gaps also belong here and are worth resolving if
+> you have the information: the missing API/interface reference, a "streaming vs fixed
+> tables" explainer, and the outdated extension-server explainer.
+
+---
+
+## Session 6 — Firmware build & release
+
+### Paste into a fresh chat
+
+I'm rewriting the documentation for the PandABlocks org. Work through the questions in
+this message **one at a time**: ask a question, wait for my answer, then summarise my
+answer in 2–4 bullet points before moving to the next. When all questions are answered,
+compile every bullet point into a single Markdown knowledge file I can copy into my repo.
+
+**Target documentation architecture (decided):**
+
+- **meta-panda** — the front door and primary home: tutorials, architecture,
+ hardware-target descriptions, web-control UI docs, most user-facing docs, plus
+ **developer docs for the Yocto firmware build** (this session's home). It assembles the
+ firmware and ships an offline copy of the docs inside it.
+- **PandABlocks-FPGA** — block- and target-specific docs; build, test, upgrade firmwares.
+- **PandABlocks-server** — the TCP server interface; build, test, integrate.
+- **PandABlocks-rootfs** — being archived; any still-valid content moves to meta-panda
+ (the build has migrated to Yocto).
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
+
+**This session covers:** building the firmware image (Yocto/kas), the release artifacts
+and process, supported hardware targets, and the version scheme. The developer build docs
+live in meta-panda; this session also decides the fate of the rootfs `building.md`.
+
+**Relevant findings from the gap analysis:**
+
+Duplications:
+- `make-release.rst` is byte-identical in github.io and meta-panda (97 w); meta-panda's
+ copy still links to `github.com/PandABlocks/PandABlocks.github.io/releases`.
+- `run-container.rst` is identical in github.io and meta-panda (167 w; same
+ REPO_DIR/VIVADO_DIR/BUILD_DIR volume mounts, same "reistry" typo).
+- Building the image: three overlapping-but-divergent guides — rootfs `building.md`
+ (Diamond rootfs builder + Xilinx SDK + `CONFIG` + zpkg), meta-panda `build.rst`
+ (kas/Yocto) and meta-panda `manual-build.rst` (manual Yocto/bitbake).
+
+Gaps:
+- Supported MACHINE values: build docs mention `pandabox` (default), `xu5-s1`, `xu5-st1`
+ and ZedBoard, but no reference page enumerates the supported targets or their
+ differences. (Hardware-target descriptions are slated for the meta-panda front door.)
+- kas image version ↔ firmware version: `build.rst` sets `KAS_IMAGE_VERSION="4.8"` with no
+ explanation of how this relates to the PandA firmware release a user is trying to build.
+
+**Questions:**
+
+1. rootfs `building.md` describes building via the Diamond rootfs builder + Xilinx SDK +
+ `CONFIG` + zpkg, while meta-panda `build.rst` describes kas/Yocto producing opkg/ipk.
+ Which is the canonical build path for a new user in 2026, and should `building.md` be
+ retired or marked legacy (it lives in the to-be-archived rootfs)?
+2. Release artifacts: github.io `remote.rst` says download `boot-x.x.zip` containing
+ `imagefile.cpio.gz`/`uImage`; meta-panda `remote.rst` says `boot-{MACHINE}.tar.gz`
+ containing `rootfs.squashfs`/`Image`. What is the current release artifact name and
+ format?
+3. meta-panda `make-release.rst` links to
+ `github.com/PandABlocks/PandABlocks.github.io/releases`. Should this point at the
+ meta-panda releases page instead (copy-paste leftover)?
+4. `manual-build.rst` uses Xilinx's internal `gitenterprise.xilinx.com` manifest on branch
+ `rel-v2023.2`. Is that URL reachable by external users; if not, what is the public
+ equivalent, and is `rel-v2023.2` still the target branch in 2026?
+5. Both `make-release.rst` files instruct maintainers to use PEP440 version numbers and
+ GitHub "Generate release notes". Given the firmware version scheme (2.0/3.0/4.0), is
+ PEP440 the intended scheme for meta-panda/firmware releases, or only for the python
+ (github.io) repo?
+
+> While you're here, two known gaps belong in these build docs and are worth capturing if
+> you have the answers: an enumerated reference of supported MACHINE targets and their
+> differences, and an explanation of how `KAS_IMAGE_VERSION` maps to the firmware release.
+
+---
+
+## Session 7 — FPGA repo: blocks, build, test & CI
+
+### Paste into a fresh chat
+
+I'm rewriting the documentation for the PandABlocks org. Work through the questions in
+this message **one at a time**: ask a question, wait for my answer, then summarise my
+answer in 2–4 bullet points before moving to the next. When all questions are answered,
+compile every bullet point into a single Markdown knowledge file I can copy into my repo.
+
+**Target documentation architecture (decided):**
+
+- **meta-panda** — the front door and primary home: tutorials, architecture,
+ hardware-target descriptions, web-control UI docs, most user-facing docs, plus
+ developer docs for the Yocto firmware build.
+- **PandABlocks-FPGA** — block-specific and target-specific docs; how to build, test and
+ upgrade selected firmwares (this session's home).
+- **PandABlocks-server** — the TCP server interface; build, test, integrate.
+- **PandABlocks-rootfs** — being archived; still-valid content moves to meta-panda.
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
+
+**This session covers:** block-specific and target-specific docs, the per-block reference,
+and FPGA testing/CI — all living in the PandABlocks-FPGA repo.
+
+**Relevant findings from the gap analysis:**
+
+Gaps:
+- `block.rst` placeholder sections: "Writing docs" (two RST directives, how to structure),
+ "Block VHDL entity" (how to structure the VHDL entity), and "Tables will be defined here
+ too" / `table` ("Tables are treated specially") are stubs with no content.
+- Per-block reference missing: tutorials and server docs constantly reference PULSE, CLOCK,
+ PCAP, COUNTER, SEQ, TTLOUT, ADDER, V2F, etc., but the only block listing (FPGA
+ `blocks.rst`) is an outdated generated artifact, and the `modules/*/*_doc.rst` files
+ aren't in the inventory. There is no current, authored "what each block does" page.
+- V2F block is referenced (with an external paper link) in tutorial2 but is never defined
+ or documented.
+
+**Questions:**
+
+1. `block.rst` has empty placeholder sections "Writing docs", "Block VHDL entity", and
+ "Tables will be defined here too". Do you have the intended content, or should these be
+ removed?
+2. FPGA `testing.rst` says the Python tests run "as part of the Travis tests". Is CI still
+ Travis (vs GitHub Actions), and is this page current?
+3. FPGA `index.rst` routes block authors to `blocks.rst` (outdated, generated) and
+ `app.rst` (outdated). Are these being regenerated/rewritten, or should the index point
+ somewhere else?
+4. `cocotb.rst` says "Modules using IP are currently unsupported" by the cocotb runner. Is
+ that still true, and does it block testing any production blocks we should flag?
+
+> Related gaps that belong in this repo and are worth resolving if you can: an authored
+> per-block reference ("what each block does", covering PULSE/CLOCK/PCAP/COUNTER/SEQ/etc.),
+> and a definition/doc for the V2F block referenced in tutorial2.
+
+---
+
+## Coverage map
+
+Every Section 3 question and every duplication/gap is assigned to exactly one session.
+
+| Session | Section 3 questions | Section 1 duplications | Section 2 gaps |
+|---|---|---|---|
+| 1 — Architecture & tutorials | 5, 6, 7, 17, 25 | 1, 11, 12, 13, 15 | 1, 6 |
+| 2 — Web-control UI | 9, 15, 16, 24 | — | 4, 5, 10, 11 |
+| 3 — Deploy, upgrade & boot | 2, 8, 10, 27, 29, 31 | 4, 5, 6, 7, 9 | 3, 17, 18 |
+| 4 — Versioning & compatibility | 11, 12, 23 | 14 | — |
+| 5 — Server | 13, 19, 20, 21, 22, 30 | 10 | 7, 12, 13, 14 |
+| 6 — Firmware build & release | 1, 3, 4, 28, 33 | 2, 3, 8 | 15, 16 |
+| 7 — FPGA | 14, 18, 26, 32 | — | 2, 8, 9 |
+
+Q34 is resolved by the agreed architecture and is not asked.
diff --git a/knowledge/03-target-doc-map.md b/knowledge/03-target-doc-map.md
new file mode 100644
index 00000000..bdfa8d6e
--- /dev/null
+++ b/knowledge/03-target-doc-map.md
@@ -0,0 +1,169 @@
+# PandABlocks Docs — Target Map (v4)
+
+Target structure after the rewrite. Merges inventory (01) + interviews (04-1…7) + issue #6,
+with decisions D1–D10 and review items R1–R5 applied.
+
+**Conventions**
+- How-to titles/slugs use **imperative verb form** (e.g. *monitor*, not *monitoring*).
+- Each repo's contribution doc lives at **`.github/CONTRIBUTING.md`**, *included* into `how-to/contribute`.
+- Whole set converts **RST → MyST Markdown**; per-block `*_doc.rst` convert **in place under their module**.
+- **Cross-repo links via mystmd xref:** meta-panda, FPGA, server and the new devcontainer repo are
+ mystmd projects linked by xref (already planned). `PandABlocks-client` and `fastcs-PandABlocks`
+ stay Sphinx this round and are reachable via intersphinx.
+- Terminology: **"PandA Web Control"** only; never `malcolm`/`pymalcolm`/MalcolmJS in docs.
+
+**Legend** — Disposition: `keep`/`rewrite`/`new`/`move`/`convert`/`delete`/`redirect`/`archive`.
+Status: `writable-now` · `blocked: capture` · `blocked: verify` · `blocked: author` · `blocked: tooling`.
+
+---
+
+## meta-panda — canonical front door (top-level Diátaxis)
+
+### Top-level
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `README.md` | What meta-panda is/publishes, fit in PandABlocks, pointers | new | Interview1 §5 | writable-now |
+| `index.md` | Includes README + generates 4-quadrant TOC | rewrite | meta-panda `index.rst` | writable-now |
+| `.github/CONTRIBUTING.md` | Contribution process; included into `how-to/contribute` | new | Interview1 §5 | writable-now |
+
+### Tutorials
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `tutorials/tutorial0_connecting_to_web_control` | Connect to PandA Web Control at PandA IP:80, select root block, make a link; new users | move+rewrite | web-control `quick-start` | writable-now (reuse screenshots) |
+| `tutorials/tutorial1_blinking_leds` | Wire PULSE+CLOCK to blink LEDs; new users | rewrite | meta-panda t1 | writable-now |
+| `tutorials/tutorial2_position_capture` | PCAP capture modes; new users. Keep "next tutorial" promise | rewrite | meta-panda t2 | writable-now |
+| `tutorials/tutorial3_position_compare` | Position compare/trigger pulses; new users | new | human screenshots+bullets → AI | blocked: capture |
+| `tutorials/tutorial4_snake_scan` | SEQ table 2D snake scan; new users | new | human screenshots+bullets → AI | blocked: capture |
+
+### How-to
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `how-to/quickstart` — "How to get a PandA on the network" | First network setup; operators. Fix `boot.txt`→`config.txt`; add `panda-config.txt` USB override | rewrite (merge) | meta-panda + rootfs quickstart | writable-now |
+| `how-to/build` — "How to build the PandA image" | kas/Yocto build (canonical); devs. Absorbs KAS-container usage + `KAS_IMAGE_VERSION` explanation | rewrite (merge) | meta-panda `build.rst` + `run-container` (KAS part) | writable-now; KAS_IMAGE_VERSION = blocked: verify |
+| `how-to/manual-build` | Manual Yocto/bitbake; devs. Fix manifest URL → `github.com/Xilinx/yocto-manifests`, branch `rel-v2023.2` | move+rewrite | meta-panda `tutorials/manual-build` | writable-now (branch bump post-5.0: verify) |
+| `how-to/make-release` | Cut a firmware release; maintainers. Fix releases link → meta-panda | rewrite (de-dupe) | meta-panda `make-release` | writable-now |
+| `how-to/packages` | Install IPK/opkg via USB or SSH; admins | rewrite | meta-panda `packages.rst` | writable-now |
+| `how-to/upgrade-via-ssh` — "Upgrading a PandA over SSH" | Admins. Covers pre-5.0→5.x AND post-5.0; opkg-based; keep 24V FMC EEPROM (DLS-only, one-time) | rewrite | meta-panda `remote.rst` | writable-now; gap audit = blocked: verify |
+| `how-to/upgrade-via-web-admin` — "Upgrading a PandA via the web admin interface" | Operators. + legacy pre-5.0 zpg path + fresh-SD-card install | rewrite | meta-panda `web-interface.rst` | partial; legacy zpg filename = blocked: verify |
+| `how-to/use-web-control-to-set-up-a-panda` | Build/edit a design in Web Control: add/remove blocks, link, edit attributes (View/Edit, Dropdown, Text Input, Checkbox widgets); users | move+rewrite (folds attribute-widgets) | web-control `working_with_a_design` | writable-now (reuse screenshots); 4 missing widget screenshots + trailing sentence = blocked: capture |
+| `how-to/save-restore-design` | Save/restore designs via Web Control; users | split | web-control `working_with_a_design` | writable-now (reuse screenshots) |
+| `how-to/monitor-attribute-values` | View attribute values as live charts/tables; users | move+rewrite | web-control `monitoring_attribute_values` | writable-now (reuse screenshots) |
+| `how-to/integrate-with-a-panda` (R1/R4) | Control a PandA programmatically: direct to TCP server, via the Python client (`PandABlocks-client`), or from EPICS/Tango (`fastcs-PandABlocks`). Covers **getting captured data out** (binary → HDF5/numpy); integrators/devs | new | Interview5; client + fastcs repos | writable-now (skeleton + links) |
+| `how-to/test-firmware-changes` | devtool/kas → deploy → manual test, + FPGA override; devs | new | Interview5 §1–2 | writable-now |
+| `how-to/choose-fpga-bitstream` | `APP` var in config.txt; scp→opkg install→systemctl restart; devs | new | Interview5 §10; Interview3 §4 | writable-now |
+| `how-to/contribute` | Doc-authoring conventions (Diátaxis, markup, draft→AI-expand) + includes `.github/CONTRIBUTING.md`; absorbs github.io `update-tools`/`contribute`. Documents the xref/intersphinx link setup; contributors | new | Interview1 §4; github.io tooling | writable-now |
+
+### Reference
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `reference/opkg` | opkg command quick-ref; admins | keep (→MyST) | meta-panda `opkg.rst` | writable-now |
+| `reference/changes` | Breaking changes + migration per major bump, compat matrix embedded per section; admins/devs | new (consolidate) | github.io `migration_guide` + `release_compatibility` | writable-now; 3.0→4.0 = blocked: verify |
+| `reference/machine-targets` | MACHINE values table (pandabox/xu5-s1/xu5-st1/zedboard) + links to hardware descriptions | new | Interview6 §A | partial; PandABrick = blocked: verify |
+| `reference/glossary` | **Canonical** glossary (web-control + FPGA terms merged); all users | new (merge) | web-control + FPGA glossaries | writable-now |
+| `reference/troubleshooting` (R2) | FAQ/troubleshooting: can't-connect, boot failures, "more than one FPGA image satisfied" error, upgrade failures; operators/admins | new | meta-panda `quickstart.rst` "Frequently Asked Questions" section (seed) | writable-now (seed); some entries = blocked: verify |
+
+### Explanation
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `explanations/boot-process` | FIT image + rootfs.squashfs boot (canonical); devs | keep (→MyST) | meta-panda `boot-process.rst` | writable-now |
+| `explanations/architecture` | How repos/firmware fit together; **points out integration options** (TCP / Python client / EPICS+Tango); all audiences | new | Interview1; cross-session pointers; client + fastcs repos | writable-now (skeleton); detail deferrable |
+| `explanations/hardware-targets` | Per-target hardware (SoC/module, features); integrators | new | Interview6 §A | blocked: author |
+| `explanations/decisions/*` | ADRs migrated from github.io | move | github.io ADRs 0001/0002 | writable-now |
+| `explanations/web-control-ui-overview` | Tour of the four UI panels, Layout/Attribute views; users | move+rewrite | web-control `user_interface_overview` | writable-now (reuse screenshots) |
+| `explanations/understanding-attribute-state` | What Processing/Update Error/Disconnected mean; users. **Recreate the 3 state icons** (material-ui glyphs, colours per source spec); no malcolm reference in docs | move+rewrite | web-control `understanding_attribute_state`; icon colours from DiamondLightSource/malcolmjs `attributeAlarm.component.js` | writable-now (Claude clones malcolmjs + recreates icons at execution) |
+
+*Removed/absorbed:* duplicate `webcontrol/index`,`webcontrol/userguide/index`,`webcontrol/contents`,`webcontrol/userguide/contents`. `how-to/run-container` removed (KAS part → `how-to/build`; dev-container part → new PandABlocks-devcontainer repo).
+
+---
+
+## PandABlocks-devcontainer — NEW repo (standardised local dev)
+
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `README.md` + `index` | What the devcontainer is; how to use it for local dev; devs | new | Interview5 §1; meta-panda `run-container` (non-KAS part) | writable-now |
+| `how-to/local-development` | Pull/run the devcontainer for build/test/doc; referenced by FPGA + server. Fix "reistry" typo | move+rewrite | meta-panda `run-container` | writable-now |
+
+---
+
+## PandABlocks-FPGA — block/target/CI docs
+
+| Quadrant | Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|---|
+| — | `README.md` + `index` + `.github/CONTRIBUTING.md` | Module intro + 4-quadrant TOC + contribution doc | new/rewrite | Interview1 §5; FPGA `index.rst` | writable-now |
+| Reference | `reference/blocks` | Autogenerated block listing; devs. Regenerate to consume md module docs | keep (regen) | FPGA `blocks.rst` | blocked: tooling (MyST gen) |
+| Reference | `modules/*/*_doc.md` (×42) | Per-block docs (PULSE/CLOCK/PCAP/SEQ/COUNTER/LUT/…); live **under their module**; devs/users | convert (in place) | 42 `modules/*/*_doc.rst` | writable-now (mechanical RST→MD) |
+| Reference | `reference/glossary` | Link to meta-panda canonical glossary | merge | FPGA `glossary.rst` | writable-now |
+| Reference | `reference/vhdl-standard` | VHDL style standard; contributors | new | Interview1 §4 | blocked: author |
+| How-to | `how-to/app` | Assemble blocks into an app (ini, build, query); app devs | rewrite (outdated) | FPGA `app.rst` | writable-now (verify runtime steps) |
+| How-to | `how-to/block` | Writing a block; FPGA devs. Fill "Block VHDL entity" (LUT example); drop tables stub; defer "Writing docs" until MyST. **Not split** | rewrite | FPGA `block.rst` | partial; "Writing docs" = blocked: tooling |
+| How-to | `how-to/testing` | Run test suites; devs. Travis → GitHub Actions (sim) + DLS GitLab (build) | rewrite | FPGA `testing.rst` | blocked: verify (maintainer) |
+| How-to | `how-to/cocotb` | cocotb timing tests; devs. Keep "modules using IP unsupported" | rewrite | FPGA `cocotb.rst` | writable-now; IP assumption = blocked: verify |
+| How-to | `how-to/build-fpga-image` | Build an FPGA image → .ipk → pointer to choose-bitstream (meta-panda); devs | new | Interview5 §10 | writable-now |
+| How-to | `how-to/finedelay-test` | Fine-delay LVDSOUT test; hardware engineers | move | github.io `finedelay-test` (current) | writable-now |
+| How-to | `how-to/local-development` | Pointer to PandABlocks-devcontainer; devs | new (link) | devcontainer repo | writable-now |
+| How-to | `how-to/contribute` | Includes `.github/CONTRIBUTING.md`; contributors | rewrite | FPGA `contributing.rst` | writable-now |
+| Explanation | `explanations/framework` | Autogeneration framework architecture; core devs | move+rewrite | FPGA `framework.rst` (outdated) | partial; needs refresh |
+
+*Glossary:* FPGA `glossary.rst` merges into meta-panda canonical glossary; FPGA links to it.
+
+---
+
+## PandABlocks-server — TCP interface
+
+| Quadrant | Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|---|
+| — | `README.md` + `index` + `.github/CONTRIBUTING.md` | Module intro + 4-quadrant TOC + contribution doc | new/rewrite | Interview1 §5; server `index.rst` | writable-now |
+| Reference | `reference/commands` | ASCII command interface (spine of TCP ref); client devs. Includes `*IDN?` (unchanged v4.x; rootfs: field) | rewrite | server `commands.rst` | writable-now |
+| Reference | `reference/fields` | Field types/attributes; client devs. Point to streaming-tables; keep MODE matrix | rewrite | server `fields.rst` | writable-now |
+| Reference | `reference/capture` | Data-capture protocol/wire format; client devs. Keep ~60 MB/s + webcontrol caveat. **Link to meta-panda `how-to/integrate-with-a-panda`** for getting data out (R4) | rewrite | server `capture.rst` | writable-now (60MB/s = verify) |
+| Reference | `reference/capture-options` | Canonical superset of capture options + "run `*CAPTURE.OPTIONS?` live" note | new | Interview5 §4 | partial; superset = blocked: verify |
+| Reference | `reference/config` | config/registers/description files; firmware devs. config_d path OK | rewrite | server `config.rst` | writable-now |
+| Reference | `reference/extension` | Extension server; extension devs | rewrite | server `extension.rst` (outdated) | blocked: verify |
+| Reference | `reference/streaming-tables` | `<<`/`<<|` streaming for DMA tables, buffer sizes; client devs | new | Interview5 §8 | writable-now |
+| Reference | `reference/support` | Supporting tools/LEDs; operators | rewrite | server `support.rst` | writable-now |
+| Reference | `reference/c-standard` | C style standard; contributors | new | Interview1 §4 | blocked: author |
+| Explanation | `explanations/architecture` | How the server is structured internally (TCP/config/data threads, block model); core devs | new | server code + docs | writable-now (skeleton); depth = blocked: author |
+| How-to | `how-to/startup` | CLI args to start server; admins | rewrite | server `startup.rst` | writable-now |
+| How-to | `how-to/building` | Build/test server (native sim-mode; make+gcc); devs. Point to PandABlocks-devcontainer for local dev | rewrite | server `building.rst` | writable-now; CONFIG syntax = blocked: verify |
+| How-to | `how-to/contribute` | Includes `.github/CONTRIBUTING.md`; contributors | new | — | writable-now |
+
+*Removed:* SDK cross-compile path (`pandablocks-sdk.rst` + "sdk installer in host" line) → replaced by meta-panda `how-to/test-firmware-changes`. `presentation-2016-05/*` → drop. `genindex` placeholders → drop.
+
+---
+
+## PandABlocks-rootfs — ARCHIVE
+| Action | Detail |
+|---|---|
+| Disable Pages | Stop publishing rootfs docs |
+| Migrate out | boot-process (done), quickstart (→ meta-panda merge), valid bits only |
+| Retire | `building.md` (whole build guide), zpkg content |
+| Fix dangling refs | Remove `how-to/remote.md` toctree entries in `index.md`/`how-to.md` |
+| Keep | `README` pointing to meta-panda |
+
+## PandABlocks.github.io — REDIRECT
+| Action | Detail |
+|---|---|
+| Catch-all redirect | `pandablocks.github.io/` → `meta-panda/main/index.html` (single redirect) |
+| Delete (migrated) | tutorials 1–4, `make-release`, `run-container`, `remote`, `web-interface`, `migration_guide`, `release_compatibility`, `standards`, `genindex` |
+| Migrate first | ADRs `decisions/*` → meta-panda; `finedelay-test` → FPGA; `update-tools`/`contribute` → meta-panda `how-to/contribute` |
+
+---
+
+## Review items R1–R5 (resolved)
+- **R1** Integration/client pointers → `how-to/integrate-with-a-panda` (TCP / Python client / EPICS+Tango via `fastcs-PandABlocks`, **not** the archived `PandABlocks-ioc`); linked from `explanations/architecture`.
+- **R2** Troubleshooting → `reference/troubleshooting`, seeded from the quickstart FAQ.
+- **R3** Cross-repo links → mystmd xref across the 3 core repos + devcontainer (already planned); `PandABlocks-client`/`fastcs-PandABlocks` reachable via intersphinx this round.
+- **R4** Getting data out → folded into R1; cross-linked from server `reference/capture`.
+- **R5** Versioned docs / version switcher → **GitHub issue** (infrastructure; not authored this round).
+
+---
+
+## Issue backlog (for GitHub issues, scoped ~few hours each)
+
+**Human-capture:** Tutorial 3 screenshots+bullets · Tutorial 4 screenshots+bullets · web-control widget screenshots (View/Edit, Dropdown, Text Input, Checkbox) + finish trailing sentence.
+
+**Verify-then-write:** 3.0→4.0 breaking changes · capture-options superset · extension server vs implementation · `*IDN?` v4.x · 60 MB/s figure · cocotb IP assumption · CONFIG syntax · PandABrick target · `KAS_IMAGE_VERSION` mapping · legacy updater zpg filename · testing.rst CI · Xilinx branch bump post-5.0.
+
+**Author-from-scratch:** VHDL standard · C standard · hardware-target descriptions · server architecture (depth).
+
+**Infrastructure:** versioned docs / version switcher (R5).
diff --git a/knowledge/04-interview-1-architecture.md b/knowledge/04-interview-1-architecture.md
new file mode 100644
index 00000000..adc9c0c7
--- /dev/null
+++ b/knowledge/04-interview-1-architecture.md
@@ -0,0 +1,95 @@
+# PandABlocks Documentation — Session Decisions
+
+This file records the decisions made while rewriting the PandABlocks org documentation.
+Scope of this session: front-door/landing structure, where tutorials live, cross-repo
+duplication cleanup, contribution/standards pages, and navigation stubs.
+
+---
+
+## Target documentation architecture (decided previously, for context)
+
+- **meta-panda** — the front door and primary home: tutorials, architecture,
+ hardware-target descriptions, web-control UI docs, most user-facing docs, plus
+ developer docs for the Yocto firmware build. Assembles the firmware and ships an
+ offline copy of the docs, so it holds the majority.
+- **PandABlocks-FPGA** — block-specific and target-specific docs; how to build, test and
+ upgrade selected firmwares.
+- **PandABlocks-server** — the TCP server interface; how to build, test and integrate.
+- **PandABlocks-rootfs** — being archived; still-valid content moves to meta-panda (build
+ has migrated to Yocto).
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
+
+---
+
+## 1. Tutorials 1–4 — duplication across three repos
+
+- **Delete the FPGA and github.io copies outright.** No per-page cross-links or redirect
+ stubs left behind in those repos.
+- **meta-panda is the single canonical home** for the tutorials — exactly one home per
+ piece of content, no duplicate-and-link arrangements.
+- **The only redirect needed is one catch-all** from `pandablocks.github.io/` →
+ `meta-panda/main/index.html`; github.io's tutorial copies retire under that catch-all
+ rather than getting individual redirects.
+
+## 2. Tutorials 3 (position compare) and 4 (snake scan)
+
+- **Will be written** as part of this documentation task — genuinely planned, not removed.
+- **Authoring workflow:** human-generated raw material (screenshots and bullet points)
+ first, then AI-expanded into full prose.
+- **Hosted in meta-panda** alongside Tutorials 1 & 2; since real content is coming,
+ **Tutorial 2's "in the next tutorial" promise stays valid** (no need to edit it out).
+
+## 3. meta-panda structure & web-control duplication
+
+- **meta-panda is organised top-level by Diátaxis** — the four quadrants (tutorials,
+ how-to, reference, explanation) as the primary division of the whole repo.
+- **Confirmed contents include:** the tutorials (1–4), plus how-to guides for upgrading
+ the firmware and for saving/restoring designs via the web UI.
+- **The identical duplicates collapse to one** — consistent with the single-canonical-home
+ principle; the survivor is resolved by the restructure rather than kept in two places.
+- **OPEN DECISION — web-control "user guide" (reference-style) placement:** either
+ (a) break it up and scatter the pieces across the four quadrants, or (b) keep it together
+ in the reference section with selected sections extracted as how-to guides. Not yet
+ settled.
+
+## 4. Standards pages
+
+- **Code Standards split by repo, not centralised:** FPGA gets a VHDL style standard,
+ Server gets a C style standard — each lives in its own repo, not in a shared page.
+- **Documentation Standards live in meta-panda** (doc-authoring conventions — e.g.
+ Diátaxis adherence, markup conventions, the human-draft-then-AI-expand workflow).
+- **All three are unwritten and need authoring**; the old github.io `standards.rst` is
+ superseded and retires under the catch-all redirect rather than being migrated.
+
+## 5. Landing page & README strategy
+
+- **Every repo gets a top-level `README.md`** introducing the module: what it is, what it
+ publishes, how it fits into PandABlocks as a whole, and a pointer back to both its own
+ published docs and meta-panda.
+- **`index.md` includes that `README.md` *and* generates the four-quadrant TOC** —
+ README-plus-quadrants, not a from-scratch landing page that discards the README.
+- **README and landing page stay in sync by construction** — the landing page embeds the
+ README rather than duplicating it.
+- **Format migration:** the entire doc set converts from Sphinx RST to MyST Markdown
+ (mystmd) as part of this task.
+
+---
+
+## Derived action list (content to write / changes to make)
+
+- [ ] Delete Tutorials 1–4 from PandABlocks-FPGA and PandABlocks.github.io.
+- [ ] Add catch-all redirect `pandablocks.github.io/` → `meta-panda/main/index.html`.
+- [ ] Write Tutorial 3 (position compare) and Tutorial 4 (snake scan) in meta-panda
+ (human screenshots + bullets → AI expansion).
+- [ ] Restructure meta-panda top-level into the four Diátaxis quadrants.
+- [ ] Author how-to guides: upgrading firmware; saving/restoring designs via web UI.
+- [ ] Collapse the duplicate `webcontrol/index` + `webcontrol/userguide/index` and the two
+ `contents` files down to one each.
+- [ ] **Decide** web-control user-guide placement (scatter vs keep-in-reference).
+- [ ] Write VHDL code standard in PandABlocks-FPGA.
+- [ ] Write C code standard in PandABlocks-server.
+- [ ] Write Documentation Standards in meta-panda.
+- [ ] Add a top-level `README.md` to every repo (module intro, what it publishes, fit
+ within PandABlocks, pointers to its own docs + meta-panda).
+- [ ] Make each `index.md` include its `README.md` and generate the four-quadrant TOC.
+- [ ] Convert the whole doc set from Sphinx RST to MyST Markdown.
diff --git a/knowledge/04-interview-2-web-control-docs-decisions.md b/knowledge/04-interview-2-web-control-docs-decisions.md
new file mode 100644
index 00000000..402e798b
--- /dev/null
+++ b/knowledge/04-interview-2-web-control-docs-decisions.md
@@ -0,0 +1,64 @@
+# Web-Control / GUI Documentation — Decisions
+
+Destination: **meta-panda** (web-control / GUI docs).
+Scope: decisions captured for resolving the gaps found in the gap analysis of the
+web-control documentation extracted from the legacy MalcolmJS docs.
+
+---
+
+## 1. GUI URL and port
+
+- The correct address is the **PandA's own IP or hostname on port 80** (as in
+ `quickstart.rst` / `web-interface.rst`); that is what a real deployed user should type.
+- The `http://{malcolm host}/gui/` form with `localhost:3000` is a **MalcolmJS dev-docs
+ artifact** — it came from testing against a localhost deployment.
+- That localhost / `:3000` form should **never appear in the user-facing docs**; it is
+ purely a development detail.
+
+## 2. Attribute-state icons (`understanding_attribute_state.rst`)
+
+- The icon assets and the missing "table above" are **not worth chasing** — this is
+ low-value content.
+- Resolution: **describe the three states in text** (Processing, Update Error,
+ Disconnected) rather than sourcing or recreating icon images.
+- Take the **simplest approach** — drop the `*GET IMAGE*` placeholders and the
+ "table above" reference entirely, replacing them with brief text descriptions of what
+ each state means.
+- The text will describe each state **functionally** (what it signifies to the user)
+ rather than the literal glyph, since the source images are unavailable.
+
+## 3. Design-page screenshots and unfinished sentence (`working_with_a_design.rst`)
+
+- The screenshots (View/Edit, Dropdown List, Text Input, Checkbox) should come from a
+ **live GUI** — not text descriptions like the icons.
+- Capturing them is a **human task**, flagged for someone with a running PandA to grab;
+ each `*GET SCREENSHOT*` / `*GET SCREENHOST*` spot is marked as a **TODO** rather than
+ resolved now.
+- The unfinished Text Input sentence ("shown in the .") almost certainly trailed off into
+ a reference to that missing screenshot (e.g. "…shown in the screenshot below"), so it is
+ **folded into the same human task** — the wording gets finished once the screenshot
+ exists.
+
+## 4. Naming / terminology
+
+- **PandA Web Control** is technically a **pymalcolm backend + MalcolmJS frontend**, but
+ that stack is an **implementation detail only**.
+- The stack is **stable but no longer used outside PandA**, and is slated for replacement
+ in the medium term — so for now only **minimal changes for consistency** are wanted, not
+ a rewrite.
+- meta-panda docs must **never mention** `malcolm`, `pymalcolm`, or MalcolmJS.
+- Standardise on **"PandA Web Control"** as the one correct term throughout.
+
+---
+
+## Action items / human tasks
+
+- [ ] **Human task:** on a running PandA, capture live-GUI screenshots for
+ `working_with_a_design.rst`: View/Edit, Dropdown List, Text Input, Checkbox.
+- [ ] **Human task:** once the Text Input screenshot exists, finish the trailing
+ "shown in the ." sentence to reference it.
+- [ ] Replace `understanding_attribute_state.rst` `*GET IMAGE*` placeholders + "table
+ above" reference with short functional text for Processing, Update Error, Disconnected.
+- [ ] Fix all GUI-address references to the PandA IP/hostname on port 80; remove every
+ `localhost:3000` / `/gui/` dev artifact.
+- [ ] Replace all `malcolm` / `pymalcolm` / MalcolmJS references with "PandA Web Control".
diff --git a/knowledge/04-interview-3-deploy-upgrade-boot.md b/knowledge/04-interview-3-deploy-upgrade-boot.md
new file mode 100644
index 00000000..03421c63
--- /dev/null
+++ b/knowledge/04-interview-3-deploy-upgrade-boot.md
@@ -0,0 +1,91 @@
+# PandABlocks Docs — Session 3: Deploy, Upgrade & Boot
+
+Knowledge captured for the documentation rewrite. Decisions below reflect the
+target architecture in which **meta-panda is the canonical home**, **PandABlocks-rootfs
+is being archived** (valid content migrating to meta-panda), and the build has moved to
+Yocto.
+
+---
+
+## 1. Package tooling (zpkg → opkg)
+
+- Current firmware uses **opkg / `.ipk`**. **zpkg / `.zpg` is legacy (pre-5.0).** The
+ cutover happened at **release 5.0**.
+- **Pre-5.0:** PandABlocks-rootfs built the rootfs from `.zpg` files supplied by the
+ other repos.
+- **5.0 onward:** meta-panda builds the Yocto rootfs, incorporating `.ipk` packages from
+ all the other repos.
+- **PandABlocks-FPGA and PandABlocks-server can still build standalone `.ipk` packages**
+ that load into an existing Yocto rootfs — **for testing purposes only**, not the normal
+ install path. Artifact naming changed at the same time as the tooling.
+
+## 2. Network configuration file
+
+- **`config.txt` is the correct network-config file** and lives on the **SD card**. The
+ `quickstart.rst` FAQ's `boot.txt` is wrong and must be corrected to `config.txt`.
+- **`panda-config.txt` is a separate file, not an alias.** Placed on a **USB stick** it
+ acts as an **override** that is picked up at boot and takes precedence over the SD-card
+ `config.txt`.
+
+## 3. SSH update guide
+
+- **Canonical home: meta-panda.** Base it on the **opkg/`.ipk` `remote.rst`** (not the
+ legacy github.io zpkg version). Remove the dangling `how-to/remote.md` toctree
+ references from the archived rootfs docs.
+- **The guide must cover two upgrade cases:**
+ 1. **pre-5.0 → 5.x** (the zpkg → Yocto/opkg transition)
+ 2. **post-5.0** (Yocto → Yocto)
+- **Open task:** audit the `.ipk` `remote.rst` for content gaps — it's the correct
+ starting point but may be incomplete.
+
+## 4. 24V FMC EEPROM & FPGA bitstream selection
+
+- **24V FMC EEPROM population is still required post-3.0** (v4.x and v5.x) and must stay
+ in the update guide.
+- It is a **one-time migration** that writes metadata into the EEPROM **permanently** —
+ not per-install or per-upgrade.
+- It applies **only to the 24V FMC**, a physical FMC card **produced by DLS and not used
+ outside DLS**. Scope it clearly as DLS-specific; most users can ignore it.
+- **Each PandABlocks-FPGA `.ipk` ships an FPGA bitstream and declares a required FMC**,
+ validated by checking selected EEPROM values. This is what links EEPROM population to
+ firmware selection.
+- **meta-panda selects the correct FPGA image by:**
+ 1. honouring the **`APP` variable in `config.txt`** if set;
+ 2. if unset, **auto-selecting the FPGA image whose FMC requirements are satisfied** per
+ the EEPROM check;
+ 3. **erroring if more than one image** would be satisfied.
+
+## 5. Boot process
+
+- The **`imagefile.cpio.gz` / SD-card repartitioning flow is superseded.** Retire the
+ rootfs `building.md` "Boot Process" section along with the rest of the archived rootfs
+ docs.
+- **meta-panda's `boot-process.rst` (FIT image + `rootfs.squashfs`) is the canonical,
+ correct boot description.**
+
+## 6. Upgrade paths
+
+- **Two pre-5.0 upgrade paths exist:**
+ 1. **Over SSH** — covered by the SSH update guide (see §3).
+ 2. **Web-admin** — load a **legacy updater zpg** (filename TBC) from a **USB stick**.
+- **Fresh SD card install** is the standard approach for a **blank PandA**, and the
+ fallback route when an in-place upgrade isn't viable.
+
+---
+
+## Cross-cutting documentation actions
+
+- **meta-panda is canonical** for: the SSH update guide, the boot-process explanation, and
+ the upgrade how-tos (absorbing the archived rootfs material).
+- **Retire / remove from the archived rootfs docs:** the `building.md` "Boot Process"
+ section, and the dangling `how-to/remote.md` toctree entries in `index.md` / `how-to.md`.
+- **Fix the quickstart FAQ:** `boot.txt` → `config.txt`.
+- **Treat github.io's zpkg-based `remote.rst` / `web-interface.rst` as legacy reference
+ only.** Canonical procedures use opkg / `.ipk`.
+
+## Open tasks / TBC
+
+- [ ] Audit the opkg/`.ipk` `remote.rst` for content gaps.
+- [ ] Confirm the **legacy updater zpg filename** used by the web-admin pre-5.0 path.
+- [ ] Document the **legacy web-admin upgrade path** and the **fresh SD card install** in
+ meta-panda.
diff --git a/knowledge/04-interview-4-versioning-compatibility.md b/knowledge/04-interview-4-versioning-compatibility.md
new file mode 100644
index 00000000..9f15ea0e
--- /dev/null
+++ b/knowledge/04-interview-4-versioning-compatibility.md
@@ -0,0 +1,52 @@
+# Session 4 — Versioning & Compatibility
+
+Reference notes for the PandABlocks documentation rewrite. This session covers which
+releases go together, migration between releases, and the device identification string.
+This is cross-cutting material spanning **meta-panda** (compatibility/migration) and
+**PandABlocks-server** (the `*IDN?` string).
+
+---
+
+## 1. Migration notes (`reference/changes.md`)
+
+- Migration material consolidates into a single **`reference/changes.md`** in meta-panda,
+ replacing per-version migration guide files (retires the github.io `migration_guide.rst`).
+- This file documents **breaking changes and migration steps for every major version bump**
+ (e.g. 2.0 → 3.0, 3.0 → 4.0, and onward).
+- meta-panda owns this as cross-cutting reference material.
+- **Open action:** no breaking changes are recalled for 3.0 → 4.0, but this **needs
+ verifying** before the file is considered complete.
+
+---
+
+## 2. Compatibility matrix
+
+- **Pre-5.0:** the existing compatibility rule holds — you must keep the **same major
+ version number across rootfs and all zpkg files**. This matrix should be embedded
+ **within each relevant section of `reference/changes.md`** rather than as a standalone
+ file (retires the github.io `release_compatibility.rst`).
+- **Post-5.0:** the model changes to a **single unified firmware image** to load, removing
+ the multi-component version-matching problem for the common case.
+- **FPGA / rootfs compatibility (resolved):** compatibility is defined as **"matching major
+ version number between FPGA and meta-panda guarantees compatibility"**, and **both major
+ numbers bump together on a Vivado version change** (motivating the move toward a
+ Vivado-based scheme, e.g. `v2026.2`).
+- **Server:** **no longer listed in the compatibility table**, because it is compiled as
+ part of the Yocto rootfs.
+
+---
+
+## 3. The `*IDN?` identification string
+
+- The **`*IDN?` string format is unchanged in v4.x and beyond.**
+- The **`rootfs:` field still exists and correctly reports the rootfs version** (unchanged
+ meaning from its 1.1 introduction).
+- Authoritative description stays in **PandABlocks-server** docs (server-interface
+ reference); meta-panda links to it rather than duplicating.
+
+---
+
+## Outstanding actions
+
+- [ ] Verify whether there were any breaking changes between 3.0 and 4.0; populate the
+ 3.0 → 4.0 section of `reference/changes.md` accordingly.
diff --git a/knowledge/04-interview-5-server-knowledge.md b/knowledge/04-interview-5-server-knowledge.md
new file mode 100644
index 00000000..7b9b6573
--- /dev/null
+++ b/knowledge/04-interview-5-server-knowledge.md
@@ -0,0 +1,156 @@
+# PandABlocks-server — Documentation Knowledge File (Session 5)
+
+**Scope:** TCP server interface, building/integrating the server, data-capture
+semantics, and config paths — all living in the **PandABlocks-server** repo, plus
+related cross-repo docs that surfaced during the interview.
+
+> Note: the SDK cross-compile path discussed in the old docs is being **removed**
+> (see below), so several "decided" items below supersede current docs rather than
+> describing them.
+
+---
+
+## 1. Building & testing the server
+
+**Canonical workflow (largely not yet reflected in current docs):**
+
+- **Standalone build = simulation-mode testing only.** Server changes are tested
+ natively in **simulation mode** (docs live in the server repo). Requirements are
+ only `make` and `gcc`; native build, no cross-compile.
+- A forthcoming **`PandABlocks-devcontainer` image** will standardise this
+ build/test/doc flow, with the **same flow mirrored in the FPGA repo**.
+- **Live-system builds go through Yocto `devtool`**, which builds inside the **`kas`
+ container** and deploys to a PandA for **manual testing**.
+- **The SDK cross-compile path is being removed** — it is non-standard and not
+ currently used anywhere. `pandablocks-sdk.rst`'s SDK workflow should be **retired**.
+
+**Disposition of `pandablocks-sdk.rst`:**
+
+- **Delete the SDK / host-installer content** (including the unexplained
+ "the sdk installer is also provided to use it in the host directly" line — it goes
+ with the rest).
+- **Replace it with a new meta-panda doc: "How to test firmware changes on a PandA."**
+- That new doc covers:
+ - the **`devtool` flow** (build in `kas` container → deploy to a PandA for manual
+ testing), and
+ - the **FPGA override mechanism** (captured below).
+
+---
+
+## 2. FPGA override mechanism (context captured for the new meta-panda doc)
+
+- Each **PandABlocks-FPGA `.ipk` ships an FPGA bitstream and declares a required FMC**,
+ validated by checking selected **EEPROM** values. This links EEPROM population to
+ firmware selection.
+- meta-panda selects the correct FPGA image by:
+ 1. honouring the **`APP` variable in `config.txt`** if set;
+ 2. if unset, **auto-selecting the FPGA image whose FMC requirements are satisfied**
+ per the EEPROM check;
+ 3. **erroring if more than one image** would be satisfied.
+
+---
+
+## 3. `CONFIG` file syntax (server Makefile)
+
+- **Both syntaxes are believed to be supported** by the server Makefile's `CONFIG`
+ (no-spaces `KERNEL_DIR=...` and spaced `PYTHON = python3`), since `CONFIG` is read
+ as a Makefile include.
+- **OPEN QUESTION — verify** against the actual Makefile before documenting.
+- **No canonical `CONFIG` example finalised yet** — pending the syntax check.
+
+---
+
+## 4. Capture options (`*CAPTURE.OPTIONS?`)
+
+**Disagreement across pages resolved as follows:**
+
+- **Authoritative list = the superset of all four sources:**
+ `No / Value / Diff / Sum / Mean / Min / Max / Min Max / Min Max Mean / StdDev`.
+- **One canonical doc fully expands and defines each option** (the explainer page —
+ exact filename **TBC**), and **all other pages reference it** rather than re-listing.
+- That canonical doc carries a **note to run `*CAPTURE.OPTIONS?` on the live TCP
+ server** to see which options the **current firmware/FPGA bitstream combination**
+ actually supports.
+
+Sources reconciled: `capture.rst`, `commands.rst` (`*CAPTURE.OPTIONS?`),
+`fields.rst`, and meta-panda `tutorial2`.
+
+---
+
+## 5. Data-capture throughput (FRAMED RAW)
+
+- The **~60 MByte/s** FRAMED RAW figure is **still accurate** for current
+ hardware/firmware — retain as stated in `capture.rst`.
+- **Keep the "when panda-webcontrol is not installed" caveat** — webcontrol
+ contention remains the relevant limiting factor.
+
+---
+
+## 6. Config file paths
+
+- **`/opt/share/panda/config_d` is still the correct config load path** on a PandA
+ under Yocto/opkg — no change needed in `config.rst`.
+
+---
+
+## 7. TCP interface / API reference (Gap A — resolved)
+
+- **The existing server docs are essentially the TCP reference already** — move them
+ into a dedicated **reference section** with light reformatting, rather than
+ authoring from scratch.
+- **`commands.rst`** (and related server pages) become the **spine** of that reference
+ section.
+- The **empty `genindex` placeholders go away** — the rootfs `reference.md` toctree
+ entries pointing at non-existent `genindex` / "APIs" are resolved by this
+ consolidation (github.io `genindex.rst` placeholder likewise retired).
+
+---
+
+## 8. Streaming vs fixed tables (Gap B — resolved)
+
+- The **`<<` / `<<|` streaming operators are used only for long, DMA-driven tables** —
+ that's the distinguishing use case versus fixed tables.
+- This deserves its **own page in the server docs**, explaining how streaming tables
+ work, how to **choose buffer sizes**, etc.
+- **`fields.rst` points to that new page** rather than carrying the explanation itself;
+ it retains the `MODE` transition matrix as reference.
+
+---
+
+## 9. Extension server (Gap C — OPEN ITEM)
+
+- **Recorded as an open item** — the extension-server explainer (`extension.rst`) must
+ be **verified against the current implementation before rewriting**.
+- The refresh should eventually cover: what the extension server is for; how
+ `extension_read` / `extension_write` map to field access; how `.py` extension modules
+ are loaded/registered; and where they live on the system.
+- Until then, `config.rst` (server) and `block.rst` (FPGA) keep references pointing at
+ the page flagged as outdated.
+
+---
+
+## 10. Related cross-repo docs & loose threads
+
+**"How to build an FPGA image" (PandABlocks-FPGA repo):**
+
+- Lives in the **FPGA repo**; the article ends with a produced **`.ipk`** file and a
+ pointer onward to **"How to choose the FPGA bitstream"** in meta-panda.
+
+**"How to choose the FPGA bitstream" (meta-panda):**
+
+- Explains how the **`APP` variable in `config.txt`** works.
+- Points back to the FPGA doc for making the image.
+- Covers going live: **`scp` the file → `opkg install` → `systemctl restart`.**
+- **Also referenced from "How to test firmware changes on a PandA"** (the new
+ meta-panda doc from §1).
+
+---
+
+## Open items to verify before publishing
+
+1. **`CONFIG` syntax (§3):** confirm the server Makefile accepts both spaced and
+ non-spaced `=`; then settle on a canonical `CONFIG` example.
+2. **Canonical capture-options explainer (§4):** identify which doc/file is the
+ home for the fully-expanded option definitions.
+3. **Extension server (§9):** verify `extension.rst` against current implementation
+ before rewriting.
diff --git a/knowledge/04-interview-6-firmware-build-release-knowledge.md b/knowledge/04-interview-6-firmware-build-release-knowledge.md
new file mode 100644
index 00000000..5658c84f
--- /dev/null
+++ b/knowledge/04-interview-6-firmware-build-release-knowledge.md
@@ -0,0 +1,88 @@
+# Firmware Build & Release — Knowledge File (meta-panda)
+
+> Source: documentation rewrite Session 6. This file captures decisions about the
+> Yocto firmware build, release artifacts, release process, supported hardware targets,
+> and the version scheme. Developer build docs live in **meta-panda**.
+
+## 1. Canonical build path & fate of rootfs `building.md`
+
+- **Yocto (kas) is the canonical build path** for new users in 2026. The old rootfs path
+ (Diamond rootfs builder + Xilinx SDK + `CONFIG` + zpkg) is superseded.
+- **rootfs `building.md` is not migrated and not kept as legacy** — the rootfs repo is
+ being archived.
+- **Disable the published docs/Pages for the rootfs repo** so its outdated build
+ instructions are no longer visible to anyone.
+
+## 2. Release artifact name & format
+
+- The current release artifact is **`boot-{MACHINE}.tar.gz`** (the meta-panda `remote.rst`
+ description is correct).
+- Contents are **`rootfs.squashfs`** (the squashfs root filesystem) and **`Image`** (the
+ kernel image), consistent with the Yocto build.
+- The github.io description (`boot-x.x.zip` containing `imagefile.cpio.gz` / `uImage`) is
+ **outdated** and belongs to the retired build path.
+
+## 3. `make-release.rst` releases link
+
+- The releases link in meta-panda's `make-release.rst` is a **copy-paste leftover** from
+ the github.io copy and must be corrected.
+- It should point at **`github.com/PandABlocks/meta-panda/releases`**.
+- **meta-panda is the repo that cuts firmware releases**, so that is the correct releases
+ page for this document.
+
+## 4. `manual-build.rst` Xilinx manifest URL & branch
+
+- **`gitenterprise.xilinx.com` is Xilinx's internal GitHub Enterprise host — NOT reachable
+ by external/public users.** It appears in the manifest READMEs only in the
+ "clone/fork to customise" sections, which is the likely source of the confusion.
+- **Use the public manifest at `github.com/Xilinx/yocto-manifests`** instead, initialised
+ with: `repo init -u https://github.com/Xilinx/yocto-manifests.git -b `.
+ `manual-build.rst` should swap the gitenterprise URL for this one.
+- **`rel-v2023.2` is a valid public release branch** and remains the target branch for now.
+- **Branch bump planned after firmware 5.0 ships** (newer Xilinx branches currently go up
+ to `rel-v2025.2`).
+
+## 5. Version scheme (PEP440 vs firmware 2.0/3.0/4.0)
+
+- **PEP440 is the intended scheme** for meta-panda / firmware releases.
+- **The patch segment is usually dropped** (e.g. `4.0`, not `4.0.0`) because patch releases
+ are rare; a patch number is added only when a patch release is actually produced.
+- **github.io is irrelevant to this decision** — its contents are being deleted.
+- Maintainers continue to use GitHub's **"Generate release notes"** when cutting a release.
+
+---
+
+## Open items (gaps flagged for these build docs — need maintainer input)
+
+These were requested but not yet authoritatively resolved. Recorded here so they aren't
+lost; **do not treat the placeholders as confirmed.**
+
+### A. Supported MACHINE targets reference
+
+- **Confirmed `MACHINE` values:** `pandabox` (default), `xu5-s1`, `xu5-st1`, `zedboard`.
+- A newer **`PandABrick`** target now also appears in 4.x release artifacts alongside
+ `pandabox` and `xu5_st1` — confirm whether it should be listed as a supported `MACHINE`.
+- **TODO:** add a reference table enumerating each target and its differences (SoC/module,
+ intended hardware, notable feature differences). Per-target hardware descriptions are
+ slated for the meta-panda front door; this build-docs table should at minimum list the
+ valid `MACHINE` strings and link out to those descriptions.
+
+### B. `KAS_IMAGE_VERSION` ↔ firmware version mapping
+
+- `build.rst` sets `KAS_IMAGE_VERSION="4.8"` with no explanation of how it relates to the
+ PandA firmware release a user is trying to build.
+- **TODO:** document what `KAS_IMAGE_VERSION` selects and how a user picks the value that
+ corresponds to the firmware release they want. (Not resolved in this session.)
+
+---
+
+## Related cleanup actions captured along the way
+
+- meta-panda `make-release.rst` is byte-identical to the github.io copy — de-duplicate and
+ fix the releases link (see §3).
+- `run-container.rst` is duplicated between github.io and meta-panda (same
+ `REPO_DIR`/`VIVADO_DIR`/`BUILD_DIR` mounts, same "reistry" typo) — consolidate into the
+ meta-panda copy and fix the typo.
+- Building-the-image guidance is currently split across rootfs `building.md` (retire, §1),
+ meta-panda `build.rst` (kas/Yocto — canonical), and meta-panda `manual-build.rst`
+ (manual Yocto/bitbake — fix manifest URL, §4).
diff --git a/knowledge/04-interview-7-fpga-docs-knowledge.md b/knowledge/04-interview-7-fpga-docs-knowledge.md
new file mode 100644
index 00000000..449ce1c0
--- /dev/null
+++ b/knowledge/04-interview-7-fpga-docs-knowledge.md
@@ -0,0 +1,86 @@
+# Session 7 — PandABlocks-FPGA: blocks, build, test & CI
+
+Documentation knowledge captured for the **PandABlocks-FPGA** repo. This repo owns
+block-specific and target-specific docs, the per-block reference, and FPGA testing/CI.
+
+> Note on format: the org is migrating docs from RST → MyST Markdown (MySTMD). Several
+> decisions below are gated on that migration. This file is written in plain Markdown so it
+> drops into either toolchain.
+
+---
+
+## 1. `block.rst` placeholder sections
+
+The three empty placeholders in `block.rst` were resolved as follows:
+
+- **"Writing docs"** — *Keep and fill, but defer.* This section is meant to cover the two
+ RST directives and how to structure block documentation. Hold off authoring it until the
+ RST → MyST Markdown migration is done, because the directives will change.
+- **"Block VHDL entity"** — *Keep and fill.* Document how to structure the VHDL entity for a
+ block, using the **LUT block** as the worked example.
+- **"Tables will be defined here too" / `table`** — *Drop.* Tables are too complicated to
+ serve as a worked example here; remove the stub.
+
+---
+
+## 2. FPGA `testing.rst` — CI is no longer Travis
+
+The "as part of the Travis tests" wording is stale. Current state:
+
+- **CI has moved off Travis** — all Travis references in `testing.rst` are outdated and must
+ be replaced.
+- **Simulation testing now runs on GitHub Actions.**
+- **FPGA build now runs on DLS internal GitLab** (Diamond Light Source) — this is separate
+ from the simulation CI.
+- **Flag for maintainer input** — the page needs a rewrite; confirm the specifics with a
+ maintainer before finalising.
+
+---
+
+## 3. FPGA `index.rst` routing → `blocks.rst` and `app.rst`
+
+Both targets the index routes block authors to are outdated:
+
+- **`blocks.rst`** — autogenerated. Keep it as a generated artifact, but the generation
+ process needs updating to work with the MyST Markdown conversion.
+- **`app.rst`** — manually written, not generated; outdated and needs a manual content
+ refresh.
+- **Index routing** — the index can keep pointing to both, but neither is usable until the
+ generation tooling is fixed (`blocks.rst`) and the content is updated (`app.rst`).
+
+---
+
+## 4. `cocotb.rst` — "Modules using IP are currently unsupported"
+
+- **Still accurate** — the cocotb runner does not support modules using IP.
+- **Likely no impact on simulated blocks** — all soft blocks (the ones covered by
+ simulation) are believed not to use IP, so they remain testable.
+- **Flag for check** — verify this assumption against the actual block set before
+ publishing.
+
+---
+
+## Related open gaps (this repo) — not yet resolved
+
+These were noted as worth resolving but were not answered in this session. Captured here as
+TODOs rather than authored, since they need domain input or research:
+
+- **Authored per-block reference** — a current "what each block does" page covering
+ PULSE, CLOCK, PCAP, COUNTER, SEQ, TTLOUT, ADDER, V2F, etc. The only existing listing
+ (`blocks.rst`) is an outdated generated artifact, and the `modules/*/*_doc.rst` files
+ aren't in the inventory. **Status: open — needs authoring.**
+- **V2F block definition/doc** — referenced (with an external paper link) in tutorial2 but
+ never defined or documented anywhere. **Status: open — needs a definition/doc.**
+
+---
+
+## Cross-session pointers (architecture context)
+
+- **meta-panda** — front door / primary home: tutorials, architecture, hardware-target
+ descriptions, web-control UI docs, most user-facing docs, plus Yocto firmware build dev
+ docs.
+- **PandABlocks-FPGA** — *this repo*: block- and target-specific docs; build/test/upgrade
+ selected firmwares.
+- **PandABlocks-server** — TCP server interface; build, test, integrate.
+- **PandABlocks-rootfs** — being archived; still-valid content moves to meta-panda.
+- **PandABlocks.github.io** — becoming a redirect to meta-panda.
diff --git a/knowledge/05-stage-a-scaffolding-spec.md b/knowledge/05-stage-a-scaffolding-spec.md
new file mode 100644
index 00000000..2d249fea
--- /dev/null
+++ b/knowledge/05-stage-a-scaffolding-spec.md
@@ -0,0 +1,230 @@
+# Stage A — Docs Scaffolding Spec (one-off, mystmd)
+
+Instantiate the DLS python-copier-template docs skeleton into the three core repos as a
+**one-off scaffold** (not copier-managed), producing a *building, complete-but-empty* docs tree
+per repo before any content conversion. Run under Opus; output is a reviewable scaffolding PR per
+repo (pure structure, no prose).
+
+**Guiding rule:** preserve the template's structure and conventions **verbatim**; vary only the
+**leaf content pages**, which the template already expects to vary per project. A reader arriving
+from a copier-generated Python repo (PandABlocks-client, fastcs-PandABlocks — done later via
+copier) must recognise the layout instantly.
+
+Source skeleton: `docs/` with `myst.yml`, four Diátaxis landing pages, `index.md`, `images/`,
+`explanations/decisions/` (+ `COPYME`), `how-to/contribute.md`, `reference/api.md` (+ `api.json`).
+
+---
+
+## 1. Kept byte-for-byte (the familiarity surface)
+
+Do not touch these except for the per-repo header swaps in §2:
+
+- `myst.yml` `site:` block — `template: book-theme`, the four-item `nav`, `options.logo`, `options.github_url`.
+- The four landing pages `tutorials.md` / `how-to.md` / `reference.md` / `explanations.md`, each with `{toc}\n:context: children`.
+- `index.md` — README `{include}` + the four-card Diátaxis grid (only the card `:link:` targets change; see §2).
+- `explanations/decisions.md`, the `COPYME` ADR template, and the `pattern: explanations/decisions/*.md` glob.
+- `how-to/contribute.md` — the `{include} ../../.github/CONTRIBUTING.md` (already the template's pattern; just confirm path depth per repo).
+- The Reference `url:`→GitHub-releases "Release Notes" entry.
+
+## 2. Per-repo header swaps (every repo)
+
+In `myst.yml project:` change only:
+- `title:` → repo name (`meta-panda`, `PandABlocks-FPGA`, `PandABlocks-server`).
+- `github:` → repo URL.
+In `site.options:` change only:
+- `github_url:` → repo URL.
+- `logo:` → PandABlocks logo if one exists, else keep `images/dls-logo.svg` as a placeholder (flag for swap).
+
+## 3. Global deletes (all three core repos)
+
+- `reference/api.md`, `reference/api.json` — Python apidoc artifacts (no analogue in these repos).
+- The commented `myst-apidoc-plugin` `plugins:` block in `myst.yml`.
+- `tutorials/installation.md` — pip/venv install of a Python lib.
+- `how-to/run-container.md` — per the map (KAS part → `how-to/build`; dev-container part → new PandABlocks-devcontainer repo).
+
+The Reference quadrant keeps its **shape** (landing page + Release Notes `url:`); for FPGA only, the
+template's *generated* `reference/api.md` slot is replaced in-place by the *generated*
+`reference/blocks.md` (see §4), so the autogen position reads the same as the Python repos' apidoc slot.
+
+## 4. Per-repo TOC + page stubs (from target map v4)
+
+Every listed page is created as a **TODO stub** at its final path (see §7), so the build is green and
+the provenance map can point sources at pages that already exist.
+
+### meta-panda — `project.toc`
+```
+- file: index.md
+- file: tutorials.md
+ children:
+ - file: tutorials/tutorial0_connecting_to_web_control.md
+ - file: tutorials/tutorial1_blinking_leds.md
+ - file: tutorials/tutorial2_position_capture.md
+ - file: tutorials/tutorial3_position_compare.md
+ - file: tutorials/tutorial4_snake_scan.md
+- file: how-to.md
+ children:
+ - file: how-to/quickstart.md
+ - file: how-to/build.md
+ - file: how-to/manual-build.md
+ - file: how-to/make-release.md
+ - file: how-to/packages.md
+ - file: how-to/upgrade-via-ssh.md
+ - file: how-to/upgrade-via-web-admin.md
+ - file: how-to/use-web-control-to-set-up-a-panda.md
+ - file: how-to/save-restore-design.md
+ - file: how-to/monitor-attribute-values.md
+ - file: how-to/integrate-with-a-panda.md
+ - file: how-to/test-firmware-changes.md
+ - file: how-to/choose-fpga-bitstream.md
+ - file: how-to/contribute.md
+- file: explanations.md
+ children:
+ - file: explanations/boot-process.md
+ - file: explanations/architecture.md
+ - file: explanations/hardware-targets.md
+ - file: explanations/web-control-ui-overview.md
+ - file: explanations/understanding-attribute-state.md
+ - file: explanations/decisions.md
+ children:
+ - pattern: explanations/decisions/*.md
+- file: reference.md
+ children:
+ - file: reference/opkg.md
+ - file: reference/changes.md
+ - file: reference/machine-targets.md
+ - file: reference/glossary.md
+ - file: reference/troubleshooting.md
+ - url: https://github.com/PandABlocks/meta-panda/releases
+ title: Release Notes
+```
+`index.md` cards → tutorials.md / how-to.md / explanations.md / reference.md (default targets are fine).
+
+### PandABlocks-FPGA — `project.toc`
+FPGA has no Tutorials quadrant in v4. Keep the four landing pages for structural parity, but the
+tutorials landing stays empty with a one-line note (or drop the tutorials card+nav for FPGA — minor
+per-repo call; default: keep for parity).
+```
+- file: index.md
+- file: tutorials.md # empty landing (parity) — note "no tutorials yet"
+- file: how-to.md
+ children:
+ - file: how-to/app.md
+ - file: how-to/block.md
+ - file: how-to/testing.md
+ - file: how-to/cocotb.md
+ - file: how-to/build-fpga-image.md
+ - file: how-to/finedelay-test.md
+ - file: how-to/local-development.md # pointer to PandABlocks-devcontainer
+ - file: how-to/contribute.md
+- file: explanations.md
+ children:
+ - file: explanations/framework.md
+- file: reference.md
+ children:
+ - file: reference/blocks.md # GENERATED slot (replaces api.md position)
+ -
+ - file: reference/glossary.md # links to meta-panda canonical glossary
+ - file: reference/vhdl-standard.md
+ - url: https://github.com/PandABlocks/PandABlocks-FPGA/releases
+ title: Release Notes
+```
+
+### PandABlocks-server — `project.toc`
+No Tutorials quadrant in v4; same empty-landing/parity note as FPGA.
+```
+- file: index.md
+- file: tutorials.md # empty landing (parity)
+- file: how-to.md
+ children:
+ - file: how-to/startup.md
+ - file: how-to/building.md
+ - file: how-to/contribute.md
+- file: explanations.md
+ children:
+ - file: explanations/architecture.md
+- file: reference.md
+ children:
+ - file: reference/commands.md
+ - file: reference/fields.md
+ - file: reference/capture.md
+ - file: reference/capture-options.md
+ - file: reference/config.md
+ - file: reference/extension.md
+ - file: reference/streaming-tables.md
+ - file: reference/support.md
+ - file: reference/c-standard.md
+ - url: https://github.com/PandABlocks/PandABlocks-server/releases
+ title: Release Notes
+```
+
+### PandABlocks-devcontainer (new, minimal)
+Smallest repo — README + index + a single how-to. The template's `how-to/run-container.md` is a good
+base for `how-to/local-development.md` here (keep, don't delete, for this repo). Only the How-to
+quadrant is populated; other quadrants may be omitted or kept empty for parity (per-repo call).
+
+## 5. OPEN QUESTION — FPGA per-block docs (resolve as first Stage A action)
+
+Per-block docs **must stay physically next to their `module.ini`** at `modules//_doc.{rst→md}`
+(42 files). They cannot be copied/moved into `docs/`. Two ways to surface them in the docs build —
+**prototype both on FPGA and pick the one mystmd builds cleanly:**
+
+- **(a) Symlink** `modules/` (or a curated view of it) into `docs/`, then `pattern:` the linked path in the TOC.
+- **(b) Out-of-tree reference** — TOC/`pattern:` entries that reach `../modules/*/*_doc.md` from the `docs/`-rooted project.
+
+Decision criteria: keeps files physically under `modules/`; keeps `myst.yml` project root at `docs/`
+(template parity); builds without warnings; survives `myst build` + Pages deploy; doesn't break `xref`
+target generation. Document the chosen mechanism in the FPGA scaffolding PR. (Note: the Python repos
+won't hit this — their reference is apidoc — so whatever is chosen is FPGA-local and should be as
+contained as possible.)
+
+## 6. xref + intersphinx — PROTOTYPE here for upstream
+
+Net-new (absent from the skeleton). Build it in these one-off repos as a **prototype intended for
+adoption into the python-copier-template**, so the later Python repos inherit identical wiring.
+
+- Add a `project.references:`-style block to each core repo's `myst.yml` naming the other two core
+ repos + the devcontainer repo (resolving against each site's `myst.xref.json`).
+- Add intersphinx-style entries for the two Sphinx repos (`PandABlocks-client`, `fastcs-PandABlocks`)
+ via their `objects.inv`.
+- *Exact keys per current mystmd cross-references docs* — settle during the prototype.
+- **Test probe:** a real cross-link `server reference/capture` → `meta-panda reference/glossary`
+ resolves in the **built** output (not just config that parses); and one link into a Sphinx repo resolves.
+- Capture the working config as a candidate diff to upstream into the copier template.
+
+## 7. Stub page convention
+
+Each target page is created as a valid-but-empty stub so the build stays green:
+- Title (`# ` from the map).
+- A TODO admonition noting: status from v4 (`writable-now` / `blocked: capture|verify|author|tooling`),
+ and a `Source:` line (filled by the provenance map next).
+- For generated pages (`reference/blocks.md`): a placeholder note in the same spirit as the template's
+ `api.md` note, with the generator wiring left as a separate `blocked: tooling` issue.
+
+## 8. CI / Pages (not in this skeleton)
+
+The build/deploy workflow lives outside `docs/` (the copier template ships it elsewhere) and is **not**
+in the upload. Stage A must confirm or add a GitHub Actions docs build+deploy per repo. Separately:
+PandABlocks-rootfs → Pages disabled; PandABlocks.github.io → single catch-all redirect (not a myst build).
+
+## 9. Acceptance gates
+
+Per repo:
+- `myst build` exits clean (no errors); `api.md`/`api.json`/apidoc hook and the pip-install tutorial removed.
+- Every v4 target page exists as a stub at its correct Diátaxis path; the four-card index and nav resolve.
+- `index.md` README-include and `how-to/contribute.md` CONTRIBUTING-include both resolve.
+- Reference keeps the Release Notes `url:`; FPGA's `reference/blocks.md` present in the api.md slot.
+- One repo (meta-panda) deploys to GitHub Pages green via the wired workflow.
+
+FPGA-specific:
+- §5 open question resolved and documented; the 42 module-doc paths build (stub or converted), files
+ still physically under `modules/`.
+
+Cross-repo (xref prototype):
+- `references` wiring added; the server→meta-panda glossary probe resolves in built output; one
+ intersphinx link to a Sphinx repo resolves; config captured for upstream.
+
+## 10. Sequencing
+
+Stage A precedes content conversion. The provenance map is independent and can run before/parallel;
+running Stage A first lets each source section in the provenance map point at a stub that already
+exists at its final path.
diff --git a/knowledge/05-target-doc-map.md b/knowledge/05-target-doc-map.md
new file mode 100644
index 00000000..bdfa8d6e
--- /dev/null
+++ b/knowledge/05-target-doc-map.md
@@ -0,0 +1,169 @@
+# PandABlocks Docs — Target Map (v4)
+
+Target structure after the rewrite. Merges inventory (01) + interviews (04-1…7) + issue #6,
+with decisions D1–D10 and review items R1–R5 applied.
+
+**Conventions**
+- How-to titles/slugs use **imperative verb form** (e.g. *monitor*, not *monitoring*).
+- Each repo's contribution doc lives at **`.github/CONTRIBUTING.md`**, *included* into `how-to/contribute`.
+- Whole set converts **RST → MyST Markdown**; per-block `*_doc.rst` convert **in place under their module**.
+- **Cross-repo links via mystmd xref:** meta-panda, FPGA, server and the new devcontainer repo are
+ mystmd projects linked by xref (already planned). `PandABlocks-client` and `fastcs-PandABlocks`
+ stay Sphinx this round and are reachable via intersphinx.
+- Terminology: **"PandA Web Control"** only; never `malcolm`/`pymalcolm`/MalcolmJS in docs.
+
+**Legend** — Disposition: `keep`/`rewrite`/`new`/`move`/`convert`/`delete`/`redirect`/`archive`.
+Status: `writable-now` · `blocked: capture` · `blocked: verify` · `blocked: author` · `blocked: tooling`.
+
+---
+
+## meta-panda — canonical front door (top-level Diátaxis)
+
+### Top-level
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `README.md` | What meta-panda is/publishes, fit in PandABlocks, pointers | new | Interview1 §5 | writable-now |
+| `index.md` | Includes README + generates 4-quadrant TOC | rewrite | meta-panda `index.rst` | writable-now |
+| `.github/CONTRIBUTING.md` | Contribution process; included into `how-to/contribute` | new | Interview1 §5 | writable-now |
+
+### Tutorials
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `tutorials/tutorial0_connecting_to_web_control` | Connect to PandA Web Control at PandA IP:80, select root block, make a link; new users | move+rewrite | web-control `quick-start` | writable-now (reuse screenshots) |
+| `tutorials/tutorial1_blinking_leds` | Wire PULSE+CLOCK to blink LEDs; new users | rewrite | meta-panda t1 | writable-now |
+| `tutorials/tutorial2_position_capture` | PCAP capture modes; new users. Keep "next tutorial" promise | rewrite | meta-panda t2 | writable-now |
+| `tutorials/tutorial3_position_compare` | Position compare/trigger pulses; new users | new | human screenshots+bullets → AI | blocked: capture |
+| `tutorials/tutorial4_snake_scan` | SEQ table 2D snake scan; new users | new | human screenshots+bullets → AI | blocked: capture |
+
+### How-to
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `how-to/quickstart` — "How to get a PandA on the network" | First network setup; operators. Fix `boot.txt`→`config.txt`; add `panda-config.txt` USB override | rewrite (merge) | meta-panda + rootfs quickstart | writable-now |
+| `how-to/build` — "How to build the PandA image" | kas/Yocto build (canonical); devs. Absorbs KAS-container usage + `KAS_IMAGE_VERSION` explanation | rewrite (merge) | meta-panda `build.rst` + `run-container` (KAS part) | writable-now; KAS_IMAGE_VERSION = blocked: verify |
+| `how-to/manual-build` | Manual Yocto/bitbake; devs. Fix manifest URL → `github.com/Xilinx/yocto-manifests`, branch `rel-v2023.2` | move+rewrite | meta-panda `tutorials/manual-build` | writable-now (branch bump post-5.0: verify) |
+| `how-to/make-release` | Cut a firmware release; maintainers. Fix releases link → meta-panda | rewrite (de-dupe) | meta-panda `make-release` | writable-now |
+| `how-to/packages` | Install IPK/opkg via USB or SSH; admins | rewrite | meta-panda `packages.rst` | writable-now |
+| `how-to/upgrade-via-ssh` — "Upgrading a PandA over SSH" | Admins. Covers pre-5.0→5.x AND post-5.0; opkg-based; keep 24V FMC EEPROM (DLS-only, one-time) | rewrite | meta-panda `remote.rst` | writable-now; gap audit = blocked: verify |
+| `how-to/upgrade-via-web-admin` — "Upgrading a PandA via the web admin interface" | Operators. + legacy pre-5.0 zpg path + fresh-SD-card install | rewrite | meta-panda `web-interface.rst` | partial; legacy zpg filename = blocked: verify |
+| `how-to/use-web-control-to-set-up-a-panda` | Build/edit a design in Web Control: add/remove blocks, link, edit attributes (View/Edit, Dropdown, Text Input, Checkbox widgets); users | move+rewrite (folds attribute-widgets) | web-control `working_with_a_design` | writable-now (reuse screenshots); 4 missing widget screenshots + trailing sentence = blocked: capture |
+| `how-to/save-restore-design` | Save/restore designs via Web Control; users | split | web-control `working_with_a_design` | writable-now (reuse screenshots) |
+| `how-to/monitor-attribute-values` | View attribute values as live charts/tables; users | move+rewrite | web-control `monitoring_attribute_values` | writable-now (reuse screenshots) |
+| `how-to/integrate-with-a-panda` (R1/R4) | Control a PandA programmatically: direct to TCP server, via the Python client (`PandABlocks-client`), or from EPICS/Tango (`fastcs-PandABlocks`). Covers **getting captured data out** (binary → HDF5/numpy); integrators/devs | new | Interview5; client + fastcs repos | writable-now (skeleton + links) |
+| `how-to/test-firmware-changes` | devtool/kas → deploy → manual test, + FPGA override; devs | new | Interview5 §1–2 | writable-now |
+| `how-to/choose-fpga-bitstream` | `APP` var in config.txt; scp→opkg install→systemctl restart; devs | new | Interview5 §10; Interview3 §4 | writable-now |
+| `how-to/contribute` | Doc-authoring conventions (Diátaxis, markup, draft→AI-expand) + includes `.github/CONTRIBUTING.md`; absorbs github.io `update-tools`/`contribute`. Documents the xref/intersphinx link setup; contributors | new | Interview1 §4; github.io tooling | writable-now |
+
+### Reference
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `reference/opkg` | opkg command quick-ref; admins | keep (→MyST) | meta-panda `opkg.rst` | writable-now |
+| `reference/changes` | Breaking changes + migration per major bump, compat matrix embedded per section; admins/devs | new (consolidate) | github.io `migration_guide` + `release_compatibility` | writable-now; 3.0→4.0 = blocked: verify |
+| `reference/machine-targets` | MACHINE values table (pandabox/xu5-s1/xu5-st1/zedboard) + links to hardware descriptions | new | Interview6 §A | partial; PandABrick = blocked: verify |
+| `reference/glossary` | **Canonical** glossary (web-control + FPGA terms merged); all users | new (merge) | web-control + FPGA glossaries | writable-now |
+| `reference/troubleshooting` (R2) | FAQ/troubleshooting: can't-connect, boot failures, "more than one FPGA image satisfied" error, upgrade failures; operators/admins | new | meta-panda `quickstart.rst` "Frequently Asked Questions" section (seed) | writable-now (seed); some entries = blocked: verify |
+
+### Explanation
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `explanations/boot-process` | FIT image + rootfs.squashfs boot (canonical); devs | keep (→MyST) | meta-panda `boot-process.rst` | writable-now |
+| `explanations/architecture` | How repos/firmware fit together; **points out integration options** (TCP / Python client / EPICS+Tango); all audiences | new | Interview1; cross-session pointers; client + fastcs repos | writable-now (skeleton); detail deferrable |
+| `explanations/hardware-targets` | Per-target hardware (SoC/module, features); integrators | new | Interview6 §A | blocked: author |
+| `explanations/decisions/*` | ADRs migrated from github.io | move | github.io ADRs 0001/0002 | writable-now |
+| `explanations/web-control-ui-overview` | Tour of the four UI panels, Layout/Attribute views; users | move+rewrite | web-control `user_interface_overview` | writable-now (reuse screenshots) |
+| `explanations/understanding-attribute-state` | What Processing/Update Error/Disconnected mean; users. **Recreate the 3 state icons** (material-ui glyphs, colours per source spec); no malcolm reference in docs | move+rewrite | web-control `understanding_attribute_state`; icon colours from DiamondLightSource/malcolmjs `attributeAlarm.component.js` | writable-now (Claude clones malcolmjs + recreates icons at execution) |
+
+*Removed/absorbed:* duplicate `webcontrol/index`,`webcontrol/userguide/index`,`webcontrol/contents`,`webcontrol/userguide/contents`. `how-to/run-container` removed (KAS part → `how-to/build`; dev-container part → new PandABlocks-devcontainer repo).
+
+---
+
+## PandABlocks-devcontainer — NEW repo (standardised local dev)
+
+| Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|
+| `README.md` + `index` | What the devcontainer is; how to use it for local dev; devs | new | Interview5 §1; meta-panda `run-container` (non-KAS part) | writable-now |
+| `how-to/local-development` | Pull/run the devcontainer for build/test/doc; referenced by FPGA + server. Fix "reistry" typo | move+rewrite | meta-panda `run-container` | writable-now |
+
+---
+
+## PandABlocks-FPGA — block/target/CI docs
+
+| Quadrant | Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|---|
+| — | `README.md` + `index` + `.github/CONTRIBUTING.md` | Module intro + 4-quadrant TOC + contribution doc | new/rewrite | Interview1 §5; FPGA `index.rst` | writable-now |
+| Reference | `reference/blocks` | Autogenerated block listing; devs. Regenerate to consume md module docs | keep (regen) | FPGA `blocks.rst` | blocked: tooling (MyST gen) |
+| Reference | `modules/*/*_doc.md` (×42) | Per-block docs (PULSE/CLOCK/PCAP/SEQ/COUNTER/LUT/…); live **under their module**; devs/users | convert (in place) | 42 `modules/*/*_doc.rst` | writable-now (mechanical RST→MD) |
+| Reference | `reference/glossary` | Link to meta-panda canonical glossary | merge | FPGA `glossary.rst` | writable-now |
+| Reference | `reference/vhdl-standard` | VHDL style standard; contributors | new | Interview1 §4 | blocked: author |
+| How-to | `how-to/app` | Assemble blocks into an app (ini, build, query); app devs | rewrite (outdated) | FPGA `app.rst` | writable-now (verify runtime steps) |
+| How-to | `how-to/block` | Writing a block; FPGA devs. Fill "Block VHDL entity" (LUT example); drop tables stub; defer "Writing docs" until MyST. **Not split** | rewrite | FPGA `block.rst` | partial; "Writing docs" = blocked: tooling |
+| How-to | `how-to/testing` | Run test suites; devs. Travis → GitHub Actions (sim) + DLS GitLab (build) | rewrite | FPGA `testing.rst` | blocked: verify (maintainer) |
+| How-to | `how-to/cocotb` | cocotb timing tests; devs. Keep "modules using IP unsupported" | rewrite | FPGA `cocotb.rst` | writable-now; IP assumption = blocked: verify |
+| How-to | `how-to/build-fpga-image` | Build an FPGA image → .ipk → pointer to choose-bitstream (meta-panda); devs | new | Interview5 §10 | writable-now |
+| How-to | `how-to/finedelay-test` | Fine-delay LVDSOUT test; hardware engineers | move | github.io `finedelay-test` (current) | writable-now |
+| How-to | `how-to/local-development` | Pointer to PandABlocks-devcontainer; devs | new (link) | devcontainer repo | writable-now |
+| How-to | `how-to/contribute` | Includes `.github/CONTRIBUTING.md`; contributors | rewrite | FPGA `contributing.rst` | writable-now |
+| Explanation | `explanations/framework` | Autogeneration framework architecture; core devs | move+rewrite | FPGA `framework.rst` (outdated) | partial; needs refresh |
+
+*Glossary:* FPGA `glossary.rst` merges into meta-panda canonical glossary; FPGA links to it.
+
+---
+
+## PandABlocks-server — TCP interface
+
+| Quadrant | Target | Description & audience | Disposition | Source | Status |
+|---|---|---|---|---|---|
+| — | `README.md` + `index` + `.github/CONTRIBUTING.md` | Module intro + 4-quadrant TOC + contribution doc | new/rewrite | Interview1 §5; server `index.rst` | writable-now |
+| Reference | `reference/commands` | ASCII command interface (spine of TCP ref); client devs. Includes `*IDN?` (unchanged v4.x; rootfs: field) | rewrite | server `commands.rst` | writable-now |
+| Reference | `reference/fields` | Field types/attributes; client devs. Point to streaming-tables; keep MODE matrix | rewrite | server `fields.rst` | writable-now |
+| Reference | `reference/capture` | Data-capture protocol/wire format; client devs. Keep ~60 MB/s + webcontrol caveat. **Link to meta-panda `how-to/integrate-with-a-panda`** for getting data out (R4) | rewrite | server `capture.rst` | writable-now (60MB/s = verify) |
+| Reference | `reference/capture-options` | Canonical superset of capture options + "run `*CAPTURE.OPTIONS?` live" note | new | Interview5 §4 | partial; superset = blocked: verify |
+| Reference | `reference/config` | config/registers/description files; firmware devs. config_d path OK | rewrite | server `config.rst` | writable-now |
+| Reference | `reference/extension` | Extension server; extension devs | rewrite | server `extension.rst` (outdated) | blocked: verify |
+| Reference | `reference/streaming-tables` | `<<`/`<<|` streaming for DMA tables, buffer sizes; client devs | new | Interview5 §8 | writable-now |
+| Reference | `reference/support` | Supporting tools/LEDs; operators | rewrite | server `support.rst` | writable-now |
+| Reference | `reference/c-standard` | C style standard; contributors | new | Interview1 §4 | blocked: author |
+| Explanation | `explanations/architecture` | How the server is structured internally (TCP/config/data threads, block model); core devs | new | server code + docs | writable-now (skeleton); depth = blocked: author |
+| How-to | `how-to/startup` | CLI args to start server; admins | rewrite | server `startup.rst` | writable-now |
+| How-to | `how-to/building` | Build/test server (native sim-mode; make+gcc); devs. Point to PandABlocks-devcontainer for local dev | rewrite | server `building.rst` | writable-now; CONFIG syntax = blocked: verify |
+| How-to | `how-to/contribute` | Includes `.github/CONTRIBUTING.md`; contributors | new | — | writable-now |
+
+*Removed:* SDK cross-compile path (`pandablocks-sdk.rst` + "sdk installer in host" line) → replaced by meta-panda `how-to/test-firmware-changes`. `presentation-2016-05/*` → drop. `genindex` placeholders → drop.
+
+---
+
+## PandABlocks-rootfs — ARCHIVE
+| Action | Detail |
+|---|---|
+| Disable Pages | Stop publishing rootfs docs |
+| Migrate out | boot-process (done), quickstart (→ meta-panda merge), valid bits only |
+| Retire | `building.md` (whole build guide), zpkg content |
+| Fix dangling refs | Remove `how-to/remote.md` toctree entries in `index.md`/`how-to.md` |
+| Keep | `README` pointing to meta-panda |
+
+## PandABlocks.github.io — REDIRECT
+| Action | Detail |
+|---|---|
+| Catch-all redirect | `pandablocks.github.io/` → `meta-panda/main/index.html` (single redirect) |
+| Delete (migrated) | tutorials 1–4, `make-release`, `run-container`, `remote`, `web-interface`, `migration_guide`, `release_compatibility`, `standards`, `genindex` |
+| Migrate first | ADRs `decisions/*` → meta-panda; `finedelay-test` → FPGA; `update-tools`/`contribute` → meta-panda `how-to/contribute` |
+
+---
+
+## Review items R1–R5 (resolved)
+- **R1** Integration/client pointers → `how-to/integrate-with-a-panda` (TCP / Python client / EPICS+Tango via `fastcs-PandABlocks`, **not** the archived `PandABlocks-ioc`); linked from `explanations/architecture`.
+- **R2** Troubleshooting → `reference/troubleshooting`, seeded from the quickstart FAQ.
+- **R3** Cross-repo links → mystmd xref across the 3 core repos + devcontainer (already planned); `PandABlocks-client`/`fastcs-PandABlocks` reachable via intersphinx this round.
+- **R4** Getting data out → folded into R1; cross-linked from server `reference/capture`.
+- **R5** Versioned docs / version switcher → **GitHub issue** (infrastructure; not authored this round).
+
+---
+
+## Issue backlog (for GitHub issues, scoped ~few hours each)
+
+**Human-capture:** Tutorial 3 screenshots+bullets · Tutorial 4 screenshots+bullets · web-control widget screenshots (View/Edit, Dropdown, Text Input, Checkbox) + finish trailing sentence.
+
+**Verify-then-write:** 3.0→4.0 breaking changes · capture-options superset · extension server vs implementation · `*IDN?` v4.x · 60 MB/s figure · cocotb IP assumption · CONFIG syntax · PandABrick target · `KAS_IMAGE_VERSION` mapping · legacy updater zpg filename · testing.rst CI · Xilinx branch bump post-5.0.
+
+**Author-from-scratch:** VHDL standard · C standard · hardware-target descriptions · server architecture (depth).
+
+**Infrastructure:** versioned docs / version switcher (R5).
diff --git a/knowledge/06-source-provenance-map.md b/knowledge/06-source-provenance-map.md
new file mode 100644
index 00000000..3b329056
--- /dev/null
+++ b/knowledge/06-source-provenance-map.md
@@ -0,0 +1,120 @@
+# PandABlocks Docs — Source-Provenance Map
+
+Per target page: the exact source file(s) and **sections** that feed it, so each Claude Code task is
+self-contained. Word counts and section names are from a close-read of the current repos (heads of
+`main`/default). Read alongside the target map (03) and Stage A spec (05).
+
+## Corrections to v4 discovered during close-read (apply these)
+- **Web-control source lives inside meta-panda** at `docs/webcontrol/userguide/*` — *not* a separate
+ repo. (A `PandABlocks-webcontrol` repo exists but carries no published `docs/`.)
+- **Tutorials are triplicated and byte-identical** across meta-panda, FPGA and github.io. Canonical =
+ **meta-panda**; delete the FPGA and github.io copies. t1 (648w) and t2 (1167w) are real; **t3 (41w)
+ and t4 (52w) are near-empty stubs** → `blocked: capture` confirmed.
+- **`understanding_attribute_state` has EIGHT states** (Normal, Processing, Locally Edited, Update
+ Error, Warning, Error, Invalid, Disconnected) + "Presenting Status Information" — the icon-recreation
+ task covers all eight indicators, not three.
+- **FPGA `reference/changelog.rst` is empty** (3 words) → maps to the Release-Notes `url:` slot; drop the file.
+- **github.io `migration_guide.rst` only documents 2.0→3.0** — 3.0→4.0 is genuinely absent (the verify gap).
+- FPGA `app`/`block`/`testing`/`cocotb` currently sit under `reference/`; D2 moves them to `how-to/`.
+- The quickstart **FAQ (7 Qs)** is extracted out of `how-to/quickstart` into `reference/troubleshooting`.
+
+Legend: `→` = becomes; `⊃` = extract subsection; `+` = merge; status as in 03.
+
+---
+
+## meta-panda
+
+| Target | Source → sections | Action notes | Status |
+|---|---|---|---|
+| `tutorials/tutorial0_connecting_to_web_control` | `webcontrol/userguide/quick-start.rst` (376w, "Quick Start") | rewrite as tutorial0; reuse screenshots | writable-now |
+| `tutorials/tutorial1_blinking_leds` | `tutorials/tutorial1_blinking_leds.rst` (648w) | rewrite | writable-now |
+| `tutorials/tutorial2_position_capture` | `tutorials/tutorial2_position_capture.rst` (1167w) | rewrite; keep "next tutorial" promise | writable-now |
+| `tutorials/tutorial3_position_compare` | `tutorials/tutorial3_position_compare.rst` (41w **stub**) | author from human screenshots+bullets | blocked: capture |
+| `tutorials/tutorial4_snake_scan` | `tutorials/tutorial4_snake_scan.rst` (52w **stub**) | author from human screenshots+bullets | blocked: capture |
+| `how-to/quickstart` ("How to get a PandA on the network") | `how-to/quickstart.rst` (817w: Getting a PandA on the network, Override file, Web Interface, Web Admin) + rootfs `how-to/quickstart.md` | merge; fix `boot.txt`→`config.txt` in *Override file*; add `panda-config.txt` USB override; **FAQ section moves to reference/troubleshooting** | writable-now |
+| `how-to/build` ("How to build the PandA image") | `how-to/build.rst` (275w: Building the panda image, Output Files) + `how-to/run-container.rst` ⊃ KAS part (167w: Run in a container, Starting the container) | merge; fold in `KAS_IMAGE_VERSION` | partial; KAS_IMAGE_VERSION = blocked: verify |
+| `how-to/manual-build` | `tutorials/manual-build.rst` | fix manifest URL → `Xilinx/yocto-manifests`, branch `rel-v2023.2` | writable-now (post-5.0 branch = verify) |
+| `how-to/make-release` | `how-to/make-release.rst` | de-dupe vs github.io copy; fix releases link → meta-panda | writable-now |
+| `how-to/packages` | `how-to/packages.rst` | →MyST | writable-now |
+| `how-to/upgrade-via-ssh` ("Upgrading a PandA over SSH") | `how-to/remote.rst` (245w: Updating the rootfs, Update 24V eeprom) | keep 24V EEPROM as DLS-only one-time; cover pre-5.0 + post-5.0 | writable-now; gap audit = verify |
+| `how-to/upgrade-via-web-admin` ("Upgrading a PandA via the web admin interface") | `how-to/web-interface.rst` (240w: Updating the rootfs) | + legacy pre-5.0 zpg path + fresh-SD-card install | partial; zpg filename = verify |
+| `how-to/use-web-control-to-set-up-a-panda` | `webcontrol/userguide/working_with_a_design.rst` (4882w) ⊃ Adding/Removing a Block, Working with the Block Palette, Specifying Block Attributes (Types, Obtaining Info, Setting, **View/Edit, Dropdown, Text Input, Checkbox**, Exporting, Local vs Server, Attribute Change Lifecycle), Complex Attributes (Tables), Block Methods, Block Ports, Linking Blocks | folds the attribute-widgets; the 4 widget subsections need new screenshots | writable-now (reuse screenshots); widget screenshots + trailing sentence = blocked: capture |
+| `how-to/save-restore-design` | `working_with_a_design.rst` ⊃ Saving a Design, Opening an Existing Design | split out of the above | writable-now (reuse screenshots) |
+| `how-to/monitor-attribute-values` | `webcontrol/userguide/monitoring_attribute_values.rst` (991w: Working With Charts [Interactive, Enhanced, Exporting, Data Retrieval], Numerical Tables) | →how-to | writable-now (reuse screenshots) |
+| `how-to/integrate-with-a-panda` | NEW (Interview5; `PandABlocks-client` + `fastcs-PandABlocks` repos) | author skeleton: TCP direct / Python client / EPICS+Tango via fastcs; covers data-out (binary→HDF5/numpy) | writable-now (skeleton+links) |
+| `how-to/test-firmware-changes` | NEW (Interview5 §1–2); **replaces** `how-to/pandablocks-sdk.rst` (drop that) | author | writable-now |
+| `how-to/choose-fpga-bitstream` | NEW (Interview5 §10; Interview3 §4); seed from quickstart FAQ "override FPGA bitstream variant" | author | writable-now |
+| `how-to/contribute` | github.io `how-to/contribute.rst` + `how-to/update-tools.rst` (84w) + `reference/standards.rst` (17w: Code Standards) + `{include} .github/CONTRIBUTING.md` | merge doc-standards + tooling; document xref/intersphinx setup here | writable-now |
+| `reference/opkg` | `reference/opkg.rst` | →MyST | writable-now |
+| `reference/changes` | github.io `reference/migration_guide.rst` (119w: **only 2.0→3.0**) + `release_compatibility.rst` (32w) | consolidate per-major with compat embedded; **3.0→4.0 absent** | blocked: verify |
+| `reference/machine-targets` | NEW (Interview6 §A) | MACHINE table + links to hardware-targets | partial; PandABrick = verify |
+| `reference/glossary` | `webcontrol/userguide/glossary.rst` (732w) **+** FPGA `reference/glossary.rst` | canonical merge; others link here | writable-now |
+| `reference/troubleshooting` | ⊃ `how-to/quickstart.rst` "Frequently Asked Questions" — 7 Qs: static network; disable sub-net validation; recover from catastrophic changes; load rootfs to RAM at boot; system freeze after FPGA load; override FPGA bitstream variant; authorise ssh public key | seed page; add boot/FMC/upgrade errors | writable-now (seed); some = verify |
+| `explanations/boot-process` | `explanations/boot-process.rst` | keep →MyST | writable-now |
+| `explanations/architecture` | NEW (Interview1) | skeleton; points to integration options | writable-now (skeleton) |
+| `explanations/hardware-targets` | NEW (Interview6 §A) | per-target hardware | blocked: author |
+| `explanations/web-control-ui-overview` | `webcontrol/userguide/user_interface_overview.rst` (1150w: Components, Principle views, Layout View, Attribute View, Panel Popping) | →explanation | writable-now (reuse screenshots) |
+| `explanations/understanding-attribute-state` | `webcontrol/userguide/understanding_attribute_state.rst` (535w: **8 states** + Presenting Status Information) | recreate **8** state icons from malcolmjs colour spec; no malcolm in docs | writable-now (Claude recreates icons) |
+| `explanations/decisions/*` | github.io `explanations/decisions/0001-record-architecture-decisions.rst`, `0002-switched-to-pip-skeleton.rst` | move | writable-now |
+| `.github/CONTRIBUTING.md`, `README.md`, `index.md` | NEW (Interview1 §5) + meta-panda `index.rst` | scaffold | writable-now |
+| **DROP** | `webcontrol/index.rst`, `webcontrol/contents.rst`, `webcontrol/userguide/index.rst`, `webcontrol/userguide/contents.rst`, `how-to/pandablocks-sdk.rst`, `how-to/run-container.rst` (after split) | intros→front door, TOCs→quadrants | — |
+
+---
+
+## PandABlocks-FPGA
+
+| Target | Source → sections | Action notes | Status |
+|---|---|---|---|
+| `reference/blocks` | `blocks.rst` (autogenerated listing) | regenerate to consume md module docs | blocked: tooling |
+| `modules/*/*_doc.md` (×42) | `modules/*/*_doc.rst` (×42, beside `.block.ini`/`.timing.ini`) | mechanical RST→MD **in place**; surfacing = §5 open question (symlink vs out-of-tree) | writable-now |
+| `how-to/app` | `reference/app.rst` (364w: App ini [`.`,`[BLOCK]`], App build process, Querying at runtime) | →how-to; verify runtime steps | writable-now |
+| `how-to/block` | `reference/block.rst` (1610w: Architecture, Modules, Block ini, Block Simulation, Timing ini, Target ini, Writing docs, Block VHDL entity) | →how-to; **not split**; fill *Block VHDL entity* (LUT example); defer *Writing docs* until MyST | partial; "Writing docs" = blocked: tooling |
+| `how-to/testing` | `reference/testing.rst` (274w: Python tests, HDL tests) | Travis → GitHub Actions (sim) + DLS GitLab (build) | blocked: verify |
+| `how-to/cocotb` | `reference/cocotb.rst` (742w: About, Running, Results [Timing/Waveforms/Coverage], How It Works, Writing Tests for New Modules) | keep "modules using IP unsupported" | writable-now; IP note = verify |
+| `how-to/build-fpga-image` | NEW (Interview5 §10) | build → .ipk → pointer to meta-panda choose-bitstream | writable-now |
+| `how-to/finedelay-test` | github.io `how-to/finedelay-test.rst` (183w) | move | writable-now |
+| `how-to/local-development` | NEW (pointer to PandABlocks-devcontainer) | link | writable-now |
+| `how-to/contribute` | `reference/contributing.rst` → `.github/CONTRIBUTING.md` + `{include}` | →how-to | writable-now |
+| `explanations/framework` | `reference/framework.rst` (500w: Softblocks, Wrappers, Config_d entries, Test benches) | →explanation; refresh (outdated) | partial |
+| `reference/glossary` | `reference/glossary.rst` → merge into meta-panda canonical | FPGA links to canonical | writable-now |
+| `reference/vhdl-standard` | NEW (Interview1 §4) | author | blocked: author |
+| `README.md`, `index.md` | FPGA `index.rst` | scaffold | writable-now |
+| **DROP** | `reference/changelog.rst` (empty, 3w) → Release-Notes `url:` slot; FPGA + github.io tutorial copies | — | — |
+
+---
+
+## PandABlocks-server
+
+| Target | Source → sections | Action notes | Status |
+|---|---|---|---|
+| `reference/commands` | `commands.rst` (1984w: Configuration Commands, System Commands) | spine of TCP ref; keep `*IDN?` (unchanged v4.x) | writable-now |
+| `reference/fields` | `fields.rst` (2671w: Field Types, Field Sub-Types, Summary of Sub-Types, Summary of Attributes) | keep MODE matrix; point to streaming-tables | writable-now |
+| `reference/capture` | `capture.rst` (1460w: Capture Configuration, Data Capture Port ⊃ Capture Options, Data Transport Formatting, Data Header, Experiment Completion, High performance mode, Examples) | keep ~60 MB/s + webcontrol caveat; **link to meta-panda integrate-with-a-panda** for data-out | writable-now; 60MB/s = verify |
+| `reference/capture-options` | ⊃ `capture.rst` "Capture Options" + Interview5 §4 superset | "run `*CAPTURE.OPTIONS?` live" note | partial; superset = verify |
+| `reference/config` | `config.rst` (1198w: config [Field type/subtype], registers [+ extension syntax], description) | →MyST | writable-now |
+| `reference/extension` | `extension.rst` (739w: Extension Modules, Injected Values) | verify vs implementation | blocked: verify |
+| `reference/streaming-tables` | NEW (Interview5 §8) | `<<` / `<<|`, buffer sizes | writable-now |
+| `reference/support` | `support.rst` (391w: Useful Tools, Panda Status LEDs) | →MyST | writable-now |
+| `reference/c-standard` | NEW (Interview1 §4) | author | blocked: author |
+| `explanations/architecture` | NEW (server code + docs) | skeleton (TCP/config/data threads, block model); depth later | writable-now (skeleton); depth = blocked: author |
+| `how-to/startup` | `startup.rst` (501w: Starting Panda Server) | →how-to | writable-now |
+| `how-to/building` | `building.rst` (493w: Dependencies, CONFIG file, Build Targets, Generated Files) | point to devcontainer for local dev | writable-now; CONFIG syntax = verify |
+| `how-to/contribute` | NEW + `{include} .github/CONTRIBUTING.md` | →how-to | writable-now |
+| `README.md`, `index.md` | server `index.rst` | scaffold | writable-now |
+| **DROP** | `presentation-2016-05/*` (building/panda/server); SDK cross-compile path (replaced by meta-panda test-firmware-changes) | — | — |
+
+---
+
+## PandABlocks-rootfs — archive
+- `how-to/quickstart.md` → merged into meta-panda `how-to/quickstart` (network setup).
+- `how-to/building.md` → retire (whole build guide superseded).
+- boot-process already migrated to meta-panda.
+- Disable Pages; remove dangling `how-to/remote.md` toctree entries in `index.md`/`how-to.md`; `README` → meta-panda.
+
+## PandABlocks.github.io — redirect (migrate first, then single redirect)
+- `explanations/decisions/0001`, `0002-switched-to-pip-skeleton` → meta-panda `explanations/decisions/`.
+- `how-to/finedelay-test` → FPGA.
+- `how-to/update-tools` + `how-to/contribute` + `reference/standards` → meta-panda `how-to/contribute`.
+- `reference/migration_guide` + `reference/release_compatibility` → meta-panda `reference/changes`.
+- **Delete (migrated/dupes):** `tutorials/*`, `how-to/make-release`, `how-to/remote`, `how-to/web-interface`, `how-to/run-container`, `reference/genindex`, `how.rst`, `tutorial.rst`.
+- Catch-all redirect `pandablocks.github.io/` → `meta-panda/main/index.html`.
diff --git a/knowledge/07-handoff-guide.md b/knowledge/07-handoff-guide.md
new file mode 100644
index 00000000..cb513dcd
--- /dev/null
+++ b/knowledge/07-handoff-guide.md
@@ -0,0 +1,54 @@
+# PandABlocks Docs Rewrite — Claude Code Hand-off Guide
+
+How to execute the rewrite from the planning artifacts. Read top-to-bottom once, then work task by task.
+
+## Artifact set (read in this order)
+1. `01-inventory.md` — what exists today (≈86 files, 5 repos).
+2. `02-gap-analysis-draft.md` — duplications, gaps, open questions (now resolved below).
+3. `04-interview-1…7` — the maintainer decisions behind every structural call.
+4. `03-target-doc-map.md` — **the target structure** (every page × repo × quadrant × disposition × status). Source of truth for *what goes where*.
+5. `05-stage-a-scaffolding-spec.md` — **how to scaffold** each repo from the DLS mystmd skeleton.
+6. `06-source-provenance-map.md` — **for each target page, which source sections feed it**. Source of truth for *what to put in each page*.
+
+If 03 and 06 ever disagree, 06 is newer (it includes close-read corrections listed at its top).
+
+## Execution order & model per stage
+| Stage | What | Model | Notes |
+|---|---|---|---|
+| A | Scaffold all repos to a green, empty-but-complete build (05) | Opus | One PR per repo. Resolve FPGA modules question + xref prototype here. Gate: `myst build` green + one Pages deploy. |
+| B | Create GitHub issues from the 03 backlog | Sonnet | Needs PAT. Group by knowledge area; one issue per scoped item; link each to its stub page. |
+| C | Icon recreation (8 attribute-state icons from malcolmjs colour spec) | Opus | Clone DiamondLightSource/malcolmjs; no "malcolm" in docs. |
+| D | Bulk content conversion (mechanical RST→MyST, the 42 module docs + straightforward pages) | Sonnet | Chunk = one repo × one quadrant. Fill stubs; commit per file. |
+| E | Hard content conversion (own task each — see below) | Opus | Judgment + restructuring. |
+| F | Final cross-repo verification (xref end-to-end, intersphinx, all builds + Pages, rootfs Pages off, github.io redirect) | Opus | Integration gate. |
+| (opt) | Assurance pass over 06 + the hard rewrites + xref config | Fable | Only if max fidelity wanted; ~2× Opus cost. |
+
+## Chunking rule
+One Claude Code task = **one repo × one Diátaxis quadrant**, EXCEPT these get their **own task** (large or judgment-heavy):
+- meta-panda `working_with_a_design.rst` (4882w → splits into `use-web-control-to-set-up-a-panda` + `save-restore-design`)
+- server `fields.rst` (2671w), `commands.rst` (1984w), `capture.rst` (1460w → also spawns `capture-options`)
+- FPGA `block.rst` (1610w → fill VHDL-entity, defer Writing-docs)
+
+≈18–20 tasks total.
+
+## Branch / commit / durable-state discipline
+- One **branch per repo** (e.g. `docs-rewrite`); never commit conversions straight to default.
+- **Commit after every file** with a clear message; small commits survive a crashed session.
+- Keep `docs/PROGRESS.md` (template provided) in each repo and update the relevant line in the **same commit** as the file it tracks. This is the crash-recovery checklist.
+- **GitHub issues are durable state** for blocked items — a stub + its issue means that page is "done for this round."
+- Copy `03`, `05`, `06` into each repo (e.g. under `docs/_rewrite/`) so every task is self-contained without this web session.
+
+## Stub convention (Stage A and any blocked page)
+Each stub: a title + a MyST admonition carrying the `status` from 03/06 and a `Source:` line from 06, plus a link to its GitHub issue if blocked. Stubs must be valid MyST so the build stays green.
+
+## Per-task loop
+1. Read the page's row in `06` (source file + sections) and `03` (disposition + status).
+2. Read the live source file(s) in the repo; convert/merge/split per the notes.
+3. Apply the interview fixes called out in the row (URL fixes, `boot.txt`→`config.txt`, etc.).
+4. If `blocked: *`: leave the stub, ensure the issue exists, move on.
+5. `myst build`; fix until green. Commit file + PROGRESS line.
+
+## Open items to settle in-flight (not blockers)
+- FPGA per-block docs: symlink `modules/` into `docs/` vs out-of-tree TOC reference — prototype both in Stage A, pick the clean build, document it.
+- xref/intersphinx exact keys — settle against current mystmd cross-references docs during Stage A; capture config for upstream into the copier template.
+- CI/Pages workflow is not in the skeleton upload — confirm or add the GitHub Actions docs build+deploy per repo in Stage A.
diff --git a/knowledge/08-runbook.md b/knowledge/08-runbook.md
new file mode 100644
index 00000000..6b6fadec
--- /dev/null
+++ b/knowledge/08-runbook.md
@@ -0,0 +1,96 @@
+# PandABlocks Docs Rewrite — Runbook & Claude Code Prompts (human-facing)
+
+This is the only operational file you drive from. Everything else in `meta-panda/knowledge/` is
+reference material that the prompts below point Claude Code at — you never edit it by hand.
+
+## File roles
+**You act on:** this file, `07-handoff-guide.md`, and the issue backlog in `03`.
+**Claude Code reads (in `meta-panda/knowledge/`):** `03`, `05`, `06` (primary); `01`, `02`,
+`04-interview-*` (background); `PROGRESS-template.md`; `docs-skeleton/` (extracted `docs.zip`).
+
+In every prompt below, `/workspaces/meta-panda/knowledge` = the absolute path of `meta-panda/knowledge`
+(e.g. `~/src/meta-panda/knowledge`). Set it once; it's reachable from every repo's session because
+it's a sibling checkout (or symlink `knowledge/` into each repo if you prefer).
+
+---
+
+## One-time setup (you)
+1. Create the `docs` branch in `meta-panda`, `PandABlocks-FPGA`, `PandABlocks-server`. *(Superseded 2026-06: no separate PandABlocks-devcontainer repo — each repo carries its own `.devcontainer/` + Dockerfile.)*
+2. Put all knowledge files in `meta-panda/knowledge/`; extract `docs.zip` to `meta-panda/knowledge/docs-skeleton/`.
+3. Have a GitHub PAT ready (scopes: repo, issues) for Stage B; authenticate `gh` in that terminal.
+4. Two decisions are yours (not blockers): confirm whether all **8** attribute-state icons need distinct glyphs or some collapse; and (optional) whether you have a preference on the FPGA module-docs surfacing or the xref keys, else let CC prototype and report.
+
+## How to run across 5-hour windows
+Sequential, one session per task, `/clear` between tasks, `/model` to switch. Suggested window plan:
+- **Window 1:** Stage A scaffold (Prompt A) for all four repos. Opus-heavy; review the four scaffold PRs at the end.
+- **Window 2–3:** Bulk conversion (Prompt D) repo by repo on Sonnet; drop in hard files (Prompt E) on Opus as budget allows. Run Stage B (Prompt B) as a short Sonnet burst once stubs exist.
+- **Last window:** Icons (Prompt C) and final verification (Prompt F) on Opus.
+End every window at a clean committed state on a whole quadrant or repo.
+
+Budget tip: Prompt A can be split — do steps 1–3,5,6 on **Sonnet** (mechanical), then steps 4 + the
+FPGA modules prototype on **Opus**. That stretches the Opus budget.
+
+---
+
+## PROMPT A — Stage A scaffold · model: Opus (or split, see tip) · run from each repo root on `docs`
+```
+You are scaffolding the documentation for this repository as part of a multi-repo docs rewrite. Work only on the `docs` branch.
+
+Read first: /workspaces/meta-panda/knowledge/05-stage-a-scaffolding-spec.md (how to scaffold), /workspaces/meta-panda/knowledge/03-target-doc-map.md (this repo's target pages), and the corrections at the top of /workspaces/meta-panda/knowledge/06-source-provenance-map.md (apply them). The mystmd skeleton to instantiate is /workspaces/meta-panda/knowledge/docs-skeleton/.
+
+Following 05 exactly:
+1. Instantiate the skeleton into docs/ as a one-off (not copier-managed). Keep every structural element byte-for-byte; swap only title / github / github_url / logo.
+2. Delete reference/api.md, reference/api.json, the apidoc plugins block, tutorials/installation.md; for core repos delete how-to/run-container.md.
+3. Build project.toc and the index.md card targets from this repo's section in 03/06. Create EVERY target page as a valid TODO stub: title + a MyST admonition carrying the page's `status` and a `Source:` line from 06 (link an issue placeholder if blocked).
+4. Add the xref `references:` block naming the other core repos + devcontainer, and intersphinx entries for PandABlocks-client and fastcs-PandABlocks. Prove a cross-link resolves in the BUILT output.
+5. Copy /workspaces/meta-panda/knowledge/PROGRESS-template.md to docs/PROGRESS.md, set the repo name, tick Stage-A items as you go.
+6. Run `myst build` until green; commit after each step; open a PR from `docs` titled "docs: Stage A scaffold".
+
+FPGA ONLY: also resolve per-block-docs surfacing — prototype BOTH (a) symlink modules/ into docs/ and (b) an out-of-tree TOC reference to ../modules/*/*_doc.md — pick whichever builds clean with the files staying physically under modules/, and record the choice in PROGRESS.md.
+
+Gate: green `myst build`, every target page present as a stub, xref probe resolves. Stop and report BEFORE converting any real content.
+```
+
+## PROMPT B — GitHub issues · model: Sonnet · run from meta-panda with `gh` authenticated (PAT)
+```
+Create GitHub issues for the docs-rewrite backlog. The backlog is the "Issue backlog" section of /workspaces/meta-panda/knowledge/03-target-doc-map.md (Human-capture, Verify-then-write, Author-from-scratch, Infrastructure).
+
+For each item: create one issue in the relevant PandABlocks/, titled clearly; body states the target page it blocks (look it up in /workspaces/meta-panda/knowledge/06-source-provenance-map.md), the category, and exactly what a human must do (treat each as a few hours of work). Group closely related items by knowledge area. Label `docs-rewrite` + the category. Use the `gh` CLI.
+Then write each issue number into that repo's docs/PROGRESS.md "Blocked" section and into the matching stub page's admonition, and commit those edits on `docs`. List the issues created at the end.
+```
+
+## PROMPT C — Recreate attribute-state icons · model: Opus · run from meta-panda on `docs`
+```
+Recreate the attribute-state icons for explanations/understanding-attribute-state. Clone DiamondLightSource/malcolmjs and read the colour/glyph spec in attributeAlarm.component.js. There are EIGHT states: Normal, Processing, Locally Edited, Update Error, Warning, Error, Invalid, Disconnected (see /workspaces/meta-panda/knowledge/06-source-provenance-map.md).
+Recreate each as a small standalone SVG (material-style glyph in the spec colour) under docs/images/attribute-state/, and wire them into the understanding-attribute-state page. Do NOT mention malcolm or MalcolmJS anywhere in the docs — the repo is only the source of the colours. `myst build` green; commit on `docs`.
+```
+
+## PROMPT D — Bulk conversion · model: Sonnet · run per repo, once per quadrant, on `docs`
+```
+Convert the {QUADRANT} pages for this repo from RST to MyST Markdown, on the `docs` branch.
+For each page in this repo's {QUADRANT} section of /workspaces/meta-panda/knowledge/06-source-provenance-map.md: read the cited source file and sections, convert/merge/split exactly as the row says, apply every listed fix (URL corrections, boot.txt->config.txt, title changes, etc.), and replace the stub.
+SKIP these own-task files (done separately on Opus): working_with_a_design, fields, commands, capture, block.
+SKIP any page marked blocked:* — leave its stub and ensure its issue is linked.
+Reuse existing screenshots/assets in place.
+After each file: `myst build`, then commit the file together with its docs/PROGRESS.md line. Report done/skipped at the end.
+
+(FPGA reference quadrant only: the 42 modules/*/*_doc.rst conversions are independent and identical in shape — you may fan them out to sub-agents, one batch each, but YOU commit the results sequentially.)
+```
+
+## PROMPT E — Hard files · model: Opus · one session each, on `docs`
+Run once per file, pasting the matching SPECIFICS line:
+```
+Convert {FILE} on the `docs` branch, following its row in /workspaces/meta-panda/knowledge/06-source-provenance-map.md and the disposition in /workspaces/meta-panda/knowledge/03-target-doc-map.md. Restructure into clean MyST, preserve ALL technical specifics (matrices, tables, examples, figures), apply the listed fixes, and split into the named target pages where the row says. `myst build` green; commit per target page + its PROGRESS line.
+SPECIFICS: {SPECIFICS}
+```
+- **meta-panda working_with_a_design.rst** — split into how-to/use-web-control-to-set-up-a-panda (the bulk, attribute widgets folded in) + how-to/save-restore-design (the Saving/Opening sections). The four widget subsections (View/Edit, Dropdown, Text Input, Checkbox) stay stubbed as blocked:capture with their issue linked.
+- **server fields.rst** — keep the MODE matrix and the Summary-of-Sub-Types / Summary-of-Attributes tables; point to reference/streaming-tables.
+- **server commands.rst** — preserve the Configuration and System command tables; keep `*IDN?`.
+- **server capture.rst** — keep the ~60 MB/s figure + webcontrol caveat; EXTRACT the "Capture Options" subsection into reference/capture-options (add the "run `*CAPTURE.OPTIONS?` live" note); link meta-panda how-to/integrate-with-a-panda for getting data out.
+- **FPGA block.rst** — fill the "Block VHDL entity" section (LUT example); defer "Writing docs" (blocked:tooling, link its issue); do NOT split.
+
+## PROMPT F — Final cross-repo verification · model: Opus · run from any repo
+```
+Final cross-repo verification of the docs `docs` branches. Confirm: every repo's `myst build` is green; xref links resolve across meta-panda / PandABlocks-FPGA / PandABlocks-server in BUILT output; intersphinx links into PandABlocks-client and fastcs-PandABlocks resolve; GitHub Pages deploys green per repo; PandABlocks-rootfs Pages is disabled; PandABlocks.github.io serves the single catch-all redirect to meta-panda.
+Fix what you can; file issues for the rest. Capture the working xref/intersphinx config as a diff suitable for upstreaming into the python-copier-template. Summarise final status against /workspaces/meta-panda/knowledge/03-target-doc-map.md.
+```
diff --git a/knowledge/09-fresh-eyes-review.md b/knowledge/09-fresh-eyes-review.md
new file mode 100644
index 00000000..09e8451c
--- /dev/null
+++ b/knowledge/09-fresh-eyes-review.md
@@ -0,0 +1,201 @@
+# Fresh-eyes review of the docs branches (pre-push)
+
+Read as: (1) a brand-new PandABox owner starting from the meta-panda index, assuming all
+Stage-B issues eventually get done by a human; (2) a user doing typical tasks — updating
+firmware, deploying a custom bitstream, writing a new FPGA block and adding it to an image.
+Every claim was checked against the repo sources (Makefiles, `conf/machine/`, `server.c`,
+legacy RST), not just read for style.
+
+**Status update (2026-06-12):** everything fixable without user input has now been
+**applied** to the working trees of all three repos. All three docs sites rebuild cleanly
+(`myst build`: no errors, no new warnings) and `create-issues.sh` passes `bash -n` with all
+of its sed/perl targets re-verified against the edited pages. What remains is listed in
+[What's left](#whats-left) below.
+
+## Overall verdict (unchanged)
+
+The structure is right. Diátaxis split is clean, the meta-panda-as-root model works, the
+tutorial sequence 0→1→2 is genuinely good, and the server reference quadrant is strong.
+The big problems were concentrated in one factually wrong page (FPGA `build-fpga-image`),
+one internally inconsistent page (server `streaming-tables` vs `fields`), and a handful of
+accuracy errors — all now fixed.
+
+---
+
+## A. Factual errors — ALL FIXED ✅
+
+### A1. FPGA `how-to/build-fpga-image.md` described a nonexistent kas/bitbake flow ✅ FIXED
+**Rewritten from scratch** around the real flow verified against the Makefile:
+`cp CONFIG.example CONFIG` → set `APP_NAME` (from `apps/*.app.ini`) and `VIVADO`/
+`VIVADO_VER` (default 2023.2) → `make` (≡ `make ipk`; `make all-ipks` for every app) →
+`build/panda-fpga-__all.ipk` → `scp` + `opkg install` (or Web Admin).
+Links to the dev-container setup and meta-panda deploy pages. *(Q2 confirmed by user:
+make-only, no kas path — clarifying sentence added to the page.)*
+
+### A2. FPGA `how-to/app.md` — wrong output format / variable ✅ FIXED
+zpkg → `.ipk` (`panda-fpga-__all.ipk`), `APPS = PandABox-no-fmc` →
+`APP_NAME = pandabox-no-fmc`, added `make all-ipks` and a link to `build-fpga-image`.
+*(The `*METADATA.APPNAME?` example was later user-confirmed as kebab-case following the
+`.ipk` name and corrected to `pandabox-fmc-24vio` — see What's left #6.)*
+
+### A3. meta-panda `reference/machine-targets.md` machine list ✅ FIXED
+Table now matches `conf/machine/`: dropped nonexistent `xu5-s1`, added `pandabox2`.
+`pandabrick` row de-flagged (it exists in-tree: `conf/machine/pandabrick.conf`); a verify
+comment now sits on `xu5-st1` (support tier unknown). **`create-issues.sh` updated to
+match**: I4 repurposed from "verify PandABrick" to "verify support tiers + details"
+(its sed retargeted to the new comment), I8's machine list corrected.
+
+### A4. server `streaming-tables.md` vs `fields.md` ✅ FIXED
+- MODE transition table corrected to match `fields.md` and legacy `fields.rst`:
+ `STREAMING` + `<` = Reject, `STREAMING_LAST` rejects all but `<0`, completed/`[HEALTH]`
+ row added; prose about the implicit FPGA completed state restored.
+- `B` description fixed (just base-64 content); the `left:right` format moved to a new,
+ correct `FIELDS` entry.
+- `LENGTH`/`MAX_LENGTH` now both say 32-bit **words** in both pages (fields.md summary
+ table rows fixed too).
+
+### A5. server `how-to/startup.md` ✅ FIXED
+Second `-p` → `-P` *pid-file*; added `-r` *rootfs-version* (reported via `*IDN?`).
+Verified against `server.c` getopt string and usage text.
+
+### A6. Capture-option drift across three pages ✅ FIXED (verified against `pos_out.c`)
+Ground truth from `server/pos_out.c` (`capture_option_info` + `nominal_capture_masks`):
+individual options Value/Diff/Sum/Mean/Min/Max/StdDev (StdDev only listed when the FPGA
+supports it); curated enums add No, Min Max, Min Max Mean, **Mean StdDev**.
+`capture-options.md` is now the true superset (combinations + full enum list, caution
+downgraded to a note); `capture.md` and `fields.md` gained the StdDev / Mean StdDev rows
+so all three pages agree. **Bonus fix found en route:** `commands.md` omitted the
+`METADATA` change group (`*CHANGES.METADATA` exists in `system_command.c`) — added to all
+four places. **I14 in `create-issues.sh` slimmed** to a ~30-min live-server confirmation
+(its sed replaced with a working perl substitution, dry-run tested).
+
+### A7. meta-panda `integrate-with-a-panda.md` wrong link ✅ FIXED
+Now points at the server commands reference (absolute Pages URL, Stage F swap comment).
+
+### A8. `Image` vs `image.ub` ✅ FIXED (Q6 answered by source)
+`build.sh:22` and `_make_boot.yml` copy the fitImage to **`image.ub`**; the boot archive
+contains `boot.bin, boot.scr, image.ub, rootfs.squashfs, target-defs`. `upgrade-via-ssh.md`
+corrected; all three pages now agree.
+
+### A9. `modules/lut/lut_doc.md` truncated sentence ✅ FIXED
+Restored the dropped cross-ref as a link to the server fields reference.
+
+### A10. fields.md loose ends ✅ FIXED (Q7 answered by source)
+- `*CHANGES.PARAM` → `*CHANGES.CONFIG` in both places. Verified: change groups in
+ `config_server.h`/`system_command.c` are CONFIG/BITS/POSN/READ/ATTR/TABLE/METADATA
+ (no PARAM); `param`/`time` classes use `CHANGE_IX_CONFIG` (`register.c:288`,
+ `time.c:374`).
+- enum `LABELS` attribute removed from the sub-type summary (no such attribute in the
+ server source; labels come via `*ENUMS`).
+
+## B. Web-control content provenance — ✅ RESOLVED (user confirmed against live UI)
+
+User answers (2026-06-11): port colours are only **Boolean = Blue** and **Int32 =
+Orange** (Motor/NDArray rows deleted); Exports/camelCase is correct; the method
+execution log is correct but there is only a **single method: *Save*** on the Parent
+Block (taking the design name as its input parameter); Auto Layout is accurate; the
+save dialog field is labelled **Design Name** — "Filename" appears nowhere in the GUI.
+All applied to `use-web-control-to-set-up-a-panda.md` and `save-restore-design.md`.
+**I2 restored to screenshot-only scope** (verification checklist removed).
+
+## C. Cross-link & asset integrity
+
+### C1. Figures served from `docs/_legacy_rst/` ✅ FIXED
+- meta-panda: all 19 referenced images copied to `docs/images/webcontrol/` and every
+ reference repointed (tutorial0, use-web-control, web-control-ui-overview,
+ monitor-attribute-values, understanding-attribute-state). Zero `_legacy_rst` image
+ refs remain.
+- FPGA: `build_arch.png` copied to `docs/images/` and `block.md` repointed.
+- `_legacy_rst/` deletion is now safe (images-wise) in both repos.
+
+### C2. Dead `meta-panda:` xrefs ✅ FIXED (Q8 decided: absolute URLs)
+The only offenders were in `build-fpga-image.md`, which was rewritten using absolute
+Pages URLs with `` comments (the same pattern server
+`capture.md` already used). Repo-wide grep confirms no `(meta-panda:` links remain.
+
+### C3. "Prompt C" runbook jargon in published page ✅ FIXED
+`understanding-attribute-state.md` placeholders reworded to *(icon pending)*; the HTML
+comments retain the `docs/images/attribute-state/.svg` target paths so Prompt C can
+still find them.
+
+### C4. PandABlocks-devcontainer ✅ RESOLVED — decision changed to per-repo devcontainers
+User decision (2026-06-11): **no separate PandABlocks-devcontainer repo.** Each repo
+carries its own `.devcontainer/devcontainer.json` + Dockerfile, modelled on
+python-copier-template (`ubuntu-devcontainer:noble` base, `developer` target), with
+repo-specific tools to be added. meta-panda alone uses the kas base
+(`ghcr.io/siemens/kas/kas:4.8`, matching `KAS_IMAGE_VERSION` in build.sh; placed at
+`.devcontainer/Dockerfile` because the root `Dockerfile` is the existing rockylinux
+FPGA-tools/CI container and must not be touched). Created in all three repos; all
+doc pointers updated (FPGA `local-development.md`, server `building.md` tip,
+meta-panda `contribute.md` xref table); commented `PandABlocks-devcontainer:`
+reference keys removed from all three `myst.yml` files; runbook Stage F prompt and
+one-time-setup step annotated as superseded.
+
+## D. Structure & gaps
+
+### D1. Root index Yocto-first framing ✅ FIXED
+`README.md` (included by the index) now opens with three sentences of PandABlocks-level
+framing — what a PandA is, what these docs cover, where component docs live — before the
+`meta-panda`-layer paragraph.
+
+### D2. Unboxing signpost ✅ FIXED
+`tutorials.md` landing and tutorial 0 prerequisites now point users whose PandA isn't on
+the network yet at `how-to/quickstart`.
+
+### D3. meta-panda how-to TOC ordering ✅ FIXED
+`docs/myst.yml` TOC rebanded: use (quickstart, use-web-control, save-restore, monitor,
+integrate) → administer (upgrade ×2, packages, choose-fpga-bitstream) → develop (build,
+manual-build, test-firmware-changes, make-release, contribute), with YAML comments
+marking the bands.
+
+### D4. FPGA block→deploy journey ✅ FIXED
+`block.md` gained a "Next steps" section chaining block → app → build-fpga-image →
+choose-fpga-bitstream; `how-to.md` landing gained a one-line pipeline overview.
+
+### D5. `CLOCKS` vs `CLOCK1` ✅ FIXED (Q5 answered by source)
+The shipped `template_tutorial1_leds.json` design uses `CLOCK1`/`CLOCK2`, and the firmware
+module is `modules/clock` (no CLOCKS block). Tutorial 1 corrected to **CLOCK1** in both
+places.
+
+### D6. Minor batch — MOSTLY FIXED
+- ✅ meta-panda glossary `App` entry now leads with `.ipk`, demotes zpkg to legacy; FPGA
+ glossary `App` entry now says `.ipk`, and its `Zpkg` entry gained the legacy/replaced
+ note.
+- ⏳ `web-control-ui-overview.md` **Auto Layout** — folded into the extended I2 (see §B).
+- ⏳ FPGA `framework.md` "needs a refresh" note still has no tracking issue (issues don't
+ exist yet — could be linked after the script runs, or left for Stage F).
+- ⏳ `finedelay-test.md` raw `PandABlocks.github.io` script URL — Stage F note unchanged.
+
+## E. Issue-script changes made ✅
+
+All applied to `create-issues.sh` (syntax-checked, every sed/perl target re-verified):
+1. **I2** — title + body extended with the §B live-UI verification checklist.
+2. **I4** — repurposed: machine list is now ground-truthed; remaining work is support
+ tiers (xu5-st1/zedboard) and Notes-column details (pandabox2/pandabrick); sed
+ retargeted to the new HTML comment in machine-targets.md.
+3. **I8** — machine list corrected to `conf/machine/` ground truth.
+4. **I14** — slimmed to a live-server confirmation of the now source-verified capture
+ options; broken sed replaced with a tested perl substitution.
+
+---
+
+(whats-left)=
+## What's left
+
+| # | Item | Why it needs you |
+|---|---|---|
+| 1 | ~~§B web-control content~~ | ✅ Resolved — user confirmed against live UI, all trims applied (see §B). |
+| 2 | ~~C4 devcontainer pointers~~ | ✅ Resolved — per-repo devcontainers created in all three repos (see C4). |
+| 3 | ~~README machine list~~ | ✅ Resolved — user confirmed (2026-06-12) xu5-st1 and zedboard are dev-only. README stays at three; `machine-targets.md` notes the tier split; I4 slimmed to pandabox2/pandabrick hardware details only (sed retargeted, verified). |
+| 4 | **framework.md refresh note** | Untracked "needs a refresh" flag — link to an issue after the script runs, or fold into Stage F. |
+| 5 | **finedelay script URL** | Stage F item: if PandABlocks.github.io becomes a redirect, the raw script needs a new home. |
+| 6 | ~~app.md `*METADATA.APPNAME?` example~~ | ✅ Resolved — user confirmed (2026-06-12): kebab-case, following the `.ipk` name (e.g. `panda-fpga-pandabox-fmc-acq430_4.2b1.ipk` → `pandabox-fmc-acq430`). Example corrected to `pandabox-fmc-24vio`; stale verify note removed. |
+
+## Remaining questions
+
+*All answered.* Q1 web control and Q4 devcontainer — user, see §B and C4. **Q2 (FPGA
+build)** — user confirmed (2026-06-12): FPGA is strictly make-driven, producing the
+`.ipk` with a custom script; no kas involved; meta-panda only *includes* that `.ipk`
+in the system image. A clarifying sentence was added to `build-fpga-image.md`. Former
+Q3 machine list, Q5 CLOCKS, Q6 image.ub, Q7 \*CHANGES group and Q8 interim links were
+all resolved against repo sources — see A3, D5, A8, A10, C2 above.
diff --git a/knowledge/PROGRESS-template.md b/knowledge/PROGRESS-template.md
new file mode 100644
index 00000000..ef85925e
--- /dev/null
+++ b/knowledge/PROGRESS-template.md
@@ -0,0 +1,32 @@
+# Docs Rewrite Progress —
+
+Tracks every target page for this repo. Update the relevant line **in the same commit** as the file
+it refers to. Statuses: ☐ todo · ◐ stub · ✅ converted · 🔍 needs-review · ⛔ blocked (→ issue #).
+Expand the page list for this repo from `06-source-provenance-map.md`.
+
+## Stage A — scaffold
+- ☐ skeleton instantiated (title/github/logo swapped, apidoc + pip-tutorial removed)
+- ☐ TOC + stubs for every target page present
+- ☐ `index.md` README-include + `how-to/contribute` CONTRIBUTING-include resolve
+- ☐ xref/intersphinx wired + cross-link probe resolves in built output
+- ☐ (FPGA only) module-docs surfacing decided + 42 paths build
+- ☐ `myst build` green
+- ☐ Pages deploy green
+
+## Tutorials
+- ☐ tutorials/ — source: —
+
+## How-to
+- ☐ how-to/ — source: —
+
+## Reference
+- ☐ reference/ — source: —
+
+## Explanations
+- ☐ explanations/ — source: —
+
+## Blocked (issues raised)
+- ⛔ — issue # —
+
+## Notes
+- (record any deviation from 03/06 here, with reason)
diff --git a/knowledge/docs-skeleton/explanations.md b/knowledge/docs-skeleton/explanations.md
new file mode 100644
index 00000000..a1dca5ac
--- /dev/null
+++ b/knowledge/docs-skeleton/explanations.md
@@ -0,0 +1,7 @@
+# Explanations
+
+Explanations of how it works and why it works that way.
+
+```{toc}
+:context: children
+```
diff --git a/knowledge/docs-skeleton/explanations/decisions.md b/knowledge/docs-skeleton/explanations/decisions.md
new file mode 100644
index 00000000..44e42668
--- /dev/null
+++ b/knowledge/docs-skeleton/explanations/decisions.md
@@ -0,0 +1,5 @@
+# Architectural Decision Records
+
+Architectural decisions are made throughout a project's lifetime. As a way of keeping track of these decisions, we record these decisions in Architecture Decision Records (ADRs) listed below.
+
+For more information on ADRs see this [blog by Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions).
diff --git a/knowledge/docs-skeleton/explanations/decisions/0001-record-architecture-decisions.md b/knowledge/docs-skeleton/explanations/decisions/0001-record-architecture-decisions.md
new file mode 100644
index 00000000..44d234ef
--- /dev/null
+++ b/knowledge/docs-skeleton/explanations/decisions/0001-record-architecture-decisions.md
@@ -0,0 +1,18 @@
+# 1. Record architecture decisions
+
+## Status
+
+Accepted
+
+## Context
+
+We need to record the architectural decisions made on this project.
+
+## Decision
+
+We will use Architecture Decision Records, as [described by Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions).
+
+## Consequences
+
+See Michael Nygard's article, linked above. To create new ADRs we will copy and
+paste from existing ones.
diff --git a/knowledge/docs-skeleton/explanations/decisions/0002-switched-to-python-copier-template.md b/knowledge/docs-skeleton/explanations/decisions/0002-switched-to-python-copier-template.md
new file mode 100644
index 00000000..66fe5d8b
--- /dev/null
+++ b/knowledge/docs-skeleton/explanations/decisions/0002-switched-to-python-copier-template.md
@@ -0,0 +1,28 @@
+# 2. Adopt python-copier-template for project structure
+
+## Status
+
+Accepted
+
+## Context
+
+We should use the following [python-copier-template](https://github.com/DiamondLightSource/python-copier-template).
+The template will ensure consistency in developer
+environments and package management.
+
+## Decision
+
+We have switched to using the template.
+
+## Consequences
+
+This module will use a fixed set of tools as developed in `python-copier-template`
+and can pull from this template to update the packaging to the latest techniques.
+
+As such, the developer environment may have changed, the following could be
+different:
+
+- linting
+- formatting
+- pip venv setup
+- CI/CD
diff --git a/knowledge/docs-skeleton/explanations/decisions/COPYME b/knowledge/docs-skeleton/explanations/decisions/COPYME
new file mode 100644
index 00000000..b466c792
--- /dev/null
+++ b/knowledge/docs-skeleton/explanations/decisions/COPYME
@@ -0,0 +1,19 @@
+# 3. Short descriptive title
+
+Date: Today's date
+
+## Status
+
+Accepted
+
+## Context
+
+Background to allow us to make the decision, to show how we arrived at our conclusions.
+
+## Decision
+
+What decision we made.
+
+## Consequences
+
+What we will do as a result of this decision.
diff --git a/knowledge/docs-skeleton/how-to.md b/knowledge/docs-skeleton/how-to.md
new file mode 100644
index 00000000..ba801fd7
--- /dev/null
+++ b/knowledge/docs-skeleton/how-to.md
@@ -0,0 +1,7 @@
+# How-to Guides
+
+Practical step-by-step guides for the more experienced user.
+
+```{toc}
+:context: children
+```
diff --git a/knowledge/docs-skeleton/how-to/contribute.md b/knowledge/docs-skeleton/how-to/contribute.md
new file mode 100644
index 00000000..6e419797
--- /dev/null
+++ b/knowledge/docs-skeleton/how-to/contribute.md
@@ -0,0 +1,2 @@
+```{include} ../../.github/CONTRIBUTING.md
+```
diff --git a/knowledge/docs-skeleton/how-to/run-container.md b/knowledge/docs-skeleton/how-to/run-container.md
new file mode 100644
index 00000000..48a6c98c
--- /dev/null
+++ b/knowledge/docs-skeleton/how-to/run-container.md
@@ -0,0 +1,14 @@
+# Run in a container
+
+Pre-built containers with python-copier-template-example and its dependencies already
+installed are available on [Github Container Registry](https://ghcr.io/DiamondLightSource/python-copier-template-example).
+
+## Starting the container
+
+To pull the container from github container registry and run:
+
+```
+$ docker run ghcr.io/diamondlightsource/python-copier-template-example:latest --version
+```
+
+To get a released version, use a numbered release instead of `latest`.
diff --git a/knowledge/docs-skeleton/images/PandA-logo-for-black-background.svg b/knowledge/docs-skeleton/images/PandA-logo-for-black-background.svg
new file mode 100644
index 00000000..f52449b4
--- /dev/null
+++ b/knowledge/docs-skeleton/images/PandA-logo-for-black-background.svg
@@ -0,0 +1,331 @@
+
+
+
+
diff --git a/knowledge/docs-skeleton/index.md b/knowledge/docs-skeleton/index.md
new file mode 100644
index 00000000..e65e5b02
--- /dev/null
+++ b/knowledge/docs-skeleton/index.md
@@ -0,0 +1,42 @@
+---
+site:
+ hide_outline: true
+---
+
+```{include} ../README.md
+:end-before:
diff --git a/knowledge/docs-skeleton/tutorials.md b/knowledge/docs-skeleton/tutorials.md
new file mode 100644
index 00000000..eac69798
--- /dev/null
+++ b/knowledge/docs-skeleton/tutorials.md
@@ -0,0 +1,7 @@
+# Tutorials
+
+Tutorials for installation and typical usage. New users start here.
+
+```{toc}
+:context: children
+```
diff --git a/knowledge/docs-skeleton/tutorials/installation.md b/knowledge/docs-skeleton/tutorials/installation.md
new file mode 100644
index 00000000..4342d8d8
--- /dev/null
+++ b/knowledge/docs-skeleton/tutorials/installation.md
@@ -0,0 +1,53 @@
+# Installation
+
+## Check your version of python
+
+You will need python 3.11 or later. You can check your version of python by
+typing into a terminal:
+
+```
+$ python3 --version
+```
+
+## Create a virtual environment
+
+It is recommended that you install into a “virtual environment” so this
+installation will not interfere with any existing Python software:
+
+```
+$ python3 -m venv /path/to/venv
+$ source /path/to/venv/bin/activate
+```
+
+## Installing the library
+
+You can now use `pip` to install the library and its dependencies:
+
+```
+$ python3 -m pip install dls-python-copier-template-example
+```
+
+If you require a feature that is not currently released you can also install
+from github:
+
+```
+$ python3 -m pip install git+https://github.com/DiamondLightSource/python-copier-template-example.git
+```
+
+The library should now be installed and the commandline interface on your path.
+You can check the version that has been installed by typing:
+
+```
+$ python-copier-template-example --version
+```
+
+## Verify the installation
+
+You can also verify the installation from a Python interpreter:
+
+```python
+>>> from python_copier_template_example import greet
+>>> greet("World")
+'Hello, World!'
+
+```