refactor: `mvp-system` is now a standalone app, `myelin`
Promote the `mvp-system` workspace library crate to a standalone application at `apps/myelin`, rebranding the MVP system along with its binaries, node image, and spec.
- workspace `Cargo.toml`: swap member `crates/mvp-system` -> `apps/myelin` and drop `apps` from `exclude` so the app joins the workspace
- `apps/myelin/Cargo.toml`: declare package `myelin` with `autobins = false` and explicit `[[bin]]` targets `myelin-worker`, `myelin-orchestrator`, `myelin-chat`
- `apps/myelin/src`: move the whole `mvp-system` source tree and rebrand module surfaces (`chat/mod.rs`, `prompt/mod.rs`); add `bin/chat.rs` (`myelin::run_chat_from_args`) and delete the old `mvp_chat.rs`
- `apps/myelin/node-image`: relocate the worker image assets from `apps/mvp-node/` (Dockerfile, Dockerfile.base, tinygrad_worker.py, entrypoint, e2e script) and rename `MVP_SYSTEM_SPEC.md` -> `MYELIN_SPEC.md`
- `xtask`: rewrite build/reference paths for the rename (~1000-line churn); add `crates/dashboard/ACTOR_PANEL_SPEC.md`
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-08-01 09:46:55 +00:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
BASE_IMAGE=${BASE_IMAGE:-myelin-node-base:cuda12.6}
|
|
|
|
|
IMAGE=${IMAGE:-myelin-node:latest}
|
|
|
|
|
CONTAINER=${CONTAINER:-myelin-node-e2e-$$}
|
|
|
|
|
GPUS=${MYELIN_CUDA_GPUS:-all}
|
|
|
|
|
PROMPT=${MYELIN_NODE_SELF_TEST_PROMPT:-ping}
|
|
|
|
|
TIMEOUT_SECS=${MYELIN_NODE_E2E_TIMEOUT_SECS:-1800}
|
2026-08-15 08:17:48 +00:00
|
|
|
FRAME_LOG=${MYELIN_TELEMETRY_FRAME_LOG:-/var/log/myelin-telemetry.ndjson}
|
refactor: `mvp-system` is now a standalone app, `myelin`
Promote the `mvp-system` workspace library crate to a standalone application at `apps/myelin`, rebranding the MVP system along with its binaries, node image, and spec.
- workspace `Cargo.toml`: swap member `crates/mvp-system` -> `apps/myelin` and drop `apps` from `exclude` so the app joins the workspace
- `apps/myelin/Cargo.toml`: declare package `myelin` with `autobins = false` and explicit `[[bin]]` targets `myelin-worker`, `myelin-orchestrator`, `myelin-chat`
- `apps/myelin/src`: move the whole `mvp-system` source tree and rebrand module surfaces (`chat/mod.rs`, `prompt/mod.rs`); add `bin/chat.rs` (`myelin::run_chat_from_args`) and delete the old `mvp_chat.rs`
- `apps/myelin/node-image`: relocate the worker image assets from `apps/mvp-node/` (Dockerfile, Dockerfile.base, tinygrad_worker.py, entrypoint, e2e script) and rename `MVP_SYSTEM_SPEC.md` -> `MYELIN_SPEC.md`
- `xtask`: rewrite build/reference paths for the rename (~1000-line churn); add `crates/dashboard/ACTOR_PANEL_SPEC.md`
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-08-01 09:46:55 +00:00
|
|
|
|
|
|
|
|
cleanup() {
|
|
|
|
|
docker rm -f "$CONTAINER" >/dev/null 2>&1 || true
|
|
|
|
|
}
|
|
|
|
|
trap cleanup EXIT
|
|
|
|
|
|
|
|
|
|
cargo build --release -p myelin --bin myelin-worker
|
|
|
|
|
docker build -f apps/myelin/node-image/Dockerfile.base -t "$BASE_IMAGE" .
|
|
|
|
|
docker build -f apps/myelin/node-image/Dockerfile --build-arg BASE_IMAGE="$BASE_IMAGE" -t "$IMAGE" .
|
|
|
|
|
|
|
|
|
|
docker run -d \
|
|
|
|
|
--name "$CONTAINER" \
|
|
|
|
|
--gpus "$GPUS" \
|
|
|
|
|
-e MYELIN_NODE_SELF_TEST_PROMPT="$PROMPT" \
|
|
|
|
|
-e MYELIN_NODE_MAX_RUNTIME_SECS=1 \
|
|
|
|
|
-e MYELIN_SELF_TEST_MAX_TOKENS="${MYELIN_SELF_TEST_MAX_TOKENS:-1}" \
|
|
|
|
|
-e MYELIN_MODEL_CACHE_DIR=/var/cache/myelin-models \
|
2026-08-15 08:17:48 +00:00
|
|
|
-e MYELIN_TELEMETRY_FRAME_LOG="$FRAME_LOG" \
|
refactor: `mvp-system` is now a standalone app, `myelin`
Promote the `mvp-system` workspace library crate to a standalone application at `apps/myelin`, rebranding the MVP system along with its binaries, node image, and spec.
- workspace `Cargo.toml`: swap member `crates/mvp-system` -> `apps/myelin` and drop `apps` from `exclude` so the app joins the workspace
- `apps/myelin/Cargo.toml`: declare package `myelin` with `autobins = false` and explicit `[[bin]]` targets `myelin-worker`, `myelin-orchestrator`, `myelin-chat`
- `apps/myelin/src`: move the whole `mvp-system` source tree and rebrand module surfaces (`chat/mod.rs`, `prompt/mod.rs`); add `bin/chat.rs` (`myelin::run_chat_from_args`) and delete the old `mvp_chat.rs`
- `apps/myelin/node-image`: relocate the worker image assets from `apps/mvp-node/` (Dockerfile, Dockerfile.base, tinygrad_worker.py, entrypoint, e2e script) and rename `MVP_SYSTEM_SPEC.md` -> `MYELIN_SPEC.md`
- `xtask`: rewrite build/reference paths for the rename (~1000-line churn); add `crates/dashboard/ACTOR_PANEL_SPEC.md`
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-08-01 09:46:55 +00:00
|
|
|
${HF_TOKEN:+-e HF_TOKEN="$HF_TOKEN"} \
|
|
|
|
|
"$IMAGE" >/dev/null
|
|
|
|
|
|
|
|
|
|
deadline=$((SECONDS + TIMEOUT_SECS))
|
|
|
|
|
while (( SECONDS < deadline )); do
|
|
|
|
|
logs=$(docker logs "$CONTAINER" 2>&1 || true)
|
|
|
|
|
if grep -q '"type":"ready"' <<<"$logs" && grep -q '"type":"self_test_completed"' <<<"$logs"; then
|
|
|
|
|
frames=$(docker exec "$CONTAINER" cat "$FRAME_LOG" 2>/dev/null || true)
|
|
|
|
|
if grep -q '"channel":"myelin.node.ready"' <<<"$frames" &&
|
|
|
|
|
grep -q '"channel":"myelin.worker.weights"' <<<"$frames" &&
|
|
|
|
|
grep -q '"channel":"myelin.worker.prompt"' <<<"$frames"; then
|
|
|
|
|
printf '%s\n' "$logs"
|
|
|
|
|
printf '%s\n' "$frames"
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
if grep -q 'WorkerFatal\|myelin-node: .*failed\|ModelLoadFailed\|GgufDownloadFailed' <<<"$logs"; then
|
|
|
|
|
printf '%s\n' "$logs" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
sleep 5
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
docker logs "$CONTAINER" 2>&1 || true
|
|
|
|
|
echo "myelin-node Docker E2E timed out after ${TIMEOUT_SECS}s" >&2
|
|
|
|
|
exit 1
|