mesurer-solid 0.1.5 → 0.1.7-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_INTEGRATION.md +74 -348
- package/README.md +72 -366
- package/dist/agent.d.ts +24 -0
- package/dist/arrange.js +16 -15
- package/dist/core.d.ts +1 -0
- package/dist/core.js +116 -99
- package/dist/index.d.ts +8 -3
- package/dist/index.js +2893 -1985
- package/dist/inject-script.js +76 -12
- package/dist/inject.js +2782 -1891
- package/dist/screenshot.js +1 -1
- package/package.json +1 -1
- package/skills/mesurer-ui/SKILL.md +82 -393
package/AGENT_INTEGRATION.md
CHANGED
|
@@ -1,32 +1,10 @@
|
|
|
1
1
|
# Mesurer agent integration
|
|
2
2
|
|
|
3
|
-
Mesurer's agent integration is
|
|
3
|
+
Mesurer's agent integration is the rendered page itself. The coding agent reads `window.__MESURER__` through the browser control it already has, consumes human visual intent, edits normal application source, and verifies the real Live result.
|
|
4
4
|
|
|
5
|
-
There is no Mesurer MCP
|
|
5
|
+
There is no Mesurer MCP server, localhost daemon, Send-to-agent callback, or harness-specific transport.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
```text
|
|
10
|
-
human visual intent
|
|
11
|
-
↓
|
|
12
|
-
Arrange / annotation / selection
|
|
13
|
-
↓
|
|
14
|
-
window.__MESURER__
|
|
15
|
-
↓
|
|
16
|
-
structured rendered evidence + optional harness screenshot
|
|
17
|
-
↓
|
|
18
|
-
agent edits normal source
|
|
19
|
-
↓
|
|
20
|
-
real render / HMR
|
|
21
|
-
↓
|
|
22
|
-
fresh Live review/context
|
|
23
|
-
↓
|
|
24
|
-
validated result
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Install the portable Agent Skill
|
|
28
|
-
|
|
29
|
-
Use the stable package by default:
|
|
7
|
+
## Install the Agent Skill
|
|
30
8
|
|
|
31
9
|
```bash
|
|
32
10
|
npx --yes --package=mesurer-solid mesurer-skill install
|
|
@@ -34,7 +12,7 @@ npx --yes --package=mesurer-solid mesurer-skill install
|
|
|
34
12
|
|
|
35
13
|
Use `mesurer-solid@beta` only when intentionally validating a prerelease.
|
|
36
14
|
|
|
37
|
-
The
|
|
15
|
+
The installer writes a self-contained skill and injection artifact:
|
|
38
16
|
|
|
39
17
|
```text
|
|
40
18
|
.agents/skills/mesurer-ui/
|
|
@@ -43,11 +21,9 @@ The installed skill is self-contained:
|
|
|
43
21
|
└── inject-script.js
|
|
44
22
|
```
|
|
45
23
|
|
|
46
|
-
|
|
24
|
+
## Reuse a live instance
|
|
47
25
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
Before injecting anything:
|
|
26
|
+
Before injecting anything, check whether Mesurer is already connected:
|
|
51
27
|
|
|
52
28
|
```js
|
|
53
29
|
const hasMesurer = Boolean(
|
|
@@ -60,92 +36,31 @@ if (hasMesurer) {
|
|
|
60
36
|
}
|
|
61
37
|
```
|
|
62
38
|
|
|
63
|
-
If
|
|
39
|
+
If it exists, use that instance. A person may already have selected targets, guides, measurements, annotations, Arrange intent, text/style intent, or screenshot review state. That state is part of the request.
|
|
64
40
|
|
|
65
|
-
The injector reuses a
|
|
41
|
+
The injector reuses a connected instance by default. Deliberate replacement requires:
|
|
66
42
|
|
|
67
43
|
```js
|
|
68
44
|
window.__MESURER_CONFIG__ = { reuseExisting: false }
|
|
69
45
|
```
|
|
70
46
|
|
|
71
|
-
Do not
|
|
47
|
+
Do not replace a live instance while consuming human review state.
|
|
72
48
|
|
|
73
49
|
## Inject only when absent
|
|
74
50
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
With the installed skill, evaluate `.agents/skills/mesurer-ui/assets/inject-script.js`. With the npm package installed, use `mesurer-solid/inject-script`.
|
|
78
|
-
|
|
79
|
-
```js
|
|
80
|
-
import { readFile } from "node:fs/promises"
|
|
81
|
-
import { fileURLToPath } from "node:url"
|
|
82
|
-
|
|
83
|
-
const source = await readFile(
|
|
84
|
-
fileURLToPath(import.meta.resolve("mesurer-solid/inject-script")),
|
|
85
|
-
"utf8",
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
const alreadyPresent = await browser.evaluate(() => Boolean(
|
|
89
|
-
window.__MESURER__ &&
|
|
90
|
-
window.__MESURER_INSTANCE__?.element?.isConnected
|
|
91
|
-
))
|
|
92
|
-
|
|
93
|
-
if (!alreadyPresent) {
|
|
94
|
-
await browser.evaluate(source)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
await browser.evaluate(() => window.__MESURER__.ready())
|
|
98
|
-
```
|
|
51
|
+
Use the browser, Electron, WebView, Playwright, CDP, or other evaluation channel the harness already owns. With the installed skill, evaluate `.agents/skills/mesurer-ui/assets/inject-script.js`. With the npm package installed, read `mesurer-solid/inject-script`.
|
|
99
52
|
|
|
100
|
-
Do not
|
|
53
|
+
Do not mutate application source or create another browser connection merely to get Mesurer into a page the harness can already evaluate.
|
|
101
54
|
|
|
102
|
-
|
|
55
|
+
The optional human Screenshot plugin remains disabled during normal agent injection unless configured before first injection:
|
|
103
56
|
|
|
104
57
|
```js
|
|
105
58
|
window.__MESURER_CONFIG__ = { screenshot: true }
|
|
106
59
|
```
|
|
107
60
|
|
|
108
|
-
##
|
|
61
|
+
## Inventory human intent
|
|
109
62
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
```js
|
|
113
|
-
window.__MESURER__.capabilities()
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
The context-oriented surface is:
|
|
117
|
-
|
|
118
|
-
```text
|
|
119
|
-
context
|
|
120
|
-
select
|
|
121
|
-
annotations
|
|
122
|
-
review
|
|
123
|
-
capturePlan
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
When `arrangePlugin()` is mounted, it also reports:
|
|
127
|
-
|
|
128
|
-
```text
|
|
129
|
-
arrange
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
and exposes:
|
|
133
|
-
|
|
134
|
-
```text
|
|
135
|
-
arrangements()
|
|
136
|
-
arrange(id)
|
|
137
|
-
showArrange(id, state)
|
|
138
|
-
arrangeCapturePlan(id, state)
|
|
139
|
-
reviewArrange(id, tolerance?)
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
There is no `send`, `screenshots`, or `sendContext` delivery capability. Screenshot bytes stay with the outer browser harness.
|
|
143
|
-
|
|
144
|
-
## Broad Mesurer/context requests mean inspect all human intent
|
|
145
|
-
|
|
146
|
-
If the user says “check Mesurer,” “check Measure,” “look at Mesurer context,” “see what I highlighted/moved/annotated,” or otherwise asks generally about Mesurer state, treat that as a request to inspect the **combined live review state**, not only the return value of `context()`.
|
|
147
|
-
|
|
148
|
-
Start with a non-destructive inventory:
|
|
63
|
+
For a broad request such as “check Mesurer,” collect all relevant state before editing source:
|
|
149
64
|
|
|
150
65
|
```js
|
|
151
66
|
const capabilities = window.__MESURER__.capabilities().capabilities
|
|
@@ -154,6 +69,9 @@ const annotations = await window.__MESURER__.annotations()
|
|
|
154
69
|
const arrangements = capabilities.arrange
|
|
155
70
|
? await window.__MESURER__.arrangements()
|
|
156
71
|
: []
|
|
72
|
+
const textEdits = capabilities.textEdit
|
|
73
|
+
? await window.__MESURER__.textEdits()
|
|
74
|
+
: []
|
|
157
75
|
|
|
158
76
|
let selection = null
|
|
159
77
|
try {
|
|
@@ -161,7 +79,7 @@ try {
|
|
|
161
79
|
} catch {}
|
|
162
80
|
```
|
|
163
81
|
|
|
164
|
-
|
|
82
|
+
Resolve relevant records before HMR can replace their DOM targets:
|
|
165
83
|
|
|
166
84
|
```js
|
|
167
85
|
const annotationContexts = await Promise.all(
|
|
@@ -173,58 +91,41 @@ const annotationContexts = await Promise.all(
|
|
|
173
91
|
const arrangeIntents = await Promise.all(
|
|
174
92
|
arrangements.map((intent) => window.__MESURER__.arrange(intent.id)),
|
|
175
93
|
)
|
|
176
|
-
```
|
|
177
94
|
|
|
178
|
-
|
|
95
|
+
const textEditIntents = await Promise.all(
|
|
96
|
+
textEdits.map((intent) => window.__MESURER__.textEdit(intent.id)),
|
|
97
|
+
)
|
|
98
|
+
```
|
|
179
99
|
|
|
180
|
-
|
|
100
|
+
Treat annotation notes, Arrange Desired geometry, and text/style Desired state as intent. Treat selection, measurements, distances, geometry, and computed styles as rendered evidence.
|
|
181
101
|
|
|
182
|
-
##
|
|
102
|
+
## Select exact targets
|
|
183
103
|
|
|
184
|
-
|
|
104
|
+
Do not overwrite a meaningful human selection until its context has been retained. When there is no relevant human selection and the exact targets are known:
|
|
185
105
|
|
|
186
106
|
```js
|
|
187
|
-
const
|
|
188
|
-
|
|
107
|
+
const context = await window.__MESURER__.select([
|
|
108
|
+
"#pricing-card",
|
|
109
|
+
"#pricing-cta",
|
|
110
|
+
])
|
|
189
111
|
```
|
|
190
112
|
|
|
191
|
-
Each
|
|
113
|
+
Each selector must resolve to exactly one target. Missing or ambiguous selectors throw rather than binding to a guess.
|
|
192
114
|
|
|
193
|
-
|
|
115
|
+
For multi-selection, inspect every selected target and the relevant pair relationships. Prefer `selection.visualContext.distances`; use `distance(a, b)` when a needed pair has no existing evidence.
|
|
194
116
|
|
|
195
|
-
|
|
117
|
+
## Arrange intent
|
|
196
118
|
|
|
197
|
-
|
|
119
|
+
Arrange expresses requested geometry, not source implementation.
|
|
198
120
|
|
|
199
121
|
```js
|
|
200
|
-
await window.__MESURER__.
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
await window.__MESURER__.prepareCapture()
|
|
204
|
-
try {
|
|
205
|
-
// outer harness captures Before with beforePlan
|
|
206
|
-
} finally {
|
|
207
|
-
await window.__MESURER__.finishCapture()
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
await window.__MESURER__.showArrange(arrangeId, "desired")
|
|
211
|
-
const desiredPlan = await window.__MESURER__.arrangeCapturePlan(arrangeId, "desired")
|
|
212
|
-
|
|
213
|
-
await window.__MESURER__.prepareCapture()
|
|
214
|
-
try {
|
|
215
|
-
// outer harness captures Desired with desiredPlan
|
|
216
|
-
} finally {
|
|
217
|
-
await window.__MESURER__.finishCapture()
|
|
218
|
-
}
|
|
122
|
+
const intents = await window.__MESURER__.arrangements()
|
|
123
|
+
const intent = await window.__MESURER__.arrange(arrangeId)
|
|
219
124
|
```
|
|
220
125
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
For source-mounted integrations that use this capture workflow, mount `contextPlugin()` together with `arrangePlugin()` so the generic capture preparation methods are available.
|
|
126
|
+
A 96px Desired offset does not mean production source should use `transform: translateX(96px)`. Implement the visual outcome through the application's real flex/grid, spacing, sizing, ordering, or component structure.
|
|
224
127
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
After editing source:
|
|
128
|
+
After source changes:
|
|
228
129
|
|
|
229
130
|
```js
|
|
230
131
|
await window.__MESURER__.stable()
|
|
@@ -232,265 +133,90 @@ await window.__MESURER__.showArrange(arrangeId, "live")
|
|
|
232
133
|
const review = await window.__MESURER__.reviewArrange(arrangeId)
|
|
233
134
|
```
|
|
234
135
|
|
|
235
|
-
Live removes
|
|
236
|
-
|
|
237
|
-
```text
|
|
238
|
-
Before Desired Live
|
|
239
|
-
x 120 → x 284 x 276
|
|
240
|
-
remaining +8px
|
|
241
|
-
|
|
242
|
-
edit source
|
|
243
|
-
↓
|
|
244
|
-
Live x 284
|
|
245
|
-
↓
|
|
246
|
-
matched ✓
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
If review is still numerically wrong, continue editing. If it is `stale` or `partial`, do not silently bind the intent to a different element.
|
|
250
|
-
|
|
251
|
-
## Context acquisition after Arrange preservation
|
|
252
|
-
|
|
253
|
-
Once any relevant Arrange intent is retained, use this order for ordinary context.
|
|
254
|
-
|
|
255
|
-
### Existing human selection or annotation
|
|
256
|
-
|
|
257
|
-
```js
|
|
258
|
-
const workspace = await window.__MESURER__.context()
|
|
259
|
-
const annotations = await window.__MESURER__.annotations()
|
|
260
|
-
|
|
261
|
-
let selection = null
|
|
262
|
-
try {
|
|
263
|
-
selection = await window.__MESURER__.context({ scope: "selection" })
|
|
264
|
-
} catch {}
|
|
265
|
-
```
|
|
136
|
+
Live removes the temporary Arrange preview before measuring source output.
|
|
266
137
|
|
|
267
|
-
|
|
138
|
+
Arrange preview ownership is conservative. Mesurer restores an older transform only while the element still carries the exact preview value and priority Mesurer applied. Host-authored transform changes survive review, refresh, and disposal.
|
|
268
139
|
|
|
269
|
-
|
|
270
|
-
const context = await window.__MESURER__.context({
|
|
271
|
-
annotation: annotation.id,
|
|
272
|
-
})
|
|
273
|
-
```
|
|
140
|
+
See [Arrange](../../docs/ARRANGE.md).
|
|
274
141
|
|
|
275
|
-
|
|
142
|
+
## Text and Typography intent
|
|
276
143
|
|
|
277
|
-
|
|
144
|
+
Direct text editing records copy and typography intent without pretending to edit source. The human-facing tool is **Typography**; the internal compatibility id remains `text-inspector`.
|
|
278
145
|
|
|
279
|
-
|
|
146
|
+
Editing starts by double-click/double-tap while Select or Typography is active. Arrange keeps Select active, so editing works while Arrange remains selected.
|
|
280
147
|
|
|
281
|
-
|
|
282
|
-
const context = await window.__MESURER__.context({ scope: "selection" })
|
|
283
|
-
```
|
|
148
|
+
Native editing stays native. Mesurer does not intercept form controls or descendants that inherit `contenteditable`. A nested `contenteditable="false"` boundary ends inherited editability and can become a Mesurer target when the direct-text rules otherwise pass.
|
|
284
149
|
|
|
285
|
-
|
|
150
|
+
The editing UI exposes direct B/I/U, Font, Size, Weight, rendered-page colors, custom color, and a separate Text/H1/H2/H3 semantic preset popup. Missing heading levels are not invented.
|
|
286
151
|
|
|
287
|
-
|
|
152
|
+
If Typography was already explicitly selected, the direct-edit session suppresses the older hover/pinned Typography surface so the field has one live card. The normal surface returns when editing ends.
|
|
288
153
|
|
|
289
|
-
|
|
154
|
+
Read durable intent through:
|
|
290
155
|
|
|
291
156
|
```js
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
"#pricing-cta",
|
|
295
|
-
])
|
|
157
|
+
const edits = await window.__MESURER__.textEdits()
|
|
158
|
+
const intent = await window.__MESURER__.textEdit(textEditId)
|
|
296
159
|
```
|
|
297
160
|
|
|
298
|
-
`
|
|
299
|
-
|
|
300
|
-
Every selector must resolve to exactly one page target. Invalid, missing, or ambiguous selectors throw.
|
|
301
|
-
|
|
302
|
-
## What context contains
|
|
161
|
+
Treat `intent.desired` and style deltas as visual/source requirements, not inline CSS instructions. Look for the application's semantic props, classes, design tokens, CSS variables, theme values, or stylesheet rules that produce the requested render.
|
|
303
162
|
|
|
304
|
-
|
|
163
|
+
Verification must use Live source with the Desired preview inactive. Text/style preview ownership follows the same conservative rule as Arrange: while the DOM still equals Mesurer's owned value, undo/redo can move it to the restored Desired value; once the application changes it, Mesurer preserves the host value instead of overwriting it during history or cleanup.
|
|
305
164
|
|
|
306
|
-
|
|
307
|
-
schema / id / createdAt
|
|
308
|
-
scope
|
|
309
|
-
page
|
|
310
|
-
viewport / DPR / scroll
|
|
311
|
-
coordinateSpace
|
|
312
|
-
regions
|
|
313
|
-
visualState
|
|
314
|
-
rulersVisible
|
|
315
|
-
xrayVisible
|
|
316
|
-
targets[]
|
|
317
|
-
ref
|
|
318
|
-
inspection.selector
|
|
319
|
-
inspection.rect
|
|
320
|
-
margin / padding / border
|
|
321
|
-
typography
|
|
322
|
-
appearance
|
|
323
|
-
layout
|
|
324
|
-
scroll / overflow
|
|
325
|
-
visualContext
|
|
326
|
-
guides[]
|
|
327
|
-
measurements[]
|
|
328
|
-
distances[]
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
Prefer rendered numbers over screenshot estimates or source assumptions.
|
|
165
|
+
See [Direct text editing and Typography](../../docs/TEXT_EDITING.md).
|
|
332
166
|
|
|
333
|
-
##
|
|
167
|
+
## Annotation and context review
|
|
334
168
|
|
|
335
|
-
|
|
169
|
+
A saved annotation carries target-bound intent and an immutable baseline:
|
|
336
170
|
|
|
337
171
|
```js
|
|
338
|
-
const
|
|
172
|
+
const context = await window.__MESURER__.context({ annotation: annotationId })
|
|
339
173
|
```
|
|
340
174
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
```text
|
|
344
|
-
Card A width: 320px
|
|
345
|
-
Card B width: 320px
|
|
346
|
-
A → B horizontal gap: 24px
|
|
347
|
-
A/B top-edge delta: 0px
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
For large repeated sets, focus on adjacent or user-relevant relationships rather than dumping all O(n²) pairs.
|
|
351
|
-
|
|
352
|
-
## Fresh evidence is required after visual edits
|
|
353
|
-
|
|
354
|
-
Wait for the actual rendered page:
|
|
175
|
+
After source changes:
|
|
355
176
|
|
|
356
177
|
```js
|
|
357
178
|
await window.__MESURER__.stable()
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
Then use the strongest applicable path.
|
|
361
|
-
|
|
362
|
-
Arrange:
|
|
363
|
-
|
|
364
|
-
```js
|
|
365
|
-
await window.__MESURER__.showArrange(arrangeId, "live")
|
|
366
|
-
const review = await window.__MESURER__.reviewArrange(arrangeId)
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
Annotation:
|
|
370
|
-
|
|
371
|
-
```js
|
|
372
179
|
const review = await window.__MESURER__.review(annotationId)
|
|
373
180
|
```
|
|
374
181
|
|
|
375
|
-
|
|
182
|
+
`review()` can report exact geometry/evidence changes without any external message transport.
|
|
376
183
|
|
|
377
|
-
|
|
378
|
-
const after = await window.__MESURER__.context({ scope: "selection" })
|
|
379
|
-
```
|
|
184
|
+
## Screenshots
|
|
380
185
|
|
|
381
|
-
|
|
186
|
+
For ordinary coding-agent evidence, the outer harness owns screenshot bytes while Mesurer prepares capture presentation:
|
|
382
187
|
|
|
383
188
|
```js
|
|
384
|
-
const
|
|
385
|
-
changedSelectorA,
|
|
386
|
-
changedSelectorB,
|
|
387
|
-
])
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
For meaningful visual work, lint/typecheck/tests/build are not enough. They validate implementation mechanics, not the rendered result.
|
|
391
|
-
|
|
392
|
-
## Screenshot ownership
|
|
393
|
-
|
|
394
|
-
Mesurer has two different screenshot roles.
|
|
395
|
-
|
|
396
|
-
### Human camera tool
|
|
397
|
-
|
|
398
|
-
The optional `mesurer.screenshot` plugin gives the person a camera tool:
|
|
399
|
-
|
|
400
|
-
```ts
|
|
401
|
-
import { mountMesurer } from "mesurer-solid"
|
|
402
|
-
import { screenshotPlugin } from "mesurer-solid/screenshot"
|
|
403
|
-
|
|
404
|
-
const mesurer = mountMesurer({
|
|
405
|
-
plugins: [screenshotPlugin()],
|
|
406
|
-
})
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
It captures HiDPI-aware PNGs and can copy/download them or keep a draggable preview/viewer. Preserve an existing human screenshot preview unless the task explicitly requires manipulating it.
|
|
410
|
-
|
|
411
|
-
### Agent screenshot evidence
|
|
412
|
-
|
|
413
|
-
The outer coding harness owns screenshot bytes so it controls the exact browser, viewport, timing, and artifact destination. Mesurer supplies exact geometry and clean capture presentation:
|
|
414
|
-
|
|
415
|
-
```js
|
|
416
|
-
const plan = await window.__MESURER__.capturePlan({ scope: "selection" })
|
|
417
|
-
|
|
189
|
+
const plan = await window.__MESURER__.capturePlan({ annotation: annotationId })
|
|
418
190
|
await window.__MESURER__.prepareCapture()
|
|
419
191
|
try {
|
|
420
|
-
//
|
|
192
|
+
// harness screenshot
|
|
421
193
|
} finally {
|
|
422
194
|
await window.__MESURER__.finishCapture()
|
|
423
195
|
}
|
|
424
196
|
```
|
|
425
197
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
Use both signals:
|
|
198
|
+
The optional `mesurer-solid/screenshot` plugin is a separate human camera workflow. It is not an agent delivery capability. Preserve an existing human preview unless the task is specifically about Screenshot behavior.
|
|
429
199
|
|
|
430
|
-
|
|
431
|
-
Mesurer context/review → geometry, box model, styles, distances, overflow
|
|
432
|
-
real screenshot → composition, hierarchy, clipping, color, visual judgment
|
|
433
|
-
```
|
|
200
|
+
## Revalidate after source edits
|
|
434
201
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
For context plus Arrange:
|
|
438
|
-
|
|
439
|
-
```ts
|
|
440
|
-
import {
|
|
441
|
-
contextPlugin,
|
|
442
|
-
mountMesurer,
|
|
443
|
-
} from "mesurer-solid"
|
|
444
|
-
import { arrangePlugin } from "mesurer-solid/arrange"
|
|
445
|
-
|
|
446
|
-
const mesurer = mountMesurer({
|
|
447
|
-
agent: true,
|
|
448
|
-
plugins: [
|
|
449
|
-
contextPlugin(),
|
|
450
|
-
arrangePlugin(),
|
|
451
|
-
],
|
|
452
|
-
})
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
The same API is available on `mesurer.agent` and, when configured, `window.__MESURER__`.
|
|
456
|
-
|
|
457
|
-
Arrange remains optional. Applications that only want the base inspector or context workflow do not pay for the Arrange entry-point bundle.
|
|
458
|
-
|
|
459
|
-
## Low-level inspection
|
|
460
|
-
|
|
461
|
-
These remain useful for focused queries:
|
|
202
|
+
After HMR or reload settles:
|
|
462
203
|
|
|
463
204
|
```js
|
|
464
|
-
window.__MESURER__.inspect(".selector")
|
|
465
|
-
window.__MESURER__.inspectAll(".selector")
|
|
466
|
-
window.__MESURER__.at(x, y)
|
|
467
|
-
window.__MESURER__.distance(".a", ".b")
|
|
468
|
-
window.__MESURER__.viewport()
|
|
469
|
-
await window.__MESURER__.feedback([".selector"])
|
|
470
|
-
await window.__MESURER__.state()
|
|
471
205
|
await window.__MESURER__.stable()
|
|
472
206
|
```
|
|
473
207
|
|
|
474
|
-
|
|
208
|
+
Then compare the same evidence retained before editing:
|
|
475
209
|
|
|
476
|
-
|
|
210
|
+
- Arrange Desired against Live through `reviewArrange()`;
|
|
211
|
+
- text/style Desired against Live with the text preview inactive;
|
|
212
|
+
- saved annotations through `review()`;
|
|
213
|
+
- current selections and measurements through fresh `context()`;
|
|
214
|
+
- exact geometry through `inspect()`, `distance()`, and `viewport()`.
|
|
477
215
|
|
|
478
|
-
|
|
216
|
+
Do not clear human history merely to expose Live state, and do not reinject just to refresh context.
|
|
479
217
|
|
|
480
|
-
|
|
481
|
-
1. discover/reuse Mesurer and preserve human state
|
|
482
|
-
2. if the request is broad, inventory Arrange + annotations + selection + workspace context before narrowing
|
|
483
|
-
3. consume relevant Arrange intent first
|
|
484
|
-
4. capture Before/Desired when useful, before source edits
|
|
485
|
-
5. consume existing annotation/selection context
|
|
486
|
-
6. resolve exact targets; ask only when genuinely ambiguous
|
|
487
|
-
7. edit normal source
|
|
488
|
-
8. wait for stable render
|
|
489
|
-
9. switch Arrange to Live when applicable
|
|
490
|
-
10. get fresh Arrange review/context and optional screenshot
|
|
491
|
-
11. iterate until rendered evidence supports completion
|
|
492
|
-
```
|
|
218
|
+
## Completion rule
|
|
493
219
|
|
|
494
|
-
|
|
220
|
+
A meaningful Mesurer call should affect the work. If exact geometry is available, use it instead of estimating pixels from a screenshot. If the user already encoded intent in Arrange, text editing, annotations, or selection, consume it before asking them to repeat it.
|
|
495
221
|
|
|
496
|
-
|
|
222
|
+
The repository's packaged [`mesurer-ui` skill](./skills/mesurer-ui/SKILL.md) carries the operational version of this contract for coding agents. [Browser and agent integration](../../docs/BROWSER_HARNESS.md) documents the outer harness boundary.
|