Skip to content

The three repositories

gorge's work is split across three Git repositories with one-way dependencies: the public engine, a public compliance repository that checks it, and a private companion module that builds on it. This page is for anyone deciding where a change belongs, or wondering why a file they expected is not in this repository. It covers what each repository holds, which way the imports run and what enforces that, licensing, how the companions pin gorge, and how changes reach main.

Verified 2026-10-21 against gorge develop @ 513a2a0c3 and the two companions as they stood that day.

At a glance

gorge gorge-compliance four-yay
Visibility public public private
Licence Apache-2.0 Apache-2.0 (private)
Module github.com/adams-shaun/gorge github.com/adams-shaun/gorge-compliance github.com/adams-shaun/four-yay
Holds the rules engine, the reference server gorged, the baseline and hosted bots, the browser client, contributor tooling the compliance oracles (gorge vs XMage vs Forge), the hand-written Oracle-text scenarios, the XMage-ported scenarios, the certification ratchet the maintainers' extensions: research, draft events, research bots, the dirty-dirac kernel, and the demo's deployment tooling
Depends on nothing (the root go.mod has no require lines) gorge, pinned by commit gorge, pinned by commit
You need it to… build, run, test or embed the engine measure gorge against independent engines nothing in gorge
gorge public · Apache-2.0 engine/ server/ bots/ cmd/ web/ testkit/ cli/ imports nothing outside the standard library gorge-compliance public · Apache-2.0 oracles, scenarios, certification ratchet four-yay private research, draft events, dirty-dirac, demo ops imports gorge at GORGE_PIN imports gorge at GORGE_PIN gorge never imports either (no require lines: TestRootModuleHasNoRequires)
Arrows point from the importer to the imported module. Both companions build against one pinned gorge commit; the companions do not import each other.

gorge (this repository)

The deterministic, event-sourced rules engine and everything needed to use it: the card compiler (engine/cards), the rules core (engine/), the reference server (server/gorged, with its thin main in cmd/gorged), the default and hosted bots (bots/), the Svelte browser client (web/), public test support for outside modules (testkit/, cli/), the architecture ratchets (internal/), and the developer commands (cmd/). The full tree is on Repository layout.

gorge is meant to build, test and run on its own: nothing here needs either companion. It exposes a few extension seams, which are ordinary exported gorge API:

Seam What plugs in
bots.Register (bots/registry.go) a bot policy joins the registry the server offers
server/gorged.RegisterNetBot a network-backed hosted bot, with its flags
server/gorged.Extensions a draft-event runtime under /api/events; with none, gorged -events is refused at startup (TestEventsNeedAPlugin)
engine/rules' exported oracle runner (RunOracleScenarioJSON, RunOracleAuditScenarioJSON, CheckOracleScenarioJSON) gorge-compliance's scenario drivers
testkit/ (testutil, bench, paymirror) and cli/ test fixtures, the head-to-head game runner, command-line plumbing

Changing one of these is an API change for the companions, so it is sequenced as described below.

gorge-compliance

gorge-compliance exists to give confidence in the rules engine. It checks gorge card by card against three independent references and holds the results to coverage targets:

  • hand-written Oracle-text scenarios: JSON files written from a card's printed text and the Comprehensive Rules by an author who has not read the card's script (scenarios/oracle/);
  • XMage, an independent Java engine (MIT): generated scenarios are replayed in both engines and their snapshots diffed;
  • Forge, the engine the card scripts come from, adjudicated against the other two;
  • plus XMage's own interaction tests, translated into gorge's scenario schema (scenarios/xmageport/).

It drives gorge only through the exported oracle runner. gorge keeps that runner (engine/rules/oracle_*.go), its unit tests, and nine residual scenario files that its own card tests load (engine/rules/testdata/oracle/), played by engine/rules/oracle_contract_test.go (TestOracleRunnerContract) as the runner's contract check. A scenario file lives in exactly one of the two repositories.

gorge does not gate on gorge-compliance, but its published figures come from there. A nightly job on gorge-compliance's main measures every set's compliance status at the pinned gorge and force-pushes it as one commit to an orphan docs-data branch: per-set status rows for Level A and Level B, and a meta.json naming the gorge-compliance commit, the gorge pin, FORGE_REF and the date. gorge's docs build fetches that branch and renders the per-set table on Card support; if the branch is missing, the page falls back to its committed snapshot. The same nightly workflow runs the drift check described under Pinning.

four-yay

four-yay is the maintainers' private companion module. It holds work built on top of gorge that is not part of the public surface: research, draft events, research bots, the dirty-dirac kernel, and the tooling that deploys the public demo. It imports gorge at a pinned commit, the same way gorge-compliance does (Pinning); gorge never imports it, and nothing in gorge needs it to build or test. The dirty-dirac pages describe that kernel's design.

Dependency direction and what enforces it

flowchart LR
  compliance["gorge-compliance"] -->|"go.mod require<br/>at GORGE_PIN"| gorge["gorge"]
  fouryay["four-yay (private)"] -->|"go.mod require<br/>at GORGE_PIN"| gorge
  gorge -.->|"never"| compliance
  gorge -.->|"never"| fouryay
