Skip to content

Commit ad3224c

Browse files
fix(aspect+e2e): make tests truthful + ums-mcp Mutex + install Elixir (unblocks #149) (#150)
## Summary Two failing checks (Aspect 27 fails + E2E 1 fail) had four distinct root causes. Each fixed at source: ### Aspect — Thread Safety + ABI Contract + SPDX (27 → 0 fails) | # | Root cause | Fix | |---|---|---| | 1 | Comment filters broken — `^\s*--` / `^\s*\|\|\|` never matched because `grep -rn` output starts with `path:lineno:`, not content | Anchor at `:[[:space:]]*--` / `:[[:space:]]*\|\|\|` + add trailing `-- … <pat>` comment filter, factored into `strip_comments_and_docstrings` helper | | 2 | `believe_me` check didn't exempt the 5 documented class-J axioms in `src/abi/Boj/SafetyLemmas.idr` | Added `PROOF_EXEMPT` regex; passes on documented axioms, fails on any new use elsewhere | | 3 | Aspect 1 Mutex check fired on purely-functional FFI (e.g. `burble_admin_ffi.zig` — 3 exports, zero file-scope globals — table lookups over `i32`) | Refined to only fail when there's ALSO `^(pub )?var <ident>` file-scope global state. Purely-functional exports now get an explicit pass message | | 4 | Aspect 4 had no concept of stub-or-by-design cartridges — 15 fails for "incomplete layers" included 10 manifest-only stubs (cartridge.json declares API; abi/ ffi/ not yet written) and 5 intentionally proof-free observability/glue (boj-health, claude-ai-mcp, lang-mcp, orchestrator-lsp-mcp, toolchain-mcp) | Added `"status": "stub" \| "ffi_only" \| "complete"` (default `complete`) field to `cartridge.json`. Aspect 4 honours it and reports `(N complete, M stub, K ffi_only)` so categories stay visible in CI logs | | 5 | **Real bug**: `cartridges/ums-mcp/ffi/ums_ffi.zig` has 15 C-ABI exports operating on a global `var sessions: [MAX_SESSIONS]SessionSlot`, no Mutex. Once the filter fixes narrow Aspect 1 to true positives, this is the one that remains. | Added `var sessions_mu: std.Thread.Mutex` and `sessions_mu.lock(); defer sessions_mu.unlock();` to all 14 sessions-touching exports. `ums_can_transition` is pure (enum→enum) and stays lock-free. Mirrors `g_state_mu` in `cartridges/007-mcp/ffi/oo7_mcp_ffi.zig:79`. `zig build` passes | After all five: **115 passed / 0 failed / 1 warning** (was 87/27/1). The one warning (`federation.zig` `catch unreachable`) was pre-existing — out of scope here. ### E2E — Full REST + MCP Bridge (failing since 2026-05-20) `tests/e2e_full.sh` requires `mix` to start the Elixir backend, but `.github/workflows/e2e.yml` never installed Elixir/OTP. Added an `erlef/setup-beam@v1.18.2` step (Elixir 1.18 + OTP 27 — matches the estate convention used in every repo's hypatia-scan.yml) plus a `mix deps.get` step before the test runs. ## Test plan - [x] `bash tests/aspect_tests.sh` — 115/0/1 (was 87/27/1) - [x] `cd cartridges/ums-mcp/ffi && zig build` — clean - [x] All 15 `cartridge.json` files still valid JSON - [x] `e2e.yml` YAML parses; step ordering correct (setup-beam before build-FFI / run-e2e) ## Foundational follow-up (NOT in this PR — flagged) Same gap as `r-g-t-v#89` and `absolute-zero#42`: `main` branch protection has no `required_status_checks` block, so red-CI PRs can merge despite three workflows (E2E + Aspect + Bench, OpenSSF Scorecard Enforcer, Instant Sync) being persistently red on main. Hypatia PR #316 ships BH001/BH002/BH003 to detect this class estate-wide; the BH001 rule fires on exactly this repo. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6626b52 commit ad3224c

20 files changed

Lines changed: 210 additions & 32 deletions

File tree

.github/workflows/e2e.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,28 @@ jobs:
5656
with:
5757
deno-version: v2.x
5858

59+
- name: Install Elixir + OTP
60+
# tests/e2e_full.sh requires `mix` on PATH to start the Elixir
61+
# backend (elixir/ — `mix run --no-halt`). Pinned to match the
62+
# estate convention (see hypatia-scan.yml across the org).
63+
uses: erlef/setup-beam@fc68ffb90438ef2936bbb3251622353b3dcb2f93 # v1.18.2
64+
with:
65+
elixir-version: '1.18'
66+
otp-version: '27'
67+
5968
- name: Install system dependencies
6069
run: sudo apt-get update && sudo apt-get install -y curl jq
6170

71+
- name: Fetch Elixir deps
72+
working-directory: elixir
73+
run: mix deps.get
74+
75+
- name: Compile Elixir deps
76+
# Pre-compile so the in-test `mix run --no-halt` doesn't have
77+
# to do it on the critical path of the 60s server-start window.
78+
working-directory: elixir
79+
run: mix compile
80+
6281
- name: Build FFI libraries
6382
run: |
6483
cd ffi/zig && zig build

.github/workflows/zig-test.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,14 @@ jobs:
5252
all="$(ls -d cartridges/*/ffi/ 2>/dev/null | sed 's|cartridges/||;s|/ffi/||' | sort)"
5353
if [ "$EVENT" = "pull_request" ]; then
5454
git fetch --no-tags --depth=50 origin "$BASE_REF" || true
55-
changed="$(git diff --name-only "origin/${BASE_REF}...HEAD" -- 'cartridges/**' \
55+
# Only scope cartridges whose `ffi/` actually changed —
56+
# `cartridge.json` edits (e.g. adding a status field) and
57+
# `abi/` edits should not pull a cart into this FFI test
58+
# job, which exists to validate Zig builds. Using
59+
# `cartridges/*/ffi/**` as the pathspec ensures only
60+
# ffi-relevant diffs count (also matches the workflow's
61+
# own `on.paths` filter — they were inconsistent before).
62+
changed="$(git diff --name-only "origin/${BASE_REF}...HEAD" -- 'cartridges/*/ffi/**' \
5663
| awk -F/ '{print $2}' | sort -u)"
5764
scope=""
5865
while IFS= read -r cart; do

