Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/DISCUSSION_TEMPLATE/cartridge-proposal.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ body:
attributes:
value: |
Proposing a new cartridge for the Ayo (community) menu? Tell us about it!
Cartridges follow the three-layer stack: Idris2 ABI + Zig FFI + V-lang Adapter.
Cartridges follow the stack: Idris2 ABI + Zig FFI, served by the Elixir adapter.
See docs/DEVELOPERS.md for the full guide.
- type: input
attributes:
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ jobs:
[ -f "$cart/build.zig" ] && (cd "$cart" && zig build) || true
done

- name: Build V adapter
run: |
cd adapter/v && v -o boj-server . || echo "V adapter build attempted"

- name: Run E2E full test suite
run: bash tests/e2e_full.sh

Expand Down
30 changes: 1 addition & 29 deletions .github/workflows/lsp-dap-bsp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,34 +91,6 @@ jobs:
cd "$GITHUB_WORKSPACE"
done

adapter-check:
name: V-lang Adapter Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install V-lang
run: |
sudo apt-get update && sudo apt-get install -y libgc-dev
git clone --depth=1 https://github.com/vlang/v
cd v && make && sudo ./v symlink
- name: Check LSP/DAP/BSP adapters
run: |
for cart in lsp-mcp dap-mcp bsp-mcp; do
echo "=== Checking $cart adapter ==="
adapter_dir="cartridges/$cart/adapter"
if [ ! -d "$adapter_dir" ]; then
echo "ERROR: $adapter_dir missing"
exit 1
fi
v_files=$(find "$adapter_dir" -name '*.v' | wc -l)
if [ "$v_files" -eq 0 ]; then
echo "ERROR: No .v files in $adapter_dir"
exit 1
fi
v check "$adapter_dir"/*.v 2>&1 || { echo "ERROR: V check failed for $cart"; exit 1; }
echo " V-lang check passed ($v_files files)"
done

panel-validation:
name: Panel Manifest Validation
runs-on: ubuntu-latest
Expand Down Expand Up @@ -153,7 +125,7 @@ jobs:
completeness:
name: Cartridge Completeness Check
runs-on: ubuntu-latest
needs: [abi-check, ffi-build, adapter-check, panel-validation]
needs: [abi-check, ffi-build, panel-validation]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Verify triadic structure
Expand Down
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,6 @@ src/abi/build/
# Cartridge Idris2 build artifacts
cartridges/*/abi/build/

# V-lang build artifacts
adapter/v/boj-server
v.mod.lock

# Hypatia scanner logs
.hypatia/

Expand Down
6 changes: 3 additions & 3 deletions 0-AI-MANIFEST.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
Class 1 (Simple) — self-contained cartridges via GitHub Actions.
Class 2 (Orchestrator) — unified gateways (WS/MQTT/Webhook).
Class 3 (Multiplier) — Elixir/BEAM for mass concurrency.
Every cartridge has Idris2 ABI + Zig FFI + V-lang Adapter triple.")
Every cartridge has Idris2 ABI + Zig FFI; the Elixir backend serves the network adapter.")

;; ===================================================================
;; CONTEXT TIERS
Expand Down Expand Up @@ -65,7 +65,7 @@
├── src/abi/ # Idris2 ABI (Catalogue, Protocol, Domain, Menu, Federation)
├── ffi/zig/ # Zig FFI (catalogue mount/unmount, loader)
├── generated/abi/ # Auto-generated C headers
├── adapter/v/ # V-lang triple adapter (REST+gRPC+GraphQL, port 9000)
├── elixir/ # Elixir triple adapter (REST+gRPC+GraphQL, Plug/Cowboy)
├── cartridges/ # One dir per matrix cell (database-mcp, nesy-mcp, fleet-mcp, ...)
├── container/ # Stapeln container ecosystem
├── panll/src/ # PanLL panel (ReScript/TEA)
Expand All @@ -77,7 +77,7 @@
;; ===================================================================

