feat(ext): add coordSpaceDemo.v2 canary for D-coord-space (W6.P4.D / A13)

Strangler-pattern v2 example demonstrating the single-coordinate-space policy from D-coord-space (ACCEPTED 2026-05-18, option iii) and Axiom A13 (Single Coordinate Space — Canvas).

Three sections: (1) default path — every NodeHandle spatial accessor speaks canvas units; (2) escape-hatch path — globalThis.app.canvas.{ds,canvas} + window.devicePixelRatio with the required '// escape-hatch — see D-coord-space.md' annotation comment on every use site; (3) cliff documentation — what's NOT on the public surface (no getScreenPosition, no space param, no branded ClientPoint type).

Serves as the executable canary that the documented pattern actually works. Authors and AI agents reading the v2 extensions/core/*.v2.ts directory see the policy demonstrated alongside the existing dynamicPrompts/previewAny/imageCrop/noteNode/slotDefaults/rerouteNode/webcamCapture examples.

knip.config.ts: add new file to strangler ignore list. Phase A gates: format clean / lint 0 errors 3 pre-existing warnings / knip 6 pre-existing tag hints + 1 pre-existing config hint.
This commit is contained in:
Connor Byrne
2026-05-18 16:13:15 -07:00
parent f182d1ff96
commit 616a30ddb3
2 changed files with 80 additions and 1 deletions

View File

@@ -90,7 +90,10 @@ const config: KnipConfig = {
'src/extensions/core/rerouteNode.v2.ts',
'src/extensions/core/slotDefaults.v2.ts',
// W6.P3.D — defineWidget+mount showcase port (D-widget-converge / A12).
'src/extensions/core/webcamCapture.v2.ts'
'src/extensions/core/webcamCapture.v2.ts',
// W6.P4.D — canvas-units canary + escape-hatch annotation example
// (D-coord-space / A13).
'src/extensions/core/coordSpaceDemo.v2.ts'
],
vite: {
config: ['vite?(.*).config.mts']

View File

@@ -0,0 +1,76 @@
/**
* CoordSpaceDemo — canary example for the D-coord-space PICK
* (W6.P4 ACCEPTED 2026-05-18, Axiom A13 Single Coordinate Space).
*
* Shows three things:
*
* 1. **The default — canvas units everywhere.** `node.getPosition()` /
* `getSize()` / `setPosition()` / `setSize()` all speak canvas units.
* Zoom and pan don't perturb the numbers; devicePixelRatio is
* invisible. This is the path 96%+ of extensions should ever take.
*
* 2. **The escape-hatch — explicit + annotated.** For the legitimate
* cases that need screen-space coords (custom GPU canvas, floating
* overlay anchored to absolute browser coords, hi-DPI export math),
* drop to `window.app.canvas.{ds,canvas}` + `window.devicePixelRatio`.
* Every escape-hatch use site MUST carry the
* `// escape-hatch — see D-coord-space.md` comment so reviewers
* (human or AI) can see the dependency is deliberate.
*
* 3. **The cliff — what's NOT on the public surface.** No
* `node.getScreenPosition()`, no `node.getCSSPosition()`, no
* `space: 'client' | 'css'` parameter, no branded `ClientPoint`
* type. Reaching for any of those is a sign the author wants the
* escape-hatch.
*/
import { defineExtension, defineNode, type NodeHandle } from '@/extension-api'
defineNode({
name: 'Comfy.CoordSpaceDemo.V2',
nodeCreated(node: NodeHandle) {
// ── (1) Default path: canvas units, no conversion needed ──────────
const [x, y] = node.getPosition() // canvas units
const [w, h] = node.getSize() // canvas units
// Move a node 16 canvas units down-and-right of its current spot.
// No /scale, no *scale, no devicePixelRatio — the runtime owns it.
node.setPosition([x + 16, y + 16]) // canvas units
// Reserve a minimum size — also canvas units; zoom doesn't matter.
if (w < 200) node.setSize([200, h])
}
})
defineExtension({
name: 'Comfy.CoordSpaceDemo.V2.Escape',
setup() {
// ── (2) Escape-hatch path — explicit + annotated ──────────────────
//
// Use case: extension wants to draw a 2x-pixel-density preview
// thumbnail PNG of the visible viewport. PNG export needs *device
// pixels* (so the saved image is crisp on hi-DPI displays); the v2
// public surface does not expose dpr or screen-pixel sizing.
//
// The escape-hatch is the same shape extension authors are already
// using today (213 dpr hits across 27 repos in the W6.P4.R1 sweep).
// escape-hatch — see D-coord-space.md § Documentation contract
const dpr = window.devicePixelRatio
// escape-hatch — see D-coord-space.md § Documentation contract
const canvas = globalThis.app?.canvas
if (!canvas) return
// escape-hatch — see D-coord-space.md § Documentation contract
const { scale } = canvas.ds
// escape-hatch — see D-coord-space.md § Documentation contract
const rect = canvas.canvas.getBoundingClientRect()
// From here, the author owns dpr math + canvas↔screen conversions.
// The runtime makes no stability promise about ds.scale or the
// shape of window.app.canvas — escape-hatch is intentionally
// fragile per Axiom A13.
void { dpr, scale, rect }
}
})