#!/usr/bin/env bats # Seam: the frank-large Kairic Edge root unit on dankclaw. # # The 2026-09-21 cutover moved this service from the unsloth llama.cpp # prebuilt (b11030-mix-5ff778e, ROCm gfx1151) serving # unsloth/Qwen3.8-Flash-Next-GGUF:UD-IQ4_XS onto the Kairic Edge runtime # (ciru-ai/ROCmFPX, branch kairic-edge-qwen38-27b-v1.2, commit 205a3e5) # serving jcbtc/Qwen3.8-27B-IU4-Kairic-Edge, still as a ROOT unit: a # source-built runtime has no container image to install and no generated # unit to dodge. This seam pins what a flag list cannot show: the # operator's one-stream / full-window shape, the payload the serve script # refuses to start without, the MTP + n-gram spec wiring (DFlash is NOT # available for this model), compatibility mode (the harness needs # sampling/tools/reasoning, which fast-greedy rejects), a deploy handler # that gates on the port, and the fact that the sweep for a stray # benchmark run cannot take frank-small down with it. load helpers ENV_FILE="$REPO_ROOT/scripts/frank-large.env" UNIT="$REPO_ROOT/scripts/frank-large.service" SERVE="$REPO_ROOT/scripts/serve-frank-large.sh" FETCH="$REPO_ROOT/scripts/download-frank-large-kairic.sh" BUILD="$REPO_ROOT/scripts/build-kairic-edge-gfx1151.sh" REMOTE_DEPLOY="$REPO_ROOT/scripts/deploy-remote.sh" @test "the frank-large unit, env, serve and build files exist where the deployer installs them from" { [ -f "$ENV_FILE" ] [ -f "$UNIT" ] [ -x "$SERVE" ] [ -f "$BUILD" ] } @test "frank-large is boot-persistent, self-healing and unprivileged" { grep -q '^WantedBy=multi-user.target$' "$UNIT" grep -q '^Restart=on-failure$' "$UNIT" grep -q '^RestartSec=' "$UNIT" grep -q '^User=dank$' "$UNIT" # The engine pins staging buffers; the memlock budget must be unbounded # or the load fails on the RLIMIT. grep -q '^LimitMEMLOCK=infinity$' "$UNIT" # The unit runs the repo's own serve script with the repo's env. grep -q 'ExecStart=/home/dank/serverAppConfigs/scripts/serve-frank-large.sh' "$UNIT" grep -q 'FRANK_LARGE_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-large.env' "$UNIT" } @test "the operator's shape is one stream of the full 262144 window with MTP depth 4" { local ctx slots ctx="$(sed -nE 's/^CONTEXT_SIZE=([0-9]+)$/\1/p' "$ENV_FILE")" slots="$(sed -nE 's/^PARALLEL_SLOTS=([0-9]+)$/\1/p' "$ENV_FILE")" # 262144 is the model's native window (the operator's call, 2026-09-21). [ "$ctx" -eq 262144 ] # One stream. [ "$slots" -eq 1 ] # MTP depth 4 (the model's MTP layers) + n-gram drafting (24/64/64). grep -q '^SPEC_DRAFT_N_MAX=4$' "$ENV_FILE" } @test "the harness needs compatibility mode (sampling, tools, reasoning)" { # The fast-greedy path rejects sampling, penalties, probabilities, # grammar-constrained tool calls, logit bias, LoRA and a reasoning # budget. The harness needs all three, so COMPATIBILITY_MODE=1. grep -q '^COMPATIBILITY_MODE=1$' "$ENV_FILE" # The serve script enables the fastpath off in compatibility mode. grep -q 'LLAMA_TARGET_GREEDY_ARGMAX_FASTPATH=0' "$SERVE" } @test "frank-large stays text-only" { # The Kairic Edge model is text-only (no vision projector). The fleet's # image path is frank-small; models.yml declares frank-large text-only. ! grep -q -- '--mmproj' "$SERVE" grep -q -- '--mmproj' "$REPO_ROOT/scripts/serve-frank-small.sh" } @test "the serve script pins the Kairic Edge runtime and refuses a missing build" { grep -q 'ROCmFPX-kairic' "$SERVE" grep -q 'llama-server' "$SERVE" # A missing runtime or payload is a deploy error with a pointer, not a # restart loop. grep -q 'Kairic Edge runtime not found' "$SERVE" grep -q 'missing asset' "$SERVE" # The Qwen3.8 template keeps prior thinking blocks across turns only # when the kwarg is set. grep -q 'preserve_thinking' "$SERVE" } @test "the serve script wires the MTP + n-gram spec method and the sidecars" { # The Kairic Edge model uses native MTP depth 4 + n-gram drafting # (24/64/64). DFlash is NOT available for this model (no DRAFT_DFLASH # spec type in the Kairic Edge runtime). grep -q -- '--spec-type draft-mtp' "$SERVE" grep -q -- '--kairic-edge' "$SERVE" grep -q -- '--spec-draft-n-max' "$SERVE" # The three PromptForge sidecars (FFN, GDN, GDN-Output) are wired via # the PROMPTFORGE_* env block. grep -q 'PROMPTFORGE_IU4_SIDECAR' "$SERVE" grep -q 'PROMPTFORGE_GDN_SIDECAR' "$SERVE" grep -q 'PROMPTFORGE_GDN_OUTPUT_SIDECAR' "$SERVE" } @test "the payload is fetched resumably and verified against declared sizes + sha256" { grep -q 'jcbtc/Qwen3.8-27B-IU4-Kairic-Edge' "$FETCH" grep -q -- '-fL -C -' "$FETCH" # Each file's local sha256 is compared to its declared oid and a # mismatch fails the run. grep -q 'SHA256 MISMATCH' "$FETCH" } @test "the build script pins the Kairic Edge commit and the CK patch" { grep -q 'fdf4bb7fcc984811cef48ce817d89aac064b984a' "$BUILD" grep -q 'composable-kernel-gfx1151-iu4.patch' "$BUILD" grep -q 'gfx1151' "$BUILD" } @test "the fleet endpoint and alias survive the cutover" { grep -q '^HOST=0.0.0.0$' "$ENV_FILE" grep -q '^PORT=7770$' "$ENV_FILE" grep -q '^MODEL_DIR=/home/dank/models/Qwen3.8-27B-IU4-Kairic-Edge$' "$ENV_FILE" grep -q -- '--alias frank-large' "$SERVE" } @test "the deploy handler retires the halogen quadlet without deleting it" { grep -q 'retire_halogen_large_quadlet' "$REMOTE_DEPLOY" grep -q 'HOME/.AGENTTRASH' "$REMOTE_DEPLOY" ! grep -qE '(^|[^[:alnum:]_])rm (-[a-zA-Z]+ )?.*frank-large' "$REMOTE_DEPLOY" } @test "the deploy handler installs the root unit, gates the port and refuses a missing payload" { grep -q 'relink_unit frank-large' "$REMOTE_DEPLOY" grep -q 'systemctl enable frank-large.service' "$REMOTE_DEPLOY" grep -q 'wait_port_free 7770' "$REMOTE_DEPLOY" grep -q '127.0.0.1:7770/health' "$REMOTE_DEPLOY" grep -q 'LLM_LARGE_MODEL' "$REMOTE_DEPLOY" grep -q 'LLM_LARGE_DRAFT' "$REMOTE_DEPLOY" } @test "the stray-run sweep cannot take frank-small down" { # frank-small on this host is ALSO a llama-server. The sweep must match # the model path, not the binary name, or a frank-large deploy restarts # the 3090 endpoint. grep -q "pkill -f 'Qwen3.8-27B-IU4-Kairic-Edge'" "$REMOTE_DEPLOY" # ...and only inside the large handler: extract it and check there is no # bare binary-name pkill in it. local large large="$(sed -n '/^deploy_llm_large() {/,/^}/p' "$REMOTE_DEPLOY")" ! grep -q 'pkill -x llama-server' <<<"$large" } @test "the halogen quadlet is archived, not live" { [ ! -e "$REPO_ROOT/dankclaw/frank-large/quadlet/frank-large.container" ] [ -f "$REPO_ROOT/dankclaw/.AGENTTRASH/frank-large.container.halogen" ] }