From ef01b8d2b75f9538fd47c3eccdb19dfde2b2628d Mon Sep 17 00:00:00 2001
From: bertona88
Date: Mon, 27 Jul 2026 20:51:12 +0200
Subject: [PATCH 1/3] feat: add Paper Figure Studio and OpticalSetup bridge
---
.github/workflows/validate.yml | 34 +
.gitignore | 1 +
ACCEPTANCE_TESTS.md | 71 +
CLAIMS_AND_VALIDATION.md | 51 +
INTERFACE_CONTRACT.md | 66 +
PHOTONICS_MODEL_CONTRACT.md | 77 +
README.md | 25 +-
app/.gitignore | 3 +
app/CHANGELOG_PAPER_STUDIO.md | 113 +
app/README.md | 233 ++
app/build_single.py | 51 +
app/docs/PAPER_FIGURE_STUDIO.md | 34 +
app/icon.svg | 6 +
app/index.html | 304 +++
app/integrations/opticalsetup/README.md | 35 +
.../opticalsetup/receiver-adapter.js | 101 +
app/manifest.webmanifest | 20 +
app/src/analysis.js | 661 ++++++
app/src/app.js | 1894 +++++++++++++++++
app/src/bridge.js | 115 +
app/src/circuit.js | 598 ++++++
app/src/complex.js | 93 +
app/src/coupler-view.js | 468 ++++
app/src/export.js | 293 +++
app/src/geometry.js | 139 ++
app/src/models.js | 773 +++++++
app/src/physics.js | 736 +++++++
app/src/plot.js | 271 +++
app/styles.css | 956 +++++++++
app/sw.js | 50 +
app/tests/analysis.test.mjs | 93 +
app/tests/export.test.mjs | 79 +
app/tests/geometry-models.test.mjs | 67 +
app/tests/paper-bridge.test.mjs | 123 ++
app/tests/physics.test.mjs | 39 +
package.json | 6 +
36 files changed, 8676 insertions(+), 3 deletions(-)
create mode 100644 .github/workflows/validate.yml
create mode 100644 ACCEPTANCE_TESTS.md
create mode 100644 CLAIMS_AND_VALIDATION.md
create mode 100644 INTERFACE_CONTRACT.md
create mode 100644 PHOTONICS_MODEL_CONTRACT.md
create mode 100644 app/.gitignore
create mode 100644 app/CHANGELOG_PAPER_STUDIO.md
create mode 100644 app/README.md
create mode 100644 app/build_single.py
create mode 100644 app/docs/PAPER_FIGURE_STUDIO.md
create mode 100644 app/icon.svg
create mode 100644 app/index.html
create mode 100644 app/integrations/opticalsetup/README.md
create mode 100644 app/integrations/opticalsetup/receiver-adapter.js
create mode 100644 app/manifest.webmanifest
create mode 100644 app/src/analysis.js
create mode 100644 app/src/app.js
create mode 100644 app/src/bridge.js
create mode 100644 app/src/circuit.js
create mode 100644 app/src/complex.js
create mode 100644 app/src/coupler-view.js
create mode 100644 app/src/export.js
create mode 100644 app/src/geometry.js
create mode 100644 app/src/models.js
create mode 100644 app/src/physics.js
create mode 100644 app/src/plot.js
create mode 100644 app/styles.css
create mode 100644 app/sw.js
create mode 100644 app/tests/analysis.test.mjs
create mode 100644 app/tests/export.test.mjs
create mode 100644 app/tests/geometry-models.test.mjs
create mode 100644 app/tests/paper-bridge.test.mjs
create mode 100644 app/tests/physics.test.mjs
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
new file mode 100644
index 0000000..f77b30f
--- /dev/null
+++ b/.github/workflows/validate.yml
@@ -0,0 +1,34 @@
+name: Validate successor candidate
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ validate:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 22
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Validate application
+ run: npm run app:validate
+
+ - name: Ensure generated build stays untracked
+ run: test -z "$(git status --short -- app/dist)"
diff --git a/.gitignore b/.gitignore
index 2f083fe..6a15c50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.DS_Store
node_modules/
prototype/node_modules/
+app/dist/
diff --git a/ACCEPTANCE_TESTS.md b/ACCEPTANCE_TESTS.md
new file mode 100644
index 0000000..61d36c5
--- /dev/null
+++ b/ACCEPTANCE_TESTS.md
@@ -0,0 +1,71 @@
+# Acceptance tests
+
+## Automated gate
+
+From the repository root:
+
+```sh
+npm run app:validate
+```
+
+The gate must:
+
+1. parse every `app/src/*.js` runtime module and the OpticalSetup receiver adapter;
+2. pass the complete Node regression suite with no failures;
+3. build `app/dist/PicSetup-Lab-10x-preview.html`;
+4. leave generated `app/dist/` output untracked.
+
+The existing prototype remains independently checkable:
+
+```sh
+npm run prototype:test
+npm run prototype:check
+```
+
+The `prototype/` tree object must be identical to the base commit.
+
+## Required model and graph cases
+
+The automated suite must cover:
+
+- lossless coherent-network conservation and finite residuals;
+- Mach–Zehnder and resonator response over declared sweeps;
+- physical and schematic route-length contracts;
+- hierarchy collapse/expand response preservation;
+- deterministic tuning, tolerance, and pulse fixtures;
+- semantic, SAX, gdsfactory, and S-parameter workflows;
+- typed-domain compatibility and exclusion of non-optical links from the coherent solve;
+- the hybrid paper template's component vocabulary and optical/electrical/RF/control graph;
+- `setup-port/1` encoding, URL, manifest, and receiver round trips;
+- explicit unresolved spatial state at the OpticalSetup boundary.
+
+## Browser acceptance journey
+
+Serve `app/` over HTTP and verify in a current browser:
+
+1. The application loads without runtime errors.
+2. A user can create, connect, move, inspect, save, and reopen a photonic circuit.
+3. Wavelength or phase changes produce complementary MZI output behavior.
+4. Unsupported or disconnected state produces an explicit warning rather than a fabricated result.
+5. Paper Figure Studio opens the included hybrid template.
+6. The template contains a chip figure, OpticalSetup boundaries, RF/electrical/control wiring, instrumentation, plot, image placeholder, panel label, and operating-condition annotation.
+7. Component label placement, metadata visibility, connection labels, offsets, and arrow direction are editable.
+8. SVG export is content cropped and opens as a valid vector document.
+9. PNG export has a white or transparent background as selected and a publication-scale resolution.
+10. Bridge JSON and the bridge manifest identify `setup-port/1`, units, both power references, omissions, source identity, and target URL.
+11. Opening a bridge retains `incomingBridge` and `bridgeSchema=setup-port/1` in the OpticalSetup URL.
+12. No action implies that the external OpticalSetup receiver is already deployed.
+
+## Pull-request acceptance
+
+Before review:
+
+- CI is green on the proposed commit.
+- The diff is confined to the successor application, governing contracts, documentation, scripts, and validation workflow.
+- `prototype/` is unchanged.
+- No generated `dist/`, dependency directory, credential, or machine-specific `/mnt/data` path is committed.
+- The PR description separates implemented behavior from manual browser evidence, external receiver work, merge, and deployment.
+
+## Production acceptance
+
+Merge does not by itself authorize replacement of the public prototype. A production release requires explicit approval, a scoped deployment plan, a live URL/version check, browser smoke on the deployed artifact, and a recorded rollback path.
diff --git a/CLAIMS_AND_VALIDATION.md b/CLAIMS_AND_VALIDATION.md
new file mode 100644
index 0000000..744b914
--- /dev/null
+++ b/CLAIMS_AND_VALIDATION.md
@@ -0,0 +1,51 @@
+# Claims and validation
+
+## Candidate status
+
+The application under `app/` is a greenfield successor candidate. The current public site continues to use the immutable `prototype/` snapshot unless a separately authorized release replaces it.
+
+## Supported claims
+
+Subject to the automated checks and the declared model contract, the candidate may be described as:
+
+- a browser-based semantic PIC and publication-figure workbench;
+- an interactive reduced-order coherent scattering-network simulator;
+- a typed hybrid figure editor whose non-optical domains remain outside the optical solve;
+- a Paper Figure Studio with content-cropped SVG and high-resolution PNG export;
+- a sender and neutral receiver-adapter proposal for the versioned `setup-port/1` OpticalSetup boundary;
+- a dependency-light local application that can produce a standalone HTML build.
+
+The included component models are analytical, imported, pedagogical, or reduced order as their definitions state. Output is suitable for topology exploration, system-level reasoning, teaching, and figure composition within those assumptions.
+
+## Prohibited claims
+
+Without additional primary validation, the candidate must not be described as:
+
+- fabrication ready, mask-layout ready, DRC clean, or foundry qualified;
+- a calibrated predictor of device, thermal, electrical, RF, control, biological, behavioral, operational, or performance outcomes;
+- a full-vector, multimode, polarization-resolved, nonlinear, or full-wave electromagnetic solver;
+- proof that imported S-parameters are passive, causal, correctly referenced, or process valid;
+- a deployed OpticalSetup receiver, live synchronization layer, or coupled PicSetup/OpticalSetup solver;
+- the current production site merely because local tests or a standalone build pass.
+
+## Validation matrix
+
+| Boundary | Evidence | What it establishes | What it does not establish |
+| --- | --- | --- | --- |
+| JavaScript syntax | `npm run app:check` | Runtime and receiver modules parse in Node | Browser behavior or model correctness |
+| Model and interface regression | `npm run app:test` | Declared invariants, exports, typed-domain isolation, template, and bridge round trips | Full browser interaction or external receiver integration |
+| Standalone packaging | `npm run app:build` | Multi-file source can be bundled into one local HTML artifact | Public deployment |
+| Browser smoke | Serve `app/` and exercise the acceptance journey | Current browser loads and primary UI/export actions work | Cross-browser completeness or production acceptance |
+| Prototype preservation | Compare the `prototype/` tree against the base commit | Prior-art snapshot was not modified | Production availability |
+| Pull-request CI | GitHub Actions validation on the proposed commit | Clean-run reproducibility in the hosted runner | Merge, release, DNS, or live-site replacement |
+| Live verification | Inspect the deployed URL and release identity after an authorized deployment | Public artifact and selected smoke behavior are live | Scientific calibration or user acceptance |
+
+## Export claims
+
+Semantic JSON preserves the hybrid graph and bridge manifest. SAX YAML and gdsfactory Python are topology scaffolds restricted to physical optical content; they are not PDK-qualified layouts or substitutes for foundry compact models.
+
+SVG/PNG output is publication-oriented composition. A stylized plot panel is diagram content unless replaced by exported numerical data. Image panels preserve user-supplied imagery but do not validate its provenance or quantitative meaning.
+
+## Reporting results
+
+Validation reports must give exact pass/fail counts, record warnings, and identify skipped manual or external checks. Tests, browser smoke, deployment, OpticalSetup receiver adoption, and public acceptance are separate completion boundaries.
diff --git a/INTERFACE_CONTRACT.md b/INTERFACE_CONTRACT.md
new file mode 100644
index 0000000..5e335f1
--- /dev/null
+++ b/INTERFACE_CONTRACT.md
@@ -0,0 +1,66 @@
+# Interface contract
+
+## Internal semantic graph
+
+The saved PicSetup document is the source of truth for circuit topology, figure composition, component parameters, units, model versions, and provenance.
+
+Components expose typed ports. Connections declare one of:
+
+- `optical`
+- `electrical`
+- `rf`
+- `control`
+- `annotation`
+
+The editor must reject incompatible port/domain combinations. Semantic JSON preserves the complete hybrid graph. SAX- and gdsfactory-oriented handoffs include only physical optical topology and must state that figure-only objects and non-optical links were omitted.
+
+## OpticalSetup bridge: `setup-port/1`
+
+The first cross-setup interface is a deterministic, versioned document handoff between a PicSetup optical boundary and OpticalSetup.
+
+Every payload contains:
+
+- `schema`: exactly `setup-port/1`;
+- a stable bridge ID;
+- source application, document, component ID, and component name;
+- target application and URL;
+- `domain`: exactly `optical`;
+- interface kind and direction;
+- a declared reference frame and orientation;
+- wavelength in nanometres;
+- PicSetup-side and OpticalSetup-side power in milliwatts;
+- an explicit power reference and coupling efficiency;
+- polarization, guided-mode label, boundary phase, and CW/pulsed timing;
+- supported capabilities and explicit omissions;
+- an optional return URL;
+- a creation timestamp.
+
+Allowed directions are `input`, `output`, and `bidirectional`. Supported interface kinds distinguish fiber mode, chip-edge mode, grating/free-space mode, and free-space beam boundaries.
+
+The sender encodes JSON as base64url and opens the target with:
+
+```text
+?incomingBridge=&bridgeSchema=setup-port/1
+```
+
+Base64url is transport encoding, not encryption, authentication, or authorization. Bridge payloads must not contain secrets.
+
+## Power and state boundary
+
+The payload carries both interface-side powers and the coupling efficiency so the reference is inspectable. The receiver must not silently reinterpret one side's power as the other.
+
+PicSetup exports a scalar guided-mode boundary. It does not invent or transfer beam waist, numerical aperture, sampled transverse field, wavefront, or laboratory coordinates. Those properties remain unresolved until OpticalSetup supplies them.
+
+Phase is a declared boundary value in radians. CW/pulsed state includes repetition rate in megahertz and pulse duration in picoseconds only when pulsed. `createdAt` records document handoff time; it is not a shared simulation clock.
+
+## Receiver and ownership
+
+`app/integrations/opticalsetup/receiver-adapter.js` validates and normalizes the payload into a neutral boundary descriptor. It deliberately stops before scene creation.
+
+OpticalSetup must map that descriptor into its own component and scene APIs, choose unresolved spatial state, and review/deploy the receiver in Luca Genchi's repository. PicSetup must not copy OpticalSetup private state or claim receiver deployment based on the sender adapter.
+
+The initial interface is not live synchronization, co-simulation, or a distributed multi-physics solve. Stable bridge identity and a return URL allow later workflows without implying real-time authority.
+
+## Evolution
+
+Incompatible changes require a new schema identifier. Receivers must reject unsupported schema or domain values rather than guessing. Optional extensions must preserve the meaning and units of existing fields and keep unknown state explicit.
diff --git a/PHOTONICS_MODEL_CONTRACT.md b/PHOTONICS_MODEL_CONTRACT.md
new file mode 100644
index 0000000..e4194d1
--- /dev/null
+++ b/PHOTONICS_MODEL_CONTRACT.md
@@ -0,0 +1,77 @@
+# Photonics model contract
+
+## Status and ownership
+
+This contract governs the greenfield candidate under `app/`. It does not describe or modify the immutable production snapshot under `prototype/`.
+
+PicSetup owns guided photonic topology and reduced-order circuit behavior. OpticalSetup owns free-space optical geometry and propagation. ElectricalSetup owns electrical drive and readout dynamics. A typed boundary may exchange declared state between those domains; it does not transfer model ownership.
+
+## State and governing equation
+
+Each modeled optical port carries an incoming complex amplitude `a` and outgoing complex amplitude `b`. Amplitudes are power normalized, so `|a|²` and `|b|²` are optical powers in milliwatts.
+
+Every compact component contributes a wavelength-dependent scattering relation:
+
+```text
+b = S a + s
+```
+
+Waveguide connections contribute the propagation operator `C`. The complete connected optical network is solved simultaneously:
+
+```text
+(I - S C) b = s
+```
+
+The reported linear-system residual and the optical power budget are separate diagnostics. A small algebraic residual is not evidence of a physically complete loss model.
+
+## Units and conventions
+
+- Vacuum wavelength is expressed in nanometres.
+- Geometric and optical path lengths are expressed in micrometres.
+- Optical powers are expressed in milliwatts.
+- Phase values in solver state are radians. Display controls may expose degrees when labeled.
+- A port represents one declared scalar guided mode, TE0-like by default.
+- Component port reference planes are the component connection points represented in the semantic graph.
+- Connection direction and component port roles determine the sign and source/sink interpretation; visual arrow direction alone has no solver authority.
+
+Physical routing numerically integrates the rendered path to obtain geometric length. Schematic routing uses the connection's explicit optical length. The interface must identify which mode is active.
+
+## Solver admission
+
+Only connections whose declared domain is `optical` and whose ports are optically compatible enter `C`.
+
+`electrical`, `rf`, `control`, and `annotation` connections remain part of the semantic document and publication figure, but they do not enter the coherent optical solve. Diagram-only objects never acquire a compact optical model merely because they are visually connected.
+
+The modeled registry includes analytical or imported reduced-order components such as sources, couplers, splitters, phase and amplitude elements, resonators, filters, detectors, crossings, terminations, grating/edge interfaces, delay lines, imported S-parameter blocks, and reducible passive hierarchy. Each definition must declare its ports, parameters, active-model scope, provenance, assumptions, and rendering metadata.
+
+## Power accounting
+
+The solver reports launched, detected, terminated, component-loss, waveguide-loss, and unaccounted power where the selected models expose enough state. Conservation tests use passive, lossless fixtures with declared matched boundaries. Lossy or incomplete circuits must not be described as conservative merely because the numerical residual is small.
+
+## Validity domain
+
+The candidate is an interactive compact-model workbench. It is not:
+
+- a cross-section or full-chip Maxwell solver;
+- a fabrication-ready mask-layout or DRC tool;
+- a calibrated foundry model library;
+- a polarization-resolved or multimode solver unless an imported model explicitly supplies those channels;
+- a nonlinear, thermal-crosstalk, RF, SPICE, PCB, control-system, or full-wave time-domain simulator;
+- proof of passivity, causality, reference-plane correctness, or fabrication validity for user-imported S-parameters.
+
+Pulse analysis reconstructs a linear response from sampled frequency-domain compact models. Detector bandwidth may shape the electrical pulse readout but does not alter the CW optical network.
+
+## Required validation
+
+Changes to the model layer must retain:
+
+- finite complex amplitudes and bounded numerical residuals for supported connected fixtures;
+- lossless passive power conservation within the tolerance recorded in the test;
+- complementary Mach–Zehnder outputs under wavelength or phase variation;
+- physical/schematic route-length semantics;
+- hierarchy collapse/expand response preservation;
+- deterministic seeded tolerance results;
+- isolation of non-optical connection domains from the coherent solve;
+- explicit warnings for invalid, disconnected, unsupported, or numerically problematic states.
+
+Passing these checks validates the declared reduced-order behavior only. It does not establish fabrication accuracy, live deployment, or public acceptance.
diff --git a/README.md b/README.md
index 6e9d381..9edc6ba 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
- **Live prototype:** https://picsetup.com/
- **Prototype release verified:** 2026-07-26 (`20260726T002235Z-478235af2650`); check the URL for current availability
- **Field:** Integrated photonics
-- **Status:** Greenfield planning wrapper with a preserved prototype snapshot
+- **Status:** Greenfield successor candidate with a preserved production prototype
## Vision
@@ -23,7 +23,26 @@ PicSetup is part of the **Setup Universe**: independently deployed scientific an
Read [AGENTS.md](./AGENTS.md) before planning or implementing work.
-The present browser demo should not constrain the next architecture. Before substantial implementation, this repository expects `VISION.md`, `PHOTONICS_MODEL_CONTRACT.md`, `INTERFACE_CONTRACT.md`, `CLAIMS_AND_VALIDATION.md`, and `ACCEPTANCE_TESTS.md`.
+The present browser demo should not constrain the next architecture. The candidate successor is governed by `VISION.md`, `PHOTONICS_MODEL_CONTRACT.md`, `INTERFACE_CONTRACT.md`, `CLAIMS_AND_VALIDATION.md`, and `ACCEPTANCE_TESTS.md`.
+
+## Successor candidate
+
+`app/` contains the dependency-light greenfield workbench candidate. It combines an editable semantic PIC canvas, compact coherent-network analysis, typed cross-domain figure connections, publication SVG/PNG export, and versioned OpticalSetup bridge ports.
+
+Paper Figure Studio can combine simulated photonic objects with diagram-only instruments, RF/electrical/control wiring, plots, image panels, annotations, and chip boundaries without admitting non-optical links into the coherent solve. Its included hybrid template demonstrates the complete figure workflow.
+
+The `setup-port/1` bridge is a deterministic document handoff. PicSetup emits an explicit scalar guided-mode boundary; OpticalSetup retains authority over free-space geometry, beam waist, numerical aperture, wavefront, and receiver-side scene construction. The neutral receiver adapter under `app/integrations/opticalsetup/` is a focused integration proposal, not a deployment to Luca Genchi's repository.
+
+To validate or serve the candidate locally:
+
+```sh
+npm run app:validate
+npm run app:serve
+```
+
+Then open http://127.0.0.1:4174/.
+
+The candidate is not deployed by the current Pages workflow. Acceptance, merge, and replacement of the live prototype remain separate decisions.
## Prototype model boundary
@@ -52,7 +71,7 @@ npm run prototype:serve
Then open http://127.0.0.1:4173/?setup=pic.
-These commands validate only the legacy prototype. This wrapper intentionally has no future-product test suite until the greenfield implementation begins.
+These commands validate only the legacy prototype. The successor has its own tests and build under `app/`; neither suite demonstrates a production deployment.
## Setup Universe
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..68a8c3e
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+*.log
+dist/
diff --git a/app/CHANGELOG_PAPER_STUDIO.md b/app/CHANGELOG_PAPER_STUDIO.md
new file mode 100644
index 0000000..cd42964
--- /dev/null
+++ b/app/CHANGELOG_PAPER_STUDIO.md
@@ -0,0 +1,113 @@
+# PicSetup Paper Figure Studio — implementation notes
+
+## What changed
+
+The uploaded PicSetup Lab source was extended from a compact PIC analysis canvas into a hybrid analysis-and-publication workbench.
+
+### Paper Figure Studio
+
+- Dedicated **Paper** entry point in the top bar.
+- White or transparent paper preview, optional export grid and port markers.
+- Content-cropped SVG export with embedded styles.
+- High-resolution PNG export; the included example exports at 2400 × 1796 px.
+- Editable component-label placement, metadata visibility, X/Y label offsets, and rotation.
+- Editable connection labels, X/Y offsets, and start/end/bidirectional arrows.
+- Background chip boundary, panel letters, annotations, image/micrograph panels, and stylized plot panels.
+- Included **Hybrid PIC paper figure** template combining a PIC, OpticalSetup boundaries, RF/electrical/control wiring, instrumentation, plot, micrograph placeholder, and operating-condition callout.
+
+### New photonic and system vocabulary
+
+New compact or interface elements include:
+
+- edge coupler;
+- OpticalSetup bridge port;
+- spiral delay line;
+- four-channel AWG;
+- thermo-optic heater with an electrical control terminal.
+
+New publication/system elements include:
+
+- fiber array;
+- polarization controller;
+- optical instrument;
+- RF source;
+- electrical amplifier/TIA;
+- oscilloscope;
+- controller;
+- generic laser/receiver/driver/processor/sample system block;
+- chip boundary;
+- image panel;
+- plot panel;
+- text annotation;
+- panel label.
+
+### Typed graph and solver boundary
+
+Connections now have explicit `optical`, `electrical`, `rf`, `control`, or `annotation` domains. Ports are checked for compatibility. Only optical links enter the coherent scattering solve; the other domains remain editable and exportable without being misinterpreted as waveguides.
+
+The semantic netlist preserves the full hybrid figure graph. SAX and gdsfactory handoffs intentionally contain only physical optical topology.
+
+### OpticalSetup bridge
+
+PicSetup now emits the versioned `setup-port/1` contract. A bridge records:
+
+- stable bridge identity;
+- source document/component and target application;
+- interface direction and physical kind;
+- wavelength;
+- PicSetup-side and OpticalSetup-side powers with an explicit power reference;
+- coupling efficiency;
+- polarization and guided mode;
+- boundary phase;
+- CW/pulsed state, repetition rate, and pulse duration;
+- capabilities, omissions, reference frame, and return URL.
+
+Opening a bridge launches:
+
+```text
+https://opticalsetup.com/sketch/?incomingBridge=&bridgeSchema=setup-port/1
+```
+
+The source also includes a framework-independent receiver parser at:
+
+```text
+integrations/opticalsetup/receiver-adapter.js
+```
+
+That adapter validates and normalizes the handoff without inventing beam waist, NA, wavefront, or laboratory coordinates. OpticalSetup still needs to map the normalized descriptor into its own scene/component creation API and deploy that receiver. The current integration is a deterministic document handoff, not live synchronization or a distributed multi-physics solve.
+
+## Validation
+
+- JavaScript syntax checks passed for every runtime and receiver-adapter module.
+- Full Node regression suite: **19/19 passed**.
+- Browser smoke test passed for:
+ - loading the 19-object / 14-link hybrid template;
+ - connection figure controls;
+ - component figure controls;
+ - OpticalSetup bridge actions;
+ - Paper Figure Studio;
+ - SVG export;
+ - PNG export;
+ - bridge-manifest export;
+ - generated OpticalSetup URL and query payload.
+- No browser runtime errors were produced in the smoke run. The only warnings came from intentionally loading the standalone file in a null-origin test page, where `localStorage` is unavailable; normal HTTP serving avoids that condition.
+
+## Run
+
+```bash
+python -m http.server 8000
+```
+
+Open `http://localhost:8000`.
+
+Rebuild the portable one-file version with:
+
+```bash
+python build_single.py
+```
+
+Run tests with:
+
+```bash
+node --test tests/*.test.mjs
+```
diff --git a/app/README.md b/app/README.md
new file mode 100644
index 0000000..fa7530a
--- /dev/null
+++ b/app/README.md
@@ -0,0 +1,233 @@
+# PicSetup — PIC analysis and publication-figure workbench
+
+PicSetup is a dependency-light, mobile-first environment for integrated photonics. It combines an editable semantic PIC canvas, a simultaneous complex scattering solver, an interactive analysis Lab, reusable hierarchy, and a **Paper Figure Studio** for building the system-level figures commonly used in papers: a chip schematic connected to external optics, RF/electrical instrumentation, control blocks, plots, micrographs, labels, and operating-condition callouts.
+
+The product boundary is deliberate. PicSetup owns guided-wave photonic topology and compact models. Free-space laboratory optics remain the domain of [OpticalSetup](https://opticalsetup.com/sketch/), connected through explicit, versioned optical bridge ports rather than by pretending that every domain uses one solver.
+
+Everything runs in the browser. A backend is not required.
+
+## Run locally
+
+Serve this directory with any static web server:
+
+```bash
+python -m http.server 8000
+```
+
+Open `http://localhost:8000`.
+
+Build the completely self-contained preview:
+
+```bash
+python build_single.py
+```
+
+The portable build is written to `dist/PicSetup-Lab-10x-preview.html`. The multi-file application remains the preferred form for development and PWA installation.
+
+## Primary workflows
+
+### Circuit analysis
+
+1. Build or open a PIC on the canvas.
+2. Pin a detector, optical probe, port, waveguide, or circuit-level measurement.
+3. Open **PicSetup Lab**.
+4. Sweep an active optical parameter, tune selected knobs toward a target, run tolerance analysis, or reconstruct a linear pulse response.
+5. Apply an operating point back to the live circuit, preserve a baseline, or export the semantic state for another tool.
+
+### Paper figures
+
+1. Open **Paper** and load the included **Hybrid PIC paper figure** template, or add figure elements to an existing circuit.
+2. Combine simulated PIC components with diagram-only instruments, system blocks, typed links, panel letters, text, plots, and image panels.
+3. Edit component-label placement, metadata visibility, connection labels, direction arrows, panel dimensions, and the figure background.
+4. Export a cropped publication SVG or high-resolution PNG. Semantic JSON remains available when the figure must stay editable.
+
+## What is implemented
+
+### Semantic circuit canvas
+
+- Touch, pen, mouse, keyboard, and mobile-first interaction.
+- Component placement, direct dragging, freehand waveguide routing, undo/redo, deletion, local save, autosave, JSON import/export, and URL sharing.
+- Pinch/wheel zoom, pan, fit, component focus, larger invisible touch targets, and semantic zoom that reveals detail progressively.
+- Explicit **Physical** and **Schematic** routing modes.
+ - Physical: the rendered cubic curve is numerically integrated and used as optical length.
+ - Schematic: the drawing is visual and each waveguide owns an explicit optical length.
+- Optional physical snap grid, micrometre scale, exact route length, phase, minimum-curvature radius, and user-declared bend-radius validation.
+- Solid single-color CW illumination, optional nonphysical direction tracers, and pulse-envelope packets whose length and spacing are controlled separately.
+
+### Compact-model circuit engine
+
+Every optical port carries incoming and outgoing complex, power-normalized modal amplitudes:
+
+```text
+b = S a + s
+```
+
+Waveguides form the wavelength-dependent connection operator `C`, and the complete optical circuit is solved simultaneously:
+
+```text
+(I - S C) b = s
+```
+
+The coherent model registry includes:
+
+- laser source, photodetector, non-perturbing optical probe, and matched termination;
+- phase shifter, electro-optic modulator, thermo-optic heater, and attenuator;
+- directional coupler, 2×2 MMI, Y splitter, and waveguide crossing;
+- add-drop ring, Bragg filter, arrayed waveguide grating, and spiral delay line;
+- grating coupler, edge coupler, and OpticalSetup bridge boundary;
+- wavelength-indexed generic complex S-parameter block;
+- hierarchical block reduced live from a stored passive subcircuit.
+
+Each simulated definition owns its ports, parameters, active-model scope, provenance, assumptions, compact scattering model, rendering metadata, and inspector contract.
+
+### Paper Figure Studio
+
+Paper Figure Studio adds a publication-composition layer without weakening the physics boundary.
+
+- White or transparent paper canvas, optional grid and port visibility, content-aware export crop, SVG export, and high-resolution PNG export.
+- Resizable chip boundary with background layering.
+- Panel letters, free text annotations, operating-condition callouts, and movable/hideable component metadata.
+- Configurable connection labels, label offsets, and start/end/bidirectional arrows.
+- Image panels for local optical micrographs, SEMs, photographs, or renderings, with contain/crop controls.
+- Stylized plot panels for figure composition; real numerical traces should still be exported from PicSetup Lab.
+- External figure vocabulary including fiber arrays, polarization controllers, optical instruments, RF generators, amplifiers/TIAs, oscilloscopes, controllers, and generic laser/receiver/driver/processor/sample blocks.
+- Included hybrid template combining free-space/fiber handoffs, a PIC transmitter/receiver, RF drive, thermal bias, photocurrent readout, control, a plot, a micrograph placeholder, and paper annotations.
+
+Diagram-only figure objects are declared as such, excluded from hierarchy reduction, and never silently substituted for a compact optical model.
+
+### Typed cross-domain graph
+
+Connections carry a declared domain:
+
+- `optical` — guided/fiber/free-space optical boundary links;
+- `electrical` — voltage/current/readout wiring;
+- `rf` — RF/coax drive links;
+- `control` — logical control and automation;
+- `annotation` — explanatory figure relationships.
+
+Port compatibility is checked while wiring. Only optical links enter the coherent network solve. Electrical, RF, control, and annotation links remain editable, inspectable, and exportable, but cannot accidentally become optical waveguides.
+
+### OpticalSetup bridge ports
+
+The **OpticalSetup port** is a real typed boundary, not a decorative hyperlink. It supports:
+
+- OpticalSetup → PicSetup, PicSetup → OpticalSetup, or bidirectional direction;
+- free-space, fiber, chip-edge, or vertical-grating interface kind;
+- wavelength, explicitly referenced power on both sides of the interface, coupling efficiency, polarization, guided mode, boundary phase, and CW/pulsed timing;
+- bridge ID, target OpticalSetup URL, return URL, capabilities, and explicit omissions.
+
+PicSetup serializes the handoff as the versioned `setup-port/1` contract and opens the target editor with:
+
+```text
+?incomingBridge=&bridgeSchema=setup-port/1
+```
+
+It can also copy or download the bridge JSON and export a manifest containing every OpticalSetup bridge in the figure.
+
+**Integration boundary:** this source completes the PicSetup sender/exporter side. The live OpticalSetup editor must add an `incomingBridge` adapter before the URL automatically creates a corresponding fiber/free-space boundary object. Until that receiver is deployed, the target opens with the complete payload preserved in the URL; this is not live synchronization or a distributed multi-physics solve.
+
+### Trust and diagnostics
+
+- Solver residual is reported separately from optical power accounting.
+- Power budget distinguishes launched, detected, terminated, component loss, waveguide loss, and unaccounted power.
+- Model warnings identify invalid parameters, unsupported operating conditions, and optional bend-radius violations.
+- Inspector fields state whether a parameter is active in CW, pulse, electrical, global, visual, or diagram-only scope.
+- Parameter links keep compatible knobs synchronized during direct edits, sweeps, tuning, and tolerance runs.
+- No hidden geometry substitution: grouping, rendering, and solving preserve declared optical-length contracts.
+
+### PicSetup Lab
+
+#### Sweep
+
+- Sweep wavelength or any active CW compact-model/waveguide parameter.
+- Plot multiple pinned measurements simultaneously.
+- Inspect a live operating-point cursor and apply it back to the circuit.
+- Save baseline traces and export CSV.
+- Derive maximum/minimum transmission, insertion loss, extinction ratio, 3 dB bandwidth, free spectral range, phase excursion, and group delay where the data support them.
+- Compare paired outputs through imbalance and contrast metrics.
+
+#### Tune
+
+- Maximize, minimize, or target a pinned measurement.
+- Select one to four compatible design knobs.
+- Add a wavelength robustness window so tuning optimizes more than a single nominal point.
+- Preview the proposed circuit and explicitly apply it to the canvas.
+
+#### Tolerance
+
+- Seeded Monte Carlo analysis with absolute or relative Gaussian variation.
+- Yield against a threshold and criterion.
+- Distribution histogram, best/worst sampled results, deterministic ±3σ corner search, and correlation-based sensitivity ranking.
+- Click a sensitivity result to highlight the responsible component or route.
+
+#### Pulse
+
+For a linear circuit, PicSetup builds a transform-limited Gaussian source spectrum, solves the complex transfer function over frequency, reconstructs the temporal optical envelope, and applies detector bandwidth to produce an electrical response. It reports delay, output pulse width, peak transmission, and repetition period.
+
+This is spectral compact-model reconstruction—not nonlinear propagation or a full-wave time-domain field solve.
+
+### Hierarchy and reuse
+
+- Multi-select passive optical components and collapse them into a reusable external scattering block.
+- Expand the block back into its internal graph.
+- Preserve circuit response across collapse and expansion, including boundary optical lengths.
+- Export a block as semantic JSON.
+- Non-optical links and publication-only objects are rejected from compact optical hierarchy rather than being dropped silently.
+- Included templates: hybrid PIC paper figure, Mach–Zehnder interferometer, add-drop ring, delay interferometer, and filter bank.
+
+### Workflow exports
+
+- Portable PicSetup experiment JSON.
+- Semantic netlist JSON with model provenance, assumptions, parameters, typed ports, endpoints, hierarchy, links, domain counts, figure-object counts, and bridge manifest.
+- SAX-oriented YAML scaffold containing only physical optical topology.
+- Starter gdsfactory Python topology containing only physical optical topology.
+- Complex S-parameter import from JSON or CSV.
+- Auto-layout for imported semantic netlists.
+
+The SAX and gdsfactory outputs deliberately omit figure-only objects and non-optical wiring. They are handoff scaffolds, not a PDK-qualified layout, DRC-clean routing solution, or substitute for foundry compact models.
+
+## Architecture
+
+```text
+src/models.js simulated and diagram-only component/port registry
+src/physics.js typed network assembly, route contracts, templates, hierarchy
+src/bridge.js setup-port/1 OpticalSetup payloads, URLs, and manifests
+src/geometry.js shared cubic paths, adaptive length, curvature/radius
+src/analysis.js measurements, sweeps, metrics, tuning, tolerances, pulses
+src/plot.js interactive Canvas Lab plots
+src/export.js semantic/SAX/gdsfactory/S-parameter workflow exports
+src/circuit.js SVG renderer, paper layers, typed links, semantic zoom
+src/coupler-view.js progressive local directional-coupler physics views
+src/app.js interaction state, inspectors, Paper Studio, persistence/PWA
+integrations/opticalsetup/ receiver parser and neutral boundary adapter
+```
+
+The application has no runtime package dependency. Browser modules are kept separate during development and converted to Blob-backed modules by `build_single.py` for the one-file preview.
+
+## Declared physics and integration limits
+
+- One scalar TE₀-like optical channel per declared port unless an imported model defines otherwise.
+- Compact circuit models, not a cross-section or full-chip Maxwell solve.
+- Directional-coupler local field views use compact transverse profiles and visibly magnify the carrier oscillation.
+- Default compact models are analytical approximations intended for topology and system-level reasoning; provenance is shown in the inspector.
+- Bend radius is validated only when the user supplies a minimum. PicSetup does not invent bend loss from an unspecified process stack.
+- Detector bandwidth acts in pulse/electrical analysis; it does not alter the CW optical network.
+- Pulse reconstruction assumes a linear time-invariant circuit over the sampled spectrum.
+- Imported S-parameter quality, passivity, causality, and reference-plane correctness remain the user’s responsibility.
+- Figure-only electrical/RF/control blocks are not SPICE, RF, PCB, or control-system simulations.
+- The OpticalSetup bridge exchanges a typed boundary state; it does not transfer a transverse field, automatically infer beam waist/NA/wavefront, or synchronize two solvers in real time.
+- Large embedded images are best shared through JSON/SVG or the source file rather than very long URL fragments.
+
+## Tests
+
+Run the complete test suite:
+
+```bash
+node --test tests/*.test.mjs
+```
+
+The suite covers complex-network conservation and residuals, exact rendered/model route length, curvature, physical/schematic routing, component registry dimensions, hierarchy response preservation, MZI and ring sweeps, phase/group-delay metrics, linked parameters, target tuning, deterministic Monte Carlo and corners, pulse reconstruction, semantic/SAX/gdsfactory exports, S-parameter import, auto-layout, typed-domain solver isolation, the hybrid paper template, and `setup-port/1` bridge round trips.
+
+## PWA
+
+When served over HTTP(S), the service worker caches the application shell and all source modules—including `src/bridge.js`—for offline reuse. Installability depends on normal browser PWA requirements and origin security rules.
diff --git a/app/build_single.py b/app/build_single.py
new file mode 100644
index 0000000..c79c8f4
--- /dev/null
+++ b/app/build_single.py
@@ -0,0 +1,51 @@
+from pathlib import Path
+import json, re
+
+root = Path(__file__).resolve().parent
+html = (root / 'index.html').read_text()
+css = (root / 'styles.css').read_text()
+order = ['complex', 'geometry', 'models', 'physics', 'bridge', 'analysis', 'plot', 'export', 'circuit', 'coupler-view', 'app']
+mods = {name: (root / 'src' / f'{name}.js').read_text() for name in order}
+
+html = re.sub(r'\s*]*>', '', html)
+html = re.sub(r'\s*]*>', '', html)
+html = html.replace(' ', f' ')
+html = html.replace(' ', '')
+source_json = json.dumps(mods, ensure_ascii=False).replace('', '<\\/script>')
+
+# Create module Blob URLs in dependency order and replace each static relative import
+# with the generated URL before the dependent Blob is created.
+bootstrap = f''' '''
+html = html.replace('
+
+
+
+
+ PicSetup
+ Untitled experiment
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Converged0.0 ms
+
+
+
+
+
+
+
+
+
Begin with a sourcePlace components, then draw between compatible ports.
Component libraryAnalytical, measured, or imported compact models
+
+
+
+
+
+
+
+
+
∿
PicSetup LabMeasure across the design space
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
', bootstrap + '\n')
+dist = root / 'dist'
+dist.mkdir(exist_ok=True)
+out = dist / 'PicSetup-Lab-10x-preview.html'
+out.write_text(html)
+
+print(out, out.stat().st_size)
diff --git a/app/docs/PAPER_FIGURE_STUDIO.md b/app/docs/PAPER_FIGURE_STUDIO.md
new file mode 100644
index 0000000..4380ba6
--- /dev/null
+++ b/app/docs/PAPER_FIGURE_STUDIO.md
@@ -0,0 +1,34 @@
+# Paper Figure Studio and OpticalSetup bridges
+
+## Why this layer exists
+
+PIC papers often combine several visual domains in one figure: the on-chip circuit, free-space or fiber coupling, electrical/RF drive and readout, control software, plots, and microscope/SEM panels. PicSetup now represents that complete composition while preserving a strict boundary between simulation and illustration.
+
+## Simulated versus diagram-only objects
+
+Simulated photonic objects participate in the coherent compact-model network. Diagram-only objects carry typed ports and publication metadata, render and export normally, but do not enter the optical solver. This prevents an RF cable, controller, image panel, or generic instrument from silently becoming a waveguide.
+
+## Figure workflow
+
+1. Open **Paper** from the top bar.
+2. Load **Hybrid PIC paper figure**, or add elements from the component library.
+3. Select a component to edit its figure label, label placement, metadata visibility, offsets, and rotation.
+4. Select a typed connection to edit its label, direction arrow, and label offsets.
+5. Attach a local image to a micrograph/image panel from its inspector.
+6. Export a cropped SVG or high-resolution PNG.
+
+The plot panel is a composition placeholder. Quantitative plots should be exported from PicSetup Lab and inserted as images or reconstructed downstream.
+
+## OpticalSetup handoff
+
+An OpticalSetup port emits `setup-port/1`, containing:
+
+- stable bridge ID and source document/component identity;
+- target application and return URL;
+- direction and physical interface kind;
+- wavelength, explicit PicSetup-side and OpticalSetup-side powers, coupling efficiency, polarization, guided mode, phase, and CW/pulsed timing;
+- supported capabilities and unsupported properties.
+
+The URL uses `incomingBridge` plus `bridgeSchema`. The companion receiver parser is in `integrations/opticalsetup/receiver-adapter.js`.
+
+The contract is intentionally narrower than a universal simulator. PicSetup owns the scalar guided-mode boundary. OpticalSetup owns beam waist, numerical aperture, wavefront, spatial coordinates, and free-space propagation.
diff --git a/app/icon.svg b/app/icon.svg
new file mode 100644
index 0000000..f9afcd2
--- /dev/null
+++ b/app/icon.svg
@@ -0,0 +1,6 @@
+
diff --git a/app/index.html b/app/index.html
new file mode 100644
index 0000000..b8e9eed
--- /dev/null
+++ b/app/index.html
@@ -0,0 +1,304 @@
+
+
+