Skip to content
Draft
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
118 changes: 117 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# CI: run the repo's own dependency-free gate (`make check` = clean + portable
# CPU build + C unit suites + Python stdlib tests) on the three claimed
# platforms. No model downloads, no CUDA, no external deps — by design (#140).
# platforms, then validate the locked Nix package on Linux and macOS. No model
# downloads or full-model inference — by design (#140).
name: check

on:
Expand All @@ -10,13 +11,105 @@ on:
branches: [main, dev]

jobs:
committed-range:
name: Committed range whitespace
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Reject whitespace errors in the exact committed range
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PUSH_BEFORE_SHA: ${{ github.event.before }}
PUSH_HEAD_SHA: ${{ github.sha }}
run: |
set -euo pipefail
if [[ "$EVENT_NAME" == "pull_request" ]]; then
range="${PR_BASE_SHA}...${PR_HEAD_SHA}"
echo "checking pull-request range ${range}"
git diff --check "$range"
elif [[ "$PUSH_BEFORE_SHA" =~ ^0+$ ]]; then
empty_tree="$(git hash-object -t tree /dev/null)"
echo "checking new-history range ${empty_tree}..${PUSH_HEAD_SHA}"
git diff --check "$empty_tree" "$PUSH_HEAD_SHA"
else
range="${PUSH_BEFORE_SHA}..${PUSH_HEAD_SHA}"
echo "checking push range ${range}"
git diff --check "$range"
fi

linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: make check
run: make -C c check

