AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
A 4×3 dev-board test rack, all printed: ESP32-S3 USB/IP node per bay, sliding drawers with a hidden drag chain, swappable board plates. Interactive 3D model.
Translation pending
Developer toolsPython · CGitHub @kartbenOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
3D-printed, tilted test shelf for 16 dev boards: sliding drawers, per-bay ESP32-S3 running Zephyr (USB/IP, power switching, metering), KiCad PCBs, OpenSCAD parts, BOM and an interactive 3D viewer
Taken from the repository README
Loading the full README.
Read the full README ↗An all-printed, tilted test rack for development boards (12 in its default 4 × 3 layout) — every board in its own sliding drawer, power-switched, current-metered and exposed over the network with USB/IP by a Zephyr-powered ESP32-S3 in each bay.
▶ Interactive 3D model · BOM · Architecture · Mechanics · Cabling · Power · Electronics · Assembly · Firmware · Standalone bays · CI
config/rack.yaml:
OpenSCAD parts, KiCad schematics and PCBs (schematic-as-code, Freerouting),
the BOM with LCSC part numbers, and the interactive viewer.| Bay B3 pulled out, still connected: a DATA ×4 at the back serves two XIAOs and two Pico 2s | The DATA ×4 up close: a USB-C lead per board, Dupont jumpers wiring a UART between two of them (real models) |
| Row B: the GIGA's LVGL screen in B2, between two DATA ×4 bays | Bay node — ESP32-S3 (8 MB PSRAM), 2 USB muxes, TPS2553, INA226, CAN, 60 V buck |
Neutral technical renders: the rack, one bay exploded, side view.
config/rack.yaml single source of truth (rows, bays, tilt, dimensions, population)
mechanical/ OpenSCAD: lib/, parts/, boards/boards.yaml, generated/ (from the config)
electronics/
tools/ schematic-as-code (eda.py), PCB builder (pcbgen.py), catalogue, LCSC resolver
bay-node/ design.py + generated KiCad project, fab/, docs/
power-hub/ design.py + generated KiCad project, fab/, docs/
data-port/ the drawer's USB-C port board: design.py + generated KiCad project, fab/, docs/
camera-pod/ the camera pod's board (lead, camera header, 3.3 V, LEDs): design.py + KiCad, fab/, docs/
lib/ custom symbol(s), cached JLC basic passives
site/ GitHub Pages: three.js viewer + BOM page (assets generated)
bom/ full rack BOM (CSV + summary)
render/ Blender scene + photoreal renders
tools/ build.py (config/STL/web), kicad.sh, bom.py, jlc_mcp.py, notice/ (FreeCAD line art)
docs/ design documentation
Prerequisites: Python ≥ 3.10 with pyyaml numpy trimesh (pip install -r tools/requirements.txt),
Docker (for KiCad 10, Freerouting and — if not installed locally — OpenSCAD).
python tools/build.py all # config → STLs → web viewer assets
tools/kicad.sh bay-node --route --fab # schematic, PCB, autoroute, Gerbers/BOM/CPL, renders
tools/kicad.sh power-hub --route --fab
tools/kicad.sh data-port --route --fab
tools/kicad.sh camera-pod --route --fab
python tools/bom.py # full rack BOM
python -m http.server -d site 8000 # open http://localhost:8000
Generated outputs (STLs, Gerbers, renders, PDFs, GLBs, the BOM) are committed with the change that alters
them, never for a date: python tools/keep_unchanged.py puts back every regenerated file whose content didn't
change (tools/kicad.sh … --fab runs it on its board).
For screenshots the viewer takes URL parameters: ?bay=B4&openbay=1&view=dut&hideui
pulls bay B4's drawer out and frames its DUT cable (DATA port to board), with no UI.
?bay=B2&view=camera&camlight=1&preview=B2 looks into a camera bay with its LEDs on and opens what
its camera sees (an Arducam Mega with a ~120° lens: fisheye, noise, auto-exposure and JPEG, at 5 fps).
The viewer lights the rack like the photos: a real room (Poly Haven's "Small Empty Room 1", CC0, cut to
512 × 256 in site/assets/env/), AgX with Blender's "Medium High Contrast" look, PETG with its layer lines.
Its High quality box (on by default on a desktop GPU, off on phones and small GPUs, and dropped by itself
under 25 fps) adds ambient occlusion (GTAO), a glow on the status LEDs and the camera lights, 4× MSAA through
the post-processing and 4096² sun shadows; ?quality=high or ?quality=low forces one for screenshots.
Photoreal renders (Blender + Cycles) start from render/assembly.glb, baked
from the same scene as the viewer by python tools/assembly_glb.py --hq (--hq:
full-resolution part meshes instead of the viewer's lighter ones). Either
render headless in Docker (tools/render.sh hero) or drive a Blender you
already have open — GPU and all — through the Blender MCP add-on's socket:
python tools/blender_live.py exec render/live_scene.py # (re)build the scene
python tools/blender_live.py exec render/live_render.py hero # → docs/img/hero.jpg
python tools/blender_live.py exec render/live_render.py drawer:B3 docs/img/drawer.jpg
python tools/assembly_glb.py --hq --explode-bay B2 --out render/bay-exploded.glb # one bay, layers apart
python tools/blender_live.py exec render/live_scene.py render/bay-exploded.glb
python tools/blender_live.py exec render/live_render.py exploded
The photo shots (docs/img/photo-*.jpg) use their own scene: a small office
lit through a window, PETG with 0.2 mm layer lines and
rounded edges, scanned oak and plaster (CC0 textures from Poly Haven), a laptop
showing a Zephyr shell, wired to bay B4 by a USB-C cable that hangs as a real
one would (a catenary), depth of field, bloom and a vignette, rendered at 2× and averaged down:
python tools/fetch_render_assets.py # CC0 textures + vendor board models → render/assets/
python tools/board_models.py # normalise the board models (docs/boards-3d.md)
python render/screen_terminal.py # the laptop's screen → render/assets/
node tools/lvgl_frame.mjs music 480 800 # B2's GIGA display: one frame of the viewer's LVGL demo
# (the drawer fronts' status screens: assembly_glb.py draws them)
python tools/assembly_glb.py --hq --with-pc-cable --open-bays B3 --out render/assembly-photo.glb
python tools/blender_live.py exec render/live_photo.py build
python tools/blender_live.py exec render/live_photo.py shot desk # desk, drawer, detail → docs/img/photo-*.jpg
Change the rack in config/rack.yaml (tilt, rows, columns, panel thickness,
which bays get cameras, which board sits where) and rebuild.
v0.2 — the printed panel frame replaces the aluminium frame, not yet
built. Mechanics are printable and parametric, the power box included;
still to design: double-width bays (see mechanical.md).
Each drawer front carries the node's 1.9" touch display, waiting on the
module to check its fit before a test print. Five PCBs (bay node, power hub,
DATA port, DATA ×4 v2, camera pod) pass ERC and DRC, are routed and smoothed,
and went through a schematic review
(schematic-review-2026-10-25.md) and a
datasheet audit; none is fabricated yet (see
electronics.md). The node firmware:
firmware.md.
Board outlines marked verified: false in boards.yaml are approximate.
Hardware (mechanical and electronics design files): CERN-OHL-P-2.0. Software (tools, viewer, firmware): Apache-2.0. See LICENSE.