Bringing Linux up on a new board is one question asked a hundred times a day: the touchscreen is dead, why? The answer is always in the device tree, and the tools for finding it are dmesg and grep.
The Linux device tree is already a tree of nodes with typed relationships. Jac
is a language whose primitives are nodes, edges and walkers. JacOS takes that
correspondence seriously. It reads the device tree out of a running kernel and
materialises it as a live Jac graph: 465 nodes and 732 edges off a real Motorola
Moto E4. A device's vdd-supply = <&pm8937_l6> phandle becomes a typed
SuppliedBy edge; clocks = <&gcc 42> becomes ClockedBy. Once those edges exist,
"what does this device depend on" is a traversal.
Assessment is dispatched by node type on arrival — can check_regulator with
Regulator entry, can check_device with Device entry. A regulator is healthy
if its rail is enabled; a device is healthy if a driver bound. Those are
different questions and the walker never branches on kind: it arrives and the
right ability fires. Descent is one generic exit ability on the HwNode base, so
traversal policy is written once for the whole machine. Root cause is ranked by
walking the dependency chain and preferring the deepest, most fundamental fault.
byLLM's return type is a typed Diagnosis object, so the type is the schema —
there is no prompt template and no output parsing anywhere in the repo. The
walker finds the fault; the LLM only phrases it.
The same walkers drive both frontends. The web console's client does
root spawn DiagnoseNode(...) and the server wrapper spawns the identical
Diagnose walker the CLI spawns. One graph, two frontends, zero duplicated
diagnostic logic.
We brought a phone that already runs Linux; today we built the layer on top. Every number above was verified on that hardware.
For a board bring-up engineer or postmarketOS porter, this turns tribal knowledge into a query. And it makes a $10 phone out of a drawer — CPU, battery, modem, sensors — worth reviving instead of throwing away.
tools/dtb.py walks /sys/firmware/devicetree/base and resolves every phandle into a typed node/edge spec, then joins it against sysfs for live state. src/topology.jac declares the HwNode hierarchy and the five edge archetypes. src/importer.jac materialises the spec into Jac archetypes hung off root — and because Jac persists everything reachable from root, that graph is the database. No ORM, no schema, no serialisation layer in the repo.
src/diagnose.jac holds the walkers: Diagnose (spawn on a symptom, traverse outward, assess each hop, rank a root cause), Survey and Probe. src/explain.jac declares the byLLM Diagnosis object. src/jacos.jac is the CLI. src/main.jac plus src/webapi.sv.jac and src/components/ManPage.cl.jac are the fullstack web console — Jac 0.16.7 codespaces, no jac-cloud needed.
On the device: busybox-only capture scripts, and an offline install that unzips the jaclang wheel and points PYTHONPATH at it, because the phone has no pip and no network.

Log in or sign up for Devpost to join the conversation.