wheel-backend:
name: Wheel backend (Linux, ${{ matrix.label }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- label: setuptools 77.0.1 minimum
requirement: setuptools==77.0.1
expected: 77.0.1
- label: current setuptools
requirement: setuptools
expected: current
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
# This is the lane's only dependency resolution step. The packaging test
# itself builds and installs without package-index access, using
# --no-index and --no-build-isolation.
- name: Install selected wheel backend
run: python -m pip install --upgrade "${{ matrix.requirement }}"
- name: Verify selected backend
env:
EXPECTED_SETUPTOOLS: ${{ matrix.expected }}
run: |
python - <<'PY'
import os
import setuptools

actual = setuptools.__version__
expected = os.environ["EXPECTED_SETUPTOOLS"]
print("setuptools", actual)
if expected != "current" and actual != expected:
raise SystemExit(
"expected setuptools %s, got %s" % (expected, actual)
)
PY
- name: Build and smoke-test wheel without index access
run: >-
python -m unittest -v
c.tests.test_ramdisk_packaging.RamdiskPackagingTest.test_wheel_contains_runnable_ramdisk_control_plane

wheel-isolated:
name: Wheel backend (Linux, default isolated PEP 517)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Report packaging frontend
run: python -m pip --version
- name: Build, install, and smoke-test with default PEP 517 isolation
env:
COLIBRI_TEST_ISOLATED_PEP517: '1'
run: >-
python -m unittest -v
c.tests.test_ramdisk_packaging.RamdiskPackagingTest.test_default_isolated_pep517_wheel_installs_and_runs

windows:
# The job that would have caught #68/#137 pre-merge: native MinGW-w64
# (MSYS2/UCRT64), the exact toolchain the README's Windows port targets.
Expand Down Expand Up @@ -55,3 +148,26 @@ jobs:
run: brew install libomp
- name: make check
run: make -C c check

nix:
name: Nix flake (${{ matrix.name }})
strategy:
fail-fast: false
matrix:
include:
- name: Linux
os: ubuntu-latest
- name: macOS
os: macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install Nix
# cachix/install-nix-action v31.10.7, pinned to its verified release commit.
uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
- name: Validate locked, model-free flake
run: |
nix flake check --no-update-lock-file --print-build-logs
nix build --no-link --print-build-logs .#colibri
63 changes: 63 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -257,5 +257,68 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install supported TUI dependency
run: python3 -m pip install -r c/requirements-tui.txt
- name: Python test suite
run: cd c && python3 -m unittest discover -s tests -p 'test_*.py'

ramdisk-integration:
# P0.1: the only Python test that mounts a REAL tmpfs (prepare/status/destroy,
# swap-before/after, durable-state survival) is gated on COLI_RAMDISK_INTEGRATION=1
# and otherwise never runs -- so those documented invariants were unverified in CI.
# Run the whole test as root in a private mount namespace. --kill-child and
# namespace teardown contain mounts even if the test or workflow is interrupted.
name: RAM-disk integration (real tmpfs lifecycle)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Real-tmpfs prepare/status/destroy
run: |
cd c
sudo unshare --mount --fork --kill-child --propagation private \
env COLI_RAMDISK_INTEGRATION=1 \
/usr/bin/python3 -m unittest discover \
-s tests -p 'test_ramdisk_integration.py' -v

ramdisk-e2e:
# P0.2: launch the REAL engine on a tmpfs int4 model and assert the live PROF
# output reports ~0 physical SSD reads (the zero-SSD-read contract the unit
# suite fakes via FakeEngine). This is the first CI job to generate and run a
# model, so it leans on the HF GLM modeling code in tools/make_glm_bench_model
# staying importable. This is a blocking contract: a physical-read regression
# must fail the pull request.
name: RAM-disk e2e (real engine, zero-SSD-read)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install fixture deps
run: |
pip install --no-input torch --index-url https://download.pytorch.org/whl/cpu
pip install --no-input transformers safetensors
- name: Build colibri
run: cd c && make colibri
- name: Generate canonical int4 fixture and stage it onto tmpfs
run: |
cd c
canonical="${RUNNER_TEMP}/glm_i4"
staged="/dev/shm/glm_i4"
python3 tools/make_glm_bench_model.py --fp8 \
--output "${RUNNER_TEMP}/glm_fp8" --device cpu
python3 tools/convert_fp8_to_int4.py \
--indir "${RUNNER_TEMP}/glm_fp8" --outdir "${canonical}" \
--ebits 4 --group-size 128 --min-free-gb 1
mkdir -p "${staged}"
cp -a --reflink=never "${canonical}/." "${staged}/"
findmnt -T "${canonical}" -n -o FSTYPE | grep -Ex 'ext4|xfs'
findmnt -T "${staged}" -n -o FSTYPE | grep -Fx 'tmpfs'
test "$(stat -c %d "${canonical}")" != "$(stat -c %d "${staged}")"
find "${canonical}" -maxdepth 1 -type f -name '*.safetensors' \
-exec mv -- '{}' '{}.canonical-only' \;
- name: Zero-SSD-read end-to-end assertion
env:
COLI_RAMMAP_E2E_CANONICAL: ${{ runner.temp }}/glm_i4
COLI_RAMMAP_E2E_STAGED: /dev/shm/glm_i4
run: cd c && python3 -m unittest discover -s tests -p 'test_rammap_e2e.py' -v
24 changes: 23 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ jobs:
cp c/resource_plan.py dist/
cp c/doctor.py dist/
cp c/autotune.py dist/
cp c/ramdisk.py dist/
cp c/ramdisk_ui.py dist/
cp c/ramdisk_textual.py dist/
mkdir -p dist/ramdisk_support
cp c/ramdisk_support/*.py dist/ramdisk_support/
cp c/requirements-tui.txt dist/
cp LICENSE dist/
# web/dist sits NEXT TO coli in the archive; both coli and openai_server.py
# probe that layout as well as the source checkout's one-level-up form.
Expand Down Expand Up @@ -158,7 +164,7 @@ jobs:
sys.exit("FAIL: coli would not resolve these next to itself: " + ", ".join(missing))
print("OK: every engine is where coli's engine_for() looks for it")
PYCHK
out=$(python3 coli info 2>&1 || true)
out=$(python3 coli info --model . 2>&1)
echo "$out"
case "$out" in
*"engine is not built"*) echo "FAIL: coli cannot find the packaged engine"; exit 1 ;;
Expand All @@ -173,6 +179,22 @@ jobs:
test -f web/dist/index.html || { echo "FAIL: dashboard missing from archive"; exit 1; }
test -f web/dist/experts.json || { echo "FAIL: expert atlas missing from archive"; exit 1; }
python3 -c "import sys; sys.path.insert(0, '.'); from openai_server import APIHandler as A; d = A.WEB_DIST; assert (d / 'index.html').is_file(), 'server resolved WEB_DIST to %s, which has no index.html' % d; assert (d / 'experts.json').is_file(), 'no expert atlas under %s' % d; print('OK: the packaged server resolves the dashboard at', d)"
echo "$out" | grep -Fq "ready ✓" || { echo "FAIL: coli cannot find the packaged engine"; exit 1; }
python3 coli ramdisk --help > ramdisk-help.txt
grep -Fq "interleaved = one shared model copy" ramdisk-help.txt || {
echo "FAIL: packaged RAM-disk UI modules did not load"; exit 1;
}
test -z "$(find ramdisk_support -type f ! -name '*.py' -print -quit)" || {
echo "FAIL: packaged RAM-disk support contains generated artifacts"; exit 1;
}
python3 -m compileall -q ramdisk.py ramdisk_ui.py ramdisk_textual.py ramdisk_support
PYTHONPATH=. python3 -c "import pkgutil, ramdisk_support; [__import__(item.name) for item in pkgutil.walk_packages(ramdisk_support.__path__, ramdisk_support.__name__ + '.')]"
test -f requirements-tui.txt || {
echo "FAIL: packaged Textual dependency contract is missing"; exit 1;
}
python3 -m pip install --disable-pip-version-check -r requirements-tui.txt
PYTHONPATH=. python3 -c "import ramdisk_textual; assert ramdisk_textual.RamdiskTextualApp"
echo "OK: packaged engine and guided Textual UI load from one archive"

# Only the archives -- never the loose files. `dist/colibri-*.*` used to work by accident
# (the engine was versioned, so it did not match); now that the engine is plainly named,
Expand Down
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,38 @@ c/tests/test_tier
c/mio_env/
c/bench/
c/tests/test_decode_batch
c/tests/test_st_mirror
c/tests/test_i4_acc512
c/tests/test_idot
c/tests/test_i4_grouped
c/tests/test_stops
c/tests/test_kv_alloc
c/tests/test_int3
c/tests/test_int3_load
c/tests/test_logit_nan
c/tests/test_pipe_block
c/tests/test_sample_nan
c/tests/test_tok_o200k
c/tests/test_uring
c/tests/*.exe
olmoe_merged/
olmoe_i4/
c/olmoe_merged/
c/olmoe_i4/
.idea
c/tiny_inkling/
c/tests/test_rammap
c/tests/test_rammap.exe
c/tests/test_st_pread
c/tests/test_st_pread.exe
c/tests/test_topp
c/tests/test_topp.exe
c/tests/test_dsa_select
c/tests/test_dsa_select.exe
c/tests/bench_topp
c/tests/bench_topp.exe
c/tests/bench_dsa_select
c/tests/bench_dsa_select.exe

# Claude Code working directory (agent worktrees, session scratch) — never a repo artifact
.claude/
66 changes: 61 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,11 @@ git clone https://github.com/JustVugg/colibri && cd colibri/c
./setup.sh # checks gcc/OpenMP, builds, self-tests
```

Want `coli` on your PATH? From a checkout, `pip install -e .` registers it (the
engine still lives in `c/` — an editable install from the clone, not a wheel).
Want `coli` on your PATH? From a checkout, `pip install -e .` registers it; the
editable install continues to use the engine in `c/`. A wheel bundles the
launcher, server control plane, and guided RAM-disk UI, but not a
platform-specific native engine binary. Build the engine from source or point
`COLI_ENGINE` at a compatible release binary before starting inference.

### 2. Get the model

Expand Down Expand Up @@ -400,13 +403,23 @@ COLI_MODEL=/nvme/glm52_i4 ./coli plan # inspect the planned VRAM/RAM/disk pl
COLI_MODEL=/nvme/glm52_i4 ./coli doctor # read-only readiness check
COLI_MODEL=/nvme/glm52_i4 ./coli doctor --deep # strict tensors/shards/index/mirror preflight
COLI_MODEL=/nvme/glm52_i4 ./coli tune # measure and save this machine's fastest safe execution profile
./coli ramdisk --model /nvme/glm52_i4 # Linux NUMA/tmpfs staging and managed engines
./coli web --model /nvme/glm52_i4 # API + dashboard, and opens a browser
./coli serve --model /nvme/glm52_i4 # API + dashboard, no browser (headless)
```

On Windows the same commands work with `python coli chat --model D:\glm52_i4`.
The engine at runtime is pure C — python is only used by the one-time converter
and the optional API gateway.
On Windows the portable commands work with syntax such as
`python coli chat --model D:\glm52_i4`.
The engine runtime remains pure C. Python is used by the standard-library CLI,
one-time converter, optional API gateway, and RAM-disk control plane.

`coli ramdisk` opens a guided Linux RAM-workspace console. A new workspace asks
for **Fastest GPU staging** (default), **Single RAM copy**, **Minimal RAM**, or
**Multiple NUMA replicas**. Each choice produces a draft that shows the exact
copy count, NUMA nodes, CPU mask, RAM cost, engines, and endpoints before
anything is mounted. GPU-aware placement falls back visibly to a shared
single-copy plan when it cannot prove a safe CUDA/NUMA layout; it never selects
replicas automatically.

#### The same commands run any of the models

Expand Down Expand Up @@ -456,6 +469,49 @@ Two things that differ per model, both documented in the per-model page:
| OpenAI-compatible API, KV slots, web dashboard | [docs/api.md](docs/api.md) |
| Grammar-forced drafts (structured output) | [docs/grammar-draft.md](docs/grammar-draft.md) |
| Environment variable inventory | [docs/ENVIRONMENT.md](docs/ENVIRONMENT.md) |
| CLI flags and RAM-disk lifecycle commands | [docs/SETTINGS.md](docs/SETTINGS.md) |
| Shared full-model RAM-workspace TUI how-to | [docs/ramdisk-tui-howto.md](docs/ramdisk-tui-howto.md) |
| RAM-workspace TUI operator and developer guide | [docs/ramdisk-tui.md](docs/ramdisk-tui.md) |

## Development checks

The normal cross-platform gate is model-free:

```bash
make -C c check
```

It builds the portable CPU engine and runs the C and Python unit, CLI, and
packaging suites. It does not require `COLI_MODEL`, download model weights, or
run full-model inference. The committed Nix flake provides the equivalent
reproducible Linux/macOS package validation:

```bash
nix flake check --no-update-lock-file
nix build --no-link .#colibri
```

The repository uses Nix directly and does not carry a Devbox configuration;
`flake.lock` is the single committed dependency lock for this environment.

Real Linux RAM-disk validation is explicitly opt-in. Run these only in a
suitable privileged/private mount environment:

```bash
cd c
COLI_RAMDISK_INTEGRATION=1 python3 -m unittest discover -s tests -p 'test_ramdisk_integration.py' -v
COLI_RAMMAP_E2E_CANONICAL=/path/on/disk/glm_i4 \
COLI_RAMMAP_E2E_STAGED=/dev/shm/glm_i4 \
python3 -m unittest discover -s tests -p 'test_rammap_e2e.py' -v
```

The first gate exercises the real tmpfs lifecycle with a generated tiny
fixture. The second consumes two existing compatible GLM int4 namespaces
supplied by the caller; it never downloads one. The canonical namespace must be
block-backed (its safetensor shards are hidden after staging) and the staged
namespace must be tmpfs-backed and complete, proving the engine bound
`COLI_WEIGHTS_DIR` rather than falling back to SNAP. Both tests skip when their
environment gates are absent.

## What's next

Expand Down
Loading