Skip to content

About

Template for AI agents working on analog IC designs.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

agentic-design-template

A starting point for an agent-first analog design repo. The parts every design shares — run ledger, lints, context pack, spec checks — come from the SpiceXplorer platform package spicexplorer-harness. This repo holds only what is specific to one design: harness.yaml, the docs under doc/, the design/ code that builds decks and measures them, and the agent definitions and method notes under .claude/.

Instantiate

  1. export SX_ROOT=<your spicexplorer-workspace checkout> (the lab's ~/.sx_env does this), then get the tree. Prefer make new in macanalog-design-directory: it names the repo by the lab convention, creates it from the template on GitHub, clones it and runs the make init of step 2 for you. Otherwise copy the tree by hand. A tree copied from a commit that is not a release tag also records that commit — git -C <template checkout> rev-parse HEAD > .sx/template-commit — so make template-update merges from it and not from the tag .sx/template-version names.
  2. make init: it links .sx/platform -> $SX_ROOT/spicexplorer-platform, initialises the .sx/skills library (analog-skill-directory) with its agent/skill links, and runs uv sync. Repeat in every new checkout or worktree.
  3. Fill harness.yaml, pyproject.toml (name, description) and every <…> in CLAUDE.md and doc/. Declare the process in harness.yaml (pdk: ihp-sg13g2, as the kit's own preflight reports it) and run make init again: when the library ships a pdk-<id> link set for that process, it links those skills too. make lint warns while pdk: is empty.
  4. Rename the design package: git mv design <name>, set package: in harness.yaml, and update the imports plus Makefile and experiments/_template/. The package is named for the DESIGN — the instances are ldo/ and mzm_tx/. make lint checks the package is importable; layout/signoff.py and scripts/lint.py resolve it from package: and need no edit.
  5. The harness, core and waveview are editable path dependencies through .sx/platform (make init made the link; a read-only SX_ROOT is fine). A design that pulls in a further spicexplorer-* member names it in both dependencies and [tool.uv.sources], then runs uv sync once.
  6. make doctor must report the lane alive: it runs a one-resistor deck with a per-run .spiceinit through ngspice, driven by design/sim_ngspice.py — this repo's policy layer over the platform's run_deck, and what design/sim.py re-exports while lane: is absent. A commercial-PDK design instead sets lane: bridge in harness.yaml, fills in design/pdk.py (REVISION, SECTIONS, the two variable names) and adds the bridge-lane package to pyproject.toml; its make doctor runs the same probe on the EDA server. Then implement design/dut.py (benches() + deck(bench)) and design/metrics.py's KEYMAP. make test covers the generic modules and the scorecard lifecycle.
  7. make certify (add ARGS="--author X --verified-by Y" once a second actor has re-measured it), add the dir to frozen: and the scorecard to reference_scorecard:, then make freeze.
  8. make lint must pass before the first experiment. make guard is the one command that runs it with make test and a clean-tree check before a push; make hook-install is the recommended per-clone step that attaches it to git push (see below).
  9. For the layout lane, uncomment the spicexplorer-gmid / -layout / -signoff sources in pyproject.toml and uv sync.

Before you push

The workflow is feat/<name> branch → PR → squash (CLAUDE.md, "Parallel sessions, blast radius, git"). make guard is what makes it safe to automate: it refuses unless the tree is clean — both git diff and git diff --cached, because staged-but-uncommitted is exactly the window a && chain slips through — and make lint and make test are green, printing one REFUSING: line naming the clause that failed. GUARD_SKIP_TEST=1 make guard drops only the test clause and says so, for a design whose suite is too slow to sit in front of every push.

make hook-install installs a pre-push hook that runs it (make hook-remove uninstalls). It is opt-in — make init does not install it — because a hook that blocks ordinary work gets removed, and the only hook this repo ships by default is the NDA kit-tree ask-hook, which asks rather than blocks. The hook honours core.hooksPath, never overwrites a pre-push you wrote, and its refusal names both deliberate bypasses (git push --no-verify, GUARD_SKIP_TEST=1 git push). Linked worktrees share the hooks directory, so one install covers every worktree of the clone. make lint reports whether the hook is there as an INFO line; it is never a failure.

Repository map

Three kinds of directory, and the difference between them is the whole organizing idea: experiments/ is where work happens, signoff/ is what survived it, and doc/ is what was learned. Everything else is plumbing.

path what
harness.yaml the design described to the harness: spec rows, frozen dirs, denylist, ledger columns
CLAUDE.md the entry map agents read first — including "Where things go"
doc/ target spec, design reference (constraints), benches, environment, experiment log, journal + index, reviews/ (verifier reports), the memory model
design/ this design's own code. Yours to write: dut (sizing point → deck), metrics (measure, check, log), bench (the reductions). Generic, imported as-is: sim (the lane dispatcher — lane: in harness.yaml selects sim_ngspice, the default policy layer over spicexplorer_core.spice_engine.run_deck, or sim_bridge + pdk for a commercial kit simulated on the EDA server), exp (labelled batches, markdown, CSV), plot (spec boxes). Data stimulus and eye metrics are the platform's — spicexplorer_waveview.stimulus / .eye — imported directly by the designs that send symbols
experiments/NNN-*/ one directory per hypothesis, tagged with its phase; _template/ is the shape — README.md, run.py (simulates into git-ignored out/, committed figs/ and tables/) and mk_readme.py (regenerates the README from out/*.json)
signoff/ the design of record, one directory per simulation fidelity (prelayout, postlayout-pex, postlayout-em, and whatever physics a design adds) plus schematic/ and layout/. signoff/README.md is the index: what is signed off, at which fidelity, by whom, when
layout/ the layout as code: PLAN.template.md (the plan a designer copies to layout/<cell>/PLAN.md before any geometry), gen_cell.py (open-lane generator contract, LayoutParams, the per-net obstacle map), gen_cell_bridge.py (the lane: bridge generator skeleton: plan(params, kit) -> LayoutPlan, every kit fact read from $SX_KIT_FILE by name) and signoff.py (build → render → DRC → current density → LVS → PEX → the cell's own benches on the open lane; build → one batch DRC/LVS/PEX on the EDA server → the cell's own benches on the extracted DSPF on lane: bridge). Its output lands in signoff/layout/
references/ papers, datasheets and standards + INDEX.md (cite by handle, never by filename)
tests/ make test: the generic design/ modules (the live-lane test skips without ngspice)
scripts/lint.py repo-specific checks on top of the harness — including artifact-home, which keeps the map above true
scripts/clean_runs.py make clean-runs (sweep the run dirs whose reduction is recorded and whose log has gone cold) and the scratch report make doctor prints
scripts/githook.py make hook-install / make hook-remove: the opt-in pre-push hook that runs make guard
scripts/session_pack.py the SessionStart hook: the bare make pack output, cut to memory.pack_budget; silent and exit 0 on any error or without a venv
scripts/pdk_links.py the step of make init and make skills-update that links the library's pdk-<id> skills for the pdk: declared in harness.yaml, and the private per-kit skill library $SX_KIT_SKILLS names (each link written to that clone's info/exclude, never committed)
scripts/layout_lane.py the arguments make layout-flow hands workflows.layout for the lane: in harness.yaml: the open lane's generator, or on lane: bridge the bridge generator, the literal $SX_KIT_FILE, OA_LIB and WORKAREA (else $<PREFIX>_OA_LIB and $<PREFIX>_WORKAREA, the variables layout/signoff.py reads), and --load for LOAD=1 or else --skip drc,lvs,pex,benches (doc/environment.md, row OA library); it exits 2 before the workflow starts when one is missing
notebooks/ executed in place by make notebooks, outputs committed
.sx/ the per-checkout plumbing make init sets up: platform (git-ignored link to $SX_ROOT/spicexplorer-platform) and skills (the analog-skill-directory submodule: shared agents, skills, guard hooks, bin/sx-link)
.claude/agents/ links into .sx/skills/agents/ (the library's design link set, 15 agents): variant-runner, signoff-verifier, schematic-builder, schematic-reviewer, paper-analyst, gardener, the layout chain (brief-author, designer, reviewer, schematic-codesign), the four use-case agents (design-tutor, troubleshooter, design-customizer, results-analyst) and pr-reviewer; design-specific agents are plain files beside them
.claude/skills/ links into .sx/skills/skills/ (the design link set, 27 skills): the visual-evidence methods (schematic of record, testbench schematics, findings as plots, layout evidence), measurement-setup-of-record (the measurement traps of the lane, the harness and the experiment process), design-writing (every document this repo produces), analog-knowledge-authoring (the standard a knowledge skill is written to), gm/ID sizing + LUTs, current mirrors, layout annotation, optimizer convergence plots, neutral naming, spicexplorer-tools, sx-contributing, sx-coding-style, sx-use-cases, hand-analysis, postlayout-analysis (a post-layout metric shift attributed to nets), the remote-simulator learning journal, the bridge-lane skill and the bridge's two simulator skills, and the bridge layout lane's two skills (the commercial-kit layout lane, and the review setup of record in the kit's editor) and the bridge lane's checkpoint skill (the incremental uploads to the design's OA library), and agent-run-hygiene (how an agent runs long jobs: no kit text on a command line, waits on a pid, a stall check); plus the library's pdk-<id> set when pdk: in harness.yaml names a process it has one for
.claude/settings.json a copy of the library's settings file (.sx/skills/settings/project-settings.json): the one PreToolUse hook (.sx/skills/hooks/cmc_ask_hook.py), under which any tool call that names a path in the NDA kit tree, an MCP tool call included, asks for permission and nothing else is blocked (owner ruling 2026-09-07), and the permissions a design session needs. The template adds one SessionStart hook: scripts/session_pack.py prints the bare context pack, cut to memory.pack_budget, into each new session (doc/memory/README.md §1)
runs/ ledger.ndjson, git-ignored; the numbers worth keeping move into experiment READMEs and signoff/
(the scratch root) rawfiles, run dirs and simulator logs — $SX_SCRATCH, never the repo. A raw record is scratch, not evidence: reduce it, commit the reduction, make clean-runs

About

Template for AI agents working on analog IC designs.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages