docs: scaffold the Integration Kit — front page, outline, and the checks
All checks were successful
PR Checks / template (pull_request) Successful in 6s
PR Checks / links (pull_request) Successful in 7s

Phase 5 slice 0 (MODULE_SYSTEM.md §2.11.1). The repo's governance, the front
page, the book's outline, and the CI that keeps the whole thing from rotting.

README.md
  What the reader is building, all three parts, and the draft banner: the kit is
  finished when someone outside this project builds a working module by
  following it alone, and that has not happened. Says the sidecar rule plainly
  (MODULE_API.md §2.7) rather than leaving it to chapter 3, because a reader who
  skims the front page and starts coding should still get that one right.

book/README.md
  The outline of four chapters, landed before the prose so the shape can be
  argued with. Chapters are named but NOT linked — a link to a file that does
  not exist is what the link check is for, and an outline should not be the
  first thing to fail it.

CONTRIBUTING.md
  The rule that governs every change here: the kit never re-specifies a
  contract. Also the prose conventions, and why the pinned ref points at core's
  `edge` rather than `main`.

SECURITY.md
  Scoped for a repo that runs nothing: the two things that ARE reportable are a
  template that teaches an insecure pattern (it is meant to be copied) and a
  chapter that teaches something dangerous.

scripts/checkLinks.js
  Relative links resolve; anchors match a real heading; no link pins a reader to
  a commit snapshot of a moving document. Nothing is fetched — a self-hosted
  Gitea would fail on a credential-less runner and teach us to ignore red.
  Fences and code spans are stripped by a line walk, not a regexp.

  Its first run found a real one: a PR template's relative links resolve from
  the REPO ROOT, because that is where their text ends up when Gitea inlines
  them into a pull request body. Encoded, with the reason.

scripts/checkCoreApi.js
  The anti-rot check. Asserts template/module.json's `coreApi` EQUALS the pinned
  core's MODULE_API_VERSION — equality, not "satisfies", because a range check
  stays green across a contract bump and green would then mean "the template
  still loads" instead of "someone has re-read the book". Both failure branches
  and the pass were exercised against a real core checkout.

ci/core-ref.json
  The pin, same convention as Module-uo's. Points at `edge`: core's `main` has
  no server/src/modules/ until the cutover, and that pin is one of the things
  the cutover has to revisit.

.gitea/workflows/pr-checks.yml
  Two jobs. `links` always runs; `template` is conditional on
  template/module.json existing, so the repo is gated now and the job arms
  itself when slice 1 lands, with no edit to the workflow. Same guard Module-uo
  used through its planning phase.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-12 09:47:22 -05:00
parent f9694be6a0
commit cffd525bdf
13 changed files with 991 additions and 0 deletions

