|
| 1 | +# SPDX-License-Identifier: PMPL-1.0-or-later |
| 2 | +# stapeln.toml — Layer-based container build for nextgen-languages monorepo |
| 3 | +# |
| 4 | +# stapeln builds containers as composable layers (German: "to stack"). |
| 5 | +# Each layer is independently cacheable, verifiable, and signable. |
| 6 | +# |
| 7 | +# nextgen-languages is a monorepo containing 14 experimental language |
| 8 | +# implementations. Each language has its own build toolchain (Rust, OCaml, |
| 9 | +# Elixir, Deno/ReScript, Zig FFI, Idris2 ABI). Layers are structured so |
| 10 | +# toolchain images are shared across languages that use the same stack. |
| 11 | + |
| 12 | +[metadata] |
| 13 | +name = "nextgen-languages" |
| 14 | +version = "0.1.0" |
| 15 | +description = "Monorepo of experimental programming language compilers and interpreters" |
| 16 | +author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>" |
| 17 | +license = "PMPL-1.0-or-later" |
| 18 | +registry = "ghcr.io/hyperpolymath" |
| 19 | + |
| 20 | +[build] |
| 21 | +containerfile = "Containerfile" |
| 22 | +context = "." |
| 23 | +runtime = "podman" |
| 24 | + |
| 25 | +# ── Base Layer ──────────────────────────────────────────────── |
| 26 | + |
| 27 | +[layers.base] |
| 28 | +description = "Chainguard Wolfi minimal base" |
| 29 | +from = "cgr.dev/chainguard/wolfi-base:latest" |
| 30 | +cache = true |
| 31 | +verify = true |
| 32 | + |
| 33 | +# ── Toolchain Layers ───────────────────────────────────────── |
| 34 | +# Shared toolchains reused across multiple language builds. |
| 35 | + |
| 36 | +[layers.rust-toolchain] |
| 37 | +description = "Rust nightly toolchain for Cargo-based languages" |
| 38 | +extends = "base" |
| 39 | +packages = ["rustup", "gcc", "pkgconf", "openssl-dev", "musl-dev"] |
| 40 | +commands = [ |
| 41 | + "rustup-init -y --default-toolchain nightly", |
| 42 | + "rustup target add wasm32-unknown-unknown", |
| 43 | +] |
| 44 | +cache = true |
| 45 | + |
| 46 | +[layers.ocaml-toolchain] |
| 47 | +description = "OCaml + opam + dune for OCaml-based languages" |
| 48 | +extends = "base" |
| 49 | +packages = ["ocaml", "opam", "gcc", "musl-dev", "m4", "patch"] |
| 50 | +commands = [ |
| 51 | + "opam init --disable-sandboxing --bare -y", |
| 52 | + "eval $(opam env) && opam install dune menhir ppx_deriving -y", |
| 53 | +] |
| 54 | +cache = true |
| 55 | + |
| 56 | +[layers.elixir-toolchain] |
| 57 | +description = "Elixir + Erlang/OTP for BEAM-based languages" |
| 58 | +extends = "base" |
| 59 | +packages = ["elixir", "erlang-dev"] |
| 60 | +commands = ["mix local.hex --force", "mix local.rebar --force"] |
| 61 | +cache = true |
| 62 | + |
| 63 | +[layers.deno-toolchain] |
| 64 | +description = "Deno runtime for JS/ReScript-based languages" |
| 65 | +extends = "base" |
| 66 | +packages = ["deno"] |
| 67 | +cache = true |
| 68 | + |
| 69 | +[layers.zig-toolchain] |
| 70 | +description = "Zig compiler for FFI implementations" |
| 71 | +extends = "base" |
| 72 | +packages = ["zig"] |
| 73 | +cache = true |
| 74 | + |
| 75 | +[layers.idris2-toolchain] |
| 76 | +description = "Idris2 for ABI formal definitions" |
| 77 | +extends = "base" |
| 78 | +packages = ["idris2", "gcc", "musl-dev"] |
| 79 | +cache = true |
| 80 | + |
| 81 | +# ── ABI + FFI Layer ────────────────────────────────────────── |
| 82 | +# Shared layer for languages with Idris2 ABI + Zig FFI triples. |
| 83 | + |
| 84 | +[layers.abi-ffi] |
| 85 | +description = "Combined Idris2 ABI verification + Zig FFI compilation" |
| 86 | +extends = "base" |
| 87 | +depends = ["idris2-toolchain", "zig-toolchain"] |
| 88 | +commands = [ |
| 89 | + # Verify ABI definitions compile cleanly |
| 90 | + "for lang in eclexia betlang tangle affinescript wokelang julia-the-viper oblibeny error-lang phronesis; do [ -d ${lang}/src/abi ] && (cd ${lang}/src/abi && idris2 --check Types.idr 2>/dev/null || true); done", |
| 91 | + # Build Zig FFI shared objects |
| 92 | + "for lang in eclexia betlang tangle affinescript julia-the-viper oblibeny error-lang; do [ -d ${lang}/ffi/zig ] && (cd ${lang}/ffi/zig && zig build 2>/dev/null || true); done", |
| 93 | +] |
| 94 | +cache = true |
| 95 | + |
| 96 | +# ── Language Build Layers ──────────────────────────────────── |
| 97 | +# Each language gets its own build layer extending the appropriate toolchain. |
| 98 | + |
| 99 | +[layers.build-ephapax] |
| 100 | +description = "Ephapax — linear type system language (Rust + Idris2)" |
| 101 | +extends = "rust-toolchain" |
| 102 | +depends = ["idris2-toolchain"] |
| 103 | +commands = [ |
| 104 | + "cd ephapax && cargo build --release --workspace", |
| 105 | + "[ -d ephapax/idris2/src ] && (cd ephapax/idris2 && idris2 --check src/Main.idr || true)", |
| 106 | +] |
| 107 | +cache = true |
| 108 | + |
| 109 | +[layers.build-wokelang] |
| 110 | +description = "WokeLang — consent-aware programming language (Rust + OCaml)" |
| 111 | +extends = "rust-toolchain" |
| 112 | +depends = ["ocaml-toolchain"] |
| 113 | +commands = [ |
| 114 | + "cd wokelang && cargo build --release", |
| 115 | + "cd wokelang && eval $(opam env) && dune build 2>/dev/null || true", |
| 116 | +] |
| 117 | +cache = true |
| 118 | + |
| 119 | +[layers.build-eclexia] |
| 120 | +description = "Eclexia — economics-as-code language (Rust + Idris2 ABI + Zig FFI)" |
| 121 | +extends = "rust-toolchain" |
| 122 | +depends = ["abi-ffi"] |
| 123 | +commands = ["cd eclexia && cargo build --release"] |
| 124 | +cache = true |
| 125 | + |
| 126 | +[layers.build-affinescript] |
| 127 | +description = "AffineScript — affine type system language (OCaml + Zig FFI)" |
| 128 | +extends = "ocaml-toolchain" |
| 129 | +depends = ["abi-ffi"] |
| 130 | +commands = ["cd affinescript && eval $(opam env) && dune build"] |
| 131 | +cache = true |
| 132 | + |
| 133 | +[layers.build-betlang] |
| 134 | +description = "BetLang — probabilistic programming language (Rust + Zig FFI)" |
| 135 | +extends = "rust-toolchain" |
| 136 | +depends = ["abi-ffi"] |
| 137 | +commands = ["cd betlang && cargo build --release --workspace"] |
| 138 | +cache = true |
| 139 | + |
| 140 | +[layers.build-julia-the-viper] |
| 141 | +description = "Julia the Viper — pattern-matching language (Rust + Zig FFI)" |
| 142 | +extends = "rust-toolchain" |
| 143 | +depends = ["abi-ffi"] |
| 144 | +commands = ["cd julia-the-viper && cargo build --release --workspace"] |
| 145 | +cache = true |
| 146 | + |
| 147 | +[layers.build-my-lang] |
| 148 | +description = "MyLang — personal expression language (Rust)" |
| 149 | +extends = "rust-toolchain" |
| 150 | +commands = ["cd my-lang && cargo build --release --workspace"] |
| 151 | +cache = true |
| 152 | + |
| 153 | +[layers.build-oblibeny] |
| 154 | +description = "Oblibeny — Turing-incomplete constrained form language (OCaml + Zig FFI)" |
| 155 | +extends = "ocaml-toolchain" |
| 156 | +depends = ["abi-ffi"] |
| 157 | +commands = ["cd oblibeny && eval $(opam env) && dune build"] |
| 158 | +cache = true |
| 159 | + |
| 160 | +[layers.build-tangle] |
| 161 | +description = "Tangle — entangled computation language (OCaml + Idris2 ABI + Zig FFI)" |
| 162 | +extends = "ocaml-toolchain" |
| 163 | +depends = ["abi-ffi"] |
| 164 | +commands = ["cd tangle && eval $(opam env) && dune build"] |
| 165 | +cache = true |
| 166 | + |
| 167 | +[layers.build-phronesis] |
| 168 | +description = "Phronesis — practical wisdom language (Elixir)" |
| 169 | +extends = "elixir-toolchain" |
| 170 | +commands = [ |
| 171 | + "cd phronesis && mix deps.get --only prod", |
| 172 | + "cd phronesis && MIX_ENV=prod mix compile", |
| 173 | +] |
| 174 | +cache = true |
| 175 | + |
| 176 | +[layers.build-error-lang] |
| 177 | +description = "Error-lang — error-centric programming language (Deno + Zig FFI)" |
| 178 | +extends = "deno-toolchain" |
| 179 | +depends = ["abi-ffi"] |
| 180 | +commands = ["cd error-lang && deno cache cli/main.js"] |
| 181 | +cache = true |
| 182 | + |
| 183 | +[layers.build-me-dialect] |
| 184 | +description = "Me-dialect — personal dialect language (Deno + ReScript)" |
| 185 | +extends = "deno-toolchain" |
| 186 | +commands = ["cd me-dialect && deno cache src/run.js"] |
| 187 | +cache = true |
| 188 | + |
| 189 | +[layers.build-7-tentacles] |
| 190 | +description = "7-Tentacles — multi-agent language learning (Deno + ReScript)" |
| 191 | +extends = "deno-toolchain" |
| 192 | +commands = ["cd 7-tentacles && deno cache agents/*.res 2>/dev/null || true"] |
| 193 | +cache = true |
| 194 | + |
| 195 | +[layers.build-anvomidav] |
| 196 | +description = "Anvomidav — experimental language (Elixir tests)" |
| 197 | +extends = "elixir-toolchain" |
| 198 | +commands = ["cd anvomidav && true"] |
| 199 | +cache = true |
| 200 | + |
| 201 | +# ── Aggregate Build Layer ──────────────────────────────────── |
| 202 | + |
| 203 | +[layers.build-all] |
| 204 | +description = "All languages built — aggregates every build layer" |
| 205 | +extends = "base" |
| 206 | +depends = [ |
| 207 | + "build-ephapax", |
| 208 | + "build-wokelang", |
| 209 | + "build-eclexia", |
| 210 | + "build-affinescript", |
| 211 | + "build-betlang", |
| 212 | + "build-julia-the-viper", |
| 213 | + "build-my-lang", |
| 214 | + "build-oblibeny", |
| 215 | + "build-tangle", |
| 216 | + "build-phronesis", |
| 217 | + "build-error-lang", |
| 218 | + "build-me-dialect", |
| 219 | + "build-7-tentacles", |
| 220 | + "build-anvomidav", |
| 221 | +] |
| 222 | +cache = true |
| 223 | + |
| 224 | +# ── Runtime Layer ──────────────────────────────────────────── |
| 225 | + |
| 226 | +[layers.runtime] |
| 227 | +description = "Minimal production runtime with all compiled binaries" |
| 228 | +from = "cgr.dev/chainguard/wolfi-base:latest" |
| 229 | +packages = ["ca-certificates", "curl", "libgcc"] |
| 230 | +copy-from = [ |
| 231 | + # Rust-built binaries |
| 232 | + { layer = "build-ephapax", src = "/app/ephapax/target/release/", dst = "/opt/nextgen/ephapax/" }, |
| 233 | + { layer = "build-wokelang", src = "/app/wokelang/target/release/", dst = "/opt/nextgen/wokelang/" }, |
| 234 | + { layer = "build-eclexia", src = "/app/eclexia/target/release/", dst = "/opt/nextgen/eclexia/" }, |
| 235 | + { layer = "build-betlang", src = "/app/betlang/target/release/", dst = "/opt/nextgen/betlang/" }, |
| 236 | + { layer = "build-julia-the-viper", src = "/app/julia-the-viper/target/release/", dst = "/opt/nextgen/julia-the-viper/" }, |
| 237 | + { layer = "build-my-lang", src = "/app/my-lang/target/release/", dst = "/opt/nextgen/my-lang/" }, |
| 238 | + # OCaml-built binaries |
| 239 | + { layer = "build-affinescript", src = "/app/affinescript/_build/default/bin/", dst = "/opt/nextgen/affinescript/" }, |
| 240 | + { layer = "build-oblibeny", src = "/app/oblibeny/_build/default/bin/", dst = "/opt/nextgen/oblibeny/" }, |
| 241 | + { layer = "build-tangle", src = "/app/tangle/_build/default/bin/", dst = "/opt/nextgen/tangle/" }, |
| 242 | + # Elixir releases |
| 243 | + { layer = "build-phronesis", src = "/app/phronesis/_build/prod/", dst = "/opt/nextgen/phronesis/" }, |
| 244 | + # Deno-based (copy source + cached deps) |
| 245 | + { layer = "build-error-lang", src = "/app/error-lang/", dst = "/opt/nextgen/error-lang/" }, |
| 246 | + { layer = "build-me-dialect", src = "/app/me-dialect/", dst = "/opt/nextgen/me-dialect/" }, |
| 247 | + { layer = "build-7-tentacles", src = "/app/7-tentacles/", dst = "/opt/nextgen/7-tentacles/" }, |
| 248 | + # Zig FFI shared objects |
| 249 | + { layer = "abi-ffi", src = "/app/*/ffi/zig/zig-out/lib/", dst = "/opt/nextgen/lib/" }, |
| 250 | +] |
| 251 | +entrypoint = ["/bin/sh"] |
| 252 | +user = "nonroot" |
| 253 | + |
| 254 | +# ── Security ───────────────────────────────────────────────── |
| 255 | + |
| 256 | +[security] |
| 257 | +non-root = true |
| 258 | +read-only-root = true |
| 259 | +no-new-privileges = true |
| 260 | +cap-drop = ["ALL"] |
| 261 | +seccomp-profile = "default" |
| 262 | + |
| 263 | +[security.signing] |
| 264 | +algorithm = "ML-DSA-87" |
| 265 | +provider = "cerro-torre" |
| 266 | + |
| 267 | +[security.sbom] |
| 268 | +format = "spdx-json" |
| 269 | +output = "sbom.spdx.json" |
| 270 | +include-deps = true |
| 271 | + |
| 272 | +# ── Verification ───────────────────────────────────────────── |
| 273 | + |
| 274 | +[verify] |
| 275 | +vordr = true |
| 276 | +svalinn = true |
| 277 | +scan-on-build = true |
| 278 | +fail-on = ["critical", "high"] |
| 279 | + |
| 280 | +# ── Targets ────────────────────────────────────────────────── |
| 281 | +# Targets allow building individual languages or the full monorepo. |
| 282 | + |
| 283 | +[targets.development] |
| 284 | +description = "Full monorepo with all toolchains for development" |
| 285 | +layers = [ |
| 286 | + "base", |
| 287 | + "rust-toolchain", |
| 288 | + "ocaml-toolchain", |
| 289 | + "elixir-toolchain", |
| 290 | + "deno-toolchain", |
| 291 | + "zig-toolchain", |
| 292 | + "idris2-toolchain", |
| 293 | + "abi-ffi", |
| 294 | + "build-all", |
| 295 | +] |
| 296 | +env = { LOG_LEVEL = "debug", RUST_BACKTRACE = "1" } |
| 297 | + |
| 298 | +[targets.production] |
| 299 | +description = "Minimal runtime with compiled binaries only" |
| 300 | +layers = ["runtime"] |
| 301 | +env = { LOG_LEVEL = "info" } |
| 302 | + |
| 303 | +[targets.test] |
| 304 | +description = "Full toolchains with test dependencies for CI" |
| 305 | +layers = [ |
| 306 | + "base", |
| 307 | + "rust-toolchain", |
| 308 | + "ocaml-toolchain", |
| 309 | + "elixir-toolchain", |
| 310 | + "deno-toolchain", |
| 311 | + "zig-toolchain", |
| 312 | + "idris2-toolchain", |
| 313 | + "abi-ffi", |
| 314 | + "build-all", |
| 315 | +] |
| 316 | +env = { LOG_LEVEL = "debug", RUST_BACKTRACE = "full", MIX_ENV = "test" } |
| 317 | + |
| 318 | +# ── Per-Language Targets ───────────────────────────────────── |
| 319 | +# Build individual languages in isolation. |
| 320 | + |
| 321 | +[targets.ephapax] |
| 322 | +description = "Ephapax only — linear type system language" |
| 323 | +layers = ["base", "rust-toolchain", "idris2-toolchain", "build-ephapax"] |
| 324 | +env = { LOG_LEVEL = "debug" } |
| 325 | + |
| 326 | +[targets.wokelang] |
| 327 | +description = "WokeLang only — consent-aware programming" |
| 328 | +layers = ["base", "rust-toolchain", "ocaml-toolchain", "build-wokelang"] |
| 329 | +env = { LOG_LEVEL = "debug" } |
| 330 | + |
| 331 | +[targets.eclexia] |
| 332 | +description = "Eclexia only — economics-as-code" |
| 333 | +layers = ["base", "rust-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-eclexia"] |
| 334 | +env = { LOG_LEVEL = "debug" } |
| 335 | + |
| 336 | +[targets.affinescript] |
| 337 | +description = "AffineScript only — affine type system" |
| 338 | +layers = ["base", "ocaml-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-affinescript"] |
| 339 | +env = { LOG_LEVEL = "debug" } |
| 340 | + |
| 341 | +[targets.betlang] |
| 342 | +description = "BetLang only — probabilistic programming" |
| 343 | +layers = ["base", "rust-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-betlang"] |
| 344 | +env = { LOG_LEVEL = "debug" } |
| 345 | + |
| 346 | +[targets.julia-the-viper] |
| 347 | +description = "Julia the Viper only — pattern matching" |
| 348 | +layers = ["base", "rust-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-julia-the-viper"] |
| 349 | +env = { LOG_LEVEL = "debug" } |
| 350 | + |
| 351 | +[targets.my-lang] |
| 352 | +description = "MyLang only — personal expression" |
| 353 | +layers = ["base", "rust-toolchain", "build-my-lang"] |
| 354 | +env = { LOG_LEVEL = "debug" } |
| 355 | + |
| 356 | +[targets.oblibeny] |
| 357 | +description = "Oblibeny only — Turing-incomplete constrained form" |
| 358 | +layers = ["base", "ocaml-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-oblibeny"] |
| 359 | +env = { LOG_LEVEL = "debug" } |
| 360 | + |
| 361 | +[targets.tangle] |
| 362 | +description = "Tangle only — entangled computation" |
| 363 | +layers = ["base", "ocaml-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-tangle"] |
| 364 | +env = { LOG_LEVEL = "debug" } |
| 365 | + |
| 366 | +[targets.phronesis] |
| 367 | +description = "Phronesis only — practical wisdom" |
| 368 | +layers = ["base", "elixir-toolchain", "build-phronesis"] |
| 369 | +env = { LOG_LEVEL = "debug", MIX_ENV = "prod" } |
| 370 | + |
| 371 | +[targets.error-lang] |
| 372 | +description = "Error-lang only — error-centric programming" |
| 373 | +layers = ["base", "deno-toolchain", "zig-toolchain", "idris2-toolchain", "abi-ffi", "build-error-lang"] |
| 374 | +env = { LOG_LEVEL = "debug" } |
| 375 | + |
| 376 | +[targets.me-dialect] |
| 377 | +description = "Me-dialect only — personal dialect" |
| 378 | +layers = ["base", "deno-toolchain", "build-me-dialect"] |
| 379 | +env = { LOG_LEVEL = "debug" } |
| 380 | + |
| 381 | +[targets.7-tentacles] |
| 382 | +description = "7-Tentacles only — multi-agent language learning" |
| 383 | +layers = ["base", "deno-toolchain", "build-7-tentacles"] |
| 384 | +env = { LOG_LEVEL = "debug" } |
| 385 | + |
| 386 | +[targets.anvomidav] |
| 387 | +description = "Anvomidav only — experimental language" |
| 388 | +layers = ["base", "elixir-toolchain", "build-anvomidav"] |
| 389 | +env = { LOG_LEVEL = "debug" } |
0 commit comments