# vbagent implementation handoff: current tikzphysics anchors, springs, and debug APIs Prepared 2026-09-27. Copy this entire document as the implementation prompt for an agent working in `/Users/vaibhavblayer/pypi-packages/vbagent`. ## Task Implement the latest tikzphysics authoring contract throughout vbagent: agent prompts, checker and repair prompts, scanner/solution guidance, actual agent assembly, compiler guards, examples, reference retrieval, and focused tests. Keep both spring APIs. Teach predictable integer percentage anchors for real contacts and boundaries. Compile and visually inspect representative outputs. Finish with a changed-file summary, exact test results, loaded package evidence, and links to source and rendered examples. This is an implementation task in vbagent. The package changes already exist in `/Users/vaibhavblayer/Documents/Claude/Projects/tikz_package`. Read its actual sources and docs before editing. Use current APIs directly; do not build alias compatibility layers for removed anchors. Preserve existing working features and unrelated edits. Do not publish vbagent or tikzphysics as part of this task. ## Current status and first actions - The vbagent checkout is dirty with substantial unrelated authoring, model, caching, and orchestration work. Run `git status --short`, inspect applicable `AGENTS.md`, and preserve existing changes. Stage exact owned paths if needed. - vbagent already has `TIKZPHYSICS_V15_ANCHOR_CONTRACT` and its short form in `vbagent/prompts/diagram/physics/anchor_contract.py`; extend that shared source rather than scattering competing anchor contracts. - Existing v1.5 surface/wedge/ramp guidance is mostly implemented. Verify it and retain it. New work includes all fluid/mechanics families and the spring node. - Confirmed stale prohibitions exist in mechanics, setup, generic, scanner, TikZ checker, and format checker prompts: “not a node”, “do not create a spring node”, and “do not invent spring-node anchors”. Replace their meaning in all effective prompt paths, including short variants and user templates. - Current `vbagent/utils/latex.py` guards only the old v1.5 package date with `TIKZPHYSICS_V15_VERSION_GUARD`. The package changes are now prepared as **v1.6.0 (2026/09/27)**. Require the v1.6 API, preferably with capability checks as well as version/date protection. Earlier development sources carried the old v1.5 header; include a same-header missing-API fixture. - v1.6.0 was submitted to CTAN successfully (HTTP200, Upload succeeded). Receipt: `/Users/vaibhavblayer/Documents/Claude/Projects/tikz_package/output/releases/tikzphysics-1.6.0-receipt.json`. Public publication is pending. TeX Live/Overleaf distribution is separate; do not imply automatic immediate availability. - Local user TeX installation and the generated single-file Overleaf bundle were updated and compiled. Still verify the copy loaded by each vbagent test/run. - Use `poetry run ...` in vbagent. Report unavailable tools honestly. ## Authoritative files to read All paths in this section are under `/Users/vaibhavblayer/Documents/Claude/Projects/tikz_package/`: - `CHANGELOG.md`: Unreleased plus 1.4/1.5 anchor changes. - `docs/surface-anchors.md`, `docs/wedge-anchors.md`, `docs/ramp-anchors.md`. - `docs/springs.md`, `docs/fluid-mechanics-anchors.md`, `docs/fluids.md`. - `docs/debug-overlays.md`, `docs/reference.md`, `docs/guide.md`. - `tikzlibrarytikzphysics.{core,surface,ramps,mechanics,fluids}.code.tex`. - `tikzlibrarytikzphysics.catalog.code.tex`: generated feature records. - `examples/{surface,wedge,ramp}-anchor-coverage.tex`. - `examples/spring-node-path.tex`, `examples/fluid-mechanics-anchor-coverage.tex`. - `testfiles/{geometry,spring,uniform-anchors}.lvt`. - `docs/verification-springs.md`, `docs/verification-uniform-anchors.md`. - `output/overleaf/tikzphysics.sty`: current complete single-file runtime. - `output/overleaf/main.tex`, `output/overleaf/README.txt`. Rendered galleries: surface/wedge/ramp PDFs are in `docs/`; spring and the 16-page fluid/mechanics gallery are in `output/pdf/`. Current manual is `output/pdf/tikzphysics.pdf` (64 pages). Build/distribution directories can contain older snapshots; the source files above are authoritative. ## Required authoring contract ### 1. Percentage syntax and predictability Use `(N.family-T)` where T is any integer from 0 through 100. All 101 values exist, independently of which samples the debug overlay displays. `0` is the documented start; `50` is halfway in the documented parameter; `100` is the end. Use explicit family names in generated code. A full circle/ellipse ends where it starts. Do not generate fractional percentages or values outside this range. Uniform syntax does not mean every edge runs in the same direction or every curve uses arc length. Directions are local to the node and transform with it. Do not infer direction from a family name alone. Do not globally rewrite all `left-*`/`top-*` to follow one convention: surface outlines and fluid/block outlines intentionally differ. Preserve the following per-shape maps. Straight edges interpolate linearly; combined ramps and bent wedge boundaries use distance; fluid cubic curves use the Bézier parameter; parabolas use x progress; circular/elliptical families use angular progress; U-tube outlines use distance. `50` need not be the visual centroid or the joint of a path. Contacts must use actual contact families, not bounding-box compass anchors. `center`/compass anchors still have legitimate uses for placement and labels. Native block/circle boundary anchors include outer separation; exact spring attachments exclude it. Do not assume all attachment APIs have identical outer-separation semantics. ### 2. Ground, ceiling, walls, platforms | Object | Contact family direction | Other boundaries | | --- | --- | --- | | ground | `surface`: left to right along top | bottom, left, right | | ceiling | `surface`: left to right along underside | top, left, right | | wall-left | `surface`: bottom to top along right face | left, top, bottom | | wall-right | `surface`: bottom to top along left face | right, top, bottom | | platform-left / platform-right | `surface`: floor top left to right | bottom, left, right; transition; wall-surface, wall-back, wall-base, wall-tip | | platform (two walls) | `surface`: floor top left to right | bottom, left, right; left-/right-transition; left-/right-wall-surface, wall-back, wall-base, wall-tip | For these objects, horizontal edges run left to right and vertical edges run bottom to top. Platform long wall edges run root to free tip; short wall edges run contact side to back side. `surface` is the contact midpoint. `transition` runs projecting floor tip (`pulley-center`) to `wall-root`; a sharp corner may have coincident endpoints. On two-wall platforms prefix wall/transition families and named pulley/root/centre anchors with `left-` or `right-`. Use current semantic names and percentages instead of removed redundant corner/midpoint aliases. Ground top contact is `surface-*`, not `G.top-*` or `G.floor-top-*`. Do not blindly replace every `.top` in arbitrary TikZ code; optics, standard shapes, and surviving semantic anchors have different APIs. `wall angle` rotates only a platform wall, never the floor. The `*-up` presets make vertical walls (90 degrees). Clean angled upward corners use left angle 135 or right angle 45 with zero inset/drop; positive inset/drop is rejected. Use a wedge or ramp for an inclined floor. Boundary joins are already continuous: do not add overlapping or crossing “repair” lines at the transition. ### 3. Wedges `base`: bl -> br; `right`: br -> top; `slope`: top -> bl. These outline orders stay fixed in all right-angle modes. Primary contact `surface` always goes left to right: | wedge right angle at | Primary contact | Secondary contact | | --- | --- | --- | | br | bl -> top | right-surface equals surface | | bl | top -> br | right-surface equals surface | | top | bl -> top | right-surface: top -> br | Place blocks on `surface-T`, rotate with `\geometryvalue{W}{slope angle}`; secondary top-mode contacts use `right-surface-T` and `right slope angle`. Do not use `slope-T` as a universal usable incline. `slope-mid=surface-50`, `base-mid=base-50`, `right-mid=right-50`; in top mode `slope-right-mid=right-surface-50`. `centroid` and `mid` are the drawn body's area centroid, including the four-point pulley-edge body. Contact placement guides: `tangent-before-T`, `tangent-after-T`, `normal-T`; secondary equivalents have `right-` prefixes. `surface guide length` controls their offset. Use the tangent pair with a sloped path when scope/node transformations make a stored scalar angle insufficient. `pulley edge` is valid in br/bl modes and already draws top/pulley-centre to wall-root continuously. `transition` covers that segment. The bent `right` (br) or `slope` (bl) boundary follows both segments by distance; its 50 point is on the whole path. The usable opposite incline remains straight. ### 4. Straight and curved ramps `surface-T` is the complete floor-plus-incline/curve contact by distance; `surface-start`, `surface-mid`, `surface-end` equal 0, 50, 100. Prefer explicit families; existing `(R.T)` shorthand selects surface-T. Mirrored ramps follow their orientation, so the sequence may run right to left. | Straight family | 0 -> 100 | | --- | --- | | surface | wall-bottom -> ramp-top | | floor | floor-start -> ramp-foot | | incline | ramp-foot -> ramp-top | | wall-surface | wall-bottom -> wall-top | | wall-back | base-start -> back of wall top | | wall-tip | back of wall top -> wall-top | | base | base-start -> base-end | | end | base-end -> ramp-top | | Curved family | 0 -> 100 | | --- | --- | | surface | surface-start -> curve-end | | floor | surface-start -> curve-start | | curve | curve-start -> curve-end | | start | base-start -> surface-start | | base | base-start -> back-bottom | | back | back-bottom -> back-top | | top | curve-end -> back-top | The curved floor default is **3.75cm** (50% increase from 2.5cm). Override with `curved ramp floor length` when the source diagram needs another value. `curve-T` samples only the circular part. `curve-center` is the circle centre, not a contact. Straight-ramp centre uses its full bounding box, including a wall taller than its incline. Whole-path surface50 is not necessarily a joint. Guide families are tangent-before/after and normal; curve-prefixed guides sample curve-T. `ramp guide length` controls offsets. At the sharp straight joint the guide tangent uses the incline side. ### 5. Springs: both APIs with the same style Both short `spring` and collision-safe `physicsspring` / `physics spring` spellings support nodes AND two-point paths. Prefer collision-safe style in vbagent when other libraries could define spring/block/pulley. ```tex % A connection between positioned bodies: endpoints set direction and length. \draw[physicsspring,pre length=3mm,post length=5mm] (A) -- node[midway,above=3mm] {$k$} (B.west); % An independently positioned object with reusable connection anchors. \node[physicsspring,spring length=3cm,rotate=30,anchor=start] (S) at (A) {}; \node[physicsblock,anchor=west] (B) at (S.end) {$m$}; ``` Node anchors: exact `start`, `end`, axis midpoint `center`, `coil-start`, `coil-end`, and `axis-0..100`. Axis samples the straight connection axis, not the helical wire. Compass anchors describe the coil envelope. Node default length is 3cm; `spring length` is a unit-aware alias for `minimum width`. `minimum height` reserves envelope space without changing amplitude. Rotation/scaling/mirroring preserve node geometry. Labels belong outside coil. Both forms share `pre length`, `post length`, `amplitude`, `segment length`, `aspect`, and `every spring`. Leads can be zero; node lead sum must be less than total length; amplitude/segment length must be positive. Earlier saved lead-length corruption has been fixed in the package. A spring PATH has no private `.start`, `.end`, or `.axis-*` node anchors: name endpoint coordinates or create a spring NODE when those references are needed. Keep valid old path code; checkers must preserve valid nodes too. ### 6. All native fluid and mechanics families The following is copied from the current package direction guide: Every family below supports all 101 integer percentages. | Node | Families and direction | | --- | --- | | `fluid tank` | `surface`: left to right on the liquid line. `bottom`: straight bottom, left to right. `right`: rounded-corner end to top. `left`: top to rounded-corner start. `bottom-left`, `bottom-right`: the two actual cubic corner curves, following the counterclockwise outline. | | `meniscus` | `surface`: actual cubic liquid curve, left to right. `bottom`, `right`, `left`: the vessel outline. | | `rotating fluid` | `surface`: actual parabolic liquid curve, left to right. `bottom`, `right`, `left`: the vessel outline. | | `fluid cylinder` | `surface`: left-to-right diameter of the projected liquid ellipse. `surface-rim`: the full liquid ellipse. `top`, `bottom`: full vessel ellipses. `right`: lower to upper cap centre. `left`: upper to lower cap centre. | | `pressure element` | `inlet`, `outlet`: bottom to top across each projected face. `inlet-rim`, `outlet-rim`: full face ellipses. `axis`: inlet centre to outlet centre. `bottom`, `top`: straight body edges following the outline. | | `flow tube` | `inlet`, `outlet`: bottom to top across each opening. `axis`: curved opening-centre line, left to right. `bottom`: actual lower cubic, left to right. `top`: actual upper cubic, right to left. | | `liquid ring` | `outer`, `inner`: full circular boundaries. `liquid`: filled-sector centreline, from `liquid-start` to `liquid-end`. `start`, `end`: each sector's radial face, inner to outer boundary. | | `u tube` | `left-surface`, `right-surface`: left to right across the liquid in their respective arms. `surface`: the left arm. `outer`, `inner`: left lip down the left wall, through the bend, then up to the right lip. | | `block` | `bottom`, `right`, `top`, `left`: the four boundaries following the counterclockwise outline. | | `pulley`, `particle`, `disk`, `ring` | `rim`: complete circumference, starting at the rightmost point and running counterclockwise. `25` is north, `50` west, `75` south. | | `spring` node | `axis`: exact `start` to exact `end`, left to right in local coordinates. This samples the connection axis. | For cubic curves, the percentage is the Bézier parameter; `50` is at parameter one half. For a parabola it is horizontal progress. Circles and ellipses use angular progress. U-tube outlines use distance along the complete wall–bend–wall path. This states exactly how intermediate points are determined; the package does not imply equal arc-length spacing for every kind of curve. Cylinder `left-surface` and `right-surface` now select opposite ends of the liquid diameter; `surface` is its centre. Pressure-element `inlet` and `outlet` are the projected face centres, matching `inlet-50` and `outlet-50`. U-tube `surface` matches `left-surface-50`, on real liquid rather than the empty gap. An open vessel has no invented top edge. Use its compass anchors for the nominal frame. Circular mechanics nodes retain ordinary numeric angle anchors such as `(P.90)`; explicit `(P.rim-25)` is the percentage form. Ordinary TikZ rectangle and circle shapes are unaffected. Native mechanics `outer sep` continues to offset attachment boundaries. Use actual public fluid node styles, e.g. `fluid tank` or `physics fluid tank`, `u tube` or `physics u tube`. Do not invent no-space aliases from internal shape names such as `physicsfluidtanknode`. Verify each public spelling in reference records. These are schematic geometries; package parameters do not solve hydrostatic equilibrium, flow, or fluid dynamics. Mechanics block/circle styles now use private package shapes inheriting native TikZ geometry. Standard `rectangle` and `circle` are unchanged and do NOT gain these percentage families. Labelled native circle nodes preserve rim coordinates; ordinary numeric circle anchors retain angle meaning, not percentages. Native pulley tangent routing (`to[over pulley=P]`, `tangent cs`) continues working. Do not replace native pulley routes with approximate hand-drawn arcs. ### 7. Show anchors, show keys, physicshelp These apply to native nodes across surfaces, wedges, ramps, mechanics, optics, elements, and fluids, including unnamed, transformed, and spring nodes. ```tex \node[fluid tank,show anchors,show keys, physics debug/anchor list={left-surface,surface,right-surface}, physics debug/anchor families={surface,bottom,left,right}, physics debug/anchor samples={0,25,50,75,100}] (T) {}; \draw[->] (T.surface-25) -- ++(0,1cm); ``` `show anchors` numbers named points and puts names in a table. Percentage samples require explicit family selection (`{...}` or `all`); samples control only display. An empty anchor list hides named points. Coincident anchors share a marker; nearby separate points retain their markers, with displaced numbers and leader lines when crowded. Markers are now above opaque fills. Cards are above geometry/markers (default gap4mm), tables below. Preserve custom layer order. Reusing a node name no longer leaves a stale card position. `show keys` lists DOCUMENTED DEFAULTS and API options, not applied live node values. Use `\physicshelp{spring}`, `\physicshelp{rope}`, or an assembled pic's feature name inside tikzpicture for path/pic reference cards. Paths and pics are not node-anchor objects. Assembled fluid pics keep named `(F-surface)` component coordinates; native nodes use `(F.surface-25)`. Keep `pos=.25` for ordinary path labels. The same named spring now has both node/path contexts. Create separate debug versions for QA, then remove every debug switch/card from finished question and solution figures. Clean finals must preserve exact geometry/labels and not include force vectors unless the requested figure is an FBD or explicitly contains forces. Keep optics' existing valid anchor and Snell-law limitations; this task does not redefine optics geometry. ## Implementation locations in vbagent All paths below are relative to `/Users/vaibhavblayer/pypi-packages/vbagent/`. Search further call sites; this is a verified starting list, not a closed list. ### A. Shared guidance and all effective prompt surfaces - `vbagent/prompts/diagram/physics/anchor_contract.py`: full/short contract; preserve or deliberately migrate imported constants and insertion helper. - `vbagent/prompts/diagram/physics/{mechanics,setup,generic,fbd,optics}.py`: full prompts, inline examples, user templates, output contracts. - `vbagent/prompts/diagram/tikz_checker.py`: valid spring nodes, percentage families, semantic repair rules, and checker-generated replacement examples. - `vbagent/prompts/quality/format_checker.py`: remove spring-node prohibition; preserve correct APIs during formatting. - `vbagent/prompts/content_generation/scanner/physics/common.py`: BOTH `TIKZ_GUIDELINES` and `TIKZ_GUIDELINES_SHORT` plus conflicting local bullets. - `vbagent/prompts/content_generation/solution/physics/common.py`: `LATEX_FORMATTING_RULES`, package text, source snippets, downstream callers. - `vbagent/prompts/subjects/__init__.py`: physics package/diagram instructions. Use one authoritative contract; specialized prompts may use relevant examples without reproducing all tables everywhere. Tests must inspect final assembled instructions, not merely verify that the shared module contains strings. ### B. Agent assembly, validators, routing, references - `vbagent/agents/diagram/physics/{mechanics,setup}.py`: reference-tool text, context and custom validators. Mechanics' lexical validator currently knows block/spring/pulley but lacks explicit fluid objects: accept valid native fluid apparatus where routed to mechanics/setup, and retain rejection of empty or non-TikZ output. Avoid a regex pretending to fully parse TikZ. - `vbagent/agents/diagram/base.py`, `vbagent/agents/diagram/tikz_router.py`: trace actual prompt assembly and routing. Ensure fluid apparatus reaches appropriate existing physics agents; add focused routing changes only where a concrete gap exists. A new dedicated fluid agent is not required. - `vbagent/references/store.py`, `vbagent/references/tikz_store.py` and configured reference locations: inspect retrieval for stale spring/anchor examples; update project-owned fixtures/docs and ensure retrieved legacy examples do not override current contract. Do not destructively rewrite users' archives. - Audit generator/checker feedback loops so a correct spring node or new percentage anchor isn't “repaired” into the obsolete API. - Inspect any persisted generated-artifact cache that can return old code. Invalidate/version affected outputs only if that path can bypass new guidance; do not gratuitously change unrelated prompt-cache affinity or model settings. ### C. Compiler compatibility and reliable diagnostics - `vbagent/utils/latex.py`: current shared version guard. - `vbagent/compile.py`: snippet compile and diagnostic result. - `vbagent/cli/compilation/compile_main.py`: `generate_preamble` / paper compile. - `vbagent/cli/management/archive.py`: thumbnail compile path. - `vbagent/dpp/builder.py`, `vbagent/analysis/generator.py`: additional guard users. Retain protection from genuinely old packages, then check required capabilities in one shared preamble/runtime guard. Inspect actual PGF shape-anchor definitions or use a reliable semantic probe for spring-node `axis-100`, block `bottom-50`, pulley `rim-25`, and fluid `surface-25` / U-tube arm families. The probe must recognize the actual private native shapes and work with both split and bundled runtime. The new package header is 2026/09/27 v1.6.0; verify this actual release rather than inventing a version. Distinguish a missing API from TeX syntax errors and report how to select/install current sources. Test an old fixture using the SAME v1.5.0 date/header but missing these APIs: it must fail explicitly before silently misplacing coordinates. Test the real source and single-file bundle: both must pass. Semantic changes such as U-tube surface-on-left-arm also need actual coordinate checks, not just macro presence. Do not claim macro existence proves every semantic contract. Expose/preserve logs (`\listfiles`) and recorder/file path evidence so QA can say which package loaded. For development compiles, prefer authoritative source via `TEXINPUTS`; do not embed this personal path as a production requirement. Preserve normal TeX lookup fallback (the trailing path separator) and existing environment. Check `kpsewhich -all tikzphysics.sty` and each actual compile log/recorder. The local user tree currently lives at `/Users/vaibhavblayer/Library/texmf/tex/latex/tikzphysics/`. ### D. Documentation and examples Update the existing: - `docs/examples/tikzphysics-v1.5.0-anchor-contact.tex`. - `docs/examples/tikzphysics-v1.5.0-anchor-debug.tex`. Add clearly named current-development examples for both spring forms and fluid/mechanics percentages. Document v1.6.0 capability requirements and single-file Overleaf installation. Record verification results in a project doc. Do not describe every integer coordinate as a percentage; ordinary circles still interpret bare numeric anchors as angles. ## Required regression and visual verification Start with existing tests, then add meaningful cases rather than snapshots of implementation strings alone: 1. Full/short scanner, generator, setup, mechanics, FBD, checker, solution, subject, and format prompts all contain the right relevant contract. No effective prompt bans spring nodes or mislabels rim percentages as degrees. 2. Actual agent assembly includes updated contract and output/role rules. 3. Native spring node and path both accepted and compiled; checker preserves the chosen API. Node start/end/axis50 and lead anchors numerically correct; path labels use normal TikZ placement. 4. New block/rim and all eight native fluid-node families compile at 0/25/50/75/100. At least representative numeric geometry checks go beyond compile success: cylinder opposite diameter endpoints; pressure face-centres; U-tube separate arms and primary surface on left liquid; cubic flow axis; rim quarter-turn. 5. Rotation/scaling, labelled circles, node-instance isolation, and opaque fill debug markers retain correct anchors. Standard TikZ circle/rectangle are not assumed to have package families. 6. Existing ground/ceiling/wall/platform contact rules, wedge br/bl/top modes, pulley-edge continuity/tangency, and full-path mirrored ramps remain valid. 7. Updated guard rejects old v1.2 and same-header old v1.5 without new capabilities; source and isolated single-file bundle pass. Shared snippet, paper preamble, archive thumbnail, and other guard callers have covered integration points. 8. Finish outputs omit debug helpers while QA variants demonstrate them. Focused starting commands (run from vbagent; expand only to resolve concrete remaining risk or cover affected paths): ```sh poetry run pytest tests/agents/diagram/test_tikzphysics_prompts.py tests/agents/diagram/test_tikz.py tests/agents/diagram/test_tikz_router_dispatch.py tests/cli/compilation/test_compile_preamble.py tests/cli/management/test_archive.py tests/utils/test_latex.py poetry run python -m compileall -q vbagent/prompts/diagram/physics vbagent/prompts/diagram/tikz_checker.py vbagent/prompts/quality/format_checker.py # Run the project's available formatter/linter on changed paths. git diff --check ``` Render PDFs and inspect EVERY representative QA page: a flat surface/platform, all wedge modes, straight and curved mirrored ramps, spring node+path, eight fluid nodes, block plus labelled circle/pulley, and a transformed filled node. Use real `show anchors,show keys` and selected family samples. Check physical contact positions, continuous joins, labels/tables, and pulley routes. Then compile clean final versions. Retain gallery source/PDF and exact loaded-package path/version/capability results. Test source and isolated Overleaf bundle. Report compiler absence/skips without claiming visual success. LLM smoke runs are optional; do not require paid runs for deterministic API validation. ## Acceptance / delivery - Changes implemented throughout effective prompt/repair/compile paths; existing v1.5 anchor work preserved and all newer additions covered. - Both spring APIs remain usable; no false node prohibition survives. - Per-shape direction/parameter tables are correct and examples use public styles. - Compiler distinguishes released v1.5 header from actual new API capabilities. - Focused tests pass, visual examples inspected, final figures debug-free. - Source and isolated bundle loading documented; no fabricated release claim. - Unrelated dirty work preserved; no publishing or archive destruction. - Final report: files changed, concrete behaviour, test counts/skips, visual artifact paths, loaded-package evidence, remaining limitations. The package's own latest verification already passed eight l3build suites, 82 new uniform-anchor assertions, 48 examples, 16 expected-invalid geometry cases, all 70 generated references, and source/bundle/local-installed compiles. These are package-side results, NOT evidence that vbagent integration is done.