feat(release): SemVer + ludicc --version, changesets, and x release
Some checks failed
commit-lint / conventional-commits (push) Waiting to run
bootstrap / cfree-fixpoint (push) Successful in 13s
ci / build-and-test (push) Has been cancelled

The project had no versioning discipline: 0 tags, no CHANGELOG, no way for the
compiler to report a version. Add a lightweight, native release flow.

- Versioning: SemVer, with VERSION as the single source of truth. `ludicc
  --version` (and `ludic --version`) read it at runtime — so a bump touches one
  file and never reseeds the compiler. `x version` reports it too.
- Changesets: one small Markdown file per user-facing change under changes/
  (bump level + type + summary; see changes/README.md). This replaces "remember
  to edit the changelog" with a mergeable artifact, no Node changeset tool.
- `x release [major|minor|patch] [--publish]`: fold the pending changesets into a
  new CHANGELOG.md section (grouped by type), bump VERSION, commit, and tag
  vX.Y.Z. The level defaults to the highest changeset bump. `--publish` also
  pushes and creates the Forgejo release with source + toolchain tarballs;
  tools/ci/forgejo_release.py is the small stdlib-Python HTTP glue for the
  release API (a native Http client is issue #6).

Seed the initial changesets describing the shipped surface; the first `x release`
turns them into the v0.1.0 CHANGELOG. Reseeded for the --version flag; C-free
bootstrap fixpoint holds; suites 56 / 29 / 29 on macOS, 51 / 28 (+skips) on Linux
CI, bootstrap-cfree byte-identical on both.

Part of the repository-cleanup / DX pass (with #32, #34).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-08-30 23:46:59 +03:00
parent 709465cdd8
commit fed80f2152
15 changed files with 787 additions and 293 deletions

View file

@ -17,6 +17,7 @@ program X {
import "tools.ludic"
import "selfhost_test.ludic"
import "test.ludic"
import "release.ludic"
function usage() -> void {
print("x — the Ludic task runner (run from the repository root)")
@ -35,6 +36,11 @@ program X {
print(" x test-tools the editor-toolchain suite")
print(" x golden regenerate selfhost/golden/renders.sha256 (review with git diff)")
print("")
print("release:")
print(" x version print the toolchain version (ludicc --version)")
print(" x release [major|minor|patch] [--publish]")
print(" cut a release: CHANGELOG + VERSION bump + tag (+ Forgejo release)")
print("")
print("self-host internals:")
print(" x selfhost-build [ludicc] [out] assemble + compile the self-host compiler")
print(" x bootstrap the self-hosting fixpoint proof (seeded from bin/ludicc)")
@ -75,6 +81,8 @@ program X {
if (arg_count() < 5) { err("usage: x game-build <ludicc> <game.ludic> <out>\n"); exit(1) }
exit(cmd_game_build(arg(2), arg(3), arg(4)))
}
if (cmd == "version") or (cmd == "--version") or (cmd == "-v") { exit(cmd_version()) }
if (cmd == "release") { exit(cmd_release()) }
if (cmd == "help") or (cmd == "--help") or (cmd == "-h") { usage(); exit(0) }
err(`x: unknown command '{cmd}'\n`)