Agent skill

Solver

by atopile in atopile/atopile

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.

MITAuto-check passedDevelopment

Install Solver

skills CLI
$ npx skills add atopile/atopile --skill solver -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install atopile/atopile solver --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/atopile/atopile.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/solver .claude/skills/solver && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
solver
GitHub stars
4k
Token cost
~2.3k tokens
SKILL.md length
902 words
Files
1
Skills in repo
19
Repo updated
First seen
Licence
MIT

At a glance

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.

  • Works in 4 steps: Literals are Sets (and correlation is… → Symbols (Parameters) introduce correlation → Expressions are graph objects (not just… → …
  • Modifying constraint solving
  • SKILL.md covers Quick Start, Relevant Files, Dependants (Call Sites) and How to Work With / Develop /…, plus 3 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Solver is an agent skill from atopile/atopile. 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.

Its SKILL.md is about 2.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development. The repository describes itself as: Design circuit boards with code! ✨ Get software-like design reuse 🚀, validation, version control and collaboration in hardware; starting with electronics ⚡️. The licence is MIT.

When your agent uses it

  • Modifying constraint solving
  • Parameter bounds
  • Debugging expression simplification

Example prompts

  • “/solver”

Requirements

  • Python 3

Workflow steps

4 steps, taken from the step headings in SKILL.md.

  1. Literals are Sets (and correlation is subtle)
  2. Symbols (Parameters) introduce correlation
  3. Expressions are graph objects (not just Python trees)
  4. The underlying graphs are append-only

What it can do on your machine

Read from SKILL.md and the folder at commit 619eda7. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are python).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Solver loads about 2.3k tokens when it runs. Until then it costs about 78 tokens; SKILL.md has 902 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~78
When it runs · the whole SKILL.md, loaded when a task matches
~2.3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from atopile/atopile at commit 619eda7, republished under its MIT licence (© atopile). 902 words, ~2,317 tokens.

Download SKILL.mdSave it as .claude/skills/solver/SKILL.md (or your agent's skills folder).
name
solver
description
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.

Solver Module

The solver is the heart of atopile's parameter subsystem: it symbolically simplifies and checks constraint systems built from Parameters, Literals (Sets), and Expressions.

If you are touching solver internals, read these first:

  • src/faebryk/core/solver/README.md (concepts, set correlation, append-only graphs, canonicalization)
  • src/faebryk/core/solver/symbolic/invariants.py (the actual invariants enforced during expression insertion)

Quick Start

python
import faebryk.core.node as fabll
import faebryk.library._F as F
from faebryk.core.solver.defaultsolver import DefaultSolver
from faebryk.libs.test.boundexpressions import BoundExpressions

E = BoundExpressions()

class _App(fabll.Node):
    x = F.Parameters.NumericParameter.MakeChild(unit=E.U.dl)

app = _App.bind_typegraph(tg=E.tg).create_instance(g=E.g)
x = app.x.get().can_be_operand.get()
E.is_subset(x, E.lit_op_range(((9, E.U.dl), (11, E.U.dl))), assert_=True)

solver = DefaultSolver()
res = solver.simplify(g=E.g, tg=E.tg, terminal=True).data.mutation_map
lit = res.try_extract_superset(app.x.get().is_parameter_operatable.get(), domain_default=True)
assert lit is not None

Relevant Files

  • Solver runtime + orchestration:
    • src/faebryk/core/solver/defaultsolver.py (DefaultSolver, iteration loop, terminal vs non-terminal)
    • src/faebryk/core/solver/solver.py (solver protocol + helper APIs)
  • Mutation machinery (this is where “graphs are append-only” is handled):
    • src/faebryk/core/solver/mutator.py (Mutator, Transformations, MutationStage, MutationMap, tracebacks)
  • Symbolic layer (canonical forms + invariants):
    • src/faebryk/core/solver/symbolic/invariants.py (insert_expression(...) invariant pipeline)
    • src/faebryk/core/solver/symbolic/canonical.py (canonicalization passes)
    • src/faebryk/core/solver/symbolic/* (structural + expression-wise algorithms)
  • Domain objects (what users actually create in graphs):
    • src/faebryk/library/Parameters.py (ParameterOperatables, domains, compact repr)
    • src/faebryk/library/Expressions.py (expression node types, predicates, assertables)
    • src/faebryk/library/Literals.py (Sets; numeric/boolean/enum literals)
  • Test helpers:
    • src/faebryk/libs/test/boundexpressions.py (concise graph + expression construction for tests)

Dependants (Call Sites)

  • Library components (src/faebryk/library/): define parameters/constraints (e.g. R.resistance)
  • Compiler + frontends: translate ato constraints into solver expressions
  • Picker backend: uses solver simplification + bounds extraction to prune candidate parts

How to Work With / Develop / Test

Mental Model (the parts that matter for correctness)
1) Literals are Sets (and correlation is subtle)
  • A literal like 100kOhm +/- 10% is a Set (a range), not a scalar.
  • Singleton sets are self-correlated; all other sets are treated as uncorrelated, even with themselves.
    • This is why X - X is not necessarily {0} when X is a range, but is {0} when X is a singleton.
2) Symbols (Parameters) introduce correlation
  • A Parameter behaves like a mathematical symbol (variable), not a Python variable.
  • Correlation between symbols is created via asserted constraints, most notably:
    • Is(A, B).assert_() / A.alias_is(B) creates a strong “these are the same” correlation.
    • IsSubset(A, X).assert_() / A.constrain_subset(X) constrains A to be within X.
    • IsSubset(X, A).assert_() / A.constrain_superset(X) constrains A to accept at least X.
3) Expressions are graph objects (not just Python trees)

Expressions are nodes in the Faebryk graph that point at operand nodes. This matters because…

4) The underlying graphs are append-only

The solver cannot “edit” an expression in-place. Instead it:

  • builds a new graph containing transformed/copied nodes,
  • records a mapping from old nodes → new nodes (MutationMap),
  • leaves the old graph untouched.
Development Workflow
  1. Reproduce in a minimal graph (prefer tests + BoundExpressions).
  2. Run DefaultSolver().simplify(...) and inspect the resulting MutationMap.
  3. If you’re changing rewrite logic, make sure you understand and preserve the invariant pipeline in src/faebryk/core/solver/symbolic/invariants.py::insert_expression.
  4. Add/adjust algorithms in src/faebryk/core/solver/symbolic/* (most logic lives there, not in mutator.py).
Testing
  • Solver tests live in test/core/solver/:
    • test/core/solver/test_solver.py
    • test/core/solver/test_literal_folding.py
    • test/core/solver/test_solver_util.py

Run a tight loop while iterating:

  • ato dev test --llm test/core/solver -k invariant -q
  • ato dev test --llm test/core/solver/test_solver.py::test_simplify -q

Best Practices

Prefer explicit simplify(...) arguments

DefaultSolver.simplify has a compatibility layer that accepts (tg, g) or (g, tg). In new code, prefer named args:

python
res = DefaultSolver().simplify(g=g, tg=tg, terminal=True)
mutation_map = res.data.mutation_map
Use the Mutator/insert_expression pipeline, not ad-hoc rewrites

When you “create” or “rewrite” an expression, you are really requesting that the solver insert something into the transient graph while upholding invariants. The canonical place where this happens is:

  • src/faebryk/core/solver/symbolic/invariants.py::insert_expression

If you bypass this, you will almost certainly violate an invariant and get:

  • duplicate/congruent expressions,
  • multiple incompatible bounds on an operand,
  • predicates used as operands,
  • missed literal folding, or
  • contradictions that don’t point back to the real root cause.
Show full SKILL.md (375 more words)Show less

Core Invariants (source of truth: insert_expression)

The invariant pipeline is sequencing-sensitive. At a high level it enforces (paraphrased):

  • No predicate operands: Op(P!, ...) is rewritten to use boolean literals where possible
  • Predicate literal rules: P{S|True} -> P!; P!{S/P|False} -> Contradiction; P!{S|True} -> P!
  • No literal inequalities: inequalities involving literals are rewritten into subset constraints
  • No singleton supersets as operands: f(A{S|{x}}, ...) -> f(x, ...)
  • No congruence: congruent expressions are deduplicated (with optional rules for uncorrelated congruence)
  • Minimal subsumption: stronger constraints subsume weaker ones; redundant ones become irrelevant
  • Single “merged” superset/subset per operand (e.g. intersected supersets)
  • No empty supersets/subsets: empty-set constraints are contradictions
  • Fold pure literal expressions into literals (and re-express as subset/superset where appropriate)
  • Terminate certain literal subset constraints to stop churn
  • Canonical form: expressions are created/normalized into canonical operators

When adding a new algorithm, the easiest way to stay correct is to construct a new ExpressionBuilder and let insert_expression do the hard work.

Internals & Runtime Behavior

Instantiation & Dependencies
  • DefaultSolver() holds state: when called with terminal=False, it can keep a reusable internal state for incremental solving.
  • Terminal vs non-terminal:
    • terminal=True (default) is more powerful but not intended to be reused as incremental state.
    • terminal=False runs only non-terminal algorithms and stores reusable_state for subsequent calls.
  • Graph scoping: simplify(..., relevant=[...]) is the intended hook to avoid “solve the entire world”.
Data Structures
  • MutationStage: one algorithm application over an input graph → output graph, with a Transformations object.
  • MutationMap: a chain of stages; lets you:
    • map old → new operables (map_forward)
    • map new → old sources (map_backward)
    • extract current bounds as literals (try_extract_superset; subset extraction is typically via the mapped operable’s try_extract_subset())
    • generate tracebacks for “why did this change?” (see Traceback in mutator.py)
Debugging & Logging

Useful config flags (see src/faebryk/core/solver/utils.py):

  • SLOG=1: debug logging for solver/mutator
  • SPRINT_START=1: log start of each phase
  • SVERBOSE_TABLE=1: verbose mutation tables
  • SSHOW_SS_IS=1: include subset/is predicates in graph printouts
  • SMAX_ITERATIONS=N: raise early if stuck looping (helps catch bad rewrites)

In failures, look for Contradiction / ContradictionByLiteral output: it prints mutation tracebacks back to origin expressions/parameters, which is usually the shortest path to the actual bug.

Performance
  • Prefer restricting scope via relevant=[...] when you can.
  • Avoid creating huge numbers of near-duplicate expressions; congruence + subsumption help, but churn still costs.
  • If you add an algorithm, make it idempotent (or explicitly mark/terminate what you produce) to avoid infinite iteration.

© atopile, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/solver of atopile/atopile.

Open the folder on GitHubat commit 619eda7

Compare with similar skills

Solver next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Solver compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Solver this skillatopile/atopile4k—~2.3kAutomated safety check: PassMIT
Vercel Composition Patternssupabase/supabase111k59 repos~726Automated safety check: PassMIT
Finishing a Development Branchobra/superpowers296k5 repos~1.9kAutomated safety check: PassMIT
Typescript Advanced Typesrolling-scopes/rsschool-app10k25 repos~4.2kAutomated safety check: PassMPL-2.0
PR Babysitteropeninterpreter/openinterpreter69k3 repos~4.2kAutomated safety check: PassApache-2.0
Code Review ChecklistshareAI-lab/learn-claude-code78k5 repos~1.1kAutomated safety check: PassMIT

Similar skills

  • Official

    React composition patterns that scale. An agent skill from supabase/supabase.

    111k GitHub starsUsed in 59 repos~726 tokens
    DevelopmentAuto-check passed
  • Walks the last step of a branch: confirm tests pass, detect the git environment, ask how to integrate, carry out your choice and clean up the worktree.

    296k GitHub starsUsed in 5 repos~1.9k tokens
    DevelopmentAuto-check passed
  • Typescript Advanced Types

    rolling-scopes/rsschool-app

    Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications.

    10k GitHub starsUsed in 25 repos~4.2k tokens
    DevelopmentAuto-check passed
  • PR Babysitter

    openinterpreter/openinterpreter

    Watches an open GitHub pull request until it merges, handling review comments, diagnosing CI failures and retrying flaky checks along the way.

    69k GitHub starsUsed in 3 repos~4.2k tokens
    DevelopmentAuto-check passed
  • Code Review Checklist

    shareAI-lab/learn-claude-code

    Reviews code against a five-part checklist covering security, correctness, performance, maintainability and testing, and reports findings in a fixed format.

    78k GitHub starsUsed in 5 repos~1.1k tokens
    DevelopmentAuto-check passed
  • Greploop

    onyx-dot-app/onyx

    Iteratively improves a PR (GitHub), MR (GitLab), or shelved changelist (Perforce) until Greptile gives it a 5/5 confidence score with zero unresolved comments.

    32k GitHub starsUsed in 4 repos~3.3k tokens
    DevelopmentAuto-check passed

More from atopile/atopile

All 19 skills in this repo
  • Ato Language

    atopile/atopile

    Reference for the .ato declarative DSL: type system, connection semantics, constraint model, and standard library.

    4k GitHub stars~3.5k tokensUpdated 3 mo ago
    Auto-check passed
  • Compiler

    atopile/atopile

    How the atopile compiler builds and links TypeGraphs from .ato (ANTLR front-end → AST → TypeGraph → Linker → DeferredExecutor), plus the key invariants and test entrypoints.

    4k GitHub stars~1k tokensUpdated 3 mo ago
    Auto-check passed
  • Domain Layer

    atopile/atopile

    Instructions for electronics-specific logic and build processes: netlists, PCBs, build steps, and exporters.

    4k GitHub stars~791 tokensUpdated 3 mo ago
    Auto-check passed
  • Fabll

    atopile/atopile

    How FabLL (faebryk.core.node) maps Python node/trait declarations into the TypeGraph + instance graph, including field/trait invariants and instantiation patterns.

    4k GitHub stars~1.1k tokensUpdated 3 mo ago
    Auto-check passed
  • Faebryk

    atopile/atopile

    How Faebryk's TypeGraph works (GraphView + Zig edges), how to traverse/resolve references, and how FabLL types/traits map onto edge types.

    4k GitHub stars~861 tokensUpdated 3 mo ago
    Auto-check passed
  • Graph

    atopile/atopile

    How the Zig-backed instance graph works (GraphView/NodeReference/EdgeReference), the real Python API surface, and the invariants around allocation, attributes, and cleanup.

    4k GitHub stars~952 tokensUpdated 3 mo ago
    Auto-check passed

Categories

Questions about Solver

What does Solver do?

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. Solver is an agent skill from atopile/atopile. 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.

When should I use Solver?

Solver fits situations like: modifying constraint solving; parameter bounds; debugging expression simplification.

How do I install Solver in Claude Code?

Run `npx skills add atopile/atopile --skill solver -a claude-code`. Or copy the skill folder (.claude/skills/solver in atopile/atopile) into .claude/skills/solver in your project. Claude Code loads it when a task matches its description.

How do I install Solver in Codex?

Run `npx skills add atopile/atopile --skill solver -a codex`. Or copy the skill folder (.claude/skills/solver in atopile/atopile) into .agents/skills/solver in your project. Codex loads it when a task matches its description.

Can I use Solver in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add atopile/atopile --skill solver -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/solver, .gemini/skills/solver, .github/skills/solver and .opencode/skills/solver in your project.

What does Solver need to run?

SKILL.md names no scripts, command-line tools or credentials: Solver is instructions for the agent only. Our summary lists: Python 3.

Does Solver access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Solver safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Solver use?

Solver is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Solver use?

About 2.3k tokens (SKILL.md is roughly 9.3k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Solver?

Skills that share tags, products or a category with Solver: Vercel Composition Patterns (supabase/supabase, 111k stars), Finishing a Development Branch (obra/superpowers, 296k stars), Typescript Advanced Types (rolling-scopes/rsschool-app, 10k stars) and PR Babysitter (openinterpreter/openinterpreter, 69k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Solver?

atopile (a GitHub organization) maintains it in atopile/atopile, which has 3,976 GitHub stars. The repository holds 19 skills in this directory. The repository was last updated on June 13, 2026.

Source: atopile/atopile on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.