-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJustfile
More file actions
439 lines (380 loc) · 19.2 KB
/
Justfile
File metadata and controls
439 lines (380 loc) · 19.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# SPDX-License-Identifier: MPL-2.0
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
#
# Burble — voice-first communications platform
# https://just.systems/man/en/
set shell := ["bash", "-uc"]
set dotenv-load := true
set positional-arguments := true
import? "contractile.just"
project := "burble"
version := "1.0.0"
# ═══════════════════════════════════════════════════════════════════════════════
# DEFAULT & HELP
# ═══════════════════════════════════════════════════════════════════════════════
# Show all available recipes
default:
@just --list --unsorted
# Show project info
info:
@echo "Project: {{project}} {{version}}"
@echo "Server: Elixir/Phoenix (server/)"
@echo "FFI: Zig SIMD coprocessor (ffi/zig/)"
@echo "Client: WebRTC + AI data channel (client/web/) — migrating to AffineScript"
@echo "P2P: burble-ai-bridge.js on :6474 + p2p-voice.html"
# ═══════════════════════════════════════════════════════════════════════════════
# BUILD
# ═══════════════════════════════════════════════════════════════════════════════
# Build everything (FFI + server deps)
build: build-ffi build-server
# Resolve the Erlang NIF include dir in the *shell* (where erlef/setup-beam's
# PATH reliably applies, unlike a subprocess spawned from inside `zig build`)
# and echo it. build.zig keeps its own detection as a fallback.
_erl-include:
#!/usr/bin/env bash
set -euo pipefail
if command -v erl >/dev/null 2>&1; then
root=$(erl -noshell -eval 'io:format("~s",[code:root_dir()]),halt().' 2>/dev/null || true)
vsn=$(erl -noshell -eval 'io:format("~s",[erlang:system_info(version)]),halt().' 2>/dev/null || true)
for d in "$root/usr/include" "$root/erts-$vsn/include"; do
if [ -f "$d/erl_nif.h" ]; then echo "$d"; exit 0; fi
done
fi
echo ""
# Build Zig coprocessor NIFs
build-ffi:
#!/usr/bin/env bash
set -euo pipefail
erl_inc="$(just _erl-include)"
cd ffi/zig
if [ -n "$erl_inc" ]; then
zig build -Doptimize=ReleaseFast -Derl-include="$erl_inc"
else
zig build -Doptimize=ReleaseFast
fi
cp zig-out/lib/libburble_coprocessor.so ../../server/priv/ 2>/dev/null || true
# Build Zig coprocessor (debug mode)
build-ffi-debug:
#!/usr/bin/env bash
set -euo pipefail
erl_inc="$(just _erl-include)"
cd ffi/zig
if [ -n "$erl_inc" ]; then
zig build -Derl-include="$erl_inc"
else
zig build
fi
cp zig-out/lib/libburble_coprocessor.so ../../server/priv/ 2>/dev/null || true
# Fetch Elixir deps and compile server
build-server:
cd server && mix deps.get && mix compile
# Build Idris2 ABI proofs (src/Burble/ABI/*)
# Module collision note: src/interface/abi/ also declares Burble.ABI.Types
# and is excluded from this recipe (deferred to Phase 1 module-path cleanup).
build-proofs:
# idris2 binaries built elsewhere bake in a wrong prefix; derive it
# from the idris2 on PATH (override with IDRIS2_PREFIX if needed).
cd src/Burble/ABI && IDRIS2_PREFIX="${IDRIS2_PREFIX:-$(dirname "$(dirname "$(command -v idris2)")")}" idris2 --build burble-abi.ipkg
# Build web client
build-client:
cd client/web && deno task build
# ═══════════════════════════════════════════════════════════════════════════════
# RUN
# ═══════════════════════════════════════════════════════════════════════════════
# Quick start — install, start server, open browser client
start:
./burble-launcher.sh --start
# Install desktop + menu shortcuts
install:
./burble-launcher.sh --install
# Uninstall shortcuts
uninstall:
./burble-launcher.sh --uninstall
# Open the quick-join voice client in browser (server must be running)
join:
xdg-open "file://{{justfile_directory()}}/client/web/quick-join.html"
# P2P voice — no server needed, just share a code
p2p:
xdg-open "file://{{justfile_directory()}}/client/web/p2p-voice.html"
# Start AI bridge (lets Claude Code send/receive via curl)
ai-bridge:
deno run --allow-net client/web/burble-ai-bridge.js
# P2P voice + AI bridge together
p2p-ai:
deno run --allow-net client/web/burble-ai-bridge.js &
sleep 1
xdg-open "file://{{justfile_directory()}}/client/web/p2p-voice.html"
# Start signaling relay (room-name discovery — run on any reachable machine)
relay:
deno run --allow-net --allow-env signaling/relay.js
# Full stack: relay + AI bridge + P2P voice (run this on the host machine)
full:
deno run --allow-net --allow-env signaling/relay.js &
deno run --allow-net client/web/burble-ai-bridge.js &
sleep 1
xdg-open "file://{{justfile_directory()}}/client/web/p2p-voice.html"
# Start the Elixir server (dev mode)
server:
cd server && mix phx.server
# Start the web client dev server
client:
cd client/web && deno task dev
# Build the selur-compose binary from the tools/selur-compose/ workspace.
# Once selur-compose ships as a submodule with a published crate, this becomes
# 'cargo install selur-compose' or 'cargo binstall selur-compose'.
build-selur-compose:
#!/usr/bin/env bash
set -euo pipefail
SELUR="{{justfile_directory()}}/tools/selur-compose"
if [[ ! -d "$SELUR" ]]; then
echo "ERROR: tools/selur-compose not found."
echo "Run: git submodule update --init tools/selur-compose"
exit 1
fi
echo "Building selur-compose (release)…"
cargo build --release --manifest-path "$SELUR/Cargo.toml" -p selur-compose
echo "Built: $SELUR/target/release/selur-compose"
# Start containers via selur-compose (Rust, TOML-native — no Python).
# Builds selur-compose from tools/selur-compose/ if the binary is missing.
# Once selur-compose is published and installed system-wide, the build
# guard becomes a no-op (the binary will already exist on PATH).
up:
#!/usr/bin/env bash
set -euo pipefail
SELUR_BIN="{{justfile_directory()}}/tools/selur-compose/target/release/selur-compose"
if [[ ! -x "$SELUR_BIN" ]]; then
echo "selur-compose binary not found; building from tools/selur-compose/ first…"
just build-selur-compose
fi
# Run from containers/ so build.context = ".." in compose.toml resolves
# against the compose file's directory (burble root), per compose spec.
# selur-compose v0.1 does not yet resolve relative paths against the
# compose file location — TODO file an issue and remove the cd once fixed.
cd "{{justfile_directory()}}/containers"
# --no-pull: selur-compose v0.1 pulls image-based services unconditionally
# (no pull_policy=missing). ghcr.io/hyperpolymath/verisimdb:latest is not
# published yet (the publish-verisimdb.yml workflow has not run), so a pull
# 403s and aborts `up`. The image exists locally (built + tagged from the
# nextgen-databases source earlier; coturn pinned-digest already pulled).
# Remove --no-pull once (a) the GHCR image is published AND (b) selur-compose
# v0.2 implements pull_policy=missing. Tracked in selur-compose v0.2 backlog.
exec "$SELUR_BIN" -f compose.toml up -d --no-pull
# Stop containers via selur-compose.
# Builds selur-compose from tools/selur-compose/ if the binary is missing.
down:
#!/usr/bin/env bash
set -euo pipefail
SELUR_BIN="{{justfile_directory()}}/tools/selur-compose/target/release/selur-compose"
if [[ ! -x "$SELUR_BIN" ]]; then
echo "selur-compose binary not found; building from tools/selur-compose/ first…"
just build-selur-compose
fi
cd "{{justfile_directory()}}/containers"
exec "$SELUR_BIN" -f compose.toml down
# Full deploy: build selur-compose if needed, then bring the stack up.
# Equivalent to 'just up' but makes the build step explicit.
deploy: build-selur-compose up
# Smoke-test the full deploy: clean slate, `just up`, wait 40s, then assert the
# stack is ACTUALLY healthy — not merely "no nxdomain string". A grep for the
# absence of one error string false-passes when a deeper error crash-loops the
# server (learned 2026-05-15: WS-1.6 fixed nxdomain but a migrator bug kept the
# server looping while smoke reported PASS). Real criteria:
# 1. burble_server RestartCount low (≤2) and state=running
# 2. POST /api/v1/auth/guest returns HTTP 200 (server actually serving)
# 3. no nxdomain in logs (regression guard for WS-1.6)
# The `down` makes this idempotent — selur-compose v0.1 cannot recreate an
# existing-named container (no --replace logic), so a leftover from a prior
# partial run would 125-error `up`. `-` prefix: `down` errors when nothing runs.
smoke-deploy:
-just down
just up
sleep 40
bash scripts/smoke-check.sh
# ═══════════════════════════════════════════════════════════════════════════════
# TEST
# ═══════════════════════════════════════════════════════════════════════════════
# Run all tests
test: test-server test-ffi
# Run E2E tests (server + client + FFI integration)
e2e:
just test
@echo "E2E validation passed"
# Run aspect-oriented tests
aspect:
#!/usr/bin/env bash
set -euo pipefail
bash tests/aspect/aspect_tests.sh
# Run Elixir server tests
test-server:
./scripts/ensure-msquic-version.sh
./scripts/ensure-quicer-prereqs.sh
cd server && mix test --no-start
# Guard check: fail fast if embedded msquic is on the wrong tag
guard-msquic:
./scripts/ensure-msquic-version.sh --check-only
# Guard check: fail fast if quicer source-build prerequisites are missing
guard-quicer-prereqs:
./scripts/ensure-quicer-prereqs.sh
# Run Zig FFI unit tests
test-ffi:
cd ffi/zig && zig build test
# Run coprocessor benchmarks (Elixir vs Zig)
bench:
cd server && mix bench.coprocessor
# ═══════════════════════════════════════════════════════════════════════════════
# QUALITY
# ═══════════════════════════════════════════════════════════════════════════════
# Format all code
fmt:
cd server && mix format
cd ffi/zig && zig fmt src/
# Run Elixir linter
lint:
cd server && mix credo --strict
# Type-check Elixir (Dialyzer)
dialyzer:
cd server && mix dialyzer
# Run panic-attack static analysis
scan:
panic-attack assail .
# ═══════════════════════════════════════════════════════════════════════════════
# RELEASE
# ═══════════════════════════════════════════════════════════════════════════════
# Build a release
release: build
cd server && MIX_ENV=prod mix release
# Build container images
container-build:
cd containers && podman build -f Containerfile.server -t burble-server ..
cd containers && podman build -f Containerfile.web -t burble-web ../client/web
# ═══════════════════════════════════════════════════════════════════════════════
# CLEAN
# ═══════════════════════════════════════════════════════════════════════════════
# Clean all build artifacts
clean:
cd server && mix clean
cd ffi/zig && rm -rf zig-out .zig-cache
rm -f server/priv/libburble_coprocessor.so
# Run panic-attacker pre-commit scan
assail:
@command -v panic-attack >/dev/null 2>&1 && panic-attack assail . || echo "panic-attack not found — install from https://github.com/hyperpolymath/panic-attacker"
# ═══════════════════════════════════════════════════════════════════════════════
# ONBOARDING & DIAGNOSTICS
# ═══════════════════════════════════════════════════════════════════════════════
# Check all required toolchain dependencies and report health
doctor:
#!/usr/bin/env bash
echo "═══════════════════════════════════════════════════"
echo " Burble Doctor — Toolchain Health Check"
echo "═══════════════════════════════════════════════════"
echo ""
PASS=0; FAIL=0; WARN=0
check() {
local name="$1" cmd="$2" min="$3"
if command -v "$cmd" >/dev/null 2>&1; then
VER=$("$cmd" --version 2>&1 | head -1)
echo " [OK] $name — $VER"
PASS=$((PASS + 1))
else
echo " [FAIL] $name — not found (need $min+)"
FAIL=$((FAIL + 1))
fi
}
check "just" just "1.25"
check "git" git "2.40"
check "Zig" zig "0.13"
check "cmake" cmake "3.20"
check "perl" perl "5.30"
check "make" make "4.0"
check "idris2" idris2 "0.7"
check "podman" podman "4.0"
# Optional tools
if command -v panic-attack >/dev/null 2>&1; then
echo " [OK] panic-attack — available"
PASS=$((PASS + 1))
else
echo " [WARN] panic-attack — not found (pre-commit scanner)"
WARN=$((WARN + 1))
fi
echo ""
echo " Result: $PASS passed, $FAIL failed, $WARN warnings"
if [ "$FAIL" -gt 0 ]; then
echo " Run 'just heal' to attempt automatic repair."
exit 1
fi
echo " All required tools present."
# Attempt to automatically install missing tools
heal:
#!/usr/bin/env bash
echo "═══════════════════════════════════════════════════"
echo " Burble Heal — Automatic Tool Installation"
echo "═══════════════════════════════════════════════════"
echo ""
if ! command -v just >/dev/null 2>&1; then
echo "Installing just..."
cargo install just 2>/dev/null || echo "Install just from https://just.systems"
fi
echo ""
echo "Heal complete. Run 'just doctor' to verify."
# Guided tour of the project structure and key concepts
tour:
#!/usr/bin/env bash
echo "═══════════════════════════════════════════════════"
echo " Burble — Guided Tour"
echo "═══════════════════════════════════════════════════"
echo ""
echo '// SPDX-License-Identifier: MPL-2.0'
echo ""
echo "Key directories:"
echo " src/ Source code"
echo " ffi/ Foreign function interface (Zig)"
echo " src/abi/ Idris2 ABI definitions"
echo " server/ Server-side code"
echo " client/ Client-side code"
echo " docs/ Documentation"
echo " tests/ Test suite"
echo " .github/workflows/ CI/CD workflows"
echo " contractiles/ Must/Trust/Dust contracts"
echo " .machine_readable/ Machine-readable metadata"
echo " container/ Container configuration"
echo " examples/ Usage examples"
echo ""
echo "Quick commands:"
echo " just doctor Check toolchain health"
echo " just heal Fix missing tools"
echo " just help-me Common workflows"
echo " just default List all recipes"
echo ""
echo "Read more: README.adoc, EXPLAINME.adoc"
# Show help for common workflows
help-me:
#!/usr/bin/env bash
echo "═══════════════════════════════════════════════════"
echo " Burble — Common Workflows"
echo "═══════════════════════════════════════════════════"
echo ""
echo "FIRST TIME SETUP:"
echo " just doctor Check toolchain"
echo " just heal Fix missing tools"
echo ""
echo "PRE-COMMIT:"
echo " just assail Run panic-attacker scan"
echo ""
echo "LEARN:"
echo " just tour Guided project tour"
echo " just default List all recipes"
# Print the current CRG grade (reads from READINESS.md '**Current Grade:** X' line)
crg-grade:
@grade=$$(grep -oP '(?<=\*\*Current Grade:\*\* )[A-FX]' READINESS.md 2>/dev/null | head -1); \
[ -z "$$grade" ] && grade="X"; \
echo "$$grade"
# Generate a shields.io badge markdown for the current CRG grade
# Looks for '**Current Grade:** X' in READINESS.md; falls back to X
crg-badge:
@grade=$$(grep -oP '(?<=\*\*Current Grade:\*\* )[A-FX]' READINESS.md 2>/dev/null | head -1); \
[ -z "$$grade" ] && grade="X"; \
case "$$grade" in \
A) color="brightgreen" ;; B) color="green" ;; C) color="yellow" ;; \
D) color="orange" ;; E) color="red" ;; F) color="critical" ;; \
*) color="lightgrey" ;; esac; \
echo "[](https://github.com/hyperpolymath/standards/tree/main/component-readiness-grades)"