Skip to content

Releases and vendoring

Tagged releases build a development model and a runtime model after the CI gates pass, check_runtime.py proves the runtime model holds no development code, and vendor.py syncs a reviewed vendor copy without overwriting local edits.

A pushed v* tag produces two Roblox models on the GitHub release: the whole project, and a runtime-only framework model without specs, benches, TestKit or the Simulation showcase. The release job runs the full check first and publishes nothing when a gate fails. For games that keep their own copy of the framework source, tools/vendor.py updates that copy only where it still matches the last reviewed baseline, and stops before writing anything when it finds local edits. The long-form notes are docs/vendoring.md in the repository; the per-version changes are on Changelog.

Artifact Built from Contents
ChloeKernel-<tag>.rbxm build.project.json A folder holding ReplicatedStorage (src/Shared), ServerScriptService (src/Server) and StarterPlayerScripts (src/Client): the framework, TestKit, every spec and bench, Simulation, the Main boot scripts, the Bootstraps and the Game layer.
ChloeKernelRuntime-<tag>.rbxm runtime.project.json A folder holding ReplicatedStorage.ChloeKernel and ServerScriptService.ChloeKernelServer only. Tests, Benches, TestKit and Simulation are excluded by glob. The disabled ActorPool worker template stays. No boot scripts.

Insert either model into a place to pin an exact framework version. With the runtime model, move each folder’s children into the matching service and supply your own boot script: it boots nothing by itself. The runtime model keeps the Debug modules, so the debug panels and their access gate ship with it.

To build locally:

Terminal window
rojo build build.project.json -o ChloeKernel.rbxm
rojo build runtime.project.json -o ChloeKernelRuntime.rbxm

.github/workflows/release.yml runs on any pushed tag matching v*, with permission to write releases:

  1. The checks job calls .github/workflows/ci.yml as a reusable workflow, which runs python tools/check.py with the pinned toolchain and the verified Luau runtime.
  2. The release job needs checks to pass. It installs the aftman.toml pins and builds ChloeKernel-${GITHUB_REF_NAME}.rbxm from build.project.json and ChloeKernelRuntime-${GITHUB_REF_NAME}.rbxm from runtime.project.json.
  3. It extracts the CHANGELOG.md section whose heading starts with ## <version> (the tag without its v) into RELEASE_NOTES.md, or writes See CHANGELOG.md. when there is none.
  4. It runs gh release create <tag> with both models, the title ChloeKernel <tag> and those notes.

Before 0.8.0 a tagged release built its single model without running the gates; 0.8.0 made the release depend on them and added the runtime model.

A successful Rojo build does not prove the ignore globs removed anything. The check’s runtime step builds runtime.project.json to a temporary .rbxmx and runs tools/check_runtime.py on the XML, which asserts:

  • no script source sits under a path containing Tests, Benches, TestKit or Simulation,
  • every source that is not a ModuleScript is the ActorPool/Worker Script, and its Disabled property is true,
  • the model contains the modules a runtime needs: ChloeKernel, ChloeKernel/Scope, ChloeKernel/Scheduler, ChloeKernel/Net/Packet, ChloeKernelServer, ChloeKernelServer/Data and ChloeKernelServer/Commerce/Receipts.

On success it prints Runtime model verified: <n> sources; no tests, benches, TestKit, Simulation or active bootstraps. Any failed assertion fails the check, and with it the release.

NetTap.OwnerUserIds lists operators who are always allowed the debug surface (every player’s decoded NET traffic, the server log tail and the SIM CONTROL load controls) when ChloeKernelDebug is true, whatever ChloeKernelDebugUserIds says. It always includes CryptedChloes (7241279999), the framework’s only developer: debugAllowed checks that id itself, so no edit to the table can drop it, and directive CK017 rejects code in any file that removes or replaces the entry. A game adds further operators from shared bootstrap code, so the server and clients agree: NetTap.OwnerUserIds[123456789] = true. See Production access control.

tools/vendor.py keeps a game’s vendored copy of the framework in step with this repository without overwriting edits made in the game. It maps two source folders onto the vendor layout of the game it was written for:

Framework source Vendor path in the game
src/Shared/ChloeKernel Src/ReplicatedStorage/ChloeKernel
src/Server/ChloeKernelServer Src/ServerScriptService/ChloeKernelServer

Simulation/init.luau maps to a flat Simulation.luau, which keeps that game’s existing ModuleScript identity. The mapping is fixed in the script; a game with another layout needs its own mapping.

Terminal window
python tools/vendor.py check --game /path/to/game # the default action
python tools/vendor.py record --game /path/to/game
python tools/vendor.py sync --game /path/to/game
python tools/vendor.py sync --game /path/to/game --source /path/to/other/framework/checkout

It compares file hashes (SHA-256 after normalizing CRLF to LF) against chloekernel.vendor.json in the game, the manifest of the last reviewed baseline, and classifies every mapped file:

State Meaning
same The vendor file equals the framework file.
upstream changed The vendor file still matches the baseline and the framework moved on. Safe to sync.
new upstream file The framework has a file the baseline never had and the game does not have. Safe to sync once a manifest exists.
local changes The vendor file differs from the baseline: someone edited it in the game.
unreviewed local file The vendor file exists but the baseline never recorded it.

It also lists vendor modules the framework does not have and baseline files the framework removed, as requires manual review (not deleted). It never deletes a module.

  • check prints every difference and <k>/<n> mapped files match (line endings ignored). It exits 1 on any difference, any unknown or removed module, or a missing manifest.
  • record writes the manifest for a reviewed baseline. It refuses while any mapped file differs, so it records only copies that already agree.
  • sync copies upstream changes. It refuses before writing anything when it sees local changes, unreviewed local files, unknown vendor modules or removed upstream modules, and a first sync needs a recorded manifest.

The first reconciliation is manual: run check, merge the reusable fixes from the game’s copy into the framework, never copy an old fork over newer security or lifecycle fixes, and record once every file agrees. Commit chloekernel.vendor.json with the game. It holds each file’s upstream path and hash and no machine paths. After that, a framework update is check, sync, the game’s own checks, and a commit.

  1. Before touching anything, it re-reads every destination and the manifest and aborts if any changed since it inspected them.
  2. It copies the original bytes of every file it will replace, and the old manifest, into .chloekernel-vendor-backups/<UTC time>-<12 hex digits>/ in the game, with a backup-index.json listing their hashes and the new files it will add. There is no automatic rollback.
  3. It writes each file to a temporary file in the destination folder, flushes it to disk, checks once more that the destination still holds the bytes it read, and moves the temporary file over it.
  4. It writes the new manifest last.

A conflict in the middle of a sync can leave earlier files updated, with their originals in the backup folder and the old manifest still in place. Review and reconcile that partial state before recording a new baseline. The tool makes each file write atomic, not the update as a whole; keep a clean commit in the game before you sync.

tools/test_vendor.py exercises conflict refusal, concurrent edits, path confinement, backups, line endings, metadata and the Simulation mapping without touching a real project. It runs in the vendor step of the check. To run the core regression runner against a vendored copy, pass --root /path/to/game to tools/regressions/core.py (see Regression runners).

ChloeKernel v0.9.1. Access to the framework is private and granted individually by Chloe. Games built with it credit CryptedChloes in their description.