mesh-avatar-studio
일러스트를 코딩 에이전트와 로컬 편집기로 2D 메쉬 애니메이션 아바타로 변환
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Physics-inspired vector generation for plotter-ready line art. No build step, no framework — open index.html and go. Vectura combines a rich algorithm library (flowfields, boids, attractors, Petalis, and more) with a full layer system, mirror & morph modifiers, SVG export with plotter optimization, and a Noise Rack for layered generative noise — all in vanilla JavaScript.
Node 20.19 or newer is required for the development and test toolchain.README 전문 보기 ↗Physics-inspired vector generation for plotter-ready line art. No build step, no framework — open index.html and go. Vectura combines a rich algorithm library (flowfields, boids, attractors, Petalis, and more) with a full layer system, mirror & morph modifiers, SVG export with plotter optimization, and a Noise Rack for layered generative noise — all in vanilla JavaScript.
| Flowfield | Boids | Attractor |
|---|---|---|
Option A — open directly:
Double-click index.html
Option B — serve locally:
python -m http.server
# then visit http://localhost:8000
For tests:
npm install
npm run hooks:install # one-time: installs pre-commit + pre-push (test:feedback) hooks
npm run test:feedback # bounded local check; CI (`ci-ok`) is the full gate
Node 20.19 or newer is required for the development and test toolchain; use Node 24 (.nvmrc), the CI major and the only one where golden values are checked.
CI is the full gate: the required ci-ok check covers the whole Vitest roster, the browser smoke,
perf and the routed Scene3D audits on every PR. Coverage, the full touch roster and pixel snapshots
run on main and nightly. Details: testing guide.
The
pre-pushhook runstest:feedback(bounded local feedback) before every push. A minimal browser journey runs locally; CI retains the full browser roster. Bypass withSKIP_PREPUSH=1 git push.
Vectura uses a pro-editor-style layer system with full undo history for every structural edit — reorder, group, reparent, mask toggles, and modifier changes are all first-class history steps. Layers support per-layer stroke/line-cap settings, visibility, and drag-to-reorder. Mirror Modifiers let you wrap layers in a reflective container with a full mirror-axis stack, and Morph Modifiers blend 2+ child layers into graduated in-between rings (a pro-editor-style Blend, but plotter-native).
Hide Mask Layer for invisible mask artwork and a live dimmed-descendant preview while the mask parent is being transformedInsert > Mirror Modifier adds a group-like container with drag-to-assign or drag-out child layers, + Add child-layer creation from a selected modifier, fully editable selected child layers, and mirrored closed-mask silhouettes for masked subtreesInsert > Morph Modifier adds a blend container: drop 2+ layers in and it generates N graduated in-between rings morphing one shape into the next (sequential A→B→C chaining or a cyclic loop), with controls for steps, easing, vertex resampling, start-vertex correspondence, multi-path handling, source emission, closure, and output smoothing; children auto-lock and Expand bakes each ring into its own shape layerCmd/Ctrl+G and Cmd/Ctrl+Shift+Gpathfinder container. Silhouette mode chord-closes open paths; Shape-Only mode restricts to closed shapes. Outline preserves source strokeWidth for plotter-ready line art.Cmd/Ctrl-click to toggle, or drag a marquee on the canvas; then move/rotate the group togetherCmd/Ctrl+A selects all drawable layers from anywhere outside text inputsCmd/Ctrl+E)Cmd/Ctrl+D duplicates selection; Alt-drag (Option-drag) also duplicatesCmd/Ctrl+Z and adjustable history depthA pro-editor-style shared toolbar now drives the main canvas plus the embedded designer surfaces, including selection, direct selection, hand, pen (bezier), shape, scissor, and fill tools. Shape tools create true straight-edge primitives with corner rounding, the pen tool supports full bezier editing with subtool shortcuts, and Pattern texture fills now support nested-region targeting with drag-pour behavior.
V selection, A direct selection, Space hand, P pen, M rectangle, L oval, U line, Y polygon, C scissor, F fill, Shift+F erase fill; press again to cycle subtools where availableM, Oval L, Line U, Polygon Y) live under a single long-press group on the toolbar — single-tap activates the most-recently-used variant, long-press opens the variant submenu. All four create editable expanded layers; fresh shapes stay straight-edged on mouse releaseV), outline arrow for Direct Selection (A), pen-tip for Pen (P), and a paint-bucket overlay with an auto-positioning magnifier loupe for Fill (F) that stays inside the canvas viewportAlt), polygon side-count changes while dragging (Arrow Up/Down), and corner rounding (Selection rounds all corners; Direct rounds one corner, or all selected corners together when several are selected)+ add anchor, - delete anchor, Shift+C convert anchor; while dragging a new bezier point, Alt/Option freezes the mirrored handle and lets the active handle move freelyShift-click to fill the whole containing stack, drag to keep pouring across new regions, and hold Alt/Option to temporarily erase fills while draggingShow Gaps tolerance slider that reveals near-miss tile joins in yellow and offers auto-close fixes for closable seam endpointsShift snaps)Shift constrains proportions)Select an object and a Contextual Task Bar floats just below it with the actions that matter right now — edit path, pen, stroke weight, shape properties, group/align, isolate, or text. Stroke weight and Simplify open inline sub-modes; live rectangles and polygons get a corner-radius / side-count popover. Double-clicking into a group shows an isolation breadcrumb across the top of the canvas. Toggle the bar under Document Setup → Guides & Display. No AI tooling anywhere.
.ctxbar) anchors below the selection, flips above near the viewport bottom, clamps to the viewport, yields to the tool rail, and hides during canvas drag / drawing / text-caret editsPathEditOps preview with an Auto-Smooth pass and a "{pts} pts" badge; Done commits, Esc / click-away cancelsrole="toolbar" with roving tabindex never steals focus on appearanceDocument › … › group) — click an ancestor to step out one level, the back arrow to exit one level, or the root to leave isolation; a fixed-blue top-edge line marks the isolated state.vectura and cookie preferences≤120ms fade/slide, animation disabled under prefers-reduced-motion)19+ algorithm families power each layer, all seeded for repeatable results. The Noise Rack is a universal multi-algorithm noise stacking system shared across algorithms — add layers, pick noise types, blend modes, and octave shaping without touching algorithm-specific code. Every algorithm also ships a universal preset gallery: a thumbnail dropdown of curated starting points grouped by Classic / Geometric / Organic / Complex / Evolving, plus a User section. Edit any preset and a colored save pip appears beside it — click it (or press Cmd/Ctrl+S) to name and save the look as your own preset, with one-click Undo; if you started from one of your own presets you can update it in place. Your presets save in the browser by default; in Document Setup → Preset Storage you can connect a folder on disk (Chrome/Edge) so they persist across sessions, or export/import a portable vectura-presets.json bundle to move them between machines. You can still import presets from .vectura files too. With Developer Mode on (Document Setup), the Save dialog becomes a small authoring tool: overwrite any preset — curated built-ins included — and save into a category (an existing group or a brand-new one you name), written straight into the repo's user-presets/ folder so it's commit-ready.
.stl meshes and render them as wireframes, depth-plane contours, or face/edge/vertex art with hidden-line removal; Topoform ships 10 primitives (sphere, torus, cube, cone, ellipsoid, cylinder, capsule, pyramid, superellipsoid, torus knot) with detail up to 100. All four 3D algorithms support orthographic or perspective projection, full Rotate X/Y/Z view control via sliders or the on-canvas three-ring rotation gizmo (amber X, violet Y, cyan Z — drawn ring-only, with no backing disc over the artwork), and contour/line smoothing produces true bezier curves on screen and in export. The live preview fidelity while dragging a 3D shape is tunable in Document Setup → Guides & Display → 3D move preview (Draft / Balanced / High)The SVG export modal offers a large preview pane with zoom/pan inspection, plotter optimization controls, and multi-layer line sort. Output is plotter-ready: millimeter-accurate, grouped by pen, and physically trimmed to your frame. A separate Export Animated SVG action emits a self-contained looping "draw-on" SVG for sharing the figure drawing itself.
File > Export SVG opens a pro-editor-style modal: large left-side preview pane, right-side export settings, Cancel / Export SVG at bottom-rightFile > Export Animated SVG… is a separate action that emits a self-contained, looping "draw-on" SVG whose strokes draw themselves on repeat (SMIL stroke-dashoffset), sequenced by cumulative stroke length over the active harmonograph/pendula layer's duration — so you can share the figure drawing itself. It is distinct from the canonical Export SVG, which stays clean and static (no animation contamination)Line Sort overlay styling stays scoped to the modal and never leaks into the main canvasRemove Hidden Geometry is enabled by default — exported SVGs physically trim masked or frame-hidden geometry to match the visible frame; turning it off preserves hidden source geometry through SVG clip pathsLine Sort respects the selected optimization scope across preview, stats, overlay rendering, and optimized SVG exportOverlay and Line Sort is active, the overlay gradient runs from Overlay Color to its complement by default, with a per-Line Sort secondary-color override and an on-canvas print-order legendExport Optimized is enabled by default; optimization scope defaults to All LayersLine Simplify is applied by default for new layers with Mode set to Curve; Line Sort is off by default for new layersVectura's UI follows familiar desktop-editor conventions: a desktop menu bar with File/View/Insert/Help menus, a Pen / Paper tab with the pen palette (drag-to-assign) and a realistic paper selector, Document Setup (Cmd/Ctrl+K), and a multi-skin theme system (Classic Dark/Light, Lark, and the Meridian Blue family). Cookie-backed preference persistence keeps your settings between sessions.
VECTURA.STUDIO with shortcuts for Open/Save/Import/Export/Document Setup/Reset View/Help plus an Insert menu for modifier containersPen 1 to a contrast-appropriate color. New skins can be authored without JavaScript edits — see docs/skin-authoring.md and run npm run skin:new -- <id> to scaffold one from the template.File > Document Setup (Cmd/Ctrl+K) covers machine size, Metric/Imperial switch, optional blueprint-style dimension labels, margin, on-canvas crop, margin guides, the default paper, selection-outline styling, plotter physics, optional 10mm grid overlay, and cookie preference saving with Clear Saved PreferencesThe Pen / Paper tab previews the plot the way it will come off the plotter: a realistic paper (tooth, fibres, bleed) and real pen models whose ink bleeds, blobs, pools and skips like the pen it names. Everything is a preview; the SVG stays plotter-clean.
Shift+Alt+L): the sheet goes dark and glow-in-the-dark inks emit; a canvas chip turns the lights back on. View only, never saved..json, imported pens get new ids, one undo step) and My pens, a library of saved pens in this browser (save from Ink settings, listed first in the model picker, apply / add / rename / export / delete).docs/pen-models.md.Vectura works by finger and Apple Pencil on iPad and iPhone. Panels open as drawers, the tool rail is one row, and every control has a 44 px touch target. A canvas HUD, a modifier bar and a Help Touch tab replace the mouse and keyboard.
.vectura from the Files app and save through the share sheet. Camera-roll photos are resampled to 2048 px.aria-expanded and aria-controls. Menus have aria-haspopup. Focus moves into a drawer on open and back on close.| Algorithm | Description |
|---|---|
| Flowfield | Noise Rack-driven vector fields with stacked layers feeding angle or curl flow, plus density, step, and length controls |
| Boids | Emergent flocking paths with separation, alignment, and cohesion forces |
| Attractors | Lorenz-like and chaotic strange attractor systems |
| Hyphae | Branching, growth-like structures |
| Lissajous | Harmonic parametric curves with per-endpoint truncation and self-intersection trim |
| Harmonograph | Multi-pendulum curves with damping, anti-loop drift, settle cutoff, and a reveal-only Virtual Plotter preview (the pen traces the static figure on a loop) |
| Pendula | A kinetic-harmonograph studio built in parallel with Harmonograph: a Motion Rack of assignable temporal LFOs baked into the figure, Lateral (damped spiral-in) and Pintograph (non-decaying loops) machine types, a preset gallery, and Export Animated SVG |
| Wavetable | Layered noise wave stacks with multiple line structures (horizontal, vertical, grid, isometric, lattice) |
| Rings | Concentric rings with Noise Rack layering, per-noise Orbit Field / Concentric / Top Down sampling, and a controllable center diameter |
| Topo | Contours extracted from a Noise Rack height field with stacked layers and closed-contour mapping modes |
| Grid | Rectilinear mesh deformed by a stacked Noise Rack field with Warp and Shift distortion modes |
| Text | Sets a string in a built-in single-line (monoline) stroke font — five selectable styles (Sans, Italic, Condensed, Wide, Backslant) — or any Google Font (defaults to vendored Inter; the picker previews each family in its own typeface, searches the full ~2000-family catalogue, and traces a chosen family's glyph outlines into pen paths), and fits it to the frame as pen-ready line art. Supports multi-line, alignment, letter spacing, line height, frame-fit or absolute sizing, offset and hand-drawn jitter — plus optional native bezier outlines (with a Smoothness control), (Outline Weight + Parallel/Sinusoidal/Snake thickening), of glyph interiors — the (Hatch, Wave, Dots, Contour, Spiral, Radial, Polygonal, Truchet, Maze, Stripes, Weave), with holes carved automatically — plus a draggable and, for the fill, a that shifts the radial origin — for fill-only or filled-and-outlined type, and |
Algorithm defaults live in src/config/defaults.js, modifier defaults/descriptions in src/config/modifiers.js, and algorithm descriptions in src/config/descriptions.js.
Transform & Seed inside the Algorithm panel to adjust seed, position, scale, and rotation.Use Mask on a silhouette-capable parent row to clip all indented descendants with that parent's visible silhouette. Inside the mask editor, Hide Mask Layer keeps the parent as the clipping silhouette while removing its own artwork from view and export. Mask parents ghost-preview their masked descendants outside the silhouette while you transform them, then restore normal masking on release.
Use Insert > Mirror Modifier to add a modifier container, then drag layers onto it in the Layers panel. Drag a child back out to root to unparent it. When a modifier is selected, + Add creates a normal drawable child under that modifier using the last active algorithm.
Select a child nested under a Mirror Modifier to edit it normally — the left panel switches back to Algorithm mode so parameter edits apply to the selected child while the mirror effect stays inherited from the parent.
The modifier row owns a Mirror Stack with per-axis show/hide, lock, delete, reorder, angle, and XY shift controls plus stack-level actions. Deleting the modifier dissolves only the wrapper and preserves its children.
Wallpaper mirrors open in a gallery-first Styles mode: a grid of cards, each a canonical thumbnail icon of that symmetry. Cards cover all 17 groups (in plain language) plus curated named recipes (Op-Art Weave, Courtyard, Switchback, Brick Path, Kasbah Tile, Snowflake Lace, Trefoil, …) — click one to apply it. A Surprise me dice rolls a random valid group with tasteful tile parameters (Shift-click locks the lattice family). On the canvas, drag the center puck to move the symmetry center and the rotate ring to spin the whole lattice (Shift snaps).
Switch to Build mode for the composable picker: pick a Lattice (parallelogram / rectangle / rhombus / square / hexagon), a Rotation order (1 / 2 / 3 / 4 / 6), and a Mirror set (None / Straight / Glide / …). The 17 crystallographic groups (p4m, p3m1, …) are derived from that tuple — invalid combinations snap deterministically to the closest valid group, flashing the auto-changed chips with a plain-language note. ⌘← / ⌘→ cycles through every group sharing the current lattice. Enable Show crystallographic group names in Document Setup → History & Preferences to surface the IDs alongside the chips.
Use Insert > Morph Modifier to add a blend container, then drop 2 or more layers into it in the Layers panel. The modifier fills the space between consecutive children with N graduated in-between rings — child A's shape progressively becoming child B's, including its size, position, and rotation. When two children run the same algorithm, the morph interpolates their parameters and regenerates each step (Parameter Morph, on by default) — a rotated and resized Polyhedron copy steps through the actual intermediate rotations and sizes (2D and 3D), and a changed setting (petal count, spin, density…) steps through its in-between values. Different algorithms or hand-drawn shapes blend geometry line-for-line instead, pairing paths spatially across the two children. Child layer order sets the morph direction; with 3+ children the chain runs sequentially (A→B→C, each pair its own segment) and Cyclic mode closes the loop back to A. The originals stay visible unless you turn off Emit Sources.
The morph also transitions fill: if the children carry paint-bucket fills, each in-between ring is re-filled with interpolated fill parameters (density, angle, and so on lerp between the two children when they share a fill type; a different fill type or seed switches at the midpoint). Toggle Morph Fill off for outline-only output. Pens stay discrete — each ring takes its nearest source child's pen.
The Morph panel exposes: Steps (intermediate rings per pair), Easing (Linear / Ease In / Ease Out / Ease In-Out / Cubic In / Cubic Out), Sequence (Sequential / Cyclic), Resample Count (common vertex count) and mode (Arc Length / Uniform Index), Correspondence (how start vertices align: Centroid + Angle / Nearest / Arc Length), Parameter Morph (same-algorithm pairs regenerate at interpolated parameters), Multi-Path handling when children have different path counts (Auto / Pair Paths / Index Match / Merge Centroid / Merge Longest), Morph Fill (on/off), Closure, and Smoothing. A live readout shows the child count and total step budget, with a warning when the point budget gets large.
Children dropped into a Morph group auto-lock (like Mirror). Morph output is plotter-ready polylines and is included in SVG export; Expand bakes each ring into its own shape layer.
Switch to the Petalis algorithm to access the embedded inline Petal Designer panel. Use ⧉ to pop it out into a floating window or ↩ to dock it back in.
Petal shape is driven by visible inner/outer designer curves. Controls include: always-on inner/outer count + split controls, a PETAL VISUALIZER (Overlay / Side by Side), a PROFILE EDITOR with an Inner | Outer toggle that shows one side at a time (it auto-switches to whichever side you interact with) plus per-side profile import/export and a shared Export Pair button, and Shading Stack + Modifier Stack cards where each entry has its own Petal Shape target (Inner/Outer/Both). Picking a named profile thumbnail also resets that side's Advanced sliders to a clean baseline so the shape isn't distorted by a leftover tweak; every Advanced slider (Base Flare, Base Pinch, Edge Wave, Tip Sharpness, …) shapes the designer profile.
In overlay view, clicking the visible inactive silhouette selects that shape directly. Designer interactions support Shift to constrain, Alt/Option to convert/break/remove handles, Cmd/Ctrl for temporary direct mode, middle-drag pan, and wheel zoom-to-cursor.
File > Document Setup (Cmd/Ctrl+K) covers: machine size, the document-level Metric/Imperial switch, optional blueprint-style dimension labels outside the canvas, margin, on-canvas crop, margin guides, the Default paper (Paper & Selection: a paper type or No default (follow theme), its colour, and Apply to this document), selection-outline styling, plotter physics, optional 10mm grid overlay, and cookie preference saving with Clear Saved Preferences.
The sun/moon toggle in the upper-right header switches the full UI between dark and light themes. A theme change recolours the sheet only while the document is on a plain (None) sheet in the theme's own colour and no default paper is set; an untouched Pen 1 always stays legible on the paper.
Export from File > Export SVG, which opens a large preview modal. Zoom/pan the left-side preview to inspect detail. The right side controls:
Click Export SVG to download.
| Action | Shortcut |
|---|---|
| Tools | |
| Selection tool | V |
| Lasso | Q |
| Direct selection | A |
| Hand / pan | Space |
| Pen tool | P |
| Fill | F |
| Erase fill | Shift+F |
| Add anchor | + |
| Delete anchor | - |
| Convert anchor | Shift+C |
| Rectangle | M |
| Oval | L |
| Line | U |
| Polygon | Y |
| Scissor | C |
| Canvas | |
| Pan | Shift + Drag |
| Zoom | Mouse Wheel |
| Touch pan | Two-finger drag |
| Touch zoom | Pinch |
| Layers | |
| Select all drawable layers | Cmd/Ctrl+A |
| Shift-click range | Range select |
Cmd/Ctrl-click | Toggle select |
| Drag marquee | Marquee select |
| Duplicate selection | Cmd/Ctrl+D |
| Duplicate by dragging | Alt-drag |
| Nudge | Arrow keys |
| Nudge large | Shift + Arrow keys |
| Expand layer | Cmd/Ctrl+E |
| Group layers | Cmd/Ctrl+G |
| Ungroup | Cmd/Ctrl+Shift+G |
| Gesture | Action |
|---|---|
| Tap | Select an object or layer |
| Drag a selected object | Move it (starts after 6 px) |
| Drag empty canvas | Marquee select |
| Two-finger drag | Pan the canvas |
| Pinch | Zoom the canvas |
| Two-finger tap | Undo |
| Three-finger tap | Redo |
| Double-tap | Finish a pen path |
| Press and hold the canvas (0.5 s) | Select the object and open the canvas menu (Select, Direct Selection, Hand). On empty canvas the menu offers Select All |
| Press and hold a layer row (0.5 s) | Open the layer menu (or tap ⋯) |
| Drag a grip | Reorder layers and panel list rows |
| Tap a value chip | Type an exact value |
| Press and hold a control label (0.5 s) | Reset to default |
| Press and hold an icon button (0.5 s) | Show its name |
Press and hold a tool marked ▸ | Open its variants (or tap the active tool again) |
| Modifier bar: tap a task | Apply Multi-select, Constrain, Duplicate or Pan to the next gesture |
| Modifier bar: double-tap a task | Lock it on |
| Canvas HUD buttons | Undo, Redo, Zoom Out, Zoom In, Fit |
| Command | Purpose |
|---|---|
npm run test:feedback | Bounded local feedback: critical contracts and one real browser journey |
npm run test:audit:proofs | Scene3D proof audits (tests/audit); CI runs them when scripts/audit-paths.js matches |
npm run test:runner | Process cleanup and cancellation regression checks |
npm run test:unit | Deterministic unit coverage for RNG/noise, algorithms, and utility helpers |
npm run test:integration | Engine workflow, layer lifecycle, optimization pipeline, state roundtrip, export, UI bootstrap |
npm run test:e2e | The whole Playwright roster (desktop, tablet, phone and the 11 touch projects) |
npm run test:e2e:smoke | The PR browser smoke: desktop projects plus a 2-project touch smoke |
npm run test:e2e:touch | Touch specs on 7 Chromium and 4 WebKit device projects (PW_PORT picks the dev-server port) |
npm run test:e2e:touch:audit | Touch target and layout audit against tests/e2e/touch/target-baseline.json (:full for every state) |
npm run test:visual | SVG baseline regression checks against tests/baselines/svg |
npm run test:visual:screenshots | Linux pixel snapshots in the pinned Playwright image (docker); runs nightly in CI |
npm run test:perf | Stress/performance checks for generation and optimization |
npm run test:ci | Optional full local pass: lifecycle + coverage + audits + browser roster + perf |
npm run test:update | Regenerates SVG goldens and this architecture's golden values (Node 24; review before commit) |
npm run test:vitest -- <args> | Vitest with any arguments, e.g. one file: npm run test:vitest -- run tests/unit/foo.test.js |
npm run test:playwright -- <args> | playwright test with any arguments, e.g. one spec |
All test commands run through a shared local test queue (scripts/test-queue.js): one heavy run at a time across every worktree and session on the machine; other runs wait and say who holds the lock. Do not call npx vitest / npx playwright test directly. CI bypasses the queue. Details: docs/testing.md → "Shared Local Test Queue".
Vitest scripts clean up owned workers on completion/cancellation and enforce a
30-minute local per-attempt deadline (three hours in CI), even if the launching wrapper dies. Use
VECTURA_TEST_TIMEOUT_MS to override it; see cleanup behavior and platform limits.
CI graph, goldens, corpora and push-gated follow-ups: testing guide.
Vitest config: vitest.config.mjs · Playwright config: playwright.config.js
Manual CI-equivalent setup:
npm cinpx playwright install --with-deps chromiumnpx playwright show-trace test-results/<failing-test>/trace.zip opens a saved Playwright trace locally after a failed smoke run| Change | Minimum test run |
|---|---|
| Core logic / algorithm behavior | test:unit + test:integration + test:visual |
| Export / serialization | test:unit + test:integration + test:e2e |
| UI interaction behavior | test:integration + test:e2e |
| Rendering output or baselines | test:visual (+ test:perf for heavy paths) |
| Docs-only | Link/path sanity review only |
| Full gate | CI ci-ok (local test:ci optional) |
This repository uses graphify to build an AST-based code map for efficient codebase navigation. After each commit and branch switch, git hooks automatically rebuild the graph—no API cost, just local parsing.
Setup:
pip install graphify
The knowledge graph lives in graphify-out/. Consult GRAPH_REPORT.md to navigate by community clusters and god-nodes before raw file searches.
To update manually:
graphify update .
package.json is the canonical version source. Run npm run version:sync after changing it so the UI badge and src/config/version.js stay aligned.plans.md is the active punchlist. Keep Inbox, In Progress, Done, and Decisions current in the same PR as the implementation.CHANGELOG.md is intentionally human-curated. Keep Unreleased current during development and cut versioned entries when shipping.Noise Rack; all future noise-capable algorithms should converge on that shared model.npm run profiles:bundle rebuilds src/config/petal-profiles/library.js from index.json + profile JSON files for file:// local runs; run this after editing profile JSON files.main) and the root (/) folder.All asset paths are relative (./...), so the site works under a GitHub Pages subpath.
New algorithm: create src/core/algorithms/<name>.js, register it in src/core/algorithms/index.js, wire defaults in src/config/defaults.js, add a description in src/config/descriptions.js, and add UI controls in src/ui/ui.js. Algorithm noise work must use the Noise Rack — do not introduce algorithm-specific noise stacks.
Machine sizes: live in src/config/machines.js and are used for bounds and export dimensions.
Pen palettes: live in src/config/palettes.js — edit or extend freely.
Presets: are file-based — every preset is a .vectura file under user-presets/<layer_type>/ (the directory name matches the layer type / preset_system, camelCase included). Run npm run user-presets:bundle to regenerate src/config/user-presets.js (the single generated library, loaded into window.Vectura.PRESETS); don't hand-edit it. Identity/category live in a meta:{presetId, group, system, savedAt} block; the 15 <type>-default "reset to factory" markers are synthesized by the bundler from ALGO_DEFAULTS. id is lowercase kebab-case prefixed by system (e.g. petalis-camellia-pink-perfection). With Developer Mode on, the in-app Save dialog can write these files directly into a connected user-presets/ folder.
Petalis profiles: add .json files to src/config/petal-profiles/, list them in index.json, then run npm run profiles:bundle to update library.js. Keep profiles anchor-based (inner/outer shape payloads).
Script order: keep src/config/ files before core, before UI/render, before src/main.js in index.html. All modules register on window.Vectura as IIFEs.
flowchart LR
HTML[index.html] --> Main[src/main.js]
Main --> App[src/app/app.js]
App --> UI[src/ui/ui.js]
App --> Engine[src/core/engine.js]
App --> Renderer[src/render/renderer.js]
UI --> Controls[Panels & Controls]
UI --> Export[SVG Export]
Renderer --> Canvas[(Canvas)]
Engine --> Layer[src/core/layer.js]
Engine --> Algorithms[src/core/algorithms/index.js]
Engine --> RNG[src/core/rng.js]
Engine --> Noise[src/core/noise.js]
Engine --> Modifiers["src/core/modifiers.js"]
Engine --> Display["Display Geometry / Masking"]
Modifiers --> Display
Display --> Renderer
Display --> Export
Display --> Masking["src/core/masking.js"]
Masking --> Boolean["src/core/path-boolean.js"]
Config[src/config/*.js] --> UI
Config --> Engine
Skin[src/ui/skin/*.css] --> HTML
flowchart TD
Package["package.json (Canonical Version)"] --> Sync["npm run version:sync"]
Sync --> Version["src/config/version.js"]
Sync --> Badge["index.html app badge"]
Work["Feature / Fix Work"] --> Plans["plans.md"]
Work --> Changelog["CHANGELOG.md"]
Work --> Readme["README.md"]
Work --> Harness["docs/agentic-harness-strategy.md"]
Harness --> PR[".github/pull_request_template.md"]
| Path | Purpose |
|---|---|
index.html | App shell, Tailwind CDN config, and script load order |
src/ui/skin/ | Multi-skin theme system: tokens.css + motion.css + components.css plus per-skin palette files (classic + Meridian families) |
src/app/app.js | Application orchestration, theme switching, cookie persistence, undo/redo history |
src/core/engine.js | Layer lifecycle, algorithm execution, display geometry pipeline, serialization |
src/core/algorithms/ | One file per algorithm; index.js assembles the registry |
src/core/layer.js | Layer state model |
src/core/rng.js | Seeded random number generator |
src/core/noise.js | Core noise primitives |
src/core/noise-rack.js | Universal multi-algorithm noise stacking system |
src/core/modifiers.js | Mirror-axis geometry, clipping, and reflection routines |
src/core/morph-modifier.js | Morph blend math: arc-length/uniform resampling, correspondence alignment, path interpolation, and the multi-child dispatch path |
src/core/masking.js | Silhouette capability detection, mask unions, live display-geometry masking |
src/core/path-boolean.js | Polygon normalization and path segmentation used by masking |
src/core/geometry-utils.js | Shared path smoothing, simplification, and cloning helpers |
src/core/optimization-utils.js | Path length, sort, offset helpers used by the optimization pipeline |
src/render/renderer.js | Canvas rendering, pan/zoom, multi-layer selection and transform handles |
src/ui/ui.js | Panel management, parameter controls, Petal Designer, SVG export, file I/O |
src/ui/randomization-utils.js | Shared parameter randomization engine with algorithm-specific bias profiles |
| File | Purpose |
|---|---|
AGENTS.md | Repository guardrails and mandatory contributor/agent instructions |
CHANGELOG.md | Human-curated release history with an Unreleased section |
plans.md | Active punchlist: Inbox, In Progress, Done, Decisions |
docs/agentic-harness-strategy.md | Source-of-truth harness for task intake, evidence standards, testing matrix, and doc sync policy |
docs/github-governance.md | GitHub-side setup targets for Projects, rulesets, release notes, and review policy |
docs/noise-rack-architecture.md | Migration plan and target architecture for the universal Noise Rack system |
docs/testing.md | Test command guidance and CI policy details |
docs/pre-release-hardening-log.md | Deferred hardening items for final-release prep |
CI lives in .github/workflows/test.yml:
main + nightly: visual regression and perf stress lanesmain + weekly: CodeQL analysisShift+Alt+L) darkens the sheet so glow-in-the-dark inks emit..json; save pens to My pens in this browser and reuse them..vectura file (settings.paper); the default paper lives in Document Setup ▸ Paper & Selection, replacing the Background colour picker..vectura from the Files app, save through the share sheet, and import large photos safely.CHANGELOG.md and docs/touch-audit/.CHANGELOG.md and docs/testing.md.ci-ok gates every PR. PRs run the whole Vitest roster in 8 uninstrumented shards, a 4-leg browser smoke, perf and the routed Scene3D audits. Coverage, the full touch roster and linux pixel snapshots run on main and nightly, and a red run opens an issue.plans.md.npm run test:update. Duplicate Scene3D tests were cut with mutation proofs.docs/testing.md.sx slider caps at 200) but reachable via a hand-edited or imported .vectura.weaveDepth now lives
behind a Nesting control on Amplitude Spacing and onePenDown behind a Pen down control
on Interlock Weave; both render exactly as before, and saved documents resolve to the surviving
option at load. Counting convention, stated once so the notes stop disagreeing with
themselves: PICKER_IDS — the collapsed list — is 33; the picker offers 34 (that
list plus ladder); IDS, the engine's own vocabulary, stays 48 forever. The 1.4.0 entry
below reports the same series at its own shipped figure of 35, and is left as shipped;
post-1.4.1 the correct figures are 48 → 33 with 15 aliases across 7 collapse clusters.
A picker showing a pre-collapse law now also displays the right sub-control value, and a saved
torus using Origin Spiral opens as Ladder — that one pairing cannot be plotted cleanly.strokeFillStyle control (spiral / concentric / serpentine / contourParallel)
chooses how the interior fills..vectura schema versioning, and a
coverage-threshold ratchet in CI.shadow.shadowReceiveOnObjects).interlockWeave/onePenDown/trochoidLoop/ampSpacing/weaveDepth) is measured but not yet
fixed; contourSlice's ink-merging at a torus/sphere's saddle and pole points is improved, not
eliminated; and the shadow-receive footprint projector above is tested but not yet reachable from
any real scene.Pair Paths multi-path strategy pairs paths across children by
centroid + size correspondence and is now the default, replacing the old blob-averaging fallback.1 — free-standing curtains are the look the mode exists for. Ticking Lines as Planes no
longer seeds an Occlusion Bias of 1.5, which was the largest single cause of lines poking through
the curtains in front of them (over a pixel of protrusion). All five shipped Raster-Plane presets
were zeroed to match; the Crater preset went from 925 breakthrough points to none.0, which
means "clip exactly at the silhouette"; the old 0.5 default was the slack that let a
farther row poke through. The slider stays for anyone who wants grazing lines kept whole.
Clipped lines also now end precisely on the border rather than a fraction short of it, so
the fix doesn't trade hooks for gaps. Bars, Mesh and Topography are unchanged.dX/dY chips, a full Stroke Options surface (caps / joins / miter / align / dashed lines), an anchored Pen Picker popover, Simplify / Smooth / anchor path verbs, Outline Text (a Text layer → per-glyph editable paths), and a contextual hint bar with live tool / zoom / rotation readouts. Most of these become one-click actions in the upcoming floating Task Bar; no AI tooling anywhere.penWidth × (1 − overlap), so the fill is gapless at your actual pen size.StrokeFont.weightMetrics) drives both.Vectura.faceNormal now uses Newell's method, so the Star Prism caps (and any concave face) get a correct outward normal instead of an inverted one. Existing solids are byte-for-byte unchanged.sans stroke font, so baselines are unchanged). The picker previews each Google family in its own typeface and each built-in face as an inline stroke sample, with search on both tabs; switching fonts no longer flashes the built-in placeholder before the real outlines arrive. New outline options: an opt-in Bezier Curves toggle that exports native cubic curves (handles nudged to 0/90/180/270°) with a Smoothness control; stroke emphasis via Outline Weight + Thickening Mode (Parallel/Sinusoidal/Snake, shared with Harmonograph/Rainfall); pattern fills of glyph interiors using the full shared fill engine (every fill type, holes carved automatically) for fill-only or filled-and-outlined type; and a Plot Order control that defaults to drawing left-to-right.google:<slug> so it survives save/load. Catalogue and font files load lazily and cache locally; while a family is still downloading the layer shows the built-in stroke font and swaps to the real letterforms when its outlines arrive. The default Text layer still ships on the built-in sans face, so existing presets are unchanged._ui-legacy.js (drained across units 1.5–1.10) and styles.css (drained across units 2.1–2.7) are both deleted. Every var(--color-*) reference under src/ was rewritten to var(--ui-*), the classic-skin alias maps were inlined and the --color-* defaults dropped from components.css, and the data-theme root mirror attribute is gone. New CSS now lands exclusively in src/ui/skin/.sourcePaths.meta.anchors being silently lost through Undo/Redo and .vectura save/load.npm run test:e2e runs.pmg, pgg, cmm, p4g, p3, p3m1, p31m, p6, p6m) were producing partial coverage, double-covered regions, or asymmetric overlaps from misplaced ops or wrong fundamental-domain shapes. All 17 now tile the cell exactly once, verified numerically.<1) or overlap (>1); 1.00 keeps exact tiling. Composes with all 17 groups.p3, p3m1, p4g, p6, and p6m — keeps the corrected v2 as default but recovers the pre-1.1 v1 aesthetic on demand (canonical "alternating triangles" for p3, open spacing for p3m1/p4g, dense overlap for p6/p6m)._ui-legacy.js into its own module at src/ui/panels/mirror-panel.js.package.json is already staged..nojekyll so Jekyll stops stripping _ui-legacy.js.When.* completion factories, multi-phase steps, and a draggable popover (movable: true); content rewritten across all 7 steps.chevron-down glyph with directional rotation._ui-legacy.js across panels, persistence, shell satellites, pens, pane-left, export-svg, modals, shortcuts, and grouping methods (continuation of the Meridian Blue UI architecture refactor).themes-mockup.html. Space Grotesk + JetBrains Mono typography, tighter pane geometry, slider/dial release halos, indeterminate progress bar, and family-scoped petal/pattern designer chrome.npm run skin:new -- <id> scaffolds a new skin from src/ui/skin/_template.css. Full guide at docs/skin-authoring.md. New skins ship with one CSS file + one manifest entry — no JavaScript edits.--ui-muted).motion.css has a matching prefers-reduced-motion: reduce fallback paired with a universal *, *::before, *::after guard.ui.js into ~60 satellite modules under src/ui/{shell,panels,components,overlays,modals,menus,skin} while keeping the legacy class as a thin orchestrator. Renderer's getThemeToken cache supports both --ui-* and legacy --color-* aliases for cross-skin compatibility.Insert > Mirror Modifier).U): drag two endpoints, Shift-snap to 45° increments.Vectura.SvgSanitize.sanitize() strips <script>, <foreignObject>, all on* attributes, and javascript: hrefs.Insert > Mirror Modifier container with a full mirror-axis stack, dashed canvas guide overlays, per-axis show/hide/lock/reorder controls, and mirrored closed-mask silhouette support.Hide Mask Layer..vectura round-trip, Import SVG Tile, live 3×3 seam-validation preview, and Fill/Erase Fill toolbar tools.prefers-reduced-motion, aria-live toasts, modal focus management, visible focus rings, and a minimum 11 px text-size floor.Clip trigger so the clipping-mask popover opens reliably in the saved masking workflow.id/name wiring.Mask controls, mirrored left-panel masking controls, optional hidden mask-parent artwork, and Convert To Geometry materialization into expanded lines.Inner Shape / Outer Shape profile editor cards explicitly clickable selection targets.scale values as fallback zoom.Rings Concentric sampling into a true seam-corrected ring-path field.Center Diameter control for Rings to widen the innermost ring.Top Down, Concentric, and Orbit Field.Invert Color renders as a checkbox.Noise Width sampling so increasing it widens image-based noise fields.Wavetable and other top-left-biased samplers.flowfield, grid, and phylla onto Noise Rack stacks with per-layer engine selection, blends, offsets, and octave shaping.Rings apply-mode semantics for Top Down, Concentric, and Orbit Field.Top Down and Concentric as distinct sampling models.Topo onto the Noise Rack stack while preserving all contour mapping modes.Rings onto the Noise Rack stack with multi-noise layering and per-noise Concentric / Top Down projection.src/config/version.js and npm run version:sync.plans.md and a human-curated CHANGELOG.md.wavetable, spiral, and rainfall.path / anchor / midpoint / endpoint), equal-spacing hint chips, and a hover-highlight of the path under the cursor — all behind the existing guide/snap togglesX / Y position on hover/select (with a pink anchor feature label pinned at the point) and relative dX / dY while dragging — plus a center helper point (blue diamond + center label + X / Y) revealed when hovering any object's center. Both toggle off via Document Setup ▸ Guides & Display (Coordinate readout, Center point)Alt/Option+Click a widget cycles the style (whole selected set when several corners are selected), ↑/↓ cycles it live while dragging with a style-specific cursor glyph, and double-clicking a widget opens a Corners dialog (style + numeric radius). Freeform corners stay live after editing — the widget survives the reshape for re-drags, style switches, and dialing back to square — with a document-units R: drag readout and the max-radius red cue. Styles and live-corner records persist in .vectura filesCmd while dragging overrides snapping)Esc mid-drag cancels with no copy left behind.vectura and emitted on SVG export?; shares the pen list with the docked Pens panelVectura.PathEditOps): scrubbable lossless Simplify preview, Auto-Smooth, one-shot Smooth, and anchor convert / cut / join — with live-shape auto-expand and a "Shape Expanded" toast (these become one-click Task-Bar actions in the next phase)Shift, Alt, Meta, Pan)Transform & Seed sub-panelShift for larger steps)Noise Zoom / Noise Scale values create a larger polygon footprint, and vertical line-displacement systems treat positive amplitudes as upward motionTransform & Seed sub-panel (collapsed by default) exposes seed, position, scale, and rotation. On 3D Scene layers the seed (and RANDOMIZE) now drives every stipple, jitter, dither and wobble site; documents saved before this load as legacy and keep their exact look until you edit the seed or press RANDOMIZE. The Seed and RANDOMIZE grey out with a "No effect for this style" note when no fill in the scene draws random marks (a plain Hatch or Ladder sphere, for example)Reset to Defaults restores full algorithm defaults including transform valuesAlgorithm and Algorithm Configuration⧉) and pop-back-in (↩) action; shape comes from visible inner/outer designer curves with always-on dual-ring controls, a PETAL VISUALIZER (Overlay / Side by Side), a PROFILE EDITOR with an Inner | Outer toggle (one side shown at a time, auto-switching to the side you touch), per-side profile import/export plus shared Export Pair, and matching Shading Stack + Modifier Stack cards where each card has its own Petal Shape target (Inner/Outer/Both)Isometric, Line Gap controls the visible cell spacing and Row Shift shears the whole lattice so the isometric cells stay locked togetherOrbit Field / Concentric / Top Down sampling, and a controllable center diameterNone reset mode, one-shot Apply, and Continuous Apply Changes.vectura.jsonscripts/fetch-paper-textures.jsdocs/pen-models.md)?)… overflow button on the tool rail opens a non-modal All Tools drawer listing every tool grouped by category (Select / Draw / Shapes / Type / Modify / Navigate) with a grid/list view toggle (remembered); clicking a tool activates it, hovering an entry highlights the rail slot it lives inSave/Open full projects via .vectura files; import SVGs as new layersFile → Import 3D Model… reads a .obj or .stl mesh and drops it into the 3D scene compositor as a lit, shaded, selectable object (added to the active scene, or a new scene with sun + ground); the mesh is auto-centred and unit-normalised3x3 repeat, flag seam/fill mismatches before save, save valid custom patterns to the runtime library, and carry those custom patterns inside .vectura project filessrc/config/petal-profiles in both hosted and direct file:// runs via a preloaded library.js bundledocs/touch-audit/device-checklist.md| Dotscreen | Screens an uploaded picture (or the built-in shaded sphere) into a rotatable grid of dots whose size grows with local darkness. Dots are parametric — Circle, Polygon (any side count), Star (any point count), Gear (cog count), Flower (petal count), Cross or Heart. Dot rotation can ramp across the screen along a 360° direction dial by an amount and easing curve; plus Aspect, Jitter, an optional interior Fill (hatch/spiral/dots…), Smart-Edge merging, and brightness/contrast/gamma/invert tone shaping for a plotter-ready halftone |
| Weave | Renders an uploaded picture as parallel lines that waver side to side, with darkness driving both the wave amplitude and frequency (shadows wobble tightly, highlights flatten); a Continuity selector can thread the rows into one boustrophedon stroke or stitch them with ladder connectors on both ends |
| Rainfall | Rain traces with droplet shaping, wind, and silhouette/ground controls |
| Phylla | Phyllotaxis point spirals with Noise Rack-driven organic drift over the golden-angle layout |
| Petalis | Radial petal structures with presets, a visual thumbnail gallery for the 10 petal silhouettes, embedded inner/outer curve designer, dual-ring controls, shading/modifier stacks, and Noise Rack-driven angular drift |
| Spiral | Archimedean spiral with optional closure that loops the outer end back in |
| Shape Pack | Circle/polygon packing with perspective controls |
| Terrain | Realistic terrain heightfield rendered as scanlines under a selectable projection mode — top-down, one-point, two-point, isometric, or a Free 3D orbit (yaw/pitch/roll on the shared 3D engine, with sliders + on-canvas gizmo, hidden-line removal, and the Shading & Lines powers) — with native ridged mountains, V/U valleys, river carving, ocean coastlines, and dial-in style presets |
| Horizon | Synthwave-style perspective grid draped over an opt-in mountain heightfield with center dampening, skyline relief, and an Additional Noises Noise Rack for layered displacement |
| Pattern | Texture-fill layers with a nested-region paint-bucket workflow, library + custom-tile registry, live 3×3 seam validation, and .vectura round-trip for custom imported tiles |
| SVG Distort | Import an SVG path and warp it through field-based distortion controls; integrates with the shared optimization pipeline for plotter-ready output |
| Spirograph | Roulette curves rolling primitive gear shapes around a main primitive, with inside/outside/combined paths |
| Spiralizer | Lines or marker styles (dots, filled points, plusses, crosses, squares, triangles, dashes) coiled around sphere/cone/cylinder/ellipsoid/torus/capsule and a twistable helix shape (2+ twists add DNA base-pair rungs). Markers scatter at mm spacing with a thickness selector, hollow glyphs take a universal fill (spiral, hatch, …), plus front-only or see-through projection, full-shape silhouette outlining, curve smoothing, and orthographic or perspective view |
| Polyhedron | Platonic/Archimedean solids, a swept-profile family (flat polygon, prism, antiprism, bipyramid, cone, frustum, cupola, star prism — all driven by a side count, with taper/star-inset where it applies), or imported STL meshes — face bands, edges, and vertex rings with front-face culling, dashed hidden lines, extrude/explode/twist effects, and orthographic or perspective projection |
| Topoform | Primitive 3D meshes (sphere, torus, cube, cone, ellipsoid, cylinder, capsule, pyramid, superellipsoid, torus knot) or imported STL meshes, rendered as projected wireframes or depth-plane topographic contours — with detail up to 100 on every primitive, bezier contour smoothing, dashed hidden lines, an optional Scene Lighting pass, and orthographic/perspective view |
| Raster-Plane | A height source (built-in relief, preloaded noise, imported image, or hand-painted canvas) projected as line relief, deformed mesh, raster topography, or extruded bars — Bars take a Bar Sides count (3–8) that interlocks gap-free as triangles / squares / hexagons (other counts inscribe a regular polygon in each cell), a Bar Rotate dial to orient the footprints, and a Corner Radius that fillets the bar footprints into rounded columns. Plus a Surface Noise rack stack where each layer's own Blend Mode + Field Weight emboss the surface live, a Base Height lift and a Plane Width slider for "Lines as Planes" (100% = a solid extruded slab, lower widths = free-standing planes with real gaps between rows), See-Through for an x-ray render that dots in whatever the planes hide, clean hidden-line removal on opaque bars, and orthographic or perspective view |
| 3D Scene Studio | A multi-object scene: assemble box / sphere / cylinder / cone / torus / torus-knot / capsule / superellipsoid / pyramid / plane / solids on a shared camera and render them as hidden-line-removed solids with per-object and per-face styling. Select and move / rotate / scale objects (or push-pull box faces) with on-canvas gizmos, and light with a multi-light rig — directional / ambient / point / spot, each draggable via a 3-axis light gizmo, with position-aware shading and perspective ground shadows. Surfaces render light-made tone through per-object/per-face fill mappers (hatch, crosshatch, contour, true Archimedean spiral, stipple, wireframe — each with its own control inventory: hatch angle-reference + boustrophedon linking, Min rulings — the fewest rulings a flat facet may receive when Density asks for fewer, hatch/crosshatch only — contour surface/region, stipple mark shape/size/jitter, wireframe edge-class toggles). Plus controllable cast shadows (angle / density / pen / line type / Softness / per-object cast toggle, with a Layers control — Off / 2 / 3 / 4 — that builds contact, umbra and penumbra zones in stages instead of adding flat ink), selectable highlight treatments (none / blank / dashed / dotted / sparse / altFill / burst / stipple-out), x-ray see-through back-face fills, a per-object border drawn as one contiguous silhouette outline, a shared stroke treatment (line type, hand-drawn wobble, overstroke), a Geometry selector that swaps an object's primitive in place and reveals that shape's own controls, split line output (Object tab Border lines, Style tab Fill lines with its own Curves / Smoothing / Simplify / Fidelity), and Style / Shadow / Highlight / X-ray flyouts on the contextual task bar. Each scene is a layer tree (one object per layer; boolean groups, lights, and ground as their own rows) — build it object-by-object, click the canvas or a tree row to select and edit one object, and saved single-layer scenes migrate to the tree on load (rendering identically) |
| Rename layer | Double-click layer name (touch: double-tap) |
| Make clipping mask | Shift + Drag layer onto another in the layers panel |
| Editing |
| Undo | Cmd/Ctrl+Z |
| Redo | Cmd/Ctrl+Shift+Z |
| Rotate (snap) | Shift + rotate handle |
| Constrain shape | Shift while drawing |
| Draw from center | Alt/Option while drawing |
| Polygon sides | Arrow Up/Down while dragging |
| Pen: close path | Double-click near start point |
| Pen: freeze mirror handle | Alt/Option while dragging a bezier point |
| Pen: commit | Enter |
| Pen: cancel | Esc |
| Reset value to default | Double-click control (touch: hold the label) |
| Save current settings as a preset | Cmd/Ctrl+S (config panel focused, after editing a preset) |
| Cycle wallpaper group within current lattice | Cmd/Ctrl + ← / Cmd/Ctrl + → |
| UI |
| Lights Off (glow-in-the-dark inks emit; view only) | Shift+Alt+L |
| Document Setup | Cmd/Ctrl+K |
| Help / shortcuts | ? |
npm run test:queue:status |
| Shows who holds the shared local test lock and who is waiting |
src/config/ |
| Machine profiles, algorithm defaults, modifier defaults/descriptions, palette library, preset registry |
src/config/petal-profiles/ | Petalis profile library: index.json + .json files + library.js bundle |
tests/ | Unit, integration, e2e smoke, visual baseline, and performance suites |
docs/agentic-harness-strategy.md | Agentic workflow source of truth |
docs/testing.md | Test command details and CI policy |
docs/pre-release-hardening-log.md | Deferred beta hardening ideas tracked for final-release prep |
dist/ | Optional prebuilt output (not required for local dev) |