jacobinwwey_obsidian-NotEMD/docs/maintainer/circuitikz-figure-generation-roadmap.md
aliyun1121003339 bac0fb8dc1 feat(diagrams): add managed CircuitikZ runtime and fix history scrolling
Add an optional ownership-scoped Tectonic environment with secure installation, native compile verification, and topology-preserving repair support. Harden CircuitikZ generation and preview routing, fix the history drawer scroll model, and synchronize bilingual architecture, user guidance, and localized README documentation.
2026-07-20 03:49:24 +08:00

19 KiB

date topic
2026-07-05 circuitikz-figure-generation-roadmap

circuitikz Figure Generation Roadmap

Language: English | 简体中文

This document records the circuit-diagram extension direction after the Cloudy-style editable figure work and the Drawnix export spike.

The short version: circuit diagrams should not enter Notemd as "LLM writes arbitrary TikZ." The useful target is a constrained CircuitSpec -> circuitikz adapter with golden-reference templates, compile feedback, and screenshot review. That is the only path likely to produce readable CMOS, analog, and digital-circuit figures reliably.

Current Figure Stack

The current diagram work has already moved Notemd away from renderer-specific prompt strings:

Area Current state
Semantic input DiagramSpec remains the model-facing boundary for general diagrams.
Internal figure model SemanticFigureModel powers editable HTML/SVG, Draw.io XML, and Drawnix JSON artifact export.
Obsidian UI control Developer settings and the sidebar expose preferredDiagramIntent and preferredDiagramRenderTarget; artifact/preview commands can explicitly select Mermaid, JSON Canvas, Vega-Lite, HTML, or editable HTML/SVG.
CLI artifact export npm run diagram:export-artifact exports editable-html-svg, drawio, and drawnix without Obsidian runtime.
Verification Tests check semantic annotations, visible-label parity, stable IDs, Drawnix subset validity, and CLI file output.

The render-target override is intentionally scoped to artifact and preview commands. The legacy Mermaid command stays pinned to Mermaid-compatible output, while Draw.io and Drawnix stay CLI/export-boundary targets until plugin-runtime rendering and editing contracts are proven.

This architecture is the right precedent for circuit diagrams: the model should produce structured intent, not raw final syntax, and the UI should select a renderer only after the semantic spec is stable.

Why circuitikz Is Different

circuitikz is the right syntax family for electrical circuits in Obsidian TikZJax, especially when notes need MOSFETs, resistors, supplies, grounds, voltage probes, or analog/digital teaching diagrams.

The hard problem is not syntax availability. The hard problem is layout quality under constraints:

  • LLMs can produce a topologically correct circuit that is visually unreadable.
  • Anchors such as M1.G, M1.D, and M1.S are easy to misuse if the model invents geometry late.
  • Complex circuits need routing lanes, not ad hoc wire segments.
  • TikZJax/LaTeX failures are often compile-log failures, while readability failures require rendered-image inspection.
  • A working small example does not generalize to larger CMOS blocks unless the generator owns placement and routing rules.
source note / prompt
  -> CircuitSpec
  -> topology validation
  -> layout projection
  -> circuitikz template adapter
  -> TikZJax or LaTeX render
  -> compile-log + screenshot feedback
  -> constrained repair pass

CircuitSpec

CircuitSpec should be separate from DiagramSpec at first. Do not widen DiagramSpec until two or more non-circuit targets need the same fields.

Minimum useful shape:

Field Purpose
circuitKind cmos-inverter, common-source, logic-gate, rc-network, etc.
nodes named electrical nets such as VDD, GND, vin, vout, drain, source
components typed parts with ids, terminals, labels, and optional model metadata
connections topology edges between terminals/nets
layoutHints grid positions, orientation, input/output side, routing lanes
style american voltages, label policy, voltage/current marker convention
goldenReferenceId template family used as the visual and syntax baseline

Golden Reference First

A golden reference is mandatory for reliable circuit generation. It should define:

  • the package preamble;
  • coordinate scale;
  • anchor style;
  • component orientation;
  • input/output side conventions;
  • wire routing pattern;
  • label placement rules.

For example, the common-source amplifier reference should keep the working pattern:

\documentclass[border=8pt]{standalone}
\usepackage{circuitikz}
\begin{document}
\begin{circuitikz}[american voltages, line width=0.5pt, font=\small]
\draw
  (3,5) node[vcc]{$V_{DD}$}
  to [R, l=$R_D$] (3,3);
