{"tool":"CircadianLab","what":"Browser photometric calculator for circadian (mel-EDI), illuminance (lux/fc), and glare (UGR). This API lets an AI build, score, optimize, and view rooms.","mcp":{"package":"@innerscene/circadian-lab-mcp","install":{"claudeCode":"claude mcp add circadian-lab -- npx -y @innerscene/circadian-lab-mcp","config":{"command":"npx","args":["-y","@innerscene/circadian-lab-mcp"]}},"tools":["score_room","optimize_room","create_design","render_scene","search_fixtures","lookup_fixture","get_design_reference"],"note":"MCP-capable clients can use this API as typed native tools instead of raw HTTP. render_scene returns the scene PNG as an image block the assistant can see. Convenience: a customFixtures entry may reference a library fixture as {\"iesId\": \"<variantId from search_fixtures>\"} and the MCP server fetches + injects the IES text before calling the API. Requires Node 18+; set CIRCADIAN_LAB_BASE_URL to target another host."},"coordinates":"Origin at SW floor corner. X=east(width), Y=north(depth), Z=up(height).","schema":{"id":"circadian-lab/room@1","units":"\"ft\" (default) or \"m\" — applies to all lengths and x/y/z.","room":"{ width, depth, height, reflectance?: { walls, floor, ceiling } }. Non-rectangular: give room.polygon ([[x,y],…], ≥3 pts) or room.walls ([{x1,y1,x2,y2,height?}]) instead of width/depth — each edge becomes a full-height wall and the bounding box is the room (width/depth derived if omitted; any coordinate origin is fine).","fixtures":"Array of { preset, x, y, z?, cct?, dim?, rotation?, tilt?, aimAzimuth? } (ceiling) OR { preset, wall, along?, height?|heightFromCeiling?, orientation?, count?, cct?, dim? } (wall-mounted, see wallMounting) OR { preset, regress, ... } (lay-in / drywall deep regress, see layinMounting) OR { preset, count, ... } to auto-grid. Or a single { preset, count } object.","customFixtures":"Array of { iesContent|iesHash, cct, sourceType|customDER, x, y, z?, lumens?, dim?, width?, depth?, rotation?, tilt?, aimAzimuth?, wall?, along?, height?, heightFromCeiling?, orientation? } for fixtures not in the preset library. NOTE: IES files carry no CCT — you must supply cct (and sourceType or customDER) or the circadian dose will be wrong.","aiming":"rotation (deg) spins a fixture about its own aim axis (orient a rectangular fixture, or turn an asymmetric IES pattern) — it does NOT tilt the beam. tilt (deg, 0-180) swings the whole beam off vertical: 0 = straight down, 90 = horizontal, 180 = straight UP (uplight / cove that washes the ceiling for soft indirect light). aimAzimuth (deg) is the compass bearing the tilt points toward: 0 = north (+Y), 90 = east (+X), 180 = south, 270 = west (same sense as occupant facing); only used when tilt>0. A fixture at the default ceiling height is flush-recessed, so upward light is clipped — fine for washing DOWN a wall; for an uplight/cove drop z below the ceiling (e.g. ceiling-0.3) so the upward light reaches the ceiling and bounces down. Aiming light sideways often RAISES UGR (more luminance in view, dimmer room) — verify with /score, do not assume it lowers glare.","wallMounting":"Add a \"wall\" field to a fixture (instead of x/y) to mount it flush on that wall, emitting horizontally into the room. In this form Circadian Sky reads as a backlit sky WINDOW (a standing-height window or a clerestory band). Fields: wall = \"south|east|north|west\" (or 0-3; south=Y0, north=Y-depth, west=X0, east=X-width); along = 0-1 position along the wall (default 0.5); height = center above floor (units), OR heightFromCeiling = center below ceiling (for a clerestory); orientation = \"landscape\"(default)|\"portrait\" (tall window); count = a row of N evenly along the wall. Aim is automatically the wall inward normal. WARNING: a wall window is in the occupants field of view — it gives strong vertical mel-EDI but can push UGR high (a standing-height window in front of someone can read UGR>30). Mount high (clerestory), keep it off walls people face head-on, dim it, and ALWAYS check UGR with /score.","layinMounting":"Add a \"regress\" field (a depth, room units) to a Circadian Sky fixture to make it a LAY-IN (drywall deep regress) install: the panel lays into a drywall coffer from above, its luminous window sitting `regress` above the finished ceiling, seen through an opening — it reads as a true architectural skylight instead of a flush troffer. The engine builds REAL coffer geometry (ceiling aperture + white bounce walls): high-angle light is progressively cut off (full output at nadir, hard cutoff at ~atan(window/regress) off vertical) and the clipped light bounces back out via radiosity. Fields: regress = coffer depth in units (typical 4in = 0.33 ft / 0.1 m = 2x4 flat framing + finish; clamped 0.5-24in / 0.013-0.6 m; deeper = softer, more skylight-like, stronger cutoff); regressOpening = \"glass\" (default: the drywall opening is flush with the luminous window, concealing the trim — the install-manual detail) | \"trim\" (opening at the trim/housing edge); regressWall = coffer wall (framing+finish) thickness in units (default 2in nominal; VISUAL ONLY, never changes the calc); count = a butted row of N forming ONE continuous slot (fixtures end-to-end; trims within 1/8in merge into a shared coffer — the six-fixture CS12 array install), centered at x/y; axis = \"x\"(default)|\"y\" run direction; rotation snapped to 90deg steps (coffers are framed square); x/y/cct/dim as ceiling fixtures; z and tilt are IGNORED (window sits at ceiling+regress, aimed straight down). PHOTOMETRIC TRADE (always verify with /score): UGR DROPS for oblique observers (the window vanishes from view at shallow angles — usually the point), but vertical eye-level mel-EDI ALSO DROPS vs the same panel flush, because near-horizontal light is what reaches standing eyes; directly underneath is nearly unchanged. 4in regress is mild; 8-12in is a strong architectural effect with a real dose penalty — compensate with output/count/CCT and re-score. Placement: butt exactly (use count, or centers one footprint apart — within 1/8in reads continuous, no wall built between) or keep slots clearly separate; in-between gaps build unbuildably thin drywall strips. Lay-in adds real surfaces, so calcs run somewhat slower than flush — normal.","coveMounting":"Add a \"cove\" field (a wall name, instead of x/y) to make a fixture an indirect COVE / uplight: a linear LED strip run along that wall, near the ceiling, aimed UP. The engine bounces it off the ceiling (radiosity) so the whole ceiling glows as a soft, low-glare sky — the most comfortable way to light someone lying down looking up (a patient), since no bright source is in the upward view. Fields: cove = \"south|east|north|west\" (or 0-3); lmPerFt = strip output per foot (default 250; indirect needs 300-500 for a good dose); cct = strip colour, CAPPED at 6500 (a cove is a real LED strip; no strip exceeds ~6500K); sourceType stays standard_led (do NOT use circadian_sky on a cove — Innerscene makes sky panels, not strips); coveDepth = drop below the ceiling (default ~0.25m, must be >0; deeper = lower glare, flat output); shelfWidth (ledge, ~0.15m optimal, wider does not add output); fasciaHeight (front lip; just tall enough to hide the strip, taller cuts output); along/length = a segment (default full wall); iesContent = override the strip distribution. Priced per foot (a strip), not per panel. The glowing ceiling is counted as a glare source, so UGR is real (low, not zero). Put a cove on two opposite walls for an even wash. DESIGN HINTS (patient / lying-down, verify in direction:\"horizontal\"): position beats brightness — overhead panels read UGR 30+ looking up even at the right dose, so move the source out of the upward gaze (cove, headwall, or footwall). A real-strip cove alone reaches only ~117 mel-EDI (capped at 6500K); the best patient design is a HYBRID — real-strip cove + a heavily-dimmed Circadian Sky panel to top the dose to 250 (~254 mel-EDI at UGR ~8). Counter-intuitive: at a fixed dose, mount that added panel LOW near the head (dimmed) not high/clerestory — glare scales with luminance^2, so a close panel meets the dose while barely on and reads lower glare than a far bright one. Footwall is the lowest-glare spot (forward gaze, like a wall TV) but usually holds the door, so a low dimmed headwall panel is the practical pick.","occupants":"Array of { x, y, facing?: north|east|south|west, posture?: sitting|standing|laying, recline?: 0-90 }. Measurement points; mel-EDI is read vertically in the facing direction. recline is the bed / Fowler angle for a LAYING occupant: 0 = flat on the back (gaze up), 45 = semi-Fowler, 90 = sitting upright (gaze horizontal toward `facing`, i.e. toward the foot of the bed); the eye rises off the mattress and shifts toward the feet as it raises, and mel-EDI + glare are read at that reclined eye/gaze. Bed position changes both glare (overhead sources are worst flat, gone when sitting up) and circadian dose (highest lying flat, falls as they sit up and face away — most designs drop well under 250 mel-EDI upright), so evaluate a patient at recline 0/45/90 and report the worst case.","furniture":"Array of { x, y, width, depth, height?, rotation? } (desks).","partitions":"Array of { x1, y1, x2, y2, height?, baseHeight? } (interior walls).","windows":"Array of real daylight apertures: { wall: \"south|east|north|west|ceiling\", width, height, sill?, along?|xLeft?, glazing? }. wall \"ceiling\" = a skylight (width=X-extent, height=Y-extent). sill = bottom-edge height above floor (default ~0.9m). along = 0-1 position along the wall (default centered). glazing = \"clear|double|low_e|frosted\" or explicit {transmittance,reflectance,diffusion}. Default clear.","daylight":"Sun + sky scene: { lat, lon, date:\"YYYY-MM-DD\", time?:\"HH:MM\", tz?, utc?, sky?:\"clear|intermediate|overcast\", orientation? }. Requires lat+lon and a date (or a utc instant). tz (IANA) gives exact civil time; without it the offset is approximated from longitude. orientation = building rotation deg (0 = south wall faces geographic south). See daylightNote.","daylightNote":"Windows + daylight are solved in the SAME radiosity pass as electric fixtures — direct sun + diffuse sky + bounce are added to every point, and daylight (treated ~6500K) contributes strongly to mel-EDI. Daylight only enters through apertures, so a daylight scene does nothing without a window/skylight. To evaluate TIMES OF DAY / YEAR: keep the room fixed and re-score with different daylight.time and daylight.date (e.g. 9/12/15h x Jun21/Dec21, plus an overcast case). Orientation matters: a south window takes strong direct sun (low winter sun drives the most vertical light + glare); north is soft/diffuse; east/west spike at sunrise/sunset; a skylight is even overhead with least glare. Direct-sun points can read tens of thousands of lux/mel-EDI at the glazing — check UGR.","targets":"{ deskFc?, melEDI?, ugr? } — desk footcandles (>=), vertical mel-EDI facing (>=), and UGR (<). Used by /score and required by /optimize.","view":"{ mode: 2d|3d, metric: eml|illuminance|ugr, direction, units, heatmap?, contours? }. heatmap + contours default ON. Do NOT add \"values\" — the per-cell number overlay is dense and noisy and is off by default. Only include values:true if the user explicitly asks for the exact number printed on every grid cell; otherwise omit the field entirely."},"modeling":{"oneRoomPerModel":"A room JSON models exactly ONE room. Do NOT wrap multiple rooms in a JSON array — /import, /score and /optimize take a single room object and reject an array (error: \"Provide room.width & room.depth...\"). For a multi-room floor, emit a SEPARATE room JSON (and a separate link) per room, and tell the user each opens on its own.","dontInventGeometry":"Model only the space the user asks for, from the geometry actually shown or stated — do NOT invent interior walls, partitions, or split an open area into separate enclosed rooms that are not in the plan. On a reflected ceiling plan a 2x2/2x4 ceiling grid or a fixture layout is NOT a wall; only solid wall linework (or a dimensioned enclosure) is. If a space reads as open plan, model it as one open room with NO partitions[]. If it is genuinely unclear whether a space is enclosed, ask, or model it open and say so. Add partitions[] only where the plan clearly shows full-height walls or the user requests them.","buildablePlacement":"Every design is validated before a share is returned: /score, /optimize and /import REJECT a layout (HTTP 400, kind:\"PlacementError\") if any two ceiling fixtures overlap, or a fixture footprint hangs past a wall (or above the ceiling / below the floor). This usually means the fixtures do not fit the room — e.g. too high a count for a small room, or the room dimensions are wrong (a common bug: describing a normal room but emitting tiny width/depth, or the wrong units). Fix it by enlarging the room, lowering the count, or choosing a smaller fixture; then re-submit. Sanity-check dimensions before importing: a real room is metres/many-feet across with a ~2.4-3 m (8-10 ft) ceiling, and each panel is ~0.3-1.2 m wide, so N panels need at least N times their footprint of ceiling. /optimize never returns an overlapping layout — if the room is too small it returns ok:false with a \"too small\" reason."},"presets":[{"id":"CS12","name":"Circadian Sky 1x2","size":"1×2 ft","lumens":1862,"watts":35,"sourceType":"circadian_sky","cctRange":[2200,200000],"defaultCct":40000,"tunable":true,"housingMeters":{"width":0.324,"depth":0.629,"height":0.089},"emissionMeters":{"width":0.212,"depth":0.512}},{"id":"CS22","name":"Circadian Sky 2x2","size":"2×2 ft","lumens":2763,"watts":45,"sourceType":"circadian_sky","cctRange":[2200,200000],"defaultCct":40000,"tunable":true,"housingMeters":{"width":0.629,"depth":0.629,"height":0.089},"emissionMeters":{"width":0.512,"depth":0.512}},{"id":"CS14","name":"Circadian Sky 1x4","size":"1×4 ft","lumens":2966,"watts":45,"sourceType":"circadian_sky","cctRange":[2200,200000],"defaultCct":40000,"tunable":true,"housingMeters":{"width":0.324,"depth":1.238,"height":0.089},"emissionMeters":{"width":0.212,"depth":1.112}},{"id":"CS154","name":"Circadian Sky 1.5x4","size":"1.5×4 ft","lumens":2732,"watts":45,"sourceType":"circadian_sky","cctRange":[2200,200000],"defaultCct":40000,"tunable":true,"housingMeters":{"width":0.476,"depth":1.238,"height":0.089},"emissionMeters":{"width":0.312,"depth":1.112}},{"id":"CS24","name":"Circadian Sky 2x4","size":"2×4 ft","lumens":6833,"watts":75,"sourceType":"circadian_sky","cctRange":[2200,200000],"defaultCct":40000,"tunable":true,"housingMeters":{"width":0.629,"depth":1.238,"height":0.089},"emissionMeters":{"width":0.512,"depth":1.112}},{"id":"FLUO24","name":"Fluorescent 2x4","size":"2×4 ft","lumens":5700,"watts":96,"sourceType":"fluorescent","cctRange":[3500,3500],"defaultCct":3500,"tunable":false,"housingMeters":{"width":0.61,"depth":1.219,"height":0.102},"emissionMeters":{"width":0.549,"depth":1.097}},{"id":"LED24","name":"LED Panel 2x4","size":"2×4 ft","lumens":4800,"watts":36,"sourceType":"standard_led","cctRange":[3500,3500],"defaultCct":3500,"tunable":false,"housingMeters":{"width":0.61,"depth":1.219,"height":0.025},"emissionMeters":{"width":0.58,"depth":1.189}},{"id":"LED22","name":"LED Panel 2x2","size":"2×2 ft","lumens":3600,"watts":27,"sourceType":"standard_led","cctRange":[3500,3500],"defaultCct":3500,"tunable":false,"housingMeters":{"width":0.61,"depth":0.61,"height":0.025},"emissionMeters":{"width":0.58,"depth":0.58}}],"circadianSky":{"housingDepthMeters":0.089,"cctRange":[2200,200000],"automatedSchedule":"Circadian Sky has a built-in automated 24-hour program: high CCT + high melanopic output during the day (daytime alertness / entrainment), automatically shifting to low CCT + dimmed output in the evening/night (protects melatonin + sleep). No external controls needed. IMPLICATION: model the DAYTIME PEAK (the hardest case for a mel-EDI target); the evening warm/dim scene happens automatically, so no second night-time model or warmer alternate layout is required. Tell the user the CCT/output you report is the daytime setting.","dimming":"Constant-CCT and linear: melanopic ratio is unchanged by dim; mel-EDI and lux both scale directly with the dim level (0-1).","cctResponse":[{"cct":2200,"melanopicRatio":0.365,"relativeLightOutput":0.527,"relativeMelEDIPerFixture":0.25,"cri":92.1,"r9":89},{"cct":2700,"melanopicRatio":0.497,"relativeLightOutput":0.697,"relativeMelEDIPerFixture":0.451,"cri":92.3,"r9":95},{"cct":3000,"melanopicRatio":0.544,"relativeLightOutput":0.817,"relativeMelEDIPerFixture":0.579,"cri":92.1,"r9":91},{"cct":3500,"melanopicRatio":0.61,"relativeLightOutput":1.029,"relativeMelEDIPerFixture":0.817,"cri":92.8,"r9":88},{"cct":4000,"melanopicRatio":0.688,"relativeLightOutput":1.118,"relativeMelEDIPerFixture":1,"cri":94.8,"r9":90},{"cct":4600,"melanopicRatio":0.766,"relativeLightOutput":1.207,"relativeMelEDIPerFixture":1.203,"cri":97.1,"r9":98},{"cct":5000,"melanopicRatio":0.806,"relativeLightOutput":1.16,"relativeMelEDIPerFixture":1.216,"cri":97.5,"r9":98},{"cct":6500,"melanopicRatio":0.944,"relativeLightOutput":1,"relativeMelEDIPerFixture":1.228,"cri":96.5,"r9":88},{"cct":9000,"melanopicRatio":1.084,"relativeLightOutput":0.942,"relativeMelEDIPerFixture":1.33,"cri":94.6,"r9":86},{"cct":15000,"melanopicRatio":1.243,"relativeLightOutput":0.923,"relativeMelEDIPerFixture":1.493,"cri":92.9,"r9":85},{"cct":40000,"melanopicRatio":1.389,"relativeLightOutput":0.959,"relativeMelEDIPerFixture":1.733,"cri":null,"r9":null},{"cct":200000,"melanopicRatio":1.716,"relativeLightOutput":0.762,"relativeMelEDIPerFixture":1.701,"cri":null,"r9":null}],"note":"melanopicRatio = mel-EDI per photopic lux. relativeLightOutput is 1.0 at 6500K (spec lumens), peaks ~4600K. relativeMelEDIPerFixture = ratio*output normalized to 4000K; peaks ~40000K. cri = CIE 13.3-1995 Ra, r9 = deep-red R9 (published datasheet values). Colour fidelity peaks ~5000K (Ra 97.5 / R9 98) and stays high (Ra>92) to ~15000K. At the coolest, blue-sky-like settings (above ~20000K) CRI is not defined (null) — the spectrum sits far enough off the white locus that CIE 13.3-1995 does not score it, just as it wouldn't for clear blue sky — so 40000K / 200000K carry no colour-rendering figure even though they give the most mel-EDI. See colorRendering.","colorRendering":"CCT-selection trade-off: higher CCT = more mel-EDI per fixture (the coolest settings mimic a bright blue sky, the strongest natural circadian cue), but colour appearance shifts cool and, above ~20000K, colour rendering is no longer scored. The 40000K default is a good daytime choice for offices, circulation, and wellness spaces valued for circadian dose and a daylight feel. Where accurate colour judgement matters — medical exam & dermatology (skin/tissue), retail, print/paint/art, food, and the MACROSCOPIC bench reads in a lab (colony colour/morphology, haemolysis on blood agar, chromogenic media, reagent/indicator colour) — prefer a CCT where CRI stays high: ~5000K peaks (Ra 97.5 / R9 98) and ≤6500K keeps it strong. Set optimize.cctLadder to end there, or fix cct. IMPORTANT nuance: this applies only to colour judged UNDER THE ROOM LIGHT. A task with its own dedicated source — a microscope illuminator (stained slides), a colour-viewing booth, a task lamp — is governed by that source, not the ceiling, so it does not require capping the overhead CCT. E.g. a microbiology lab: cap the overhead warm for the people and the by-eye plate/reagent reads, while slide microscopy rides the scope's own light. The Circadian Sky still delivers a solid mel-EDI dose at 5000K (mel-DER ~0.8), so this costs only modest circadian performance. Mention the CCT you chose and why for colour-critical rooms."},"endpoints":{"GET  /api/eml-calc/ai/guide":"Prose instruction manual (Markdown) — the human/AI-readable version of this doc.","GET  /api/eml-calc/ai/spec":"This document (JSON).","GET  /api/eml-calc/fixtures/search":"Find real fixtures. Filters: q, type, wattsMin/wattsMax, cct (+cctTol), lumensMin/lumensMax, beamMin/beamMax, perManufacturer (best N per manufacturer, for \"options across/from top manufacturers\"). Returns variantId usable with /fixtures/lookup.","GET  /api/eml-calc/fixtures/lookup?id=<variantId>":"Fetch a fixture incl. its real IES content (for customFixtures).","POST|GET /api/eml-calc/ai/score":"Room (+targets) -> room stats + per-occupant fc/mel-EDI/UGR + pass-fail. POST body, or GET with ?room=/?room64= (see getLinks). Use to validate a design.","POST|GET /api/eml-calc/ai/optimize":"Room + targets (+optimize knobs) -> escalates CCT -> dimming -> fixture count until targets met. Returns design, score, trace, share url. POST body, or GET with ?room=/?room64=.","POST|GET /api/eml-calc/ai/import":"Stores a room and yields a share. POST body -> returns { url }. GET ?room=/?room64= -> 302-redirects straight to the share (hand the user this link; no POST or AI network needed).","GET  /api/eml-calc/ai/render?share=<id>|?room=|?room64=&w=&h=":"PNG of a scene to show the user. Renders a stored share, or a room passed inline (?room=/?room64=). Resolution-capped; renders are queued one-at-a-time across all requests to protect server memory, so a busy server returns 429 (wait and retry). Render-mode component flags (choose which components appear in the image): chrome=0 hides UI overlays (colorbar + measurement-plane picker); occupants=0 hides the person figure; heatmap=0 renders plain lit surfaces (no overlay); lightmap=1 uses a photographic \"where the light lands\" overlay instead of the colored heatmap; solid=1 (lightmap only) renders the walls + floor + non-transparent ceiling in a light neutral tone so the room reads as a solid, evenly-lit enclosure (instead of dark walls); fixtures=0 / furniture=0 hide those. For a clean base image to feed to an image model use chrome=0&occupants=0&lightmap=1&solid=1. Camera: angle=front|corner|corner_left|wide|high picks a 3D viewpoint (render 2-3 angles for the user to choose), or give explicit camX/camY/camZ/tgtX/tgtY/tgtZ/fov (meters, room coords: origin SW floor corner, +X east, +Y north, +Z up)."},"getLinks":{"what":"score/optimize/import also accept the room in the query string, so an assistant that can GET (or just build a URL) never needs to POST.","room":"?room=<URL-encoded JSON> — the room JSON, percent-encoded (encodeURIComponent). PREFERRED: robust, inspectable, buildable by hand. Use whenever it fits (up to ~8 KB; covers most preset rooms — a 32-point oval office with 12 fixtures is ~3.8 KB).","room64":"?room64=<base64url(gzip(JSON))> — gzip the JSON then base64url it (+/ -> -_, drop =). Compact (~400 chars) but OPAQUE and FRAGILE: one altered/dropped character (URL wrapping, a bad copy) silently corrupts it and it will not decompress (import returns a 400 error page). Use ONLY when ?room= would exceed ~8 KB, and always also give the user the room JSON as a paste-in fallback.","handItToTheUser":"GET /import 302-redirects to the share, so you can just give the user the link; their browser opens it on click. You do not need to fetch it yourself.","ifALinkFails":"A broken link (esp. a long room64) almost always means the URL was truncated/altered in transit, not a server problem. Do not debug the blob — regenerate as ?room= if it fits, or hand the user the room JSON in a code block to paste into the Import window (that path cannot be corrupted by URL handling).","limits":"Safe URL ~2000 chars, practical server ceiling ~8000. Preset rooms fit easily as ?room=. customFixtures with embedded IES do NOT fit — use paste-JSON or a .zip bundle (room.json + referenced .ies files) dropped into the Import window instead."},"limits":{"maxRoomArea":400,"maxFixtures":500,"maxOccupants":50,"maxPartitions":120,"minGridSpacing":0.15,"maxOptimizeAgents":64,"maxStoreArea":50000,"maxStoreFixtures":2000,"maxStoreOccupants":500,"maxStorePartitions":1000},"workflow":{"agentic":"1) build a room JSON  2) POST /score (or /optimize) to validate/solve  3) POST /import (or use the /optimize url)  4) GET /render to see it  5) open the url for the user.","web":"No web access? ALWAYS output the full room JSON in a fenced ```json code block — that block is your deliverable, so include it every time and never reply with prose only. Then tell the user to paste it into CircadianLab's Import window and click Open (their browser computes it). Do not ask the user to POST to an endpoint themselves.","getOnly":"Can build a URL but not POST (most chat assistants)? Hand the user a GET link that opens the design: /api/eml-calc/ai/import?room64=<blob> (see getLinks). If you can also fetch URLs, GET /score or /optimize with the same param to compute real numbers before answering.","reportingResults":"Only state metric numbers (fc, mel-EDI, UGR) that you actually computed via /score or /optimize, or that the browser computed after the user opened the link. Never present numbers from this spec's examples as results for the user's room."},"examples":{"simpleText":{"schema":"circadian-lab/room@1","units":"ft","room":{"width":20,"depth":10,"height":9},"fixtures":[{"preset":"CS24","count":3}],"occupants":[{"x":10,"y":5,"facing":"north","posture":"standing"}],"targets":{"deskFc":30,"melEDI":250,"ugr":25}},"optimize":{"schema":"circadian-lab/room@1","units":"ft","room":{"width":24,"depth":18,"height":9},"occupants":[{"x":6,"y":5},{"x":18,"y":5},{"x":6,"y":13},{"x":18,"y":13}],"targets":{"deskFc":30,"melEDI":250,"ugr":25},"optimize":{"fixture":"CS24"}},"interiorWall":{"schema":"circadian-lab/room@1","units":"ft","room":{"width":24,"depth":12,"height":9},"fixtures":[{"preset":"CS22","count":8}],"partitions":[{"x1":12,"y1":0,"x2":12,"y2":8,"height":9}],"occupants":[{"x":6,"y":4,"facing":"south"},{"x":18,"y":4,"facing":"south"}],"targets":{"deskFc":30,"melEDI":250,"ugr":22}},"shapedRoomWalls":{"schema":"circadian-lab/room@1","units":"ft","room":{"height":9,"walls":[{"x1":0,"y1":0,"x2":30,"y2":0},{"x1":30,"y1":0,"x2":30,"y2":20},{"x1":30,"y1":20,"x2":10,"y2":20},{"x1":10,"y1":20,"x2":10,"y2":10},{"x1":10,"y1":10,"x2":0,"y2":10},{"x1":0,"y1":10,"x2":0,"y2":0}]},"fixtures":[{"preset":"CS24","count":6}],"occupants":[{"x":5,"y":5},{"x":20,"y":15}],"targets":{"deskFc":30,"melEDI":250,"ugr":25}}}}