.claude/skills/graph/SKILL.md
How the Zig-backed instance graph works (GraphView/NodeReference/EdgeReference), the real Python API surface, and the invariants around allocation, attributes, and cleanup. Use when working with low-level graph APIs, memory management, or building systems that traverse the instance graph.
npx skillsauth add atopile/atopile graphInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The faebryk.core.graph module is a thin Python wrapper around the Zig graph implementation.
Source-of-truth for behavior is:
src/faebryk/core/zig/src/graph/graph.zigsrc/faebryk/core/zig/src/python/graph/graph_py.zigsrc/faebryk/core/zig/gen/graph/graph.pyifrom faebryk.core.graph import GraphView
g = GraphView.create()
try:
_ = g.create_and_insert_node()
finally:
g.destroy()
src/faebryk/core/graph.pysrc/faebryk/core/zig/src/graph/graph.zigsrc/faebryk/core/zig/src/python/graph/graph_py.zigsrc/faebryk/core/zig/gen/graph/graph.pyisrc/faebryk/core/node.py (FabLL: nodes/traits are graph-backed)src/atopile/compiler/gentypegraph.py (compiler constructs typegraphs/instances via graph APIs)src/faebryk/core/graph_render.py (graph visualization)NodeReference / EdgeReference: value-like handles (UUIDs) into global backing storage in Zig.GraphView: a membership + adjacency view over those references (per-view arena + maps + bitsets).BoundNode / BoundEdge: “reference + owning GraphView pointer” wrappers used for traversal helpers.GraphView(), NodeReference(), EdgeReference() are not meant to be called; use the exposed factory methods.
GraphView.create()NodeReference.create(**attrs)EdgeReference.create(source=..., target=..., edge_type=..., **attrs)GraphView.create() allocates a Zig-side graph on the C allocator; it is freed only by GraphView.destroy().
u8 in Zig; treat them as 0..255 in Python (hashing/modulo happens on the Zig side).GraphView.init inserts a self_node; counts include it.src/faebryk/core/zig/gen/graph/graph.pyi)from faebryk.core.graph import GraphView, Node, Edge
g = GraphView.create()
try:
n1 = g.create_and_insert_node() # -> BoundNode
n2 = Node.create(name="n2") # -> NodeReference (not inserted yet)
bn2 = g.insert_node(node=n2) # -> BoundNode
e = Edge.create(source=n1.node(), target=bn2.node(), edge_type=7, name="link")
_be = g.insert_edge(edge=e) # -> BoundEdge
finally:
g.destroy()
GraphView.__repr__() prints GraphView(id=..., |V|=..., |E|=...) from Zig.python -m faebryk.core.graph (runs test_graph_garbage_collection).src/faebryk/core/zig/src/graph/*.ato dev compile (imports faebryk.core.zig, which compiles in editable installs).src/faebryk/core/zig/src/python/graph/graph_py.zig and ensure stubs regenerate.Key test entrypoints:
python -m faebryk.core.graphzig test src/faebryk/core/zig/src/graph/graph.zigdevelopment
How the Faebryk parameter solver works (Sets/Literals, Parameters, Expressions), the core invariants enforced during mutation, and practical workflows for debugging and extending the solver. Use when implementing or modifying constraint solving, parameter bounds, or debugging expression simplification.
development
# SEXP Benchmark Strategy ## Goal Measure and improve S-expression pipeline performance with a focus on: - Throughput per stage - Peak memory per stage - End-to-end behavior on realistic KiCad PCB inputs ## Pipeline Stages Benchmark these layers separately: - `tokenizer` - `ast` - `parser` (typed decode) - `encode` (typed encode to raw SEXP) - `pretty` (formatting) ## Dataset Dimensions Use a matrix over: - `depth`: shallow vs deep nesting - `size`: small, medium, large Recommended size buck
development
How the Zig S-expression engine and typed KiCad models work, how they are exposed to Python (pyzig_sexp), and the invariants around parsing, formatting, and freeing. Use when working with KiCad file parsing, S-expression generation, or layout sync.
tools
How the Zig↔Python binding layer works (pyzig), including build-on-import, wrapper generation patterns, ownership rules, and where to add new exported APIs. Use when adding Zig-Python bindings, modifying native extensions, or debugging C-API interactions.