\draw
  (3,3) to [short, *-o] (5,3) node[right]{$v_{out}$};
\draw
  (3,3) to [short] (3,2.2)
  node[nmos, anchor=D] (M1) {$M_1$};
\draw
  (M1.S) to [short] (3,0.5)
  node[ground]{};
\draw
  (M1.G) to [short, -o] (0.8,2.2)
  node[left]{$v_{in}$};
\end{circuitikz}
\end{document}

A CMOS inverter template should then constrain the model explicitly:

  • pmos above nmos;
  • VDD above, GND below;
  • common input gate routed from the left;
  • common drain output routed to the right;
  • no diagonal wires;
  • named anchors for each transistor terminal.

Validation Strategy

Do not accept "it compiled" as enough.

Gate What it catches
Spec validation missing nets, disconnected terminals, impossible terminal references
Template validation missing package preamble, invalid circuit kind, unsupported component
Compile-log parsing LaTeX/TikZJax syntax and package failures
Screenshot inspection overlaps, unreadable labels, bad routing, excessive whitespace
Golden-reference diff drift from known-good orientation and routing conventions

Screenshot feedback can be manual first. Automated screenshot checks should start with simple rules: nonblank render, bounded canvas, expected labels visible, and no obvious label overlap boxes.

Implementation Phases

Phase Scope Exit criteria
A. Prompt/runbook Document constrained circuit prompts and golden references website and maintainer docs explain circuitikz limits and usage
B. CircuitSpec prototype Add parser/types/tests for simple MOS circuits common-source and CMOS inverter specs validate without rendering
C. circuitikz adapter Emit deterministic LaTeX for golden templates generated LaTeX matches stable snapshots and contains required anchors
D. render feedback Add optional local TikZJax/LaTeX smoke path compile failures return actionable diagnostics
E. visual repair loop Feed rendered image or overlap report back into repair prompt repeated layout errors are corrected without changing topology
F. managed desktop environment Discover safe local compilers and offer an explicit managed Tectonic install UI probe/install/remove works, golden fixtures compile, and dependency-free export remains intact

Implementation Status