(critical-invariants
(rule "Three-Layer Stack: every cartridge = Idris2 ABI + Zig FFI + V-lang Adapter")
(rule "Stack: every cartridge = Idris2 ABI + Zig FFI; Elixir backend serves the network adapter")
(rule "Zero believe_me anywhere in src/abi/ or cartridges/*/abi/")
(rule "%default total on all Idris2 files")
(rule "IsUnbreakable proof required for Ready cartridges")
Expand Down
84 changes: 19 additions & 65 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -430,14 +430,14 @@ matrix:
ABI="✗"; FFI="✗"; ADAPTER="✗"; TESTS="✗"
[ -f "cartridges/$cart/abi"/*/*.idr ] 2>/dev/null && ABI="✓"
[ -f "cartridges/$cart/ffi"/*_ffi.zig ] 2>/dev/null && FFI="✓"
[ -f "cartridges/$cart/adapter"/*_adapter.v ] 2>/dev/null && ADAPTER="✓"
[ -d "elixir" ] 2>/dev/null && ADAPTER="✓"
[ -f "cartridges/$cart/ffi/build.zig" ] 2>/dev/null && TESTS="✓"
printf " %-20s %s %s %s %s\n" "$cart" "$ABI" "$FFI" "$ADAPTER" "$TESTS"
done
echo ""
echo " Core catalogue: ffi/zig/src/catalogue.zig"
echo " Dynamic loader: ffi/zig/src/loader.zig"
echo " V-lang adapter: adapter/v/src/ (directory)"
echo " REST server: elixir/ (Plug/Cowboy)"
echo " Menu: .machine_readable/servers/menu.a2ml"
echo ""

Expand All @@ -449,49 +449,24 @@ matrix:
run *args: build
#!/usr/bin/env bash
set -euo pipefail
# Preference: Elixir (Class 3) > V-lang (deprecated/banned)
# The REST surface is the Elixir backend (Class 3 Multiplier).
if [ -d "elixir" ] && command -v mix >/dev/null 2>&1; then
echo "Starting BoJ Server (Elixir Class 3 Multiplier)..."
cd elixir && exec mix run --no-halt {{args}}
else
ADAPTER="adapter/v/boj-server"
if [ ! -f "$ADAPTER" ]; then
if command -v v >/dev/null 2>&1; then
just build-adapter
else
echo "ERROR: V-lang adapter not built and 'v' not found."
echo "V-lang was banned 2026-04-10. Please use the Elixir backend (cd elixir && mix run)."
exit 1
fi
fi
echo "Starting BoJ Server (Legacy V-lang Adapter)..."
LLP="$(pwd)/ffi/zig/zig-out/lib"
for d in cartridges/*/ffi/zig-out/lib; do [ -d "$d" ] && LLP="${LLP}:$(pwd)/${d}"; done
LD_LIBRARY_PATH="${LLP}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" exec "$ADAPTER" {{args}}
echo "ERROR: Elixir backend not available (need 'elixir/' dir and 'mix')."
echo "Install Elixir/Mix, then: cd elixir && mix run --no-halt"
exit 1
fi

# Run with verbose output
run-verbose *args: build
BOJ_VERBOSE=1 just run {{args}}

# Build V-lang adapter binary (compiles full directory: REST+gRPC+GraphQL+SSE)
build-adapter: build
#!/usr/bin/env bash
set -euo pipefail
echo "Building V-lang adapter (REST+gRPC+GraphQL+SSE)..."
LFLAGS="-L$(pwd)/ffi/zig/zig-out/lib"
for d in cartridges/*/ffi/zig-out/lib; do
[ -d "$d" ] && LFLAGS="${LFLAGS} -L$(pwd)/${d}"
done
v -cc gcc -cflags "${LFLAGS} -Wl,--allow-multiple-definition -no-pie" \
-o adapter/v/boj-server adapter/v/src/
echo "Built: adapter/v/boj-server ($(du -h adapter/v/boj-server | cut -f1))"

# Install to user path
install: build-adapter
@echo "Installing boj-server..."
cp adapter/v/boj-server ~/.local/bin/boj-server
@echo "Installed to ~/.local/bin/boj-server"
# Install: the REST surface is served by the Elixir backend (cd elixir && mix run)
install: build
@echo "The BoJ REST surface is the Elixir backend; no binary is installed."
@echo "Run it with: cd elixir && mix run --no-halt (or: just run)"

# Start Cloudflare quick tunnel (exposes BoJ at *.trycloudflare.com)
tunnel:
Expand All @@ -503,14 +478,14 @@ tunnel:
serve: build
#!/usr/bin/env bash
set -euo pipefail
ADAPTER="adapter/v/boj-server"
if [ ! -f "$ADAPTER" ]; then
just build-adapter
if [ ! -d "elixir" ] || ! command -v mix >/dev/null 2>&1; then
echo "ERROR: Elixir backend not available (need 'elixir/' dir and 'mix')."
exit 1
fi
echo "Starting BoJ Server..."
echo " Local: http://localhost:7700/status"
echo " SSE: http://localhost:7703/sse"
LD_LIBRARY_PATH="$(pwd)/ffi/zig/zig-out/lib" "$ADAPTER" &
(cd elixir && mix run --no-halt) &
BOJ_PID=$!
trap "kill $BOJ_PID 2>/dev/null; kill $TUNNEL_PID 2>/dev/null; exit" INT TERM
sleep 2
Expand Down Expand Up @@ -1218,7 +1193,6 @@ doctor:
check "git" git "2.0+"
echo ""
echo "Optional tools:"
check_optional "V (vlang)" v "deprecated/banned 2026-04-10"
check_optional "Cargo" cargo "needed by launch-scaffolder (mint/provision/config)"
check_optional "cloudflared" cloudflared "needed for tunnel"
check_optional "panic-attack" panic-attack "pre-commit scanner"
Expand Down Expand Up @@ -1254,10 +1228,10 @@ doctor:
else
echo " [INFO] ffi/zig/zig-out/ not found — run 'just build'"
fi
if [ -f "adapter/v/boj-server" ]; then
echo " [OK] adapter/v/boj-server binary exists"
if [ -d "elixir" ]; then
echo " [OK] elixir/ exists (REST server backend)"
else
echo " [INFO] V-lang adapter not built — run 'just build-adapter'"
echo " [INFO] elixir/ backend not found"
fi
if [ -d "src/abi/build" ]; then
echo " [OK] src/abi/build/ exists (Idris2 ABI compiled)"
Expand Down Expand Up @@ -1317,25 +1291,6 @@ heal:
ZIG_VER=$(asdf list zig 2>/dev/null | tail -1 | tr -d ' ')
[ -n "$ZIG_VER" ] && asdf global zig "$ZIG_VER" && echo " Zig global version set: $ZIG_VER"
fi
# --- Install V (vlang) ---
if ! command -v v >/dev/null 2>&1; then
echo "Installing V (API adapter)..."
if [ ! -d "$HOME/vlang" ]; then
git clone https://github.com/vlang/v "$HOME/vlang"
fi
(cd "$HOME/vlang" && make)
# Symlink without sudo — use ~/.local/bin if writable
mkdir -p "$HOME/.local/bin"
ln -sf "$HOME/vlang/v" "$HOME/.local/bin/v"
export PATH="$HOME/.local/bin:$PATH"
if ! grep -q '\.local/bin' "$HOME/.bashrc" 2>/dev/null; then
echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.bashrc"
fi
echo " V installed at ~/.local/bin/v"
echo " (If 'v' is still not found in a new shell, run: sudo ~/vlang/v symlink)"
HEALED=$((HEALED + 1))
echo ""
fi
# --- System library dependencies ---
if command -v apt-get >/dev/null 2>&1; then
MISSING_PKGS=""
Expand Down Expand Up @@ -1390,7 +1345,7 @@ tour:
echo ""
echo " 1. Idris2 ABI — Dependent types prove correctness"
echo " 2. Zig FFI — C-compatible native execution"
echo " 3. V-lang API — REST + gRPC + GraphQL adapter"
echo " 3. Elixir API — REST + gRPC + GraphQL surface"
echo ""
echo "Three-Class Architecture:"
echo " Class 1: Simple Track — CLI/curl, self-contained"
Expand All @@ -1406,7 +1361,7 @@ tour:
echo "Key directories:"
echo " cartridges/ 70+ cartridge directories"
echo " ffi/zig/ Core catalogue FFI"
echo " adapter/v/ V-lang triple adapter"
echo " elixir/ REST server (Plug/Cowboy)"
echo " container/ Stapeln container ecosystem"
echo ""
CART_COUNT=$(ls -d cartridges/*-mcp 2>/dev/null | wc -l)
Expand Down Expand Up @@ -1442,7 +1397,6 @@ help-me:
echo "BUILD & RUN:"
echo " just build Build all Zig FFI layers (catalogue + cartridges)"
echo " just build-release Build with optimizations"
echo " just build-adapter Build V-lang API triple adapter"
echo " just run Build + start server (REST 7700, gRPC 7701, GraphQL 7702)"
echo " just run-verbose Start with verbose output"
echo " just serve Server + Cloudflare tunnel"
Expand Down
20 changes: 10 additions & 10 deletions docs/GETTING-STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
| Tool | Version | Purpose |
|------|---------|---------|
| [Zig](https://ziglang.org/download/) | 0.15+ | FFI compilation |
| [V-lang](https://vlang.io/) | 0.5.0+ | Adapter compilation |
| [Elixir](https://elixir-lang.org/) | 1.15+ | REST/gRPC/GraphQL adapter |
| GCC | any recent | Linking |

Optional:
Expand All @@ -29,18 +29,18 @@ for cart in cartridges/*/ffi; do
(cd "$cart" && zig build 2>/dev/null)
done

# Build the V adapter
cd adapter/v
v -cc gcc src/main.v -o boj-server
cd ../..
# Fetch + compile the Elixir backend (REST/gRPC/GraphQL adapter)
cd elixir
mix deps.get && mix compile
cd ..
```

### 2. Run

```bash
cd adapter/v
export LD_LIBRARY_PATH=../../ffi/zig/zig-out/lib:../../cartridges/container-mcp/ffi/zig-out/lib:../../cartridges/feedback-mcp/ffi/zig-out/lib
./boj-server
cd elixir
export LD_LIBRARY_PATH=../ffi/zig/zig-out/lib:../cartridges/container-mcp/ffi/zig-out/lib:../cartridges/feedback-mcp/ffi/zig-out/lib
mix run --no-halt
```

The server starts on three ports:
Expand Down Expand Up @@ -107,12 +107,12 @@ All ports are configurable via environment variables:
## Architecture

```
Idris2 ABI (proofs) → Zig FFI (execution) → V-lang Adapter (network)
Idris2 ABI (proofs) → Zig FFI (execution) → Elixir Adapter (network)
```

- **Idris2** defines types with dependent-type proofs (IsUnbreakable safety gate)
- **Zig** implements C-ABI exports (mount/unmount, federation, feedback, etc.)
- **V-lang** exposes everything as REST + gRPC + GraphQL
- **Elixir** exposes everything as REST + gRPC + GraphQL (Plug/Cowboy on the BEAM)

The capability matrix is 2D (protocol × domain) with an optional third axis
(backend/provider) for community extensions. See `docs/EXTENSIBILITY.md`.
Expand Down
2 changes: 1 addition & 1 deletion docs/QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ cartridges/ # Matrix cells — one dir per (Protocol x Domain) pair
fleet-mcp/ # MCP x Fleet (abi/ + ffi/)
nesy-mcp/ # MCP x NeSy (abi/ + ffi/)
agent-mcp/ # MCP x Agent (abi/ + ffi/)
adapter/v/ # V-lang triple adapter (REST+gRPC+GraphQL) — Phase 3
elixir/ # REST server backend (REST+gRPC+GraphQL, Plug/Cowboy)
container/ # Stapeln container ecosystem
docs/ # Architecture, federation, developer guides
.machine_readable/ # State files, menu, policies, contractiles
Expand Down
2 changes: 1 addition & 1 deletion docs/RSR_OUTLINE.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ boj-server/
│ └── agent-mcp/ # MCP × Agent
│ ├── abi/ # SafeOODA.idr
│ └── ffi/ # agent_ffi.zig + build.zig
├── adapter/v/ # V-lang triple adapter (Phase 3)
├── elixir/ # REST server backend (Plug/Cowboy)
├── container/ # Stapeln container ecosystem
│ ├── Containerfile # Multi-stage OCI build (Chainguard)
│ ├── compose.toml # selur-compose orchestration
Expand Down
7 changes: 3 additions & 4 deletions docs/outreach/blog-post-draft.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ The typical developer server is Python or TypeScript. BoJ uses none of those. In
|-------|----------|-----|
| ABI | Idris2 | Prove the interface is correct |
| FFI | Zig | Execute it natively |
| Adapter | V-lang | Serve it over the network |
| Adapter | Elixir | Serve it over the network |

**Why Idris2?** Because it has dependent types. Not "type-safe" in the TypeScript sense. Actually provably correct at compile time. The core safety gate is a type called `IsUnbreakable` -- it's a mathematical proof that only cartridges in the `Ready` state can be activated. The type checker enforces this, not a runtime check, not a unit test. If the proof doesn't hold, the code doesn't compile.

Expand All @@ -78,7 +78,7 @@ You literally cannot call `mount` on a cartridge that isn't `Ready`. The type sy

**Why Zig?** Because it produces C-ABI-compatible shared libraries with zero runtime dependencies. Each cartridge compiles to a `.so` file. The Zig layer bridges Idris2's proofs with actual system calls -- file I/O, networking, database connections. Cross-compilation is built in, which matters when community members run nodes on ARM, x86, or whatever they have.

**Why V-lang?** Because one V codebase exposes all three API styles (REST + gRPC + GraphQL) on dedicated ports. One language, three protocols, no code generation step.
**Why Elixir?** Because one Elixir codebase on the BEAM (Plug/Cowboy) exposes all three API styles (REST + gRPC + GraphQL) on dedicated ports, with the fault-tolerance and concurrency the BEAM is known for. One runtime, three protocols, no code generation step.

The result: a compact binary. 219 Zig tests + 8 integration tests + 32 seam checks. Thread-safe (every FFI entry point serialises on a per-module mutex). No virtualenvs, no node_modules, no pip install.

Expand All @@ -90,8 +90,7 @@ Start the server:
git clone https://github.com/hyperpolymath/boj-server.git
cd boj-server
cd ffi/zig && zig build && cd ../..
cd adapter/v && v -cc gcc src/main.v -o boj-server
./boj-server
cd elixir && mix deps.get && mix run --no-halt
```

Three ports open:
Expand Down
Loading
Loading