cartridges/boj-health/cartridge.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>",
55
"name": "boj-health",
66
"version": "0.1.0",
7+
"status": "ffi_only",
78
"description": "BoJ server self-health cartridge — status, ping, and uptime queries. Self-contained Zig FFI (.so) reference implementation: no external services required.",
89
"domain": "infrastructure",
910
"tier": "Ayo",

cartridges/chromadb-mcp/cartridge.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>",
55
"name": "chromadb-mcp",
66
"version": "0.1.0",
7+
"status": "stub",
78
"description": "Chroma vector DB — embedded (local persistent) or client/server; LLM-app-focused; metadata + document storage alongside vectors.",
89
"domain": "vector",
910
"tier": "Teranga",

cartridges/claude-ai-mcp/cartridge.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath)",
55
"name": "claude-ai-mcp",
66
"version": "0.1.0",
7+
"status": "ffi_only",
78
"description": "Anthropic Messages API cartridge -- send messages to Claude models, count tokens, manage multi-turn conversations",
89
"domain": "AI",
910
"tier": "Ayo",

cartridges/echidna-llm-mcp/cartridge.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>",
55
"name": "echidna-llm-mcp",
66
"version": "0.1.0",
7+
"status": "stub",
78
"description": "LLM advisor cartridge for the ECHIDNA formal verification engine. Provides free-form consultation (consult) and structured proof-tactic generation (suggest_tactics) by routing to Anthropic Claude via ANTHROPIC_API_KEY.",
89
"domain": "Formal Verification",
910
"tier": "Ayo",

cartridges/elevenlabs-mcp/cartridge.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>",
55
"name": "elevenlabs-mcp",
66
"version": "0.1.0",
7+
"status": "stub",
78
"description": "Text-to-speech via ElevenLabs API — high-quality voices, multilingual, voice cloning (premium tier), streaming output.",
89
"domain": "multimodal",
910
"tier": "Teranga",

cartridges/ffmpeg-mcp/cartridge.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>",
55
"name": "ffmpeg-mcp",
66
"version": "0.1.0",
7+
"status": "stub",
78
"description": "Local FFmpeg gateway — probe metadata, transcode formats, extract audio, extract frames, concatenate, trim. Glue between whisper / replicate / browser screenshots. Local-only — requires host ffmpeg binary; not Worker-compatible.",
89
"domain": "multimodal",
910
"tier": "Teranga",

cartridges/lang-mcp/cartridge.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath)",
55
"name": "lang-mcp",
66
"version": "0.1.0",
7+
"status": "ffi_only",
78
"description": "Multi-language session manager for the nextgen-languages family: Eclexia, AffineScript, BetLang, Ephapax, MyLang, WokeLang, Anvomidav, Phronesis, Error-lang, Julia-the-Viper, Me-dialect, Oblibeny. Tracks per-language sessions, delegates type-checking and evaluation to each language's CLI tool, and provides a unified interface across all dialects.",
89
"domain": "Languages",
910
"tier": "Ayo",

cartridges/orchestrator-lsp-mcp/cartridge.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"copyright": "Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>",
55
"name": "orchestrator-lsp-mcp",
66
"version": "0.1.0",
7+
"status": "ffi_only",
78
"status": "ready",
89
"description": "Cross-domain LSP orchestrator. Routes LSP requests across all 12 poly-*-lsp servers (cloud, container, iac, k8s, db, queue, secret, git, ssg, proof, observability, browser) via a single GenLSP supervisor. Inspired by poly-orchestrator-lsp (polystack, archived). Wraps the 12 domain servers into one unified textDocument interface with domain-routing based on workspace root and file type.",
910
"domain": "LSP",

0 commit comments

Comments
 (0)