From fa3229b4027bae9e6bedec510ff206fd25a559af Mon Sep 17 00:00:00 2001 From: Connor Byrne Date: Mon, 18 May 2026 16:10:00 -0700 Subject: [PATCH] =?UTF-8?q?docs(extension-api):=20D-coord-space=20(W6.P4.C?= =?UTF-8?q?)=20=E2=80=94=20single-coordinate-space=20policy=20on=20NodeHan?= =?UTF-8?q?dle=20spatial=20accessors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per D-coord-space ACCEPTED 2026-05-18 (option iii, Christian PICK) + new Axiom A13 (Single Coordinate Space — Canvas) in workspace AXIOMS.md. Expands JSDoc on NodeHandle.{getPosition,setPosition,getSize,setSize} to: (1) explicitly state 'canvas units', (2) name client/CSS spaces in prose so the distinction is visible at the API boundary, (3) document the escape-hatch (window.app.canvas.ds.{scale,offset} + window.app.canvas.canvas.getBoundingClientRect() + window.devicePixelRatio) for legitimate screen-space cases, (4) point AI agents and human authors at A13 + ADR D-coord-space, (5) carry @stability stable. Also adds a SPATIAL STATE section header comment block stating the single-space policy once at the top. No runtime surface change — getPosition/getSize/setPosition/setSize already returned/accepted canvas units post W6.P8.C (df921f3512). The PICK ships as documentation + axiom because the runtime contract was already in the right shape. R1+R2+R3 evidence (8,424 EXT hits / 103 repos / ★41,621; bug-class 2,617 hits / 71 repos / ★40,040) backs the choice. Phase A gates: format clean / lint 0 errors 3 pre-existing warnings / knip 6 pre-existing tag hints 0 failures. --- src/extension-api/node.ts | 43 +++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/extension-api/node.ts b/src/extension-api/node.ts index 7c0c3c740f..67a4149c6a 100644 --- a/src/extension-api/node.ts +++ b/src/extension-api/node.ts @@ -265,28 +265,63 @@ export interface NodeHandle { readonly comfyClass: string // ── SPATIAL STATE ───────────────────────────────────────────────────────── + // + // **Single coordinate space — canvas units.** Every spatial accessor on + // `NodeHandle` returns and accepts canvas units. Canvas units are + // independent of zoom, pan, and devicePixelRatio. They are NOT screen + // pixels and NOT CSS pixels. See Axiom A13 + // (`AXIOMS.md § A13 Single Coordinate Space`) and ADR D-coord-space for + // the full rationale + escape-hatch. /** - * Returns the node's current canvas position as `[x, y]`. + * Returns the node's current position as `[x, y]` in **canvas units**. * + * Canvas units are the LiteGraph internal coordinate space — independent + * of zoom, pan, or `devicePixelRatio`. To position a DOM overlay aligned + * with the node visually on screen, use {@link defineWidget}'s + * `mount(host, ctx)` seam (host is pre-positioned by the runtime). For + * legitimate screen-space needs (custom hit-testing, hi-DPI math, + * floating overlays anchored to absolute browser coordinates), the + * documented escape-hatch is `window.app.canvas.ds.scale` / + * `window.app.canvas.ds.offset` + `window.app.canvas.canvas + * .getBoundingClientRect()`. The escape-hatch is `@stability escape-hatch` + * (deliberately fragile) — see `D-coord-space.md § Documentation contract`. + * + * @stability stable */ getPosition(): Point /** - * Moves the node to a new canvas position. Dispatches a `MoveNode` command. + * Moves the node to a new position. **Argument is in canvas units.** + * Dispatches a `MoveNode` command. * + * No conversion is performed — passing screen pixels here will move + * the node by screen-pixel amounts in canvas space (almost always a + * bug). To convert a screen-space pointer event to canvas units before + * calling this, use the escape-hatch — see {@link getPosition} JSDoc. + * + * @stability stable */ setPosition(pos: Point): void /** - * Returns the node's current size as `[width, height]`. + * Returns the node's current size as `[width, height]` in **canvas units**. * + * Same coordinate-space semantics as {@link getPosition}: zoom and + * `devicePixelRatio` are NOT applied. A 200-canvas-unit-wide node will + * appear as 100 CSS px wide at 50% zoom or 400 CSS px wide at 200% zoom. + * For DOM-overlay sizing, prefer the {@link defineWidget} `mount` seam + * which provides a pre-positioned host. + * + * @stability stable */ getSize(): Size /** - * Resizes the node. Dispatches a `ResizeNode` command. + * Resizes the node. **Argument is in canvas units.** + * Dispatches a `ResizeNode` command. * + * @stability stable */ setSize(size: Size): void