From 0764e85002de7d840933b2e15f48f07032760e4f Mon Sep 17 00:00:00 2001 From: Nicholas Gowan Date: Sat, 17 Oct 2026 18:41:43 +0800 Subject: [PATCH 1/2] Add self-installing macOS launcher and explicit per-platform download table --- .github/workflows/release-assets.yml | 13 +++- README.md | 38 ++++++++--- Start PacePaper.command | 84 +++++++++++++++++++++---- USER_GUIDE.html | 14 ++--- USER_GUIDE.md | 14 ++--- docs/wechat-qr.png | Bin 0 -> 320978 bytes package.json | 2 +- release/README.md | 22 +++---- release/RELEASE_NOTES-0.1.0-demo.21.md | 24 +++++++ scripts/build-release.ts | 17 ++++- scripts/release-platforms.test.ts | 6 +- scripts/release-platforms.ts | 4 +- 12 files changed, 183 insertions(+), 55 deletions(-) create mode 100644 docs/wechat-qr.png create mode 100644 release/RELEASE_NOTES-0.1.0-demo.21.md diff --git a/.github/workflows/release-assets.yml b/.github/workflows/release-assets.yml index 7436460..4465b91 100644 --- a/.github/workflows/release-assets.yml +++ b/.github/workflows/release-assets.yml @@ -7,7 +7,7 @@ on: tag: description: Existing draft release tag required: true - default: v0.1.0-demo.20 + default: v0.1.0-demo.21 type: string include_macos: description: Include macOS (requires Developer ID signing and Apple notarization secrets) @@ -168,7 +168,7 @@ jobs: if [[ "$INCLUDE_MACOS" = "true" ]]; then bun run release:build else - bun run release:build --platforms=windows-x64,linux-x64 + bun run release:build --platforms=macos-source,windows-x64,linux-x64 fi - name: Verify built bundles @@ -178,6 +178,7 @@ jobs: run: | set -euo pipefail files=( + "release/PacePaper-${VERSION}-macos-source.zip" "release/PacePaper-${VERSION}-windows-x64.zip" "release/PacePaper-${VERSION}-linux-x64.tar.gz" "release/PacePaper-${VERSION}-User-Guide.html" @@ -197,6 +198,11 @@ jobs: (cd release && shasum -a 256 -c SHA256SUMS.txt) unzip -tq "release/PacePaper-${VERSION}-windows-x64.zip" tar -tzf "release/PacePaper-${VERSION}-linux-x64.tar.gz" >/dev/null + unzip -tq "release/PacePaper-${VERSION}-macos-source.zip" + source_package="PacePaper-${VERSION}-macos-source" + unzip -p "release/PacePaper-${VERSION}-macos-source.zip" "${source_package}/Start PacePaper.command" > "$RUNNER_TEMP/Start PacePaper.command" + bash -n "$RUNNER_TEMP/Start PacePaper.command" + unzip -p "release/PacePaper-${VERSION}-macos-source.zip" "${source_package}/package.json" | cmp package.json - if [[ "$INCLUDE_MACOS" = "true" ]]; then unzip -tq "release/PacePaper-${VERSION}-macos-universal.zip" extracted_mac="$RUNNER_TEMP/digitaldp-mac-verification" @@ -231,6 +237,7 @@ jobs: release/PacePaper-${{ steps.meta.outputs.version }}-macos-universal.zip release/PacePaper-${{ steps.meta.outputs.version }}-windows-x64.zip release/PacePaper-${{ steps.meta.outputs.version }}-linux-x64.tar.gz + release/PacePaper-${{ steps.meta.outputs.version }}-macos-source.zip release/PacePaper-${{ steps.meta.outputs.version }}-User-Guide.html release/PacePaper-${{ steps.meta.outputs.version }}-User-Guide.txt release/PacePaper-${{ steps.meta.outputs.version }}-Release-Notes.txt @@ -243,6 +250,7 @@ jobs: run: | set -euo pipefail files=( + "release/PacePaper-${VERSION}-macos-source.zip" "release/PacePaper-${VERSION}-windows-x64.zip" "release/PacePaper-${VERSION}-linux-x64.tar.gz" "release/PacePaper-${VERSION}-User-Guide.html" @@ -286,6 +294,7 @@ jobs: `PacePaper-${version}-User-Guide.txt`, `PacePaper-${version}-Release-Notes.txt`, "SHA256SUMS.txt", + `PacePaper-${version}-macos-source.zip`, ]; if (process.env.INCLUDE_MACOS === "true") expected.push(`PacePaper-${version}-macos-universal.zip`); diff --git a/README.md b/README.md index 3ec7f90..90bbdbb 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,27 @@ PacePaper is a local-network workspace for supervised examination practice and c PacePaper is an independent school-practice tool. It is not an official examination-delivery system, is not affiliated with or endorsed by the International Baccalaureate, Cambridge University Press & Assessment, Pearson, College Board, ACT, or any other awarding body, and should not be used to deliver live high-stakes examinations. +![WeChat contact QR code for PacePaper](docs/wechat-qr.png) + +## Download and run + +| Your computer | What to do | +| --- | --- | +| **Windows 10/11 (x64)** | Download `PacePaper-0.1.0-demo.21-windows-x64.zip`, extract it, and run `PacePaper.exe`. Nothing to install; works offline. | +| **Linux (x64)** | Download `PacePaper-0.1.0-demo.21-linux-x64.tar.gz`, extract it, and run `PacePaper`. Nothing to install; works offline. | +| **macOS (Apple silicon or Intel)** | Download `PacePaper-0.1.0-demo.21-macos-source.zip`, extract it, and double-click `Start PacePaper.command`. The launcher offers to install Bun and installs dependencies; first launch needs internet. | + +**These downloads are unsigned, so your computer may warn you the first time.** + +- **Windows:** SmartScreen may show “Windows protected your PC”. Choose **More info → Run anyway**. +- **macOS:** If the launcher cannot be opened, right-click it and choose **Open**, or run once in Terminal: + `xattr -d com.apple.quarantine "$HOME/Downloads/PacePaper-0.1.0-demo.21-macos-source/Start PacePaper.command"` + +PacePaper needs no account or licence key. The bundled sample and ordinary classroom use work offline apart from local-network sharing; optional YouTube or externally hosted HTTPS video needs internet unless hosted on the school network. + ## Try PacePaper in two minutes -**Download the latest demo** for Windows or Linux from the [releases page](https://github.com/GowangInc/PacePaper/releases). Extract the archive, open `PacePaper.exe` (Windows) or `PacePaper` (Linux), and your browser opens the teacher dashboard automatically. There is nothing to install — no Bun, no server setup, no internet connection required. Mac users can run the current source with `Start PacePaper.command` after installing [Bun](https://bun.sh/). +Use the **Download and run** table above to choose the Windows, Linux, or macOS download. On first launch you sign in with the default teacher login **`admin` / `admin`** (change it any time from the **Settings** section), and the Paper library already contains one preloaded **Sample paper** with no subject or IB branding. Open it, start a session, and you can try the whole workflow immediately — classes, timed phases, the candidate view, autosave, focus alerts, and printing — without creating anything first. @@ -142,13 +160,13 @@ The development server listens on `127.0.0.1:9148` by default. `public/index.htm ## For developers — build the desktop releases -The release builder produces shareable, self-contained macOS, Windows, and Linux bundles. They use the normal browser for the existing teacher dashboard and printing workflow; Bun, Node.js, the source checkout, and `public/` folder are not required on the recipient computer. +The release builder creates self-contained Windows and Linux bundles plus a macOS source archive. With Apple signing and notarization credentials, it can also create a signed universal macOS application. Packaged applications use the normal browser for the teacher dashboard and printing; the source archive contains the project files needed by its launcher. -The Mac bundle must be signed with a Developer ID Application certificate and notarized by Apple. The release builder deliberately refuses to create an ad-hoc-signed Mac download, because Gatekeeper can report that download as damaged without offering **Open Anyway**. +The compiled Mac application bundle must be signed with a Developer ID Application certificate and notarized by Apple. The release builder refuses to create an ad-hoc-signed app because Gatekeeper can report it as damaged without offering **Open Anyway**. The source archive does not require Apple signing. -**Version 0.1.0-demo.20 is prepared for Windows x64 and Linux x64.** Student sign-in is intentionally low-friction for a trusted school network: students choose their class and name from the active roster, with no PINs or direct links. Candidate saves use revision checks, and safe exam ending waits for each active candidate's latest save unless the teacher records an override reason. Startup database checks and verified pre-migration snapshots protect existing work. The release retains teacher-only marking controls and is not an official examination-delivery system. +**Version 0.1.0-demo.21 ships Windows x64 and Linux x64 applications plus a macOS source archive for Apple-silicon and Intel Macs.** Student sign-in is intentionally low-friction for a trusted school network: students choose their class and name from the active roster, with no PINs or direct links. Candidate saves use revision checks, and safe exam ending waits for each active candidate's latest save unless the teacher records an override reason. Startup database checks and verified pre-migration snapshots protect existing work. The release retains teacher-only marking controls and is not an official examination-delivery system. -Once the signing and notarization credentials described below are available, run `bun run release:build`. The generated archives, standalone user guides, and checksums are placed in `release/`. On macOS, use the notarized `macos-universal` archive for both Apple-silicon and Intel Macs; extract the correct platform archive and start its PacePaper app or executable. The macOS bundle and Windows executable carry the PacePaper icon; the Linux archive includes the matching PNG for desktop integration. A packaged release automatically opens the teacher dashboard on the first available local port from `9148` through `9158`, so the address may be different from `9148` when another local instance is running. The initial release is intentionally offline: it makes no licence, activation, telemetry, or other network call. See the illustrated teacher-facing [`USER_GUIDE.html`](USER_GUIDE.html), its editable [`USER_GUIDE.md`](USER_GUIDE.md) source, and [`release/README.md`](release/README.md) for concise install, storage, signing, and classroom-sharing notes. +Run `bun run release:build` to generate selected archives, standalone user guides, release notes, and checksums in `release/`. Without Apple release credentials, build the unsigned macOS source archive and the Windows/Linux applications with `bun run release:build --platforms=macos-source,windows-x64,linux-x64`; the source ZIP is built from the committed tree. With Developer ID and notarization credentials, the default build also produces a signed universal macOS app. Packaged applications open the teacher dashboard on the first available local port from `9148` through `9158`. See the illustrated [`USER_GUIDE.html`](USER_GUIDE.html), its editable [`USER_GUIDE.md`](USER_GUIDE.md) source, and [`release/README.md`](release/README.md) for install, storage, signing, and classroom-sharing details. ### macOS release credentials @@ -164,13 +182,13 @@ Set `DIGITALDP_MAC_NOTARY_KEYCHAIN` as well when the notary profile is stored in The GitHub release workflow performs the same process using these repository secrets: `APPLE_DEVELOPER_ID_P12_BASE64`, `APPLE_DEVELOPER_ID_P12_PASSWORD`, `APPLE_NOTARY_KEY_BASE64`, `APPLE_NOTARY_KEY_ID`, and `APPLE_NOTARY_ISSUER_ID`. Do not put certificate passwords or private keys in this repository. -To build only Windows and Linux without Apple credentials, explicitly select them: +To build the Windows/Linux applications and macOS source archive without Apple credentials: ```sh -bun run release:build --platforms=windows-x64,linux-x64 +bun run release:build --platforms=macos-source,windows-x64,linux-x64 ``` -For the GitHub workflow, set `include_macos` to `false` for that same platform set. The default still includes macOS and requires successful signing and notarization. Keep the release as a draft until the build and native Windows/Linux startup checks pass; publish only the files listed in that build's `SHA256SUMS.txt` plus the checksum file itself. +The source ZIP is built from the committed Git tree. The GitHub workflow builds this platform set when `include_macos` is `false`; its default also builds the signed and notarized `macos-universal` app. Keep the release as a draft until the build and native Windows/Linux startup checks pass; publish only the files listed in `SHA256SUMS.txt` plus the checksum file itself. The current release builder keeps data outside the replaceable executable, in the per-user application-data location for the platform. It does not package a live database, teacher paper, student response, or protected reference material. A fresh release seeds one generic **Sample paper** with no subject, level, or IB branding, so new users can try the exam workflow immediately; teacher-created and imported papers remain in the local library. Previously downloaded apps retain the code and examples from their own release; source edits do not update those downloads. The teacher login remains `admin` / `admin` and is reset on every app launch; it is not suitable for real student data. @@ -203,7 +221,7 @@ Open the room clock from the specific session for a projector or second screen. Linked clocks follow authoritative timing across windows, independently of decorative titles and names. Timing saves reject stale edits from another window. For a simple paper, reading and writing minutes can be corrected from the clock while the exam is ready or live: a live save moves candidate phase boundaries and deadlines immediately, which is the fastest recovery when a sitting must be extended. Ended exams and fixed timed sections remain read-only. Mounted student views refresh their server timeline without replacing editors. Check the student view before a classroom trial. -Each published build is summarized in its release notes. See the [current release notes](release/RELEASE_NOTES-0.1.0-demo.20.md) for what ships and the verification limits. +Each published build is summarized in its release notes. See the [current release notes](release/RELEASE_NOTES-0.1.0-demo.21.md) for what ships and the verification limits. Teacher-facing **Remove** actions archive records instead of permanently deleting them. Removed students cannot sign in, removed classes are unavailable for new sittings, and removed sittings disappear from the active exam list; all remain available under the corresponding **Removed** disclosure for restoration. Existing submissions stay retained and printable. Live sittings cannot be removed, classes with a live sitting must be ended first, and a student with unfinished live work cannot be removed until that response is submitted or the sitting ends. @@ -255,4 +273,4 @@ Before a classroom pilot, also test the complete teacher and student journey on ## License and support -PacePaper is open source under the [MIT License](LICENSE). The PacePaper name and icon artwork are not part of the MIT grant (see the notice in the LICENSE file). This is an independent project with no affiliation to any awarding body; it is provided for school practice and familiarisation. +PacePaper is open source under the [MIT License](LICENSE). The PacePaper name and icon artwork are not part of the MIT grant (see [TRADEMARK.md](TRADEMARK.md)). This is an independent project with no affiliation to any awarding body; it is provided for school practice and familiarisation. diff --git a/Start PacePaper.command b/Start PacePaper.command index 9fee1c7..62b0b33 100755 --- a/Start PacePaper.command +++ b/Start PacePaper.command @@ -1,20 +1,82 @@ -#!/bin/zsh +#!/bin/bash +# PacePaper — macOS double-click launcher (runs from source). +# +# Double-click this file in Finder. It checks for Bun, offers to install it if missing, +# installs npm dependencies on first run, then starts PacePaper and opens your browser. +# Keep the Terminal window open while PacePaper is in use; Control-C stops it. +# +# This file needs the project folder beside it (package.json, server.ts, src/, public/). set -u +cd "$(dirname "$0")" || exit 1 +export PATH="$HOME/.bun/bin:/opt/homebrew/bin:/usr/local/bin:$PATH" -cd -- "${0:A:h}" || exit 1 -export PATH="${HOME}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:${PATH}" +pause_then_exit() { + [ -t 0 ] && { echo; read -r -p "Press Return to close this window. " _; } + exit "${1:-1}" +} +say() { printf '%s\n' "$1"; } + +# --- 1. Bun ----------------------------------------------------------------- if ! command -v bun >/dev/null 2>&1; then - echo "PacePaper needs Bun to run from source. Install Bun, then open this file again." - echo "https://bun.sh/" - echo - read -r "?Press Return to close this window." - exit 1 + say "" + say "PacePaper runs from source with Bun (https://bun.sh), which isn't installed yet." + say "" + say "Install it, then double-click this file again:" + say " curl -fsSL https://bun.sh/install | bash" + if [ -t 0 ]; then + echo + read -r -p "Install Bun now? [y/N] " answer + case "$answer" in + [yY]*) + say "" + say "Installing Bun..." + if ! curl -fsSL https://bun.sh/install | bash; then + say "" + say "Bun's installer failed. Check your internet connection, then try again." + pause_then_exit 1 + fi + export PATH="$HOME/.bun/bin:$PATH" + if ! command -v bun >/dev/null 2>&1; then + say "" + say "Bun was installed but isn't on the PATH yet. Close this window, open it again, and retry." + pause_then_exit 1 + fi + ;; + *) + say "" + say "Nothing was installed. PacePaper needs Bun to start." + pause_then_exit 1 + ;; + esac + else + pause_then_exit 1 + fi +fi + +# --- 2. Gatekeeper quarantine ---------------------------------------------- +if command -v xattr >/dev/null 2>&1 && xattr -p com.apple.quarantine "$0" >/dev/null 2>&1; then + say "" + say "Note: macOS quarantined this download. If double-clicking does nothing, run this once in Terminal:" + say " xattr -d com.apple.quarantine \"$0\"" +fi + +# --- 3. Dependencies (first run, or after package.json changes) ------------- +if [ ! -d node_modules ] || [ package.json -nt node_modules ]; then + say "" + say "Installing dependencies (this happens once)..." + if ! bun install; then + say "" + say "Dependency install failed. PacePaper needs an internet connection for this first step." + pause_then_exit 1 + fi fi -echo "Starting PacePaper from source. Keep this window open while the app is in use." -echo "Press Control-C here when you want to stop PacePaper." -echo +# --- 4. Start --------------------------------------------------------------- +say "" +say "Starting PacePaper. Keep this window open while the app is in use." +say "Press Control-C here when you want to stop PacePaper." +say "" exec bun run start:app diff --git a/USER_GUIDE.html b/USER_GUIDE.html index c3aaaab..e5f5146 100644 --- a/USER_GUIDE.html +++ b/USER_GUIDE.html @@ -251,7 +251,7 @@

PacePaper teacher guide

This step-by-step guide covers the current PacePaper classroom demo. PacePaper runs on one teacher computer. Students use a browser to connect to that computer through the school network. Start with the guide supplied with your app download; an older download may not include features described in a newer guide.

-

This guide matches PacePaper 0.1.0-demo.19.

+

This guide matches PacePaper 0.1.0-demo.21.

PacePaper is for practice and candidate familiarisation only. It does not deliver an official examination. A fresh installation starts with one preloaded Sample paper that has no subject, level, or IB branding, so you can try the whole exam workflow before building your own. An older app download does not update itself; use the guide supplied with your version.

The four parts of the teacher dashboard

Use the left-hand menu to move between these areas:

@@ -287,18 +287,18 @@

Quick classroom checklist

The detailed instructions below follow the same order.

Step 1 — Start PacePaper

-

PacePaper is a portable app, not an installer. Extract the complete download before opening it.

+

The Windows and Linux downloads are portable apps, not installers. The Mac download is a source archive, not a native app. Extract the complete download before starting it.

- - - + + +
ComputerDownloadOpen
Apple-silicon or Intel MacUse the source option belowStart PacePaper.command
Windows x64windows-x64.zipPacePaper.exe
Linux x64linux-x64.tar.gzPacePaper
Apple-silicon or Intel MacPacePaper-0.1.0-demo.21-macos-source.zipStart PacePaper.command
Windows 10/11 x64PacePaper-0.1.0-demo.21-windows-x64.zipPacePaper.exe
Linux x64PacePaper-0.1.0-demo.21-linux-x64.tar.gzPacePaper
-

Download the latest release bundle for Windows or Linux from the project's releases page. There is no Mac app bundle; on a Mac, install Bun and follow Run from a source checkout below, with IT help for the one-time setup.

+

The Mac download is a source archive, not a compiled app. Extract the complete archive and double-click the launcher. If Bun is missing, it offers to install Bun and installs the dependencies; the first launch needs internet. Windows and Linux downloads are self-contained and work offline with bundled content. YouTube and externally hosted HTTPS videos need internet unless hosted on the school network.

  1. Open PacePaper once on the teacher computer.
  2. Leave the application running for the whole lesson.
  3. @@ -640,7 +640,7 @@

    Student quick instructions

    These independently implemented tools are for practice and are not validated replacements for approved physical calculators. The calculator does not provide CAS, proprietary firmware or document formats, saved programs, general spreadsheets, geometry, 3D graphing or model certification. Expressions are capped at 1000 characters, lists/sequences at 1000 entries, matrices at 20×20 and polynomial roots at degree 6. Quartiles use linear interpolation, which can differ from a physical calculator. Open Supported functions and keyboard controls inside the calculator for commands and conventions.

    Troubleshooting