Phase A is documented. Phase B/C now have a constrained repository prototype:

  • src/diagram/adapters/circuitikz/circuitSpec.ts defines the separate circuit-only spec boundary.
  • src/diagram/adapters/circuitikz/circuitikzExporter.ts validates topology and emits deterministic circuitikz LaTeX for common-source-amplifier, cmos-inverter, cmos-buffer / cmos-buffer-v1, cmos-transmission-gate / cmos-transmission-gate-v1, cmos-nand2 / cmos-nand2-v1, and cmos-nor2 / cmos-nor2-v1. It now projects layoutHints.inputSide and layoutHints.outputSide into constrained port placement for those golden templates, so layout-only repair candidates can move input/output ports without changing topology. The CMOS buffer template locks two cascaded inverter stages through intermediate node vmid; the CMOS transmission gate template locks parallel PMOS/NMOS pass devices between vin and vout with complementary phib / phi controls; the CMOS NAND template locks the parallel PMOS pull-up network, the series NMOS pull-down stack, and dual input nets va / vb before export; the CMOS NOR template locks the complementary series PMOS pull-up stack and parallel NMOS pull-down network before export.
  • src/diagram/adapters/circuitikz/circuitikzExporter.ts now also exposes createCircuitTopologySignature and assertCircuitTopologyUnchanged so topology-preserving repair can reject electrical drift while allowing label and layout changes.
  • scripts/export-circuitikz.js and npm run diagram:export-circuitikz provide the offline export command, including --topology-reference for repair candidates.
  • src/diagram/adapters/circuitikz/circuitikzRepairBrief.ts, --repair-brief-output, and --repair-brief produce and consume schema notemd.circuitikz.repair-brief.v1, a topology-preserving repair handoff that carries the source CircuitSpec, topology signature, compile/render diagnostics, allowed changes, prohibited topology changes, next verification steps, and a structured repairPrompt. The prompt role is topology-preserving-circuitikz-repair; it includes diagnosticFocus items derived from diagnostics and acceptanceCriteria that require candidate validation plus fresh compile and render-smoke checks. Candidate specs can be checked against the brief signature before output is written, and --repair-brief now returns repairAcceptance evidence with schema notemd.circuitikz.repair-acceptance.v1, readyForVisualAcceptance, gate-level status, blocking diagnostics, and remainingChecks. --repair-acceptance-output can persist the same evidence as a JSON file for CI or release records.
  • src/diagram/adapters/circuitikz/circuitikzDiagnostics.ts parses existing LaTeX/TikZJax compile logs into actionable diagnostics without spawning a compiler or depending on shell command resolution.
  • src/diagram/adapters/circuitikz/circuitikzCompileRunner.ts can run an explicitly configured local renderer with shell: false, placeholder-expanded arguments, structured executable diagnostics for empty, missing, or invalid renderer commands, generated-log diagnostics, and optional --expected-artifact render-smoke checks.
  • scripts/run-circuitikz-smoke-fixtures.js and npm run diagram:smoke-circuitikz now also produce explicit renderer availability evidence when no renderer is configured. The missing-configuration path still exports the deterministic fixture .tex artifacts, returns ok: false, and records rendererAvailability.status: "missing-configuration" with a compile-executable-invalid diagnostic instead of relying on platform shell discovery or silently skipping smoke evidence.
  • src/diagram/adapters/circuitikz/circuitikzRenderSmoke.ts inspects expected render artifacts. PDF and other opaque artifacts are checked for existence/non-empty output; SVG artifacts are additionally checked for an <svg> root, positive dimensions or viewBox, visible drawing elements after hidden/transparent element exclusion, optional repeated --expected-svg-text tokens, render-svg-text-path-only / pathOnlyGlyphUseCount classification for path-only labels, path-only glyph placement through resolved <use href="#..."> geometry, definition-local transforms on reusable glyph paths, path-only glyph overlap diagnostics through render-svg-path-glyph-overlap, close-path current-point resets for relative commands after Z/z, exact arc bounds for A/a arc extrema, exact Bezier curve bounds for C/S/Q/T curve extrema, stroke-width-aware SVG bounds and label overlap checks, polyline / polygon drawing geometry, positioned tspan label geometry, bounded-canvas/text-overlap diagnostics, label-vs-drawing overlap diagnostics through render-svg-label-overlap, and transform-aware geometry for common group and element transforms; PNG screenshot artifacts are decoded for positive dimensions, non-background pixels, 1/2/4/8-bit indexed-color packed samples with PLTE/tRNS palette data, grayscale/RGB tRNS transparent samples, 1/2/4/8/16-bit grayscale samples, 8/16-bit grayscale-alpha/RGB/RGBA direct samples, foreground bounds, foregroundDensity, edge-touching clipped content through render-png-content-clipped, unusually dense foreground blocks through render-png-foreground-dense, and format-specific render-png-unsupported guidance for Adam7 interlaced PNGs and unsupported indexed-color bit depths.
  • SVG expected-text smoke now also searches decoded accessibility metadata from aria-label, <title>, and <desc>. This can prove semantic label identity when a renderer preserves metadata, but it still does not prove path-only visual label legibility without the later OCR/screenshot gate.
  • SVG positioned text geometry now respects text-anchor values start, middle, and end from attributes or inline style, so centered and right-aligned labels can trigger text/text and label-vs-drawing overlap diagnostics.
  • Grouped and symbol path-only glyph definitions inside <defs> are now resolved before <use> placement, so wrapped glyph paths still participate in pathOnlyGlyphUseCount, bounded-canvas checks, and render-svg-path-glyph-overlap.
  • src/rendering/diagnostics.ts summarizes RenderArtifact.diagnostics into error/warning/info counts, and src/ui/DiagramPreviewModal.ts uses that summary in both the artifact diagnostics panel and preview history entries. Any render target can attach diagnostics to RenderArtifact.diagnostics; the preview UI shows the summary, severity, kind, message, and advice without requiring TikZJax or LaTeX in the plugin runtime.
  • src/tests/circuitikzExporter.test.ts, src/tests/circuitikzRepairBrief.test.ts, src/tests/circuitikzCompileDiagnostics.test.ts, src/tests/circuitikzRenderSmoke.test.ts, src/tests/circuitikzCompileRunner.test.ts, and src/tests/circuitikzExportCli.test.ts verify deterministic output, topology rejection, topology-preserving repair brief generation and candidate validation, package-script exposure, UTF-8 BOM handling, diagnostic parsing, shell-free compile execution, structured compile-executable-invalid / compile-executable-not-found diagnostics, diagnostics JSON output, render artifact existence/non-empty smoke checks, SVG structure checks, path-only SVG label classification, path-only glyph placement checks, definition-local glyph transform checks, path-only glyph overlap diagnostics, exact arc bounds for A/a arc extrema, exact Bezier curve bounds for C/S/Q/T curve extrema, stroke-width-aware SVG bounds and label overlap checks, polyline / polygon drawing geometry checks, positioned tspan label geometry checks, transform-aware SVG geometry checks, SVG label-vs-drawing overlap checks, PNG blank screenshot checks, indexed-color and grayscale PNG packed sample decoding, indexed-color PNG palette decoding, grayscale/RGB PNG tRNS transparent sample handling, format-specific unsupported PNG diagnostics, 16-bit direct PNG sample normalization, PNG foreground-bound and foreground-density reporting, PNG clipped-content diagnostics, dense-foreground diagnostics, and nonzero CLI exit for logs or smoke reports with errors.
  • src/tests/diagramPreviewModal.test.ts verifies that artifact diagnostics are visible in the diagram preview modal and that preview history does not collapse entries with different diagnostics.
  • src/diagram/adapters/circuitikz/circuitikzRepairLoop.ts now provides the opt-in Phase E execution boundary. It creates the dedicated repair prompt, accepts only one CircuitSpec JSON candidate, rejects topology drift before export, evaluates the generated TeX with caller-supplied compile/render evidence, and adopts the candidate only when every acceptance gate passes. The loop is deliberately capped at one attempt and remains disabled when a renderer is unavailable.
  • The common-source golden template now uses separate terminated draw paths, a lighter 0.5pt stroke, a smaller body font, and no redundant source-terminal annotation. This removes the earlier path crowding and label collision without changing electrical topology.
  • src/tests/circuitikzRepairLoop.test.ts covers successful repair, topology drift, non-JSON output, failed second-pass visual acceptance, and renderer-unavailable fail-closed behavior.
  • src/latexEnvironment/ and src/platform/desktopProcess.ts implement Phase F without enlarging the plugin bundle with a TeX distribution. Desktop users can reuse a custom/system compiler or explicitly install pinned Tectonic 0.16.9; downloads are HTTPS-host allowlisted, size-bounded, SHA-256 verified, extracted through traversal/link guards, smoke-tested in staging against six deterministic fixtures, and atomically activated with rollback and cancellation cleanup.
  • src/ui/CircuitikzEnvironmentModal.ts exposes probe, install/repair, cancel, remove, capability, progress, and bounded-log states. The module loads desktop execution code lazily; mobile retains dependency-free preview and SVG/PNG/preview-PDF export.
  • The diagram-history drawer now establishes the Grid minimum-size invariant with min-height: 0; its body owns overflow: auto and contains overscroll, so long Vault histories remain reachable without scrolling the preview behind the drawer.

