diff --git a/CLAUDE.md b/CLAUDE.md index d039e23..cffc7e2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,7 +10,7 @@ Use `docs/README.md` as the entrypoint for CC:Tweaked, Advanced Peripherals, and ## Constraints -- Do not run Lua locally or add a test harness unless asked; code executes in-game or CraftOS-PC. +- Do not add a standalone Lua test harness unless asked. Local execution happens through the CraftOS-PC harness (see `docs/install-craftos-pc.md` and ADR-0005); code otherwise executes in-game. - After editing Lua, run `just check` and fix all `luacheck` warnings. - Use 2-space indent, semicolons, and `local function`. - `require` paths are absolute ComputerCraft paths, for example `require('/apis/net')()`. diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index d84951e..aa0e5ac 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -3,6 +3,7 @@ Requirements: - `just` - `luacheck` +- [CraftOS-PC](docs/install-craftos-pc.md) ≥ v2.8.3 — local harness for the CC:Tweaked sandbox. After cloning the repository, run: @@ -10,4 +11,6 @@ After cloning the repository, run: just install ``` -This installs the local Git hooks, including a pre-push hook that runs `just check`. +This installs the local Git hooks, including a pre-commit hook that runs `just ci`. + +`just ci` is the local verification entry point. Today it verifies that `craftos --version` reports v2.8.3 or newer and runs `just check` for `luacheck`. `just test` is a placeholder for future CraftOS-PC headless integration tests. diff --git a/Justfile b/Justfile index feb8b47..fde5021 100644 --- a/Justfile +++ b/Justfile @@ -1,19 +1,62 @@ # Justfile for cc-libs -# Run `just check` to lint all Lua code with luacheck. +# Run `just ci` to verify local tooling and lint Lua code. # List available recipes. default: @just --list # Install local development tooling. -install: install-git-hooks +install: install-git-hooks check-craftos # Install Git hooks for this repository. install-git-hooks: @mkdir -p .git/hooks - @printf '%s\n' '#!/bin/sh' '' 'just check' > .git/hooks/pre-push - @chmod +x .git/hooks/pre-push - @printf '%s\n' 'Installed .git/hooks/pre-push' + @printf '%s\n' '#!/bin/sh' '' 'just ci' > .git/hooks/pre-commit + @chmod +x .git/hooks/pre-commit + @printf '%s\n' 'Installed .git/hooks/pre-commit' + +# Verify the CraftOS-PC harness is installed and recent enough. +check-craftos: + @command -v craftos >/dev/null 2>&1 || { \ + printf '%s\n' 'craftos not found on $PATH. See docs/install-craftos-pc.md.' >&2; \ + exit 1; \ + } + @version="$(craftos --version)"; \ + number="${version##* v}"; \ + case "$number" in \ + *.*.*) \ + ;; \ + *) \ + printf '%s\n' "$version"; \ + printf '%s\n' 'Could not parse CraftOS-PC version. See docs/install-craftos-pc.md.' >&2; \ + exit 1; \ + ;; \ + esac; \ + major="${number%%.*}"; \ + rest="${number#*.}"; \ + minor="${rest%%.*}"; \ + patch="${rest#*.}"; \ + patch="${patch%%[^0-9]*}"; \ + printf '%s\n' "$version"; \ + case "$major.$minor.$patch" in \ + *[!0-9.]*|.*|*..*|*.) \ + printf '%s\n' 'Could not parse CraftOS-PC version. See docs/install-craftos-pc.md.' >&2; \ + exit 1; \ + ;; \ + esac; \ + if ! { [ "${major:-0}" -gt 2 ] || \ + { [ "${major:-0}" -eq 2 ] && [ "${minor:-0}" -gt 8 ]; } || \ + { [ "${major:-0}" -eq 2 ] && [ "${minor:-0}" -eq 8 ] && [ "${patch:-0}" -ge 3 ]; }; }; then \ + printf '%s\n' 'CraftOS-PC v2.8.3 or newer is required. See docs/install-craftos-pc.md.' >&2; \ + exit 1; \ + fi + +# Local CI entry point used by Git hooks. +ci: check-craftos check test + +# Placeholder for future CraftOS-PC headless integration tests. +test: + @printf '%s\n' 'No CraftOS-PC headless integration tests yet.' # Lint all Lua source with luacheck. check: diff --git a/docs/adrs/README.md b/docs/adrs/README.md index cc2819e..93d3000 100644 --- a/docs/adrs/README.md +++ b/docs/adrs/README.md @@ -12,3 +12,4 @@ Future ADRs can reuse the shape of the existing files when it is useful. - [`adr-0002-use-eventloop-for-async-code.md`](adr-0002-use-eventloop-for-async-code.md) - Use eventloop for async code. - [`adr-0003-current-net-api-state.md`](adr-0003-current-net-api-state.md) - Current net API state. - [`adr-0004-trapos-branding-and-manifest.md`](adr-0004-trapos-branding-and-manifest.md) - TrapOS branding and manifest-driven installs. +- [`adr-0005-craftos-pc-harness.md`](adr-0005-craftos-pc-harness.md) - CraftOS-PC as the local harness. diff --git a/docs/adrs/adr-0005-craftos-pc-harness.md b/docs/adrs/adr-0005-craftos-pc-harness.md new file mode 100644 index 0000000..07db332 --- /dev/null +++ b/docs/adrs/adr-0005-craftos-pc-harness.md @@ -0,0 +1,44 @@ +# ADR 0005: CraftOS-PC As The Local Harness + +## Status + +Accepted + +## Date + +2026-06-08 + +## Context + +This repository targets CC:Tweaked on Minecraft 1.21. The Lua we ship runs inside the ComputerCraft sandbox: it depends on `os.pullEventRaw`, `peripheral`, `rednet`, `textutils.serializeJSON`, modem channels, and a handful of CC-specific globals. Standard Lua (or LuaJIT) cannot execute this code as-is, so a normal local test harness was never a serious option. + +In practice contributors have been running the code in two places: + +- In-game on a real Minecraft server, which is slow to iterate on. +- In **CraftOS-PC** (https://www.craftos-pc.cc/), a desktop emulator that ships the same ROM/BIOS as CC:Tweaked, supports modem peripherals via `periphemu`, and can run fully headless (`--cli --headless --script `). + +CraftOS-PC has been the *de facto* local harness for months, but that fact lived only as a single line in `CLAUDE.md`. There was no install guide, no minimum version, and `just install` did not check that the binary was present. The recent upgrade from v2.6.6 → v2.8.3 (the first one in years) made it obvious that this dependency needed to be made explicit. + +## Decision + +Treat CraftOS-PC as a first-class local development dependency. + +- **Minimum version `v2.8.3`** — recent enough to have the current CC:Tweaked ROM, old enough that contributors already on a 2.8.x build will not be forced to upgrade again immediately. +- **Documented install** in [`docs/install-craftos-pc.md`](../install-craftos-pc.md), with a SHA-256-verified macOS flow and pointers to the official Windows/Linux artifacts. +- **Verified by `just install`** via a `check-craftos` recipe that runs `craftos --version` and requires v2.8.3 or newer. Failure prints a one-line pointer to the install guide instead of a long stack trace. +- **`just ci` is the local verification entry point.** Today it runs `check-craftos` and `check`. The installed pre-commit hook invokes `just ci` directly. `just test` exists as the future home for CraftOS-PC-driven smoke tests. + +The existing `CLAUDE.md` constraint ("Do not run Lua locally or add a test harness unless asked") is reframed rather than removed: there is still no standalone Lua harness, and we are not adding a Busted-style test runner. The harness *is* CraftOS-PC, invoked deliberately. + +## Consequences + +- Contributors must install CraftOS-PC before `just install` succeeds. The install guide makes this a 4-step copy/paste on macOS. +- Future smoke tests have a clear home: a script under `tests/` (or similar) driven by `craftos --cli --headless --script tests/smoke.lua`, called from `just test`. +- The harness version becomes a project-level concern. When CC:Tweaked ships breaking changes that require a newer CraftOS-PC build, we bump the minimum version in `docs/install-craftos-pc.md` and `check-craftos` keeps contributors honest. +- No CI integration yet. Running CraftOS-PC headless in GitHub Actions is feasible (the AppImage works on Ubuntu runners) but is out of scope here; the contract is local-only for now. + +## Future Work + +- **Headless smoke test.** A `tests/smoke.lua` that boots an emulated computer, `require`s `/apis/eventloop`, `/apis/net`, and the router, and asserts the wiring loads without errors. Hooked into `just test`, then into `just ci` when it is ready to run on every commit. +- **CI.** Run the smoke test on push using the Linux AppImage. +- **Pinned ROM.** CraftOS-PC ships its own copy of the CC:Tweaked ROM per release. If we ever need to test against a specific in-game version, point CraftOS-PC at a vendored ROM via `--rom`. diff --git a/docs/install-craftos-pc.md b/docs/install-craftos-pc.md new file mode 100644 index 0000000..76ca6e9 --- /dev/null +++ b/docs/install-craftos-pc.md @@ -0,0 +1,69 @@ +# Install CraftOS-PC + +CraftOS-PC is the local harness used to run this repo's Lua outside of Minecraft. See [ADR-0005](adrs/adr-0005-craftos-pc-harness.md) for why. + +Minimum version: **v2.8.3**. `just install` runs `craftos --version` to verify it is on `$PATH` and recent enough. + +The upstream installation page is https://www.craftos-pc.cc/docs/installation. The notes below pin the version we test against and add a SHA-256 verification step. + +## macOS + +There is no Homebrew cask, so the install is a manual drag-to-Applications from the official GitHub release. + +```sh +# 1. Download the dmg and the published hashes. +curl -L -o ~/Downloads/CraftOS-PC.dmg \ + https://github.com/MCJack123/craftos2/releases/download/v2.8.3/CraftOS-PC.dmg + +# 2. Verify the SHA-256. +curl -sL https://github.com/MCJack123/craftos2/releases/download/v2.8.3/sha256-hashes.txt \ + | grep CraftOS-PC.dmg +shasum -a 256 ~/Downloads/CraftOS-PC.dmg +# The two hashes must match. + +# 3. Mount, install, unmount. +hdiutil attach ~/Downloads/CraftOS-PC.dmg -nobrowse +rm -rf /Applications/CraftOS-PC.app +cp -R "/Volumes/CraftOS-PC/CraftOS-PC.app" /Applications/ +hdiutil detach "/Volumes/CraftOS-PC" + +# 4. Clear Gatekeeper quarantine so the first launch is not blocked. +xattr -dr com.apple.quarantine /Applications/CraftOS-PC.app +``` + +The binary is not on `$PATH` by default. Add a symlink so `just check-craftos` can find it: + +```sh +ln -sf /Applications/CraftOS-PC.app/Contents/MacOS/craftos /usr/local/bin/craftos +``` + +User data (computer state, settings) lives in `~/Library/Application Support/CraftOS-PC` and survives a reinstall — the steps above only touch the `.app` bundle. + +## Windows + +Download `CraftOS-PC-Setup.exe` from the [latest release](https://github.com/MCJack123/craftos2/releases/latest) and run it. The installer puts `craftos.exe` on `$PATH`. + +User data: `%appdata%\CraftOS-PC`. + +## Linux + +Download `CraftOS-PC.x86_64.AppImage` from the [latest release](https://github.com/MCJack123/craftos2/releases/latest), make it executable, and symlink it into `$PATH`: + +```sh +chmod +x ~/Downloads/CraftOS-PC.x86_64.AppImage +sudo ln -sf "$HOME/Downloads/CraftOS-PC.x86_64.AppImage" /usr/local/bin/craftos +``` + +User data: `~/.local/share/craftos-pc`. + +## Verify + +```sh +craftos --version +``` + +Must report `CraftOS-PC v2.8.3` or newer. Once this works, `just install` will succeed. + +## Updating + +Repeat the steps above against the newer release. The bundle replacement is in-place; the user data directory is preserved.