diff --git a/CLAUDE.md b/CLAUDE.md index 053fe2b..0deee74 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,16 +6,16 @@ Concise guidance for agents working in this repository. ComputerCraft / CC:Tweaked Lua APIs, servers, and programs for Minecraft 1.21. Code runs in the ComputerCraft sandbox, not standard Lua. -Use `docs/README.md` as the entrypoint for CC:Tweaked, CraftOS-PC, Advanced Peripherals, and Create integration documentation links. Use `docs/adrs/README.md` for repository architecture decisions. +Use [`docs/README.md`](docs/README.md) as the entrypoint for CC:Tweaked, CraftOS-PC, Advanced Peripherals, and Create integration documentation links. Use [`docs/adrs/README.md`](docs/adrs/README.md) for repository architecture decisions. ## Constraints -- Do not add a standalone Lua test harness unless asked. Local execution happens through the CraftOS-PC harness (see `docs/install-craftos-pc.md`, `docs/craftos_pc_glossary.md`, and ADR-0005); code otherwise executes in-game. -- Do not run `just repl` as an LLM agent; it is a human-only interactive CraftOS-PC wrapper. Use `just trapos --headless --exec '; os.shutdown()'` for automated probes against the TrapOS dev environment, or `just craftos --headless --exec '; os.shutdown()'` for probes against vanilla CraftOS (no TrapOS mounts). Headless probes are the recommended way to verify hypotheses about CC:Tweaked behavior; see ADR-0012. +- Do not add a standalone Lua test harness unless asked. Local execution happens through the CraftOS-PC harness (see [`docs/install-craftos-pc.md`](docs/install-craftos-pc.md), [`docs/craftos_pc_glossary.md`](docs/craftos_pc_glossary.md), and [ADR-0005](docs/adrs/adr-0005-craftos-pc-harness.md)); code otherwise executes in-game. +- Do not run `just repl` as an LLM agent; it is a human-only interactive CraftOS-PC wrapper. Use `just trapos --headless --exec '; os.shutdown()'` for automated probes against the TrapOS dev environment, or `just craftos --headless --exec '; os.shutdown()'` for probes against vanilla CraftOS (no TrapOS mounts). Headless probes are the recommended way to verify hypotheses about CC:Tweaked behavior; see [ADR-0012](docs/adrs/adr-0012-headless-craftos-pc-as-hypothesis-probe.md). - When changing behavior, add as many useful CraftOS-PC tests as practical. It is acceptable to skip tests that require human-only validation, such as complex turtle motion, in-game UX feel, or visual approval, but still add unit-style non-regression tests for deterministic parts when possible. - Use `/apis/libtest.lua` for test scripts under `tests/`; `/programs/runtest.lua` prints `__TRAPOS_TEST_OK__` only after the suite passes. -- `libtest` cancels each case after `3`s (`--timeout ` / `--no-timeout` to override); never commit a hanging test to `tests/`. Slow harness fixtures go in `tests/harness/` behind dedicated recipes. See `docs/adrs/adr-0009-layered-test-timeouts.md`. -- Git hooks own commit/push verification: pre-commit runs `just check test`, and pre-push runs `just ci`. When explicitly asked to commit and/or push, do not run `just test` manually first; rely on the hooks. See `docs/adrs/adr-0011-git-hooks-own-commit-push-verification.md`. +- `libtest` cancels each case after `3`s (`--timeout ` / `--no-timeout` to override); never commit a hanging test to `tests/`. Slow harness fixtures go in `tests/harness/` behind dedicated recipes. See [`docs/adrs/adr-0009-layered-test-timeouts.md`](docs/adrs/adr-0009-layered-test-timeouts.md). +- Git hooks own commit/push verification: pre-commit runs `just check test`, and pre-push runs `just ci`. When explicitly asked to commit and/or push, do not run `just test` manually first; rely on the hooks. See [`docs/adrs/adr-0011-git-hooks-own-commit-push-verification.md`](docs/adrs/adr-0011-git-hooks-own-commit-push-verification.md). - After editing Lua or Markdown, run `just check` and fix all `luacheck` warnings and `lychee` broken-link reports (markdown link validation is offline-only via `just lint-markdown`). - Use 2-space indent, semicolons, and `local function`. - `require` paths are absolute ComputerCraft paths, for example `require('/apis/net')()`. @@ -33,8 +33,8 @@ Use `docs/README.md` as the entrypoint for CC:Tweaked, CraftOS-PC, Advanced Peri ## Boot And Install - `startup/servers.lua` starts `/programs`, the shell, and configured servers via `parallel.waitForAll`. -- Preserve `periphemu` guards used for CraftOS-PC emulation; see `docs/craftos_pc_glossary.md` for upstream emulator references. -- TrapOS ships as packages, each described by `packages//ccpm.json` (`name`, `version`, `dependencies`, `files`, `autostart`); `packages/index.json` lists them. Source files stay in place — descriptors only reference them. To ship a new file, add it to the right package's `files` (and `autostart` if it is a server). `packages/trapos/ccpm.json` is the full OS meta-package. See ADR-0010. +- Preserve `periphemu` guards used for CraftOS-PC emulation; see [`docs/craftos_pc_glossary.md`](docs/craftos_pc_glossary.md) for upstream emulator references. +- TrapOS ships as packages, each described by `packages//ccpm.json` (`name`, `version`, `dependencies`, `files`, `autostart`); `packages/index.json` lists them. Source files stay in place — descriptors only reference them. To ship a new file, add it to the right package's `files` (and `autostart` if it is a server). `packages/trapos/ccpm.json` is the full OS meta-package. See [ADR-0010](docs/adrs/adr-0010-ccpm-package-manager.md). - `install-ccpm.lua` is the one-time wget bootstrap. It installs only `tos-core`/`ccpm`, seeds the default `guillaumearm/cc-libs` registry on `master` (or `next` with `--beta`), and tells users to run `ccpm update` then `ccpm install trapos`. - `ccpm` (in `tos-core`) is the package manager: `apis/libccpm.lua` is the testable core (factory with injectable `http`/`stateDir`/`installRoot`), `programs/ccpm.lua` the CLI. State: `/trapos/ccpm.json` (registries), `/trapos/ccpm.lock.json` (installed packages), and `/trapos/ccpm.cache.json` (available packages from `ccpm update`). Never use the word "manifest" in ccpm — it is reserved for the OS manifest. - Add new servers to `startup/servers.lua` as needed. @@ -45,5 +45,6 @@ Use `docs/README.md` as the entrypoint for CC:Tweaked, CraftOS-PC, Advanced Peri - Programs support `-version`/`--version` and `-help`/`--help`; router also supports `-silent`/`--silent`. - French or English comments are fine; match surrounding code. - Commit messages use lightweight conventional style: `topic(scope): description` or `topic: description`. +- Reference other `.md` files (and `ADR-####`) with `[text](path)` link syntax so `just lint-markdown` (lychee) can validate them. See [ADR-0013](docs/adrs/adr-0013-markdown-link-syntax-for-cross-references.md). -See `DEVELOPMENT.md` for local setup. +See [`DEVELOPMENT.md`](DEVELOPMENT.md) for local setup. diff --git a/docs/adrs/README.md b/docs/adrs/README.md index 93c26f6..3e466d6 100644 --- a/docs/adrs/README.md +++ b/docs/adrs/README.md @@ -20,3 +20,4 @@ Future ADRs can reuse the shape of the existing files when it is useful. - [`adr-0010-ccpm-package-manager.md`](adr-0010-ccpm-package-manager.md) - ccpm package manager (packages, registries, package-aware bootstrap). - [`adr-0011-git-hooks-own-commit-push-verification.md`](adr-0011-git-hooks-own-commit-push-verification.md) - Git hooks own commit/push verification. - [`adr-0012-headless-craftos-pc-as-hypothesis-probe.md`](adr-0012-headless-craftos-pc-as-hypothesis-probe.md) - Headless CraftOS-PC as the canonical hypothesis probe (rename `just craftos` → `just trapos`, add vanilla `just craftos`). +- [`adr-0013-markdown-link-syntax-for-cross-references.md`](adr-0013-markdown-link-syntax-for-cross-references.md) - Cross-reference markdown files with `[]()` syntax (so lychee can validate them). diff --git a/docs/adrs/adr-0005-craftos-pc-harness.md b/docs/adrs/adr-0005-craftos-pc-harness.md index 3e4ebd2..687838a 100644 --- a/docs/adrs/adr-0005-craftos-pc-harness.md +++ b/docs/adrs/adr-0005-craftos-pc-harness.md @@ -17,7 +17,7 @@ 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. +CraftOS-PC has been the *de facto* local harness for months, but that fact lived only as a single line in [`CLAUDE.md`](../../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 @@ -27,11 +27,11 @@ Treat CraftOS-PC as a first-class local development dependency. - **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. - **Documented upstream navigation** in [`docs/craftos_pc_glossary.md`](../craftos_pc_glossary.md), covering CLI flags, mounts, `periphemu`, save data, and troubleshooting pages. - **Verified by `just install`** via `check-install`, which checks `craftos`, `jq`, `luacheck`, and `openssl`. `check-craftos` 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. -- **Repository-local launch recipe.** `just trapos` runs CraftOS-PC with `--directory .craftos`, keeps the macOS `--rom /Applications/CraftOS-PC.app/Contents/Resources` workaround, mounts the repository root read-only at `/trapos`, and mounts each manifest top-level directory read-only at its ComputerCraft root path. (Originally `just craftos`; renamed when a separate vanilla-emulator recipe was added — see ADR-0012.) -- **Vanilla launch recipe.** `just craftos` launches CraftOS-PC under `.craftos-vanilla/` with no mounts, for probes that should not see TrapOS files and for the `just trapos-install` end-to-end install verification. See ADR-0012. +- **Repository-local launch recipe.** `just trapos` runs CraftOS-PC with `--directory .craftos`, keeps the macOS `--rom /Applications/CraftOS-PC.app/Contents/Resources` workaround, mounts the repository root read-only at `/trapos`, and mounts each manifest top-level directory read-only at its ComputerCraft root path. (Originally `just craftos`; renamed when a separate vanilla-emulator recipe was added — see [ADR-0012](adr-0012-headless-craftos-pc-as-hypothesis-probe.md).) +- **Vanilla launch recipe.** `just craftos` launches CraftOS-PC under `.craftos-vanilla/` with no mounts, for probes that should not see TrapOS files and for the `just trapos-install` end-to-end install verification. See [ADR-0012](adr-0012-headless-craftos-pc-as-hypothesis-probe.md). - **`just ci` is the local verification entry point.** Today it runs `check-craftos`, `check`, and `test`. Local Git hooks are installed by `just install`; see [ADR-0011](adr-0011-git-hooks-own-commit-push-verification.md) for the current commit/push split. -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. +The existing [`CLAUDE.md`](../../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 @@ -41,8 +41,8 @@ The existing `CLAUDE.md` constraint ("Do not run Lua locally or add a test harne - Each test process is guarded by `TRAP_CCLIBS_TEST_TIMEOUT_SECONDS`, defaulting to `3`, so a blocked ComputerCraft event loop fails quickly and prints captured output. - The macOS install symlinks the binary into `/usr/local/bin`, which makes CraftOS-PC unable to auto-discover the ROM that ships inside the `.app` bundle (`Could not mount ROM`). The `test:` recipe works around this by passing `--rom /Applications/CraftOS-PC.app/Contents/Resources` on Darwin. Linux (AppImage) and Windows (installer) auto-discover correctly, so no flag is passed there. - `just trapos` uses repository-local save data under `.craftos/config/` and `.craftos/computer/`. This keeps emulator state out of `~/Library/Application Support/CraftOS-PC` during repository work and keeps repo files visible through read-only mounts instead of copying them into the VM save. -- `just repl` is a human-only interactive wrapper around `just trapos --cli`; automation and LLM agents must use headless `just trapos --headless --exec '; os.shutdown()'` (TrapOS dev env) or `just craftos --headless --exec '; os.shutdown()'` (vanilla emulator) invocations instead. ADR-0012 frames these as the canonical hypothesis-probe pattern. -- 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. +- `just repl` is a human-only interactive wrapper around `just trapos --cli`; automation and LLM agents must use headless `just trapos --headless --exec '; os.shutdown()'` (TrapOS dev env) or `just craftos --headless --exec '; os.shutdown()'` (vanilla emulator) invocations instead. [ADR-0012](adr-0012-headless-craftos-pc-as-hypothesis-probe.md) frames these as the canonical hypothesis-probe pattern. +- 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`](../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 diff --git a/docs/adrs/adr-0006-simplify-periphemu-bootstrap.md b/docs/adrs/adr-0006-simplify-periphemu-bootstrap.md index 959295b..d514c05 100644 --- a/docs/adrs/adr-0006-simplify-periphemu-bootstrap.md +++ b/docs/adrs/adr-0006-simplify-periphemu-bootstrap.md @@ -39,7 +39,7 @@ The CraftOS-PC data directory (`~/Library/Application Support/CraftOS-PC/`) had - `just test` is unchanged: the headless smokes set up whatever they need per script. - New contributors and fresh machines get a clean state by default — no inherited per-computer config to chase. - Cross-machine testing now requires an explicit `periphemu create` call from the shell rather than being implicit on boot. That is a deliberate trade-off: the cost is one extra command when you genuinely need a peer; the benefit is no surprise windows and no persisted ghost VMs. -- The `if periphemu then` guard (called out in CLAUDE.md) is preserved, so in-game behavior is unchanged. +- The `if periphemu then` guard (called out in [CLAUDE.md](../../CLAUDE.md)) is preserved, so in-game behavior is unchanged. ## Future Work diff --git a/docs/adrs/adr-0010-ccpm-package-manager.md b/docs/adrs/adr-0010-ccpm-package-manager.md index c1e9ed9..ba46378 100644 --- a/docs/adrs/adr-0010-ccpm-package-manager.md +++ b/docs/adrs/adr-0010-ccpm-package-manager.md @@ -88,7 +88,7 @@ first to refresh available versions. ## Consequences - The repo gains a `packages/` descriptor tree; the flat source layout is untouched. -- `just trapos` (formerly `just craftos`; see ADR-0012) no longer derives mounts +- `just trapos` (formerly `just craftos`; see [ADR-0012](adr-0012-headless-craftos-pc-as-hypothesis-probe.md)) no longer derives mounts from `manifest.json .files` (it is now `.packages`); it mounts a fixed list of top-level dirs instead. `just test` was already on fixed mounts and is unaffected. - ccpm logic is covered by `tests/ccpm.lua` (URL resolution, dependency ordering, diff --git a/docs/adrs/adr-0012-headless-craftos-pc-as-hypothesis-probe.md b/docs/adrs/adr-0012-headless-craftos-pc-as-hypothesis-probe.md index a3f25c4..5833a75 100644 --- a/docs/adrs/adr-0012-headless-craftos-pc-as-hypothesis-probe.md +++ b/docs/adrs/adr-0012-headless-craftos-pc-as-hypothesis-probe.md @@ -73,8 +73,8 @@ Conventions: good trade. - Faster convergence on correct fixes: agents stop committing speculative changes that pass `luacheck` but fail in-game. -- A named pattern (`--headless --exec '; os.shutdown()'`) shows up in `CLAUDE.md` and - `docs/install-craftos-pc.md`, so contributors and agents reach for it without rediscovery. +- A named pattern (`--headless --exec '; os.shutdown()'`) shows up in [`CLAUDE.md`](../../CLAUDE.md) and + [`docs/install-craftos-pc.md`](../install-craftos-pc.md), so contributors and agents reach for it without rediscovery. - `.craftos-vanilla/` is added to `.gitignore` alongside `.craftos/`. - `just trapos-install` is *not* part of `just ci`: it is network-dependent and slower than `just test`. Run it manually when touching `install-ccpm.lua` or ccpm package diff --git a/docs/adrs/adr-0013-markdown-link-syntax-for-cross-references.md b/docs/adrs/adr-0013-markdown-link-syntax-for-cross-references.md new file mode 100644 index 0000000..1717f36 --- /dev/null +++ b/docs/adrs/adr-0013-markdown-link-syntax-for-cross-references.md @@ -0,0 +1,41 @@ +# ADR 0013: Cross-reference Markdown Files With `[]()` Syntax + +## Status + +Accepted + +## Date + +2026-06-09 + +## Context + +[ADR-0012](adr-0012-headless-craftos-pc-as-hypothesis-probe.md) and the broader docs/ tree increasingly cross-reference each other, and ADRs reference one another by number. We recently wired `lychee` into `just check` (see the `lint-markdown` recipe in `Justfile`) so broken local links fail the build. Lychee, however, only validates *links it can see*: a bare prose mention of `docs/foo.md` or `ADR-0005`, or a backticked path like `` `docs/foo.md` ``, is invisible to it. When a doc is renamed or moved, those mentions silently rot until a human happens to read the surrounding paragraph. + +We want renames to break the build, not the docs. + +## Decision + +In every markdown file in the repository, references to other `.md` files must use markdown link syntax `[text](relative/path.md)`. This includes: + +- Direct file references (`` `docs/install-craftos-pc.md` `` → `` [`docs/install-craftos-pc.md`](docs/install-craftos-pc.md) ``). +- ADR-number references (`ADR-0005` → `[ADR-0005](docs/adrs/adr-0005-craftos-pc-harness.md)`, with the path adjusted to be relative to the referencing file). +- Plain-prose mentions (`called out in CLAUDE.md` → `called out in [CLAUDE.md](../../CLAUDE.md)`). + +Excluded by design: + +- Mentions inside fenced code blocks. They are example/code content, not cross-references, and `lychee.toml` already skips them via `include_verbatim = false`. +- Mentions inside inline code spans used purely to *illustrate* the wrong form (as in this ADR's examples above). The reader can see they are placeholders, and lychee does not extract them as links either. +- A file's own title (e.g. `# CLAUDE.md` as a heading is not a reference). + +Link paths are written relative to the file containing the link, so that `lychee --offline` resolves them on the local filesystem with no `--base` indirection. + +## Consequences + +- `just lint-markdown` (and therefore `just check`, pre-commit, and pre-push via [ADR-0011](adr-0011-git-hooks-own-commit-push-verification.md)) catches dead cross-references the moment a doc is moved or renamed. +- The convention is *social* — humans and agents must remember to apply it when writing prose. Lychee enforces correctness only once a link exists; it cannot flag a mention that should have been a link but wasn't. +- The `[`path`](path)` style (backticked path as link text) is preferred for direct file references, matching the existing house style in [`docs/README.md`](../README.md) and [`docs/adrs/README.md`](README.md). For ADR mentions in flowing prose, `[ADR-####](path)` reads better than the backticked form. + +## Future Work + +- If rot reappears anyway, add a small grep-based lint that flags unbracketed `.md` and `ADR-####` mentions and wire it into `just check`. Deferred until there is evidence the social convention is insufficient. diff --git a/docs/opencode_server_guide.md b/docs/opencode_server_guide.md index 92c8fed..62038ea 100644 --- a/docs/opencode_server_guide.md +++ b/docs/opencode_server_guide.md @@ -2,7 +2,7 @@ How to run `opencode serve` and test `ai-helloworld` from ComputerCraft directly — no proxy. -See `docs/opencode_api.md` for the full API reference. +See [`opencode_api.md`](opencode_api.md) for the full API reference. ## Architecture