Phase D now provides actionable compile and artifact diagnostics, including SVG geometry/overlap and PNG nonblank/clipping/density checks. Phase E has a bounded topology-preserving execution loop and still refuses candidates without fresh compile and render-smoke evidence. Phase F adds optional desktop discovery and user-initiated managed installation while keeping the ordinary preview/export path dependency-free. Notemd still does not embed TeX Live, MiKTeX, TinyTeX, or Tectonic archives in main.js. OCR for path-only glyph text, precise pixel-level overlap detection, complete SVG path coverage, and browser-grade text layout remain future evidence improvements.

The SVG geometry smoke also covers SVG number grammar for leading-dot decimals and explicit plus signs. This is a small but important renderer-compatibility gate because dvisvgm can emit compact decimals that should remain fractional during bounds checks.

Best Current Practice

For supported circuit families, use the structured CircuitSpec path:

  1. Provide a renderable golden reference.
  2. Ask for a named circuit family, not a vague "draw circuit."
  3. Lock orientation, anchors, and input/output sides.
  4. Let the deterministic adapter own LaTeX rather than asking the model for raw TikZ.
  5. When a local renderer is configured, use compile/render diagnostics for the single guarded repair attempt.

This will outperform unconstrained ChatGPT/Gemini TikZ generation because it limits the model's freedom to the parts that matter: choosing components and topology, not inventing every coordinate and route from scratch.

Risks

  • Pulling TikZJax into the plugin runtime would create a hard dependency on another Obsidian plugin. Keep integration optional.
  • A generic "TikZ renderer" would be too broad. Start with circuitikz and only a small set of circuit families.
  • Visual feedback without topology locking can repair layout by accidentally changing the circuit. The repair prompt must treat topology as invariant.
  • circuitikz package versions can vary. Golden references must record the expected package behavior and renderer environment.