135
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,135 @@
# Contributing to Runic Gateway — Integration Kit
Thanks for your interest! This repo is the **Integration Kit**: the instruction
book for putting a game that is not Ultima Online onto a Runic Gateway site, plus
a `template/` module that builds.
It is the only repo in this project written for someone **outside** the
organisation, and that changes what a contribution looks like here. Elsewhere the
docs record decisions; here they teach a stranger. The most valuable contribution
is not a correction — it is a report of the place you got stuck and what you did
next.
By participating you agree to abide by our [Code of Conduct](CODE_OF_CONDUCT.md).
## Status: draft
The kit's acceptance test is that **someone outside this project builds a working
module for a new game by following it alone, without reading core's source.** Until
that has happened it is a draft however finished it looks, and the README says so
on the front page. Do not remove that banner in a PR that is not the one recording
a passed acceptance run.
## The rule that governs every change here
**The kit never re-specifies a contract.** These are normative; the kit teaches and
links out:
- [`MODULE_API.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/MODULE_API.md)
— everything a module may do.
- [`MODULE_SYSTEM.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/MODULE_SYSTEM.md)
— why the system is shaped this way, and the install model.
- [`link/PLAN.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/link/PLAN.md)
and [`INTEGRATION.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/link/INTEGRATION.md)
— the game↔sidecar wire protocol.
So: **do not copy a member list, a field table or a set of rules into a chapter.**
Quote the part you are explaining, with a link, and let the reader go to the
authority for the whole. A guide that restates a contract diverges from it
silently, and the reader who follows the divergent copy gets a module that fails
validation for reasons the guide cannot explain.
If a rule looks *wrong* rather than badly explained, that is a docs-repo PR against
`MODULE_API.md`, not a change here. The kit does not get to disagree with the
contract in prose.
## Ways to contribute
- **Report where the kit failed you** through the
[issue tracker](https://gitea.whitlocktech.com/RunicGateway/Integration-kit/issues)
— templates provided. "I could not work out how to X" is a bug in this repo.
- **Fix or extend a chapter**, or the template, with a pull request.
- **Never** report a security vulnerability in a public issue — see
[SECURITY.md](SECURITY.md).
## Working on this repo
**Prerequisites:** Node 20+, and a checkout of
[`RunicGateway/website`](https://gitea.whitlocktech.com/RunicGateway/website) if you
are touching `template/` — a module is not runnable on its own.
```bash
node scripts/checkLinks.js # every relative link resolves; no commit permalinks
```
The template's own checks live under `template/` and are described in the chapter
that introduces it.
### What CI checks, and why it is shaped that way
`.gitea/workflows/pr-checks.yml` clones core at a **pinned commit** and then:
1. asserts the version `template/module.json` declares still **equals** that core's
`MODULE_API_VERSION`;
2. builds the template and runs its boundary guards;
3. runs the link check over every markdown file.
Check 1 is the anti-rot mechanism. A contract bump in core changes that number, this
repo goes red, and someone has to look at whether a chapter has become untrue — which
is the half a machine cannot check. That is also why a `MODULE_API_VERSION` bump in
core carries an obligation to pass over this kit in the same PR
([`MODULE_SYSTEM.md` §2.10](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/MODULE_SYSTEM.md)).
**The pin points at a commit on core's `edge` branch, not `main`.** The module system
has not cut over yet; `main` has no `server/src/modules/` at all. Moving the pin is a
deliberate, reviewed change — it is the moment someone re-reads the chapters — so it
is a line in the workflow rather than a floating branch name.
### Prose conventions
- **Second person, present tense.** "You register a route", not "the module author
registers a route".
- **Say why before how.** Every rule in this project exists because something broke;
a rule without its reason is one the reader will route around.
- **Examples are quotations.** Code blocks come from `template/` or from a real repo,
with a path next to them. An invented example is one nobody has compiled.
- **Own the mistakes.** Where this project got something wrong and paid for it, the
kit says so plainly. That is the part a reader cannot get anywhere else.
- One sentence per line is not required, but keep lines under ~100 characters.
### Commit messages
[Conventional Commits](https://www.conventionalcommits.org/) — `type(scope): summary`.
`docs:` for chapters, `feat:`/`fix:` for the template, `ci:` for workflows.
## Branch & PR workflow
1. Branch from `main` (`feature/…`, `fix/…`, `docs/…`, `chore/…`).
2. Keep it focused.
3. Open a pull request against `main` and fill in the template, including the
**AI-assisted contributions** disclosure.
4. A maintainer reviews; address feedback with follow-up commits.
This repo develops on its own `main` from its first commit — no `edge`, no cutover.
## AI-assisted contributions (disclosure required)
This project is developed openly with AI assistance, and we ask the same
transparency of everyone. **If you used an AI tool** (Claude, Copilot, ChatGPT,
Cursor, etc.) to help produce a contribution, you must disclose it:
- Tick the AI-usage box in the pull-request template and name the tool(s).
- Mark AI-authored commits with a trailer, e.g.
`Co-Authored-By: Claude <noreply@anthropic.com>` or `Assisted-By: <tool>`.
- You remain responsible for every line you submit: review it, understand it, and
make sure it is correct and that you have the right to contribute it.
Disclosed AI assistance is welcome. Undisclosed AI-generated contributions are not,
and may be closed.
## License
Runic Gateway is licensed under the **GNU General Public License v3.0 or later**
(see [LICENSE.md](LICENSE.md)). By submitting a contribution you agree that it is
licensed under the same terms (inbound = outbound) and that you have the right to
contribute it.