mesurer-solid 0.1.2 → 0.1.3-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 +166 -154
- package/README.md +188 -232
- package/dist/arrange.d.ts +90 -0
- package/dist/arrange.js +2907 -0
- package/dist/core.js +1 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +4392 -2494
- package/dist/inject-script.js +75 -9
- package/dist/inject.js +4937 -3795
- package/dist/screenshot.js +25 -2
- package/package.json +5 -1
- package/skills/mesurer-ui/SKILL.md +209 -139
package/dist/screenshot.js
CHANGED
|
@@ -2840,7 +2840,30 @@ var Gn = "mesurer:capture-bridge-ping", Kn = "mesurer:capture-bridge-request", q
|
|
|
2840
2840
|
command: Er,
|
|
2841
2841
|
icon: Ar,
|
|
2842
2842
|
active: C,
|
|
2843
|
-
hidden: () => !w().toolEnabled
|
|
2843
|
+
hidden: () => !w().toolEnabled,
|
|
2844
|
+
menu: {
|
|
2845
|
+
label: "Screenshot options",
|
|
2846
|
+
items: [
|
|
2847
|
+
{
|
|
2848
|
+
id: "copy",
|
|
2849
|
+
label: "Auto-copy",
|
|
2850
|
+
checked: () => w().copy,
|
|
2851
|
+
run: () => T({ copy: !w().copy })
|
|
2852
|
+
},
|
|
2853
|
+
{
|
|
2854
|
+
id: "download",
|
|
2855
|
+
label: "Auto-download",
|
|
2856
|
+
checked: () => w().download,
|
|
2857
|
+
run: () => T({ download: !w().download })
|
|
2858
|
+
},
|
|
2859
|
+
{
|
|
2860
|
+
id: "measurements",
|
|
2861
|
+
label: "Include measurements",
|
|
2862
|
+
checked: () => w().includeMeasurements,
|
|
2863
|
+
run: () => T({ includeMeasurements: !w().includeMeasurements })
|
|
2864
|
+
}
|
|
2865
|
+
]
|
|
2866
|
+
}
|
|
2844
2867
|
}), t.settings.register({
|
|
2845
2868
|
id: "screenshot",
|
|
2846
2869
|
label: "Screenshot",
|
|
@@ -2885,7 +2908,7 @@ var Gn = "mesurer:capture-bridge-ping", Kn = "mesurer:capture-bridge-request", q
|
|
|
2885
2908
|
S = !0, y += 1, u.removeEventListener("pointerdown", L), u.removeEventListener("pointermove", R), u.removeEventListener("pointerup", z), u.removeEventListener("pointercancel", B), i.removeEventListener("keydown", V, !0), v && i.clearTimeout(v), ee.dispose(), O(), cr(i), a.finishCapture(), a.dispose(), o.dispose();
|
|
2886
2909
|
});
|
|
2887
2910
|
}
|
|
2888
|
-
}), Rr = "0.1.
|
|
2911
|
+
}), Rr = "0.1.3-beta.0", zr = wr, Br = xr, Vr = Sr, Hr = Cr, Ur = 4, Wr = dr, Gr = (e, t) => Xn(e, t), Kr = (e = /* @__PURE__ */ new Date()) => Zn(e), qr = (e, t, n, r) => Yn(e, t, n, r), Jr = (e, t, n) => Jn(e, t, n), Yr = (e, t) => ur(e, t), Xr = (e) => cr(e), Zr = (e = {}) => ({
|
|
2889
2912
|
...Lr(e),
|
|
2890
2913
|
version: Rr
|
|
2891
2914
|
}), Qr = (e) => $n(e);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mesurer-solid",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3-beta.0",
|
|
4
4
|
"description": "Framework-agnostic UI measurement and inspection tools for browser apps and coding agents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
"types": "./dist/index.d.ts",
|
|
16
16
|
"import": "./dist/index.js"
|
|
17
17
|
},
|
|
18
|
+
"./arrange": {
|
|
19
|
+
"types": "./dist/arrange.d.ts",
|
|
20
|
+
"import": "./dist/arrange.js"
|
|
21
|
+
},
|
|
18
22
|
"./core": {
|
|
19
23
|
"types": "./dist/core.d.ts",
|
|
20
24
|
"import": "./dist/core.js"
|
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mesurer-ui
|
|
3
|
-
description: Use Mesurer when implementing, reviewing, debugging, or fixing frontend UI in a browser. Load for visual alignment, spacing, sizing, layout, CSS, responsive work, design/Figma implementation, screenshots, pixel discrepancies,
|
|
3
|
+
description: Use Mesurer when implementing, reviewing, debugging, or fixing frontend UI in a browser. Load for visual alignment, spacing, sizing, layout, CSS, responsive work, design/Figma implementation, screenshots, pixel discrepancies, human Mesurer selections/measurements/guides/annotations, or Arrange intents. Consume existing human visual intent before editing and obtain fresh rendered evidence before claiming completion.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Mesurer UI workflow
|
|
7
7
|
|
|
8
|
-
Mesurer is
|
|
8
|
+
Mesurer is shared visual state between the person reviewing a page and the coding agent editing it. The rendered page is the integration boundary.
|
|
9
9
|
|
|
10
10
|
There is no Mesurer MCP, WebMCP, ACP, chat-delivery daemon, session router, or Send-to-agent callback in the normal workflow. Use the browser/evaluation channel the harness already owns and read `window.__MESURER__` directly.
|
|
11
11
|
|
|
12
|
-
The
|
|
12
|
+
The central rule is:
|
|
13
13
|
|
|
14
|
-
>
|
|
14
|
+
> A meaningful Mesurer step must return evidence the agent actually consumes.
|
|
15
|
+
|
|
16
|
+
That evidence may be `MesurerContextV1`, `MesurerReviewV1`, an Arrange intent/review, or a focused low-level measurement. Do not merely draw a highlight and continue from memory.
|
|
15
17
|
|
|
16
18
|
```text
|
|
17
19
|
human visual intent or agent UI change
|
|
18
|
-
→
|
|
19
|
-
→
|
|
20
|
-
→
|
|
21
|
-
→
|
|
22
|
-
→
|
|
23
|
-
→
|
|
24
|
-
→
|
|
25
|
-
→ agent iterates until evidence supports completion
|
|
20
|
+
→ preserve existing Mesurer state
|
|
21
|
+
→ consume Arrange / annotation / selection evidence
|
|
22
|
+
→ reason from exact rendered state
|
|
23
|
+
→ edit normal source
|
|
24
|
+
→ wait for the real render
|
|
25
|
+
→ compare fresh rendered state with the human intent
|
|
26
|
+
→ iterate until the evidence supports completion
|
|
26
27
|
```
|
|
27
28
|
|
|
28
|
-
## 1.
|
|
29
|
+
## 1. Reuse the live Mesurer instance
|
|
29
30
|
|
|
30
|
-
Never reinject, dispose, or replace Mesurer just because this skill loaded. The person may already have selected elements, placed guides, measured gaps, held distances, enabled rulers/X-ray, created annotations, or kept a screenshot thumbnail/viewer open. That state is part of the user's message.
|
|
31
|
+
Never reinject, dispose, or replace Mesurer just because this skill loaded. The person may already have selected elements, placed guides, measured gaps, held distances, enabled rulers/X-ray, created annotations, arranged elements into a desired layout, or kept a screenshot thumbnail/viewer open. That state is part of the user's message.
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
Discover the current page first:
|
|
33
34
|
|
|
34
35
|
```js
|
|
35
36
|
const hasMesurer = Boolean(
|
|
@@ -44,28 +45,28 @@ if (hasMesurer) {
|
|
|
44
45
|
|
|
45
46
|
If Mesurer exists, use that exact instance. Do not evaluate the injector again and do not call `dispose()`.
|
|
46
47
|
|
|
47
|
-
If Mesurer is absent, inject the packaged classic payload through the
|
|
48
|
+
If Mesurer is absent, inject the packaged classic payload through the JavaScript-evaluation primitive the harness already owns. The installed skill contains `assets/inject-script.js`; this repository builds `packages/mesurer/dist/inject-script.js`; the npm package exposes `mesurer-solid/inject-script`.
|
|
48
49
|
|
|
49
50
|
Do not add Mesurer to application source, create another browser, create a second CDP connection, start a Mesurer server, or change the application build merely to inspect a page the harness already controls.
|
|
50
51
|
|
|
51
|
-
The injector
|
|
52
|
+
The injector reuses a live injected instance by default. `window.__MESURER_CONFIG__ = { reuseExisting: false }` is an explicit destructive replacement option for tests/tooling. Do not use it while consuming human review state.
|
|
52
53
|
|
|
53
|
-
Normal injection keeps the optional human screenshot plugin disabled. If the task
|
|
54
|
+
Normal injection keeps the optional human screenshot plugin disabled. If the task specifically needs that camera tool, configure it before first injection:
|
|
54
55
|
|
|
55
56
|
```js
|
|
56
57
|
window.__MESURER_CONFIG__ = { screenshot: true }
|
|
57
58
|
```
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
Do not replace/reinject a live instance merely to enable screenshots. Preserve current human state first.
|
|
60
61
|
|
|
61
|
-
After
|
|
62
|
+
After first injection or discovery:
|
|
62
63
|
|
|
63
64
|
```js
|
|
64
65
|
await window.__MESURER__.ready()
|
|
65
66
|
const capabilities = window.__MESURER__.capabilities()
|
|
66
67
|
```
|
|
67
68
|
|
|
68
|
-
The context surface includes:
|
|
69
|
+
The context-oriented surface includes:
|
|
69
70
|
|
|
70
71
|
```text
|
|
71
72
|
context
|
|
@@ -75,15 +76,120 @@ review
|
|
|
75
76
|
capturePlan
|
|
76
77
|
```
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
When the first-party Arrange plugin is mounted, capabilities also reports:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
arrange
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Arrange adds:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
arrangements
|
|
89
|
+
arrange
|
|
90
|
+
showArrange
|
|
91
|
+
arrangeCapturePlan
|
|
92
|
+
reviewArrange
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The optional screenshot plugin remains a separate human tool/service. It is not a screenshot-delivery capability on `window.__MESURER__`.
|
|
96
|
+
|
|
97
|
+
## 2. Consume Arrange before source edits
|
|
98
|
+
|
|
99
|
+
Arrange represents explicit human layout intent. If `capabilities.capabilities.arrange` is true, inspect it before replacing the human selection or editing source:
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
const arrangements = await window.__MESURER__.arrangements()
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
For a relevant intent:
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
const intent = await window.__MESURER__.arrange(arrangeId)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
An Arrange intent contains exact targets plus Before and Desired geometry. Treat Desired as the requested visual outcome, not as an implementation prescription.
|
|
112
|
+
|
|
113
|
+
For example, a target moving `96px` right does **not** mean production code should receive `transform: translateX(96px)`. Inspect the surrounding layout and implement the appropriate source-level change: flex/grid alignment, gap, margin, sizing, placement, component structure, or another semantic layout rule.
|
|
114
|
+
|
|
115
|
+
### Capture Before and Desired before HMR
|
|
116
|
+
|
|
117
|
+
Arrange can reconstruct both states while the original source-rendered page is still present. If the harness can capture screenshots, capture both before editing source.
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
await window.__MESURER__.showArrange(arrangeId, "before")
|
|
121
|
+
const beforePlan = await window.__MESURER__.arrangeCapturePlan(arrangeId, "before")
|
|
122
|
+
|
|
123
|
+
await window.__MESURER__.prepareCapture()
|
|
124
|
+
try {
|
|
125
|
+
// Use the current browser harness screenshot primitive with beforePlan.
|
|
126
|
+
} finally {
|
|
127
|
+
await window.__MESURER__.finishCapture()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
await window.__MESURER__.showArrange(arrangeId, "desired")
|
|
131
|
+
const desiredPlan = await window.__MESURER__.arrangeCapturePlan(arrangeId, "desired")
|
|
132
|
+
|
|
133
|
+
await window.__MESURER__.prepareCapture()
|
|
134
|
+
try {
|
|
135
|
+
// Capture the Desired state with the same harness.
|
|
136
|
+
} finally {
|
|
137
|
+
await window.__MESURER__.finishCapture()
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The user should not need to export or attach these images. The coding harness already owns screenshot bytes; Mesurer owns the reproducible visual states and capture geometry.
|
|
142
|
+
|
|
143
|
+
Retain:
|
|
144
|
+
|
|
145
|
+
- the Arrange id;
|
|
146
|
+
- target selectors/fingerprints;
|
|
147
|
+
- Before geometry;
|
|
148
|
+
- Desired geometry and offsets;
|
|
149
|
+
- the Before screenshot when available;
|
|
150
|
+
- the Desired screenshot when available.
|
|
151
|
+
|
|
152
|
+
Do this **before** source changes or HMR can alter the baseline.
|
|
153
|
+
|
|
154
|
+
### Verify the real implementation against Desired
|
|
155
|
+
|
|
156
|
+
After source changes and a stable render, switch Arrange to Live. Live removes Arrange's temporary visual preview so the page shows only what the application source actually produces.
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
await window.__MESURER__.stable()
|
|
160
|
+
await window.__MESURER__.showArrange(arrangeId, "live")
|
|
161
|
+
const review = await window.__MESURER__.reviewArrange(arrangeId)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`reviewArrange()` reports exact current-vs-Desired rectangle deltas and whether the targets match within tolerance. If it says the result is still off, continue editing.
|
|
165
|
+
|
|
166
|
+
A typical loop is:
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
Before Desired Live
|
|
170
|
+
x 120 → x 284 x 276
|
|
171
|
+
remaining +8px
|
|
172
|
+
|
|
173
|
+
edit source
|
|
174
|
+
↓
|
|
175
|
+
wait for stable render
|
|
176
|
+
↓
|
|
177
|
+
Live x 284
|
|
178
|
+
↓
|
|
179
|
+
matched ✓
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
If review reports `stale` or `partial`, do not silently transfer the intent to a different element. Resolve target identity conservatively or ask the user to reselect/rearrange if ambiguity remains.
|
|
79
183
|
|
|
80
|
-
|
|
184
|
+
Do not clear, overwrite, or discard a human Arrange intent merely to make validation pass.
|
|
81
185
|
|
|
82
|
-
|
|
186
|
+
## 3. Acquire ordinary context in the right order
|
|
83
187
|
|
|
84
|
-
|
|
188
|
+
After preserving any relevant Arrange intent, use this order for the rest of the visual evidence.
|
|
85
189
|
|
|
86
|
-
|
|
190
|
+
### A. Existing human selection or annotation
|
|
191
|
+
|
|
192
|
+
Read it before changing selection yourself:
|
|
87
193
|
|
|
88
194
|
```js
|
|
89
195
|
const workspace = await window.__MESURER__.context()
|
|
@@ -97,7 +203,7 @@ try {
|
|
|
97
203
|
}
|
|
98
204
|
```
|
|
99
205
|
|
|
100
|
-
For
|
|
206
|
+
For a relevant annotation:
|
|
101
207
|
|
|
102
208
|
```js
|
|
103
209
|
const annotationContext = await window.__MESURER__.context({
|
|
@@ -105,31 +211,29 @@ const annotationContext = await window.__MESURER__.context({
|
|
|
105
211
|
})
|
|
106
212
|
```
|
|
107
213
|
|
|
108
|
-
Treat annotation notes as human intent. Treat selection, guides, distances, measurements, geometry, computed styles, and screenshots as evidence supporting that intent.
|
|
109
|
-
|
|
110
|
-
Do not overwrite a meaningful human selection until you have read and retained its context in the current task.
|
|
214
|
+
Treat annotation notes and Arrange Desired state as human intent. Treat selection, guides, distances, measurements, exact geometry, computed styles, and screenshots as evidence supporting that intent.
|
|
111
215
|
|
|
112
|
-
|
|
216
|
+
Do not overwrite a meaningful human selection until its context has been retained in the current task.
|
|
113
217
|
|
|
114
|
-
|
|
218
|
+
### B. No relevant selection and the target is ambiguous
|
|
115
219
|
|
|
116
|
-
Ask the user to select the intended element(s) or
|
|
220
|
+
Ask the user to select the intended element(s) or region with Mesurer. Then immediately read:
|
|
117
221
|
|
|
118
222
|
```js
|
|
119
223
|
const selection = await window.__MESURER__.context({ scope: "selection" })
|
|
120
224
|
```
|
|
121
225
|
|
|
122
|
-
|
|
226
|
+
Do not guess merely to avoid asking for a selection.
|
|
123
227
|
|
|
124
|
-
### C.
|
|
228
|
+
### C. The agent knows the exact rendered target
|
|
125
229
|
|
|
126
|
-
|
|
230
|
+
Select it yourself:
|
|
127
231
|
|
|
128
232
|
```js
|
|
129
233
|
const context = await window.__MESURER__.select("#pricing-card")
|
|
130
234
|
```
|
|
131
235
|
|
|
132
|
-
For
|
|
236
|
+
For multiple targets:
|
|
133
237
|
|
|
134
238
|
```js
|
|
135
239
|
const context = await window.__MESURER__.select([
|
|
@@ -138,19 +242,13 @@ const context = await window.__MESURER__.select([
|
|
|
138
242
|
])
|
|
139
243
|
```
|
|
140
244
|
|
|
141
|
-
`select()`
|
|
142
|
-
|
|
143
|
-
1. switches Mesurer to Select and visibly highlights the exact rendered targets;
|
|
144
|
-
2. makes those elements the live Mesurer selection;
|
|
145
|
-
3. **returns selection-scoped `MesurerContextV1` after the selection settles**.
|
|
245
|
+
`select()` switches Mesurer to Select, visibly highlights the exact targets, makes them the live selection, waits for the selection to settle, and returns selection-scoped `MesurerContextV1`.
|
|
146
246
|
|
|
147
|
-
Use the returned object. Do not call `select()` only for the highlight
|
|
247
|
+
Use the returned object. Do not call `select()` only for the highlight.
|
|
148
248
|
|
|
149
|
-
|
|
249
|
+
Every supplied selector must resolve to exactly one page target. Missing, invalid, or ambiguous selectors throw. Refine the selector or ask the user to select the target rather than guessing.
|
|
150
250
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
## 3. Understand the context you receive
|
|
251
|
+
## 4. Read rendered context, not source assumptions
|
|
154
252
|
|
|
155
253
|
`MesurerContextV1` is JSON-safe and uses `viewport-css-px` coordinates. Relevant fields include:
|
|
156
254
|
|
|
@@ -179,20 +277,20 @@ visualContext
|
|
|
179
277
|
distances[]
|
|
180
278
|
```
|
|
181
279
|
|
|
182
|
-
Mesurer's rendered values are the source of truth. Prefer them over
|
|
280
|
+
Mesurer's rendered values are the source of truth. Prefer them over screenshot estimates or source-level assumptions.
|
|
183
281
|
|
|
184
282
|
Examples:
|
|
185
283
|
|
|
186
284
|
- left edges differ by `4px` → the targets are not aligned;
|
|
187
|
-
- rendered
|
|
188
|
-
- width is `318px` → do not report `320px`
|
|
189
|
-
- overflow flags are true → the rendered
|
|
285
|
+
- rendered gap is `37px` → do not claim `24px` because CSS contains `gap: 24px`;
|
|
286
|
+
- rendered width is `318px` → do not report `320px` until the browser measures it;
|
|
287
|
+
- overflow flags are true → the rendered component is overflowing even if source math looked correct.
|
|
190
288
|
|
|
191
|
-
##
|
|
289
|
+
## 5. Treat multi-selection as relational evidence
|
|
192
290
|
|
|
193
|
-
When several elements are selected,
|
|
291
|
+
When several elements are selected, inspect every relevant target and their relationships. Do not summarize the state as only “3 selected.”
|
|
194
292
|
|
|
195
|
-
For
|
|
293
|
+
For each target, consume:
|
|
196
294
|
|
|
197
295
|
```text
|
|
198
296
|
selector / identity / text / accessibility
|
|
@@ -204,52 +302,39 @@ layout: display / position / flex / grid / gap / transform / overflow
|
|
|
204
302
|
scroll/client dimensions and overflow flags
|
|
205
303
|
```
|
|
206
304
|
|
|
207
|
-
|
|
305
|
+
Start with `selection.visualContext.distances`; for a needed pair not represented there:
|
|
208
306
|
|
|
209
307
|
```js
|
|
210
308
|
const pair = window.__MESURER__.distance(selectorA, selectorB)
|
|
211
309
|
```
|
|
212
310
|
|
|
213
|
-
For a small selection, report
|
|
311
|
+
For a small selection, report useful unique pair relationships. For a large repeated set, focus on adjacent/repeated/user-relevant relationships rather than dumping O(n²) pairs.
|
|
214
312
|
|
|
215
|
-
|
|
313
|
+
## 6. Preserve the baseline before editing
|
|
216
314
|
|
|
217
|
-
|
|
218
|
-
Card A: 320 × 180
|
|
219
|
-
Card B: 320 × 180
|
|
220
|
-
Card C: 320 × 180
|
|
221
|
-
A → B horizontal gap: 24px
|
|
222
|
-
B → C horizontal gap: 24px
|
|
223
|
-
A/B top-edge delta: 0px
|
|
224
|
-
```
|
|
315
|
+
If the human supplied selection, measurements, an annotation, or Arrange state, retain the relevant baseline before source changes or HMR can replace nodes.
|
|
225
316
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
## 5. Before editing, retain the baseline you need
|
|
229
|
-
|
|
230
|
-
If the human supplied a selection, workspace measurement, or annotation, capture its relevant context before source changes or HMR can replace nodes.
|
|
231
|
-
|
|
232
|
-
For a durable human annotation:
|
|
317
|
+
Annotation:
|
|
233
318
|
|
|
234
319
|
```js
|
|
235
320
|
const before = await window.__MESURER__.context({ annotation: annotationId })
|
|
236
321
|
```
|
|
237
322
|
|
|
238
|
-
|
|
323
|
+
Live selection:
|
|
239
324
|
|
|
240
325
|
```js
|
|
241
326
|
const before = await window.__MESURER__.context({ scope: "selection" })
|
|
242
327
|
```
|
|
243
328
|
|
|
244
|
-
|
|
329
|
+
Arrange: capture the intent plus Before/Desired states as described above.
|
|
245
330
|
|
|
246
|
-
Do not mutate human guides, measurements, held distances, annotations, or screenshot preview/viewer state merely to make
|
|
331
|
+
Do not mutate human guides, measurements, held distances, annotations, Arrange history, or screenshot preview/viewer state merely to make the implementation appear correct.
|
|
247
332
|
|
|
248
|
-
##
|
|
333
|
+
## 7. Edit the real implementation
|
|
249
334
|
|
|
250
|
-
Make the smallest source change that addresses the rendered issue. Use the project's normal
|
|
335
|
+
Make the smallest source change that addresses the rendered issue. Use the project's normal source, build, and dev-server workflow.
|
|
251
336
|
|
|
252
|
-
Mesurer does not own source edits,
|
|
337
|
+
Mesurer does not own source edits, navigation, or the dev server. Do not create Mesurer-specific infrastructure for those jobs.
|
|
253
338
|
|
|
254
339
|
After HMR/render:
|
|
255
340
|
|
|
@@ -257,33 +342,37 @@ After HMR/render:
|
|
|
257
342
|
await window.__MESURER__.stable()
|
|
258
343
|
```
|
|
259
344
|
|
|
260
|
-
##
|
|
345
|
+
## 8. Fresh rendered evidence is part of completion
|
|
261
346
|
|
|
262
|
-
|
|
347
|
+
Lint, typecheck, tests, and build are implementation checks. They do not prove a visual result.
|
|
263
348
|
|
|
264
|
-
Use the strongest
|
|
349
|
+
Use the strongest applicable completion path.
|
|
265
350
|
|
|
266
|
-
###
|
|
351
|
+
### Arrange intent
|
|
267
352
|
|
|
268
353
|
```js
|
|
269
354
|
await window.__MESURER__.stable()
|
|
270
|
-
|
|
355
|
+
await window.__MESURER__.showArrange(arrangeId, "live")
|
|
356
|
+
const review = await window.__MESURER__.reviewArrange(arrangeId)
|
|
271
357
|
```
|
|
272
358
|
|
|
273
|
-
|
|
359
|
+
Continue until the live source-rendered geometry matches Desired within the expected tolerance, and use a fresh screenshot when visual composition matters.
|
|
274
360
|
|
|
275
|
-
### Human
|
|
361
|
+
### Human annotation
|
|
276
362
|
|
|
277
363
|
```js
|
|
278
364
|
await window.__MESURER__.stable()
|
|
279
|
-
const
|
|
365
|
+
const review = await window.__MESURER__.review(annotationId)
|
|
280
366
|
```
|
|
281
367
|
|
|
282
|
-
|
|
368
|
+
### Still-relevant human selection
|
|
283
369
|
|
|
284
|
-
|
|
370
|
+
```js
|
|
371
|
+
await window.__MESURER__.stable()
|
|
372
|
+
const after = await window.__MESURER__.context({ scope: "selection" })
|
|
373
|
+
```
|
|
285
374
|
|
|
286
|
-
|
|
375
|
+
### Agent-known changed targets
|
|
287
376
|
|
|
288
377
|
```js
|
|
289
378
|
await window.__MESURER__.stable()
|
|
@@ -293,69 +382,48 @@ const after = await window.__MESURER__.select([
|
|
|
293
382
|
])
|
|
294
383
|
```
|
|
295
384
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
### The affected target is now ambiguous
|
|
299
|
-
|
|
300
|
-
Ask the user to select the intended result, then read the resulting selection context. Do not manufacture confidence from a guessed selector.
|
|
301
|
-
|
|
302
|
-
A visual task is not complete merely because `select()` drew an outline. **Consume the returned context and reason from it.**
|
|
303
|
-
|
|
304
|
-
## 8. Human screenshots and agent screenshot evidence are different paths
|
|
305
|
-
|
|
306
|
-
Mesurer now has an optional first-party screenshot plugin for human capture, while coding-agent verification can continue to use the outer harness's screenshot primitive. Do not conflate the two.
|
|
307
|
-
|
|
308
|
-
### Human screenshot plugin
|
|
385
|
+
If target identity is ambiguous after the change, ask the user to select the intended result. Do not manufacture confidence from a guessed selector.
|
|
309
386
|
|
|
310
|
-
|
|
387
|
+
## 9. Human screenshots and agent screenshots are different paths
|
|
311
388
|
|
|
312
|
-
The plugin
|
|
389
|
+
The optional `mesurer.screenshot` plugin gives the person a camera tool. It can copy/download a HiDPI-aware PNG and keep a draggable preview/viewer. Do not treat it as an agent-delivery transport or destroy a human preview unless the task explicitly requires it.
|
|
313
390
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
```js
|
|
317
|
-
window.__MESURER_CONFIG__ = { screenshot: true }
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
Source-mounted applications import `screenshotPlugin` from `mesurer-solid/screenshot`. Normal browsers use `getDisplayMedia()` and reuse a live capture stream; the first-party Chrome extension enables the plugin automatically and uses `chrome.tabs.captureVisibleTab()` through its isolated-world bridge, so its camera path does not open the screen-share chooser.
|
|
321
|
-
|
|
322
|
-
The screenshot plugin is a human tool/service, not a chat or agent-delivery channel. Do not infer a `screenshots` capability on `window.__MESURER__`, and do not close or replace an existing human preview unless the task explicitly requires it.
|
|
323
|
-
|
|
324
|
-
### Agent verification screenshots
|
|
325
|
-
|
|
326
|
-
For ordinary coding-agent verification, use the current harness/browser's real screenshot primitive so the harness controls the exact viewport, timing, and artifact. Mesurer supplies geometry and clean capture scope/presentation:
|
|
391
|
+
For normal coding-agent verification, the outer harness owns screenshot bytes. Mesurer supplies exact scope and clean presentation:
|
|
327
392
|
|
|
328
393
|
```js
|
|
329
394
|
const plan = await window.__MESURER__.capturePlan({ scope: "selection" })
|
|
330
395
|
await window.__MESURER__.prepareCapture()
|
|
331
396
|
try {
|
|
332
|
-
// Use the current harness/browser
|
|
397
|
+
// Use the current harness/browser screenshot primitive.
|
|
333
398
|
} finally {
|
|
334
399
|
await window.__MESURER__.finishCapture()
|
|
335
400
|
}
|
|
336
401
|
```
|
|
337
402
|
|
|
403
|
+
Arrange follows the same ownership model through `arrangeCapturePlan()`. The important difference is that Arrange can deliberately present Before, Desired, or Live before the harness captures.
|
|
404
|
+
|
|
338
405
|
Use both signals:
|
|
339
406
|
|
|
340
407
|
```text
|
|
341
|
-
Mesurer context
|
|
342
|
-
real screenshot
|
|
408
|
+
Mesurer context/review → exact geometry, styles, distances, overflow
|
|
409
|
+
real screenshot → composition, hierarchy, clipping, color, visual judgment
|
|
343
410
|
```
|
|
344
411
|
|
|
345
|
-
Screenshots
|
|
412
|
+
Screenshots do not replace exact Mesurer measurements, and Mesurer numbers do not replace visual judgment.
|
|
346
413
|
|
|
347
|
-
##
|
|
414
|
+
## 10. HMR and stale-target rules
|
|
348
415
|
|
|
349
|
-
Annotations
|
|
416
|
+
Annotations and Arrange intents rebind conservatively after DOM replacement. If review reports `stale` or `partial`, do not silently bind human intent to a different element.
|
|
350
417
|
|
|
351
|
-
An unsaved selection can disappear when HMR replaces nodes. Preserve initial context before editing. After
|
|
418
|
+
An unsaved selection can disappear when HMR replaces nodes. Preserve initial context before editing. After render, use original exact selectors when still valid, `select()` known replacement targets when unambiguous, or ask the user to reselect when identity is uncertain.
|
|
352
419
|
|
|
353
|
-
##
|
|
420
|
+
## 11. Completion standard
|
|
354
421
|
|
|
355
|
-
A visual completion statement
|
|
422
|
+
A valid visual completion statement is grounded in fresh rendered evidence, for example:
|
|
356
423
|
|
|
357
424
|
```text
|
|
358
|
-
-
|
|
425
|
+
- Arrange Live now matches Desired within 1px
|
|
426
|
+
- selected cards measure 320px wide
|
|
359
427
|
- rendered horizontal gap is 24px
|
|
360
428
|
- selected top edges differ by 0px
|
|
361
429
|
- component horizontal overflow is false
|
|
@@ -372,13 +440,11 @@ tests passed
|
|
|
372
440
|
build passed
|
|
373
441
|
```
|
|
374
442
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
If Mesurer is available and you could identify the affected UI, finishing without fresh Mesurer context is a workflow failure.
|
|
443
|
+
If Mesurer is available and the affected UI can be identified, finishing without fresh Mesurer evidence is a workflow failure.
|
|
378
444
|
|
|
379
|
-
##
|
|
445
|
+
## 12. Low-level helpers
|
|
380
446
|
|
|
381
|
-
Use these
|
|
447
|
+
Use these only when scoped context/review is not enough:
|
|
382
448
|
|
|
383
449
|
```js
|
|
384
450
|
await window.__MESURER__.ready()
|
|
@@ -392,24 +458,27 @@ await window.__MESURER__.state()
|
|
|
392
458
|
await window.__MESURER__.stable()
|
|
393
459
|
```
|
|
394
460
|
|
|
395
|
-
Prefer `context()`, `select()`, and `review()` for human-in-the-loop work because they preserve visual meaning and
|
|
461
|
+
Prefer `arrangements()`, `context()`, `select()`, `reviewArrange()`, and `review()` for human-in-the-loop work because they preserve visual meaning and return evidence that can be carried directly into reasoning.
|
|
396
462
|
|
|
397
|
-
##
|
|
463
|
+
## 13. Do not do these things
|
|
398
464
|
|
|
399
465
|
- do not look for an MCP/WebMCP tool;
|
|
400
466
|
- do not start a local feedback server;
|
|
401
467
|
- do not discover chat/thread/session IDs;
|
|
402
468
|
- do not route Mesurer through ACP or another delivery protocol;
|
|
403
469
|
- do not recreate Send-to-agent;
|
|
404
|
-
- do not treat
|
|
470
|
+
- do not treat screenshot capture as an agent-delivery transport;
|
|
405
471
|
- do not create another browser/CDP connection when the harness already controls the page;
|
|
406
472
|
- do not reinject over live human Mesurer state;
|
|
407
473
|
- do not overwrite human selection before reading it;
|
|
474
|
+
- do not clear or alter human Arrange history to make validation pass;
|
|
475
|
+
- do not implement Arrange offsets as production transforms unless the source layout genuinely calls for that;
|
|
476
|
+
- do not capture only Desired after source editing; preserve Before and Desired first when screenshot comparison matters;
|
|
408
477
|
- do not close/destroy a human screenshot preview merely to clean up agent state;
|
|
409
478
|
- do not use `select()` with a knowingly ambiguous selector;
|
|
410
479
|
- do not ask the user to select something the agent can identify exactly itself;
|
|
411
|
-
- do not guess when the intended target really is ambiguous
|
|
412
|
-
- do not ignore
|
|
480
|
+
- do not guess when the intended target really is ambiguous;
|
|
481
|
+
- do not ignore context returned by `select()`;
|
|
413
482
|
- do not alter human measurements/guides to make validation pass;
|
|
414
483
|
- do not infer exact geometry from screenshots when Mesurer reports the number;
|
|
415
484
|
- do not claim visual completion from source/build output alone.
|
|
@@ -422,7 +491,8 @@ existing agent harness
|
|
|
422
491
|
existing rendered page
|
|
423
492
|
↕
|
|
424
493
|
window.__MESURER__
|
|
425
|
-
↳
|
|
494
|
+
↳ arrangements() / context() / select()
|
|
495
|
+
↳ reviewArrange() / review()
|
|
426
496
|
```
|
|
427
497
|
|
|
428
|
-
**
|
|
498
|
+
**Rendered evidence is the output.**
|