Boundary Enforced by
gorge imports no other module at all internal/archtest/gomod_test.go TestRootModuleHasNoRequires: the root go.mod may carry no require directive and go.sum must be empty or absent. With no require, gorge cannot import either companion.
engine/ imports nothing outside engine/ measured, not yet one test: go list -deps ./engine/... has no gorge package outside engine/ and no non-standard-library package (checked 2026-10-20). Individual forbidden edges are pinned by internal/archtest TestDependencyOrderHolds; see Invariants.
The companions use only exported gorge API Go's own visibility rules, plus gorge's internal/ packages, which no other module can import.

The direction matters for two reasons. gorge stays usable by anyone without access to the private repository, and a change in gorge can never be blocked on code its contributors cannot see.

Licensing and the Forge card scripts

gorge compiles Forge's card scripts. Those scripts are GPL-3.0; gorge is Apache-2.0. So gorge ships a compiler for the script format and never the scripts themselves:

  • make fetch-cards downloads the scripts into .cards/, which is gitignored, at the commit pinned by FORGE_REF in the Makefile, from gorge's fork adams-shaun/forge (FORGE_REPO).
  • engine/cards/boundary_test.go (TestNoForgeScriptsTracked) fails the build if a Forge script is tracked in the working tree, the index or HEAD. It recognises a script by its content, not its path.
  • Replay fixtures strip embedded token-script text before they are committed (into the gitignored cmd/repro/testdata/.tokens/).
  • Tests, docs and coverage tables name cards; they never contain script text.
  • A script that disagrees with the printed card is fixed on the fork's gorge branch and offered upstream, never patched inside gorge.

gorge-compliance follows the same rule with its own guard (internal/boundary) and reaches the corpus through a gitignored link to a gorge checkout's .cards/. Its NOTICE credits XMage (MIT), from which its set manifests and ported scenarios derive. gorge's own NOTICE credits the MIT-licensed SpellBench adapter that server/spellbench and the cmd/spellbench-gorge-* commands are derived from.

Pinning

Both companions build against one gorge commit, expressed twice:

  • a GORGE_PIN file at the repository root holding the full SHA, and
  • a require github.com/adams-shaun/gorge <pseudo-version> line in go.mod naming the same commit, so go build fetches exactly that code from the module proxy.

A pin bump is a pull request in the companion, never a side effect. For gorge-compliance it also reruns the scenario audits and the XMage pass and updates every target, because each target (the certification ratchet, the verdicts, the known-divergent rows) is a statement about the pinned commit. The procedure is gorge-compliance's docs/PINNING.md. A nightly drift job there builds against gorge main instead of the pin and reports what would change without failing.

Pinning gorge also pins the card corpus: the companions read FORGE_REF from the pinned gorge's Makefile.

Neither companion commits a go.work or a replace directive for gorge: the pin is the only way gorge reaches them. To try gorge-compliance against unmerged gorge work locally, a gitignored go.work that points at your gorge checkout works; never commit one, because it overrides the pin.

Branch flow

All three repositories land work the same way:

flowchart LR
  pr["your branch<br/>or fork"] -->|"pull request,<br/>ci green"| develop["develop"]
  develop -->|"ci green on push:<br/>promote.yml opens<br/>develop → main PR"| main["main"]
  main -->|"docs.yml"| site["this site"]
  1. Changes land on develop, through a pull request whose ci workflow (lint plus a sharded test run with the corpus fetched) is green.
  2. When ci finishes green on a push to develop, the promote workflow opens a develop → main pull request, or leaves the open one in place. Only the commit that is still develop's tip promotes.
  3. A person merges it on GitHub, with a merge commit, not a squash, so develop and main keep sharing history. Nothing pushes main directly.
  4. Pushes to main publish this site (docs.yml) and the card-coverage tables (coverage.yml, as a workflow artifact).

A change that spans repositories

Because the arrows run one way, a cross-repository change always lands in gorge first:

sequenceDiagram
  participant G as gorge
  participant C as gorge-compliance
  G->>G: PR to develop (keep the old API working if you can)
  G->>G: develop → main
  C->>C: PR: GORGE_PIN + go.mod to the new commit
  C->>C: rerun audits, update targets, adopt the new API
  Note over G,C: four-yay bumps its own pin the same way
  • The gorge commit must be pushed before a companion can pin it: the pseudo-version is resolved through the module proxy.
  • Prefer additive changes to a seam (a new function beside the old one), so the companion can move at its own pace. An incompatible change breaks the companion only at its next pin bump, and the nightly drift report shows it before that.
  • Say so in the PR when you change a seam listed above, or a file format a companion reads (server/protocol's frames, the bots/gonet network file, the bots/policynet checkpoint), so the maintainers can schedule the matching bump.

A change that fixes a card in gorge typically shows up in gorge-compliance as a stale ratchet row (a scenario that now passes) at the next pin bump; that row is deleted in the bump PR.