Tight pass on m's review of v4 (single commit per head's instruction). Six locked answers integrated: 1. mCables is a schematic, not a physical-routing tool. Stripped 'trunk', 'frame-edge corridor', 'cable tray', 'path optimisation' from §5b.1, §5b.2, §7, §8, §9. Bundling reduces to the v3 endpoint- pair rule: ≥2 cables between the same A↔B endpoint pair → group as one bundle. Anything path-shaped is "out of scope, period" (§8). 2. Solver button-only for v0 (no change). Live-solve parked at 9+. 3. Unmet-requirement quick-fix: red badge on the affected device in the inspector with a single "+ Add <type> port to <device> and re-solve" button per §5b.4. New endpoint POST /api/projects/:pid/devices/:id/ports-and-resolve chains the port insert + the solve re-run in one transaction. 4. Setup templates fold INTO v4.1. New §2.4 with the schema for setup_templates + setup_template_devices + setup_template_requirements (migration 004), 3 built-in templates seeded (Living Room, Home Office, Server Rack). New API: GET /api/setup-templates, POST /api/projects/:pid/apply-template. New UI flow: "or start from a template" section in the New Project modal + an "Apply template" action on empty projects. Built-in catalog grows to 14 types (adds Screen, Keyboard, Mouse). 5. Catalog SQL seed in migration 002 (no change). 6. Promote-to-manual: explicit button on cable inspector (no change). §8 slice 6 absorbs the templates work alongside the solver MVP. §9 closes all six v4 questions; no open design questions remain. Trailer changes to "DESIGN v4.1 READY FOR REVIEW". CLAUDE.md mirrors: schematic-only framing, 14-type catalog, setup templates as a first-class feature, quick-fix UX note.
9.2 KiB
mCables — Project Instructions
Project Overview
Cable-management framework + solver for m's setup. m declares his devices and the connection requirements between them ("NAS must connect to Switch via RJ45"). mCables runs a solver that emits the cable plan + bundle recommendations. mCables is a schematic, not a physical-routing tool — cables are straight lines between endpoints; the "maximum bundling" objective is satisfied by the endpoint-pair rule (when two or more cables share the same A↔B endpoint pair, group them into one bundle). The visual editor is still there for tweaking the plan, but the solver is the headline.
Each cable-managed environment (LOFT, OFFICE, …) is a separate
mCables project, and each project is backed by exactly one Excalidraw
drawing. The framework provides a visual web interface backed by a Go
HTTP API and SQLite, plus an export pipeline that writes .excalidraw
files via mExDraw.
Memory group_id: mcables
No CLI. Frontend-first — every interaction is through the visual
interface. The backend serves the UI and the API; there is no
mcables shell binary intended for humans.
Goal
- A reusable framework for tracking devices, ports, cables, cable types, bundles, frames — scoped per project (LOFT and OFFICE are separate projects, each a separate drawing).
- A solver that, given the project's devices + connection requirements, emits the cable plan + bundle recommendations. Objective: maximum bundling via the endpoint-pair rule (schematic only — no path/trunk/cable-tray modelling).
- A hybrid device-type catalog: 14 built-in types (NAS, PC, Mac, Notebook, TV, Soundbar, Switch, fritz, ChromeCast, SteamLink, IOx-3/6/8, Screen, Keyboard, Mouse) with default port profiles, extensible per project. Picking a type on device-create seeds the device's ports automatically; m overrides per instance.
- Setup templates for bootstrapping a project from blank to solver-ready: built-ins 'Living Room', 'Home Office', 'Server Rack' stamp their device-types + connection requirements in one transaction.
- A visual editor for switching projects, adding frames/devices, declaring requirements, running the solver, and tweaking the resulting plan. Unmet requirements get a one-click quick-fix ("+ Add <type> port to <device> and re-solve").
- A one-way export from the DB to the corresponding
.excalidrawdrawing onmxdrw.msbls.dewhenever m clicks Export — DB is authoritative, Excalidraw is the projection.
Architecture
| Layer | Tech | Notes |
|---|---|---|
| DB | SQLite | ./data/mcables.db (project-local, gitignored). Driver: modernc.org/sqlite (cgo-free). |
| Backend | Go | net/http HTTP API + static frontend via embed.FS. Standard library + minimal deps. Single binary. |
| Frontend | Vanilla JS modules + SVG, no build step | TypeScript types via JSDoc, optional tsc --noEmit in CI. Preact-via-CDN-ESM is the documented fallback if vanilla state gets painful — no build step either way. |
| Diagram I/O | mExDraw HTTP API | PUT https://mxdrw.msbls.de/api/drawings/<name>.excalidraw with Authorization: Bearer $MEXDRAW_TOKEN. (The mcp__mexdraw__* MCP tools are not currently configured for this project — workers use the raw HTTP API.) |
Hierarchy
- Project (
projectstable) is the top-level concept. LOFT, OFFICE, HOMELAB, … are separate projects. One project ↔ one.excalidrawdrawing in mExDraw.projects.drawing_namedefaults to<name>.excalidrawserver-side when omitted on create; editable later. - Frames sub-divide a project (LOFT has
desk,rack,media; OFFICE hasdesk,server). Frames are not projects — they're zones within one drawing. - Every device, port, cable, IO marker, bundle, and connection
requirement is project-scoped (
project_iddenormalised onto every row, withON DELETE CASCADEfromprojects).UNIQUE (project_id, devices.name)— no two devices in one project share a name. - Cable types are global. A single shared
cable_typestable — noproject_id. The five defaults (Power/USB/HDMI/DP/RJ45) are seeded by migration 001 once, not per project. Renaming or recolouring a type affects every project's legend immediately. - Device types are hybrid.
device_typesis one global table withproject_idNULL for the 11 built-in catalog rows (seeded by migration 002) andproject_id = currentfor project-custom types. Eachdevice_typecarries adevice_type_portsprofile that seedsportsrows when a device of that type is created. m can extend the catalog per project; built-ins are read-only from the API. - Connection requirements (
connection_requirementstable) are the solver's input. m declares "from_device ↔ to_device, preferred cable type, must_connect"; the solver assigns ports and emits cables. - Project deletion guardrail.
DELETE /api/projects/:pidrequires?confirm=<name>matching the project's current name. 400 otherwise. - Solver-owned vs. user-owned cables.
cables.auto = 1= created by the solver and replaceable on re-solve.auto = 0= hand-drawn by m, left alone by the solver. PATCHing endpoint or type of an auto cable promotes it to manual (explicit "Promote to manual" button in the inspector, per design v4 §5b.3).
Branch Strategy
main= production-deployable.mai/<worker>/<slug>= worker branches via the mai workflow.- No
devbranch — too small a project for staging. - Merge with
--no-ffto main, delete branches after merge.
Tech Stack
- Go for the backend (matches m's other tools:
m,mai, youpcms, mExDraw). - SQLite via
modernc.org/sqlite(cgo-free → cleanscratch/distroless container, no toolchain pain). - mExDraw via HTTP for diagram export. Never edit raw
.excalidrawfiles directly outside the mExDraw API. - Vanilla JS + SVG for the frontend — no build step. JSDoc-typed.
Deployment — mDock, raw docker (NOT Dokploy)
mCables runs on mDock (192.168.178.131 on the LAN, Tailscale mdock)
as a plain docker-compose service. Dokploy is for public mlake/mRiver
stuff; mDock uses raw docker compose per the conventions of the existing
mDock services (mgreen, mgeo, msports-garmin, paperless, …).
- Repo layout on mDock:
/home/m/stacks/mcables/withdocker-compose.yml,data/bind-mount, secrets in/home/m/secrets/mcables/.env. - Image:
mgit.msbls.de/m/mcables:latest(built and pushed by a Gitea Actions workflow on push tomain, runs on the self-hosted runner on mDock with labelself-hosted:host). - Port mapping:
7777:7777, exposed on the LAN — no reverse proxy. - Restart policy:
unless-stopped. - LAN URL:
http://mdock:7777. - No auth — LAN-trusted.
Local dev (no Docker): go run ./cmd/mcables against ./data/mcables.db.
Seed drawing — visual grammar reference, not a runtime importer
mxdrw.msbls.de/draw/Cable-Management.excalidraw is reference material
only. mCables does not auto-ingest it. m will rebuild LOFT and OFFICE
from scratch inside the tool — the seed exists so the exporter mimics
its visual grammar:
- Devices = rectangles with a text label.
- Ports = small ellipses (~12×9) positioned on a device edge. Positional, not containerId-bound. Stroke colour = cable type.
- Cables = arrows with
startBinding/endBindingto ports or devices or IO diamonds. - Cable types = colour, with a legend at the top-left of the project's first frame listing the project's cable_types.
- IO markers = small diamonds. Semantically wall outlets / power entry points — a cable terminating at an IO marker means "this end is plugged into a wall socket outside the diagram". They are not inter-frame bridges and they do not pair up.
- Frames = sub-zones inside a project (
desk,rack,media, …). - Lines = decorative only (legend separators in the seed). Ignored on export.
Legend colours (global, seeded once by migration 001):
| Type | Hex |
|---|---|
| Power | #e03131 |
| USB | #2f9e44 |
| HDMI | #1971c2 |
| DP | #9c36b5 |
| RJ45 | #ffd500 |
Out of scope (v0)
- Multi-user. mCables is m-only.
- Auth / sharing — LAN-trusted on mDock.
- Mobile / responsive — desktop browser only.
- Cable inventory beyond visual structure (no length, no purchase history, no SKU). Strictly visual structure for v0.
- Import from
.excalidrawat runtime. If a one-shot migration is ever needed, a separatemcables-migrateCLI tool is the right shape, not a hot API endpoint.
Worker Preferences
- Inventor shifts (design passes): conventions, schema, API, export
pipeline, mDock deploy plan, UI flows, slices. Output:
docs/design.md- open questions for m. v1–v4 are versioned in the doc's header callout.
- Coder shifts (after m's go on a design version): build to the
current design.md. Current state: slice 1 (project CRUD + global
cable_types) and slice 2 (frames + devices + drag) are merged; design
v4 reshapes slices 3+ (IO + cable-type editing → device-type catalog →
device-type manage → connection-requirements UI → solver → manual
port/cable draw → export). See
docs/design.md§8 for the current sequence. - Use Sonnet for both — structure matters more than depth.