From 69b47b7d59f2f6b0dea71b7b6a90e91c992ca6ce Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:50:51 +0100 Subject: [PATCH] build,ci: fix Hypatia env, update CI policy text to AffineScript, fix mix path in service unit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three of the four sub-parts of the deferred cleanup ledger from PR #40's out-of-scope list. The fourth (port the 6 .ts cartridge adapters to AffineScript→typed-wasm) is delegated to a scheduled remote agent that fires 2026-05-07 and runs one cartridge per pass. ## .github/workflows/hypatia-scan.yml — fix GITHUB_TOKEN missing The Hypatia scan step was failing on every PR with: Warning: Dependabot alerts unavailable: GITHUB_TOKEN not set — cannot query Dependabot alerts ##[error]Process completed with exit code 1. Hypatia's CLI calls `gh api` for Dependabot alert lookups. Without GITHUB_TOKEN in the env it can't query, and exits non-zero. Other steps in the same workflow had GITHUB_TOKEN set on a per-step basis; this moves it to job-level so all steps see it. Also adds `security-events: read` to permissions (needed for the Dependabot alert API). ## .github/workflows/{rsr-antipattern,ts-blocker}.yml — AffineScript not ReScript Per estate-wide language policy 2026-04-30: RS/TS/JS → AffineScript → typed-wasm. ReScript is also being phased out; only allowed as adapter shims to upstream ReScript-using systems. The CI "use X instead" messages now point at AffineScript, with Zig→WASM called out as the systems-level alternative. Specifically: rsr-antipattern.yml: - Header comment: "Allows: ReScript, Deno, ..." -> "Allows: AffineScript, Deno, Rust/SPARK, ..." with explicit carve-out that ReScript is shim-only. - "use ReScript instead" (TS check) -> "use AffineScript→typed-wasm instead" - "use ReScript instead" (tsconfig check) -> same - Summary banner: lists AffineScript as default, ReScript as transitional / adapter-shim only. ts-blocker.yml: - "port to Zig or ReScript" (existing-TS path) -> "port to Zig or AffineScript" - "use Zig or ReScript instead" (new-JS path) -> "use ... AffineScript→typed-wasm for application code, Zig→WASM for systems" Both keep the underlying detection unchanged; only the user-facing guidance text changes. ## elixir/boj-rest.service — replace hardcoded /usr/bin/mix The unit hardcoded `ExecStart=/usr/bin/mix run --no-halt`, which fails on hosts where Elixir is asdf-managed (the only practical way to get Elixir ≥ 1.15 on Ubuntu 24.04 LTS, since apt ships 1.14). The unit would crash-loop with: ** (Mix) You're trying to run :boj_rest on Elixir v1.14.0 but it has declared in its mix.exs file it supports only Elixir ~> 1.15 Fix: - Adds Environment=PATH including %h/.asdf/shims, %h/.cargo/bin, and %h/.local/bin (in that order before system paths). %h is systemd's home-directory specifier, so the unit is portable across users. - Adds Environment=ASDF_DIR + ASDF_DATA_DIR so the asdf shim resolves correctly under systemd's clean environment. - Changes ExecStart to `mix run --no-halt` (PATH lookup), so the asdf shim picks up whatever Elixir is pinned in .tool-versions (now 1.18.4-otp-25 per the toolchain-pins PR #41). Bumps the cartridge-count comment on LimitNOFILE from 112 to 115 to match the rest of the repo post-#40. ## What this PR does NOT do - Port any of the 6 .ts cartridge adapters to AffineScript. That is delegated to a scheduled remote agent (one cartridge per pass, weekly, starting 2026-05-07). - Re-run any tests. The systemd unit fix is verified via the live install on the maintainer's machine, where boj-rest.service is currently `active (running)` with the patched (deployed-only) Environment=PATH approach. Persisting the fix to the source template is what this PR does. - Touch any cartridge code, build wiring, or non-CI workflow logic. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/hypatia-scan.yml | 5 +++++ .github/workflows/rsr-antipattern.yml | 31 +++++++++++++++++---------- .github/workflows/ts-blocker.yml | 9 ++++++-- elixir/boj-rest.service | 16 ++++++++++++-- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index 645d75b..8f8308c 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -13,11 +13,16 @@ on: permissions: contents: read + security-events: read # Hypatia queries Dependabot alerts via the GraphQL API jobs: scan: name: Hypatia Neurosymbolic Analysis runs-on: ubuntu-latest + env: + # Hypatia's CLI calls `gh api` for Dependabot alert lookups; without this + # env var it logs "Dependabot alerts unavailable: GITHUB_TOKEN not set". + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout repository diff --git a/.github/workflows/rsr-antipattern.yml b/.github/workflows/rsr-antipattern.yml index 220feb3..0e320df 100644 --- a/.github/workflows/rsr-antipattern.yml +++ b/.github/workflows/rsr-antipattern.yml @@ -3,7 +3,9 @@ # SPDX-License-Identifier: MPL-2.0 # # Enforces: No TypeScript, No Go, No Python (except SaltStack), No npm -# Allows: ReScript, Deno, WASM, Rust, OCaml, Haskell, Guile/Scheme +# Allows: AffineScript, Deno, WASM, Rust/SPARK, OCaml, Haskell, Guile/Scheme, +# ReScript (only as adapter shim to upstream ReScript-using systems — +# per estate-wide policy 2026-04-30, RS/TS/JS default is AffineScript) name: RSR Anti-Pattern Check @@ -31,7 +33,9 @@ jobs: # Exclude .d.ts files - those are TypeScript type declarations for ReScript FFI TS_FILES=$(find . \( -name "*.ts" -o -name "*.tsx" \) | grep -v node_modules | grep -v 'bindings/deno' | grep -v '\.d\.ts$' || true) if [ -n "$TS_FILES" ]; then - echo "❌ TypeScript files detected - use ReScript instead" + echo "❌ TypeScript files detected — use AffineScript→typed-wasm instead" + echo " (Estate-wide policy 2026-04-30: RS/TS/JS default is AffineScript;" + echo " ReScript is also being phased out except as upstream-system adapters.)" echo "$TS_FILES" exit 1 fi @@ -67,7 +71,8 @@ jobs: - name: Check for tsconfig run: | if [ -f "tsconfig.json" ]; then - echo "❌ tsconfig.json detected - use ReScript instead" + echo "❌ tsconfig.json detected — use AffineScript→typed-wasm instead" + echo " (Estate-wide policy 2026-04-30: see RSR Anti-Pattern Allows list.)" exit 1 fi echo "✅ No tsconfig.json" @@ -83,11 +88,15 @@ jobs: - name: Summary run: | - echo "╔════════════════════════════════════════════════════════════╗" - echo "║ RSR Anti-Pattern Check Passed ✅ ║" - echo "║ ║" - echo "║ Allowed: ReScript, Deno, WASM, Rust, OCaml, Haskell, ║" - echo "║ Guile/Scheme, SaltStack (Python) ║" - echo "║ ║" - echo "║ Blocked: TypeScript, Go, npm, Python (non-Salt) ║" - echo "╚════════════════════════════════════════════════════════════╝" + echo "╔══════════════════════════════════════════════════════════════════╗" + echo "║ RSR Anti-Pattern Check Passed ✅ ║" + echo "║ ║" + echo "║ Allowed (default for new code): ║" + echo "║ AffineScript→typed-wasm, Deno, WASM, Rust/SPARK, OCaml, ║" + echo "║ Haskell, Guile/Scheme, SaltStack (Python) ║" + echo "║ ║" + echo "║ Allowed (transitional / adapter-shim only): ║" + echo "║ ReScript — for shims to upstream RS-using systems ║" + echo "║ ║" + echo "║ Blocked: TypeScript, Go, npm, Python (non-Salt) ║" + echo "╚══════════════════════════════════════════════════════════════════╝" diff --git a/.github/workflows/ts-blocker.yml b/.github/workflows/ts-blocker.yml index 45b576e..4733a93 100644 --- a/.github/workflows/ts-blocker.yml +++ b/.github/workflows/ts-blocker.yml @@ -17,7 +17,9 @@ jobs: # Zero-tolerance: NO .ts files anywhere in the tree. EXISTING_TS=$(find . -name "*.ts" -o -name "*.tsx" | grep -v './.git/' | grep -v node_modules | grep -v '\.gen\.' || true) if [ -n "$EXISTING_TS" ]; then - echo "❌ TypeScript files found (must be zero — port to Zig or ReScript):" + echo "❌ TypeScript files found (must be zero — port to Zig or AffineScript):" + echo " Estate-wide policy 2026-04-30: RS/TS/JS → AffineScript→typed-wasm." + echo " For systems-level code, Zig→WASM is the alternative." printf '%s\n' "$EXISTING_TS" exit 1 fi @@ -25,7 +27,10 @@ jobs: # JS: block new additions only (existing JS tracked for WASM migration). NEW_JS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E '\.(js|jsx)$' | grep -v '\.res\.js$' | grep -v '\.gen\.' | grep -v 'node_modules' || true) if [ -n "$NEW_JS" ]; then - echo "❌ New .js files detected. Target language is Zig→WASM; use Zig or ReScript instead." + echo "❌ New .js files detected." + echo " Estate-wide policy 2026-04-30: target language is AffineScript→typed-wasm" + echo " for application code, Zig→WASM for systems work. ReScript is being" + echo " phased out (only allowed as upstream-system adapter shims)." printf '%s\n' "$NEW_JS" exit 1 fi diff --git a/elixir/boj-rest.service b/elixir/boj-rest.service index 6dcfd1b..c9584ed 100644 --- a/elixir/boj-rest.service +++ b/elixir/boj-rest.service @@ -24,6 +24,15 @@ Wants=local-coord-mcp.service Type=simple WorkingDirectory=$BOJ_ROOT/elixir +# PATH must include asdf shims and ~/.cargo/bin for users running +# asdf-managed Elixir or cargo-installed `just`. Falls through to +# system paths if asdf isn't installed (in which case the elixir/mix.exs +# version requirement will fail loudly — apt's Elixir 1.14 on Ubuntu +# 24.04 LTS does not satisfy `~> 1.15`). %h is the user home directory. +Environment=PATH=%h/.asdf/shims:%h/.cargo/bin:%h/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +Environment=ASDF_DIR=%h/.asdf +Environment=ASDF_DATA_DIR=%h/.asdf + # Env vars — see elixir/config/config.exs for the full list Environment=MIX_ENV=dev Environment=BOJ_PORT=7700 @@ -31,11 +40,14 @@ Environment=BOJ_CARTRIDGES_ROOT=$BOJ_ROOT/cartridges Environment=BOJ_DATA_DIR=$HOME/.local/share/boj-server Environment=BOJ_INVOKE_CLI=$BOJ_ROOT/ffi/zig/zig-out/bin/boj-invoke -ExecStart=/usr/bin/mix run --no-halt +# Use `mix` resolved via PATH (the asdf shim picks up the version +# pinned in .tool-versions). Hardcoding /usr/bin/mix breaks when +# Elixir is asdf-managed and apt's mix is too old. +ExecStart=mix run --no-halt Restart=on-failure RestartSec=5 -# Give the Elixir/BEAM VM enough file descriptors for 112 cartridges + +# Give the Elixir/BEAM VM enough file descriptors for 115 cartridges + # one Deno worker port per JS cartridge (up to 256 concurrent workers). LimitNOFILE=65536