my-frontend-observer 0.1.0 → 0.3.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/CHANGELOG.md +82 -1
- package/README.md +30 -7
- package/dist/application/observationPersistence.js +1 -0
- package/dist/application/observationPersistence.js.map +1 -1
- package/dist/browser/chromiumAdapter.js +58 -4
- package/dist/browser/chromiumAdapter.js.map +1 -1
- package/dist/browser/evidenceCapture.d.ts +46 -3
- package/dist/browser/evidenceCapture.js +393 -94
- package/dist/browser/evidenceCapture.js.map +1 -1
- package/dist/browser/scrollCapture.d.ts +32 -0
- package/dist/browser/scrollCapture.js +163 -0
- package/dist/browser/scrollCapture.js.map +1 -0
- package/dist/browser/types.d.ts +3 -1
- package/dist/cli.js +165 -7
- package/dist/cli.js.map +1 -1
- package/dist/domain/diagnostics.d.ts +1 -1
- package/dist/domain/diagnostics.js +2 -0
- package/dist/domain/diagnostics.js.map +1 -1
- package/dist/domain/identity.d.ts +8 -3
- package/dist/domain/identity.js +10 -4
- package/dist/domain/identity.js.map +1 -1
- package/dist/domain/schema.d.ts +164 -6
- package/dist/domain/schema.js +314 -4
- package/dist/domain/schema.js.map +1 -1
- package/dist/domain/scrollEvidence.d.ts +51 -0
- package/dist/domain/scrollEvidence.js +134 -0
- package/dist/domain/scrollEvidence.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/request/request.d.ts +57 -1
- package/dist/request/request.js +292 -14
- package/dist/request/request.js.map +1 -1
- package/docs/ARCHITECTURE.md +62 -1
- package/docs/CI_CD.md +49 -8
- package/docs/COMMANDS.md +184 -9
- package/docs/CONTRACTS.md +135 -6
- package/docs/CURRENT_STATE.md +128 -6
- package/docs/DEVELOPMENT.md +41 -3
- package/docs/PROJECT_OVERVIEW.md +12 -6
- package/docs/QUICKSTART.md +3 -1
- package/docs/RELEASE.md +12 -5
- package/docs/ROADMAP.md +9 -0
- package/docs/SECURITY.md +6 -2
- package/docs/WORKFLOWS.md +41 -14
- package/package.json +1 -1
package/docs/COMMANDS.md
CHANGED
|
@@ -21,10 +21,18 @@ Options:
|
|
|
21
21
|
- `--viewport <WIDTHxHEIGHT>` — e.g. `1280x720`. Malformed syntax (missing
|
|
22
22
|
`x`, non-numeric, empty side) is rejected before any browser launches;
|
|
23
23
|
in-range bounds are enforced by the existing request validator.
|
|
24
|
-
- `--target <id=css-selector>` — an explicit observation
|
|
25
|
-
order is preserved. Parsed on the *first* `=` only, so
|
|
26
|
-
containing `=` survives intact, e.g.
|
|
27
|
-
`--target action=button[data-state="active"]`.
|
|
24
|
+
- `--target <id=css-selector>` — an explicit CSS-shorthand observation
|
|
25
|
+
target. Repeatable; order is preserved. Parsed on the *first* `=` only, so
|
|
26
|
+
a selector containing `=` survives intact, e.g.
|
|
27
|
+
`--target action=button[data-state="active"]`. Cannot be combined with
|
|
28
|
+
`--targets-file`.
|
|
29
|
+
- `--targets-file <json-file>` — loads structured semantic observation
|
|
30
|
+
targets from a local JSON file instead of `--target`. Cannot be combined
|
|
31
|
+
with `--target`. See "Structured semantic targets" below.
|
|
32
|
+
- `--scroll-scenario-file <json-file>` — loads one bounded runtime scroll
|
|
33
|
+
scenario from a local JSON file. May be combined with either `--target` or
|
|
34
|
+
`--targets-file` (it is independent of target configuration). See "Scroll
|
|
35
|
+
scenario (`--scroll-scenario-file`)" below.
|
|
28
36
|
- `--output <directory>` — portable, relative output location for the
|
|
29
37
|
observation artifact (same contract as the request's `outputLocation`; no
|
|
30
38
|
drive letter, no leading `/`, no `..` segments).
|
|
@@ -53,6 +61,170 @@ capture. CLI-syntax errors (e.g. a missing `--url`) print as `error:
|
|
|
53
61
|
<message>` followed by `observe` usage; request/capture/persistence
|
|
54
62
|
diagnostics print one per line as `[code] message`.
|
|
55
63
|
|
|
64
|
+
### Structured semantic targets (`--targets-file`)
|
|
65
|
+
|
|
66
|
+
**Current status: shipped as part of the published `my-frontend-observer@0.3.0`
|
|
67
|
+
package.** `--target` (CSS shorthand) remains fully supported alongside it.
|
|
68
|
+
|
|
69
|
+
`--targets-file <json-file>` is the public entry point to the v0.2 canonical
|
|
70
|
+
target/locator model established in `src/request/request.ts`. It supplies
|
|
71
|
+
the same `targets` collection that `--target` supplies, just in structured
|
|
72
|
+
form; both converge on the same `normalizeRequest()` validation and the same
|
|
73
|
+
downstream browser resolver - there is no separate semantic observation path.
|
|
74
|
+
|
|
75
|
+
File format (the exact, first frozen structure - the root object supports
|
|
76
|
+
only the `targets` field; any other top-level field is rejected):
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"targets": [
|
|
81
|
+
{
|
|
82
|
+
"name": "primary-navigation",
|
|
83
|
+
"locators": [
|
|
84
|
+
{ "kind": "role", "role": "navigation", "name": "Primary" },
|
|
85
|
+
{ "kind": "id", "value": "nav" }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "workspace",
|
|
90
|
+
"locators": [
|
|
91
|
+
{ "kind": "data-attribute", "attribute": "data-region", "value": "workspace" }
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Each target has a stable `name` and an ordered `locators` array (1-5
|
|
99
|
+
entries; order is the fallback order - the first locator that resolves
|
|
100
|
+
uniquely wins, an ambiguous or unevaluable locator stops immediately without
|
|
101
|
+
trying the next one). Each locator is one of the six frozen kinds:
|
|
102
|
+
|
|
103
|
+
- `{ "kind": "role", "role": "<string>", "name"?: "<string>" }`
|
|
104
|
+
- `{ "kind": "id", "value": "<string>" }`
|
|
105
|
+
- `{ "kind": "data-attribute", "attribute": "data-*", "value": "<string>" }`
|
|
106
|
+
- `{ "kind": "semantic-element", "tag": "<one of the frozen structural tags>" }`
|
|
107
|
+
- `{ "kind": "css", "selector": "<string>" }`
|
|
108
|
+
- `{ "kind": "text", "text": "<exact string>" }`
|
|
109
|
+
|
|
110
|
+
`--targets-file` itself only validates that the file is readable, is valid
|
|
111
|
+
JSON, and has an object root containing exactly a `targets` field - every
|
|
112
|
+
target/locator-internal rule (bounds, per-kind required fields, supported
|
|
113
|
+
values) is enforced by the same `normalizeRequest()` validator `--target`
|
|
114
|
+
already goes through, so both input modes produce identical diagnostics for
|
|
115
|
+
equivalent mistakes.
|
|
116
|
+
|
|
117
|
+
The path may be relative (resolved from the current working directory) or
|
|
118
|
+
absolute; it is operational input only - it never affects the observation's
|
|
119
|
+
request identity and is never written into `manifest.json`.
|
|
120
|
+
|
|
121
|
+
Example:
|
|
122
|
+
|
|
123
|
+
```powershell
|
|
124
|
+
my-frontend-observer observe `
|
|
125
|
+
--url http://localhost:3000/ `
|
|
126
|
+
--viewport 1280x720 `
|
|
127
|
+
--targets-file .\targets.json `
|
|
128
|
+
--output observations
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Scroll scenario (`--scroll-scenario-file`)
|
|
132
|
+
|
|
133
|
+
**Current status: shipped as part of the published `my-frontend-observer@0.3.0`
|
|
134
|
+
package.** Observation schema is `1.2.0`.
|
|
135
|
+
|
|
136
|
+
`--scroll-scenario-file <json-file>` is the public entry point to the v0.3
|
|
137
|
+
runtime scroll-scenario contract established in `src/request/request.ts`
|
|
138
|
+
(`ScrollScenario`/`ScrollAction`) and executed in `src/browser/`. It supplies
|
|
139
|
+
exactly the value of the normalized request's `scrollScenario` field - the
|
|
140
|
+
file root *is* the scenario object itself, with no wrapper field (unlike
|
|
141
|
+
`--targets-file`'s `{ "targets": [...] }` root).
|
|
142
|
+
|
|
143
|
+
A request supports **zero or one** scroll scenario. There are exactly two
|
|
144
|
+
supported action kinds:
|
|
145
|
+
|
|
146
|
+
Window scrolling:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"action": {
|
|
151
|
+
"kind": "window-scroll-by",
|
|
152
|
+
"deltaX": 0,
|
|
153
|
+
"deltaY": 600
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Target scrolling (the `target` value must be the stable `name` of one of the
|
|
159
|
+
observation's own configured targets - never a CSS selector, DOM id, or
|
|
160
|
+
source symbol):
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"action": {
|
|
165
|
+
"kind": "target-scroll-by",
|
|
166
|
+
"target": "tool-workspace",
|
|
167
|
+
"deltaX": 0,
|
|
168
|
+
"deltaY": 400
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`deltaX`/`deltaY` are signed integers bounded to `[-20000, 20000]`; at least
|
|
174
|
+
one must be non-zero (both zero is rejected). Every scroll/action rule -
|
|
175
|
+
supported action kind, required fields, delta types/bounds, the both-zero
|
|
176
|
+
rule, and the stable-target-name reference for `target-scroll-by` - is
|
|
177
|
+
enforced by the same `normalizeRequest()` validator used everywhere else, not
|
|
178
|
+
duplicated in CLI code; `--scroll-scenario-file` itself only validates that
|
|
179
|
+
the file is readable, is valid JSON, and has a non-array object root.
|
|
180
|
+
|
|
181
|
+
The observer performs the requested scroll immediately (no smooth-scroll
|
|
182
|
+
animation), waits exactly two `requestAnimationFrame` cycles, and captures a
|
|
183
|
+
final runtime snapshot - the same final state that the observation's ordinary
|
|
184
|
+
`pageEvidence`, `targetEvidence`, and `screenshot.png` describe. The actual
|
|
185
|
+
resulting scroll position is browser-authoritative and may be clamped by
|
|
186
|
+
document/element boundaries; a scenario that produces no movement (already at
|
|
187
|
+
a boundary, or a non-scrollable target) is still a valid, successfully
|
|
188
|
+
persisted observation, never a fabricated failure.
|
|
189
|
+
|
|
190
|
+
Usable with either target input mode:
|
|
191
|
+
|
|
192
|
+
```powershell
|
|
193
|
+
my-frontend-observer observe `
|
|
194
|
+
--url http://localhost:3000/ `
|
|
195
|
+
--target workspace=.workspace `
|
|
196
|
+
--scroll-scenario-file .\scroll.json `
|
|
197
|
+
--output observations
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```powershell
|
|
201
|
+
my-frontend-observer observe `
|
|
202
|
+
--url http://localhost:3000/ `
|
|
203
|
+
--targets-file .\targets.json `
|
|
204
|
+
--scroll-scenario-file .\scroll.json `
|
|
205
|
+
--output observations
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
`--target` and `--targets-file` remain mutually exclusive with each other,
|
|
209
|
+
exactly as before; `--scroll-scenario-file` is independent of both and is
|
|
210
|
+
never itself a third mutually-exclusive target mode. `window-scroll-by`
|
|
211
|
+
requires no configured target at all.
|
|
212
|
+
|
|
213
|
+
The path may be relative (resolved from the current working directory) or
|
|
214
|
+
absolute; it is operational input only - like `--targets-file`'s path, it
|
|
215
|
+
never affects the observation's request identity and is never written into
|
|
216
|
+
`manifest.json`. Two different scenario files with identical content produce
|
|
217
|
+
the same `requestId`; only the requested scenario *configuration*
|
|
218
|
+
participates in identity, never the runtime outcome (actual scroll
|
|
219
|
+
distance, clamping, or scroll-owner result).
|
|
220
|
+
|
|
221
|
+
If a `target-scroll-by` scenario's configured action target cannot be
|
|
222
|
+
uniquely resolved at runtime (missing, ambiguous, or otherwise unavailable),
|
|
223
|
+
the scroll is not performed, no movement is fabricated, and the observation
|
|
224
|
+
persists honestly - typically as `partial` - carrying the same
|
|
225
|
+
`target-missing`/`target-ambiguous`/`browser-evidence-unavailable` diagnostic
|
|
226
|
+
that any other unresolved configured target would produce.
|
|
227
|
+
|
|
56
228
|
## Foundation commands
|
|
57
229
|
|
|
58
230
|
- `npm install` — install dependencies (includes the `playwright` runtime
|
|
@@ -75,8 +247,11 @@ diagnostics print one per line as `[code] message`.
|
|
|
75
247
|
- `npm run build` — clean and compile `src/` (including `src/cli.ts`) to
|
|
76
248
|
`dist/`.
|
|
77
249
|
- `npm run check:docs` — validate canonical documents and roadmap structure.
|
|
78
|
-
- `npm pack --dry-run` — inspect the
|
|
79
|
-
publishing. The real tarball has been installed and exercised in a
|
|
80
|
-
temporary consumer directory (real Chromium install, real `observe`
|
|
81
|
-
real artifact) as part of v0.1
|
|
82
|
-
validation,
|
|
250
|
+
- `npm pack --dry-run` — inspect the public package's tarball inventory
|
|
251
|
+
before publishing. The real tarball has been installed and exercised in a
|
|
252
|
+
clean temporary consumer directory (real Chromium install, real `observe`
|
|
253
|
+
run, real artifact) on Windows, Linux, and macOS as part of v0.1
|
|
254
|
+
validation, again for v0.2's packed semantic `--targets-file` behavior,
|
|
255
|
+
and again for v0.3's packed `--scroll-scenario-file` window/target scroll
|
|
256
|
+
behavior (`scripts/ci/runPackedObservationSmoke.mjs`); this is local
|
|
257
|
+
package validation, not a release/publication step.
|
package/docs/CONTRACTS.md
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Current contracts
|
|
4
4
|
|
|
5
|
-
The
|
|
6
|
-
and proven both from the source checkout and from the packed npm tarball
|
|
5
|
+
The observation artifact contract is published as `my-frontend-observer@0.3.0`
|
|
6
|
+
and proven both from the source checkout and from the packed npm tarball,
|
|
7
|
+
on Windows, Linux, and macOS. The observation schema is `1.2.0` (see "v0.2
|
|
8
|
+
target contract" and "v0.3 scroll scenario contract" below):
|
|
7
9
|
|
|
8
|
-
- artifact kind `my-frontend-observer/observation`, schema version `1.
|
|
9
|
-
(independent of the package version
|
|
10
|
+
- artifact kind `my-frontend-observer/observation`, schema version `1.2.0`
|
|
11
|
+
(independent of the package version);
|
|
10
12
|
- one artifact root per observation, `<outputLocation>/<observationId>/`,
|
|
11
13
|
containing exactly `manifest.json` (the full `ObservationArtifact`, with
|
|
12
14
|
page/target evidence embedded inline) and `screenshot.png` - there is no
|
|
@@ -26,8 +28,135 @@ and proven both from the source checkout and from the packed npm tarball:
|
|
|
26
28
|
- observation/request identity, producer/package identity, and browser
|
|
27
29
|
provenance are all present in every persisted manifest.
|
|
28
30
|
|
|
29
|
-
This contract is implemented
|
|
30
|
-
|
|
31
|
+
This contract is implemented and published; no public programmatic-API
|
|
32
|
+
compatibility promise has been made.
|
|
33
|
+
|
|
34
|
+
## v0.2 target contract (shipped as part of this release)
|
|
35
|
+
|
|
36
|
+
v0.2 introduces a canonical target-configuration model: each configured target has a stable
|
|
37
|
+
observer-level `name` plus an ordered array of bounded `locators`
|
|
38
|
+
(`role`, `id`, `data-attribute`, `semantic-element`, `css`, `text`). This
|
|
39
|
+
identity is distinct from both the browser locator definition that resolves
|
|
40
|
+
it and any source-code identity. The legacy `{name, selector}` shape remains
|
|
41
|
+
accepted and normalizes to a one-item `css` locator, so every published
|
|
42
|
+
`0.1.0` CLI invocation continues to work unchanged. Locator precedence is the
|
|
43
|
+
configured array order; resolution stops on the first unique match, on any
|
|
44
|
+
ambiguous match (never falling through to a later locator), or on an
|
|
45
|
+
unevaluable locator - never silently. All six frozen locator kinds are now
|
|
46
|
+
resolved against a real Chromium page (`role` via Playwright's accessibility-
|
|
47
|
+
role/name locator with exact name matching, `id`/`data-attribute` via exact
|
|
48
|
+
CSS attribute-equals matching that never reinterprets the configured value as
|
|
49
|
+
selector syntax, `semantic-element` via the frozen tag set, `css` via the
|
|
50
|
+
existing v0.1 behavior, `text` via exact-text matching only); every kind
|
|
51
|
+
converges on the same measurement path, so locator strategy never changes the
|
|
52
|
+
resulting target evidence shape.
|
|
53
|
+
|
|
54
|
+
Each resolved target's evidence record additionally carries three bounded
|
|
55
|
+
fields: `semanticState` (a first family of `disabled`/`expanded`/
|
|
56
|
+
`checked`/`selected`/`pressed`/`current` values read from the element's own
|
|
57
|
+
native form-control properties and explicit `aria-*` attributes - a key is
|
|
58
|
+
present only when the browser exposes that state as applicable to this
|
|
59
|
+
element, so an explicit `false` is always distinguishable from "not
|
|
60
|
+
applicable"; `not-applicable` when no supported state applies at all);
|
|
61
|
+
`landmark` (derived only from the already-captured browser-exposed
|
|
62
|
+
role - never from locator kind or HTML tag - against the standard landmark
|
|
63
|
+
role set `banner`/`navigation`/`main`/`complementary`/`contentinfo`/`form`/
|
|
64
|
+
`region`/`search`); and `containment` (bounded DOM containment checked only
|
|
65
|
+
among the other explicitly configured targets in the same observation, in
|
|
66
|
+
configured order, never a layout/relationship graph - `available` when every
|
|
67
|
+
other configured target was itself resolved and checked, `partial` when one
|
|
68
|
+
or more could not be, `unavailable` when the target itself never resolved).
|
|
69
|
+
Stable observer target identity is proven, not just declared: the same
|
|
70
|
+
target configuration produces the same `requestId` across repeated
|
|
71
|
+
observations (with a fresh `observationId` each time); changing a target's
|
|
72
|
+
locator strategy while keeping its stable name changes `requestId` but not
|
|
73
|
+
the `targetEvidence` key; and actual runtime disappearance of a
|
|
74
|
+
still-configured target changes only its resolution status, never the
|
|
75
|
+
`requestId`.
|
|
76
|
+
|
|
77
|
+
The full canonical semantic target model above is reachable through the
|
|
78
|
+
real public CLI: `my-frontend-observer observe --targets-file <json-file>`
|
|
79
|
+
supplies the structured `{ "targets": [...] }` collection (see
|
|
80
|
+
`docs/COMMANDS.md` "Structured semantic targets") as an alternative to the
|
|
81
|
+
existing `--target id=css-selector` shorthand - the two are mutually
|
|
82
|
+
exclusive per invocation, and both converge on the same
|
|
83
|
+
`normalizeRequest()`/browser-resolver/artifact path, so a semantic
|
|
84
|
+
observation produces exactly the same `manifest.json` shape (schema `1.1.0`)
|
|
85
|
+
as a CSS-shorthand one. `--targets-file`'s local input path is never part of
|
|
86
|
+
the persisted request identity or artifact.
|
|
87
|
+
|
|
88
|
+
## v0.3 scroll scenario contract (shipped as part of this release)
|
|
89
|
+
|
|
90
|
+
v0.3 introduces one optional, additive request/evidence concern: a bounded
|
|
91
|
+
runtime scroll scenario, schema `1.2.0`.
|
|
92
|
+
|
|
93
|
+
A normalized request may carry `scrollScenario: { action }` with exactly one
|
|
94
|
+
of two frozen action kinds:
|
|
95
|
+
|
|
96
|
+
- `{ "kind": "window-scroll-by", "deltaX": <int>, "deltaY": <int> }`
|
|
97
|
+
- `{ "kind": "target-scroll-by", "target": "<stable target name>", "deltaX": <int>, "deltaY": <int> }`
|
|
98
|
+
|
|
99
|
+
`deltaX`/`deltaY` are signed integers bounded to `[-20000, 20000]`; at least
|
|
100
|
+
one must be non-zero. `target-scroll-by.target` refers only to an existing
|
|
101
|
+
stable configured target `name` (never a selector) and resolves through the
|
|
102
|
+
same canonical `resolveConfiguredTargets` algorithm every v0.2 locator kind
|
|
103
|
+
already uses - there is no second target-resolution path. A request with no
|
|
104
|
+
scenario normalizes and identifies exactly as it did before v0.3.
|
|
105
|
+
|
|
106
|
+
Execution (both action kinds share one code path): perform the immediate,
|
|
107
|
+
non-smooth scroll (`window.scrollBy`/`element.scrollBy`, `behavior:
|
|
108
|
+
'instant'`) on the already-navigated, already-ready page; wait exactly two
|
|
109
|
+
`requestAnimationFrame` cycles; capture a final runtime snapshot. No second
|
|
110
|
+
browser, page, or navigation is ever created. The resulting scroll position
|
|
111
|
+
is browser-authoritative and may be clamped by document/element boundaries;
|
|
112
|
+
a scenario producing no movement is still a valid, successfully persisted
|
|
113
|
+
observation.
|
|
114
|
+
|
|
115
|
+
The scenario evidence lives entirely inside the existing `manifest.json` as
|
|
116
|
+
one additional optional `scrollScenarioEvidence` field on `ObservationArtifact`
|
|
117
|
+
- there is no separate `scroll.json`/`scenario.json`. It contains:
|
|
118
|
+
|
|
119
|
+
- `initial`/`final`: bounded `ScrollRuntimeSnapshot`s (window `scrollX`/
|
|
120
|
+
`scrollY`; the browser's own scrolling-root/`documentElement`/`body`
|
|
121
|
+
metrics; per-configured-target `scrollTop`/`scrollLeft`/`scrollWidth`/
|
|
122
|
+
`scrollHeight`/`clientWidth`/`clientHeight`, actual overflow, bounding
|
|
123
|
+
rectangle, and viewport relation);
|
|
124
|
+
- `transition`: bounded before/after change evidence (window scroll deltas;
|
|
125
|
+
per-target `scrollTop`/`scrollLeft`/bounding-position/viewport-relation
|
|
126
|
+
changes; `enteredViewport`/`leftViewport`) - never a generic recursive
|
|
127
|
+
diff, and a target is simply omitted when either side's evidence isn't
|
|
128
|
+
itself usable (e.g. it never resolved);
|
|
129
|
+
- `scrollOwner`: one derived `EvidenceField<ScrollOwnerInterpretation>`
|
|
130
|
+
(`document` | `target:<stable-name>` | `none` | `indeterminate`), always
|
|
131
|
+
`source: "derived"` with non-empty `derivedFrom` naming the exact
|
|
132
|
+
contributing scroll-position measurements. Ownership is derived only from
|
|
133
|
+
observed `scrollTop`/`scrollLeft`/`window.scrollX`/`window.scrollY`
|
|
134
|
+
changes - never from bounding-rectangle movement (which moves for every
|
|
135
|
+
configured target whenever the document scrolls), computed overflow,
|
|
136
|
+
`position: fixed`/`sticky`, or DOM hierarchy.
|
|
137
|
+
|
|
138
|
+
Actual dimensional overflow (`scrollWidth > clientWidth` /
|
|
139
|
+
`scrollHeight > clientHeight`) is always reported separately from the
|
|
140
|
+
computed `overflow-x`/`overflow-y` CSS declaration; a declared
|
|
141
|
+
`overflow: auto` container with content that fits produces
|
|
142
|
+
`horizontalOverflow`/`verticalOverflow: false`. Viewport relation
|
|
143
|
+
(`above`/`intersecting`/`below`, `intersectsViewport`, `fullyWithinViewport`)
|
|
144
|
+
is derived only from bounding geometry plus viewport size, relative to the
|
|
145
|
+
browser viewport; a hidden/non-rendered target's viewport relation is
|
|
146
|
+
`not-applicable`, never a fabricated geometry claim - hidden and offscreen
|
|
147
|
+
remain distinct evidence concepts, and the existing `target-hidden`
|
|
148
|
+
diagnostic is unaffected.
|
|
149
|
+
|
|
150
|
+
The ordinary, already-existing `pageEvidence`/`targetEvidence`/
|
|
151
|
+
`screenshot.png` for a scenario observation always describe this same final
|
|
152
|
+
post-action state, never the pre-action state.
|
|
153
|
+
|
|
154
|
+
The scenario request participates in `requestId`; the runtime result
|
|
155
|
+
(actual scroll distance, clamping, or scroll-owner outcome) never does. The
|
|
156
|
+
public entry point is `my-frontend-observer observe --scroll-scenario-file
|
|
157
|
+
<json-file>` (see `docs/COMMANDS.md`); the file supplies the scenario value
|
|
158
|
+
directly, and its local path is operational input only, exactly like
|
|
159
|
+
`--targets-file`'s path - never persisted, never part of request identity.
|
|
31
160
|
|
|
32
161
|
## Approved v0.1 design inputs
|
|
33
162
|
|
package/docs/CURRENT_STATE.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Current State
|
|
2
2
|
|
|
3
|
-
The project is published at package version `0.
|
|
4
|
-
|
|
3
|
+
The project is published at package version `0.3.0` (roadmap v0.3, Runtime
|
|
4
|
+
Scrolling, Overflow, and Visibility Behavior; observation schema `1.2.0`).
|
|
5
5
|
|
|
6
6
|
## Greenfield foundation established
|
|
7
7
|
|
|
@@ -102,12 +102,134 @@ tarball/output fully cleaned up afterward. Documentation across the
|
|
|
102
102
|
repository was reconciled to this implemented state as part of the same
|
|
103
103
|
batch.
|
|
104
104
|
|
|
105
|
+
## v0.1 status
|
|
106
|
+
|
|
107
|
+
`v0.1.0` was the first published release (see `CHANGELOG.md` and
|
|
108
|
+
`docs/RELEASE.md`). Everything above this section describes that released
|
|
109
|
+
state, still present unchanged in `v0.2.0`.
|
|
110
|
+
|
|
111
|
+
## v0.2 status (Stable Semantic Targets and Region Identity) - released as 0.2.0
|
|
112
|
+
|
|
113
|
+
v0.2 is implemented and released as package version `0.2.0`, observation
|
|
114
|
+
schema `1.1.0`.
|
|
115
|
+
|
|
116
|
+
- **Canonical target/locator model.** Each configured target has a stable
|
|
117
|
+
observer-owned `name` plus an ordered, bounded `locators` array
|
|
118
|
+
(`src/request/request.ts#TargetLocator`, `NamedTarget`). This identity is
|
|
119
|
+
distinct from both the browser locator that resolves it and any
|
|
120
|
+
source-code symbol. The legacy `{name, selector}` shape remains accepted
|
|
121
|
+
and normalizes to a one-item `css` locator, so every v0.1 CLI invocation
|
|
122
|
+
continues to work unchanged. Bounds: 20 targets max, 5 locators per
|
|
123
|
+
target max (unchanged/new respectively from v0.1's target count bound).
|
|
124
|
+
- **Six frozen locator kinds, all resolved against real Chromium**: `role`
|
|
125
|
+
(Playwright's accessibility role/name locator, exact name matching),
|
|
126
|
+
`id` and `data-attribute` (exact CSS attribute-equals matching that never
|
|
127
|
+
reinterprets the configured value as selector syntax), `semantic-element`
|
|
128
|
+
(a frozen structural tag set: `header`, `nav`, `main`, `footer`,
|
|
129
|
+
`article`, `section`, `aside`, `form`, `dialog`), `css` (unchanged v0.1
|
|
130
|
+
behavior), and `text` (exact match only, no substring/fuzzy matching).
|
|
131
|
+
Locator order is the fallback order: 0 matches tries the next locator; 1
|
|
132
|
+
match selects and stops; more than 1 match is ambiguous and stops (never
|
|
133
|
+
falls through); an unevaluable locator is unavailable and stops (never
|
|
134
|
+
falls through). All six kinds converge on one measurement path
|
|
135
|
+
(`src/browser/evidenceCapture.ts#captureResolvedTargetRecord`) - locator
|
|
136
|
+
strategy never changes the resulting evidence shape.
|
|
137
|
+
- **Semantic region evidence**, added to every resolved target alongside
|
|
138
|
+
the existing v0.1 role/name capture: `semanticState` (a first bounded
|
|
139
|
+
family of `disabled`/`expanded`/`checked`/`selected`/`pressed`/`current`,
|
|
140
|
+
read from the element's own native/ARIA properties so an explicit `false`
|
|
141
|
+
is always distinguishable from "not applicable"; `checked`/`pressed` also
|
|
142
|
+
support the browser's `'mixed'` value); `landmark` (derived only from the
|
|
143
|
+
already-captured browser-exposed role - never from locator kind or HTML
|
|
144
|
+
tag - against the standard landmark role set `banner`/`navigation`/
|
|
145
|
+
`main`/`complementary`/`contentinfo`/`form`/`region`/`search`); and
|
|
146
|
+
`containment` (bounded DOM containment checked only among the other
|
|
147
|
+
explicitly configured targets in the same observation, in configured
|
|
148
|
+
order - `available`/`partial`/`unavailable`, never a layout/spatial-
|
|
149
|
+
relationship graph).
|
|
150
|
+
- **Proven identity stability**: the same target configuration produces the
|
|
151
|
+
same `requestId` across repeated observations (with a fresh
|
|
152
|
+
`observationId` every time); changing a target's locator strategy while
|
|
153
|
+
keeping its stable name changes `requestId` but not the `targetEvidence`
|
|
154
|
+
key; actual runtime disappearance of a still-configured target changes
|
|
155
|
+
only its resolution status, never the `requestId`.
|
|
156
|
+
- **Public CLI**: `my-frontend-observer observe --targets-file <json-file>`
|
|
157
|
+
supplies a structured `{ "targets": [...] }` collection as an alternative
|
|
158
|
+
to one or more `--target id=css-selector` flags; the two are mutually
|
|
159
|
+
exclusive per invocation. `--targets-file` only validates its own root
|
|
160
|
+
wrapper (readable file, valid JSON, object root with exactly a `targets`
|
|
161
|
+
field); all target/locator-internal validation stays owned by the
|
|
162
|
+
existing `normalizeRequest()`. The file path is operational input only -
|
|
163
|
+
never part of request identity, never persisted into `manifest.json`.
|
|
164
|
+
- **Observation schema `1.1.0`** (`src/domain/schema.ts#SCHEMA_VERSION`):
|
|
165
|
+
additive over the published `1.0.0` - extends `TargetEvidenceRecord` with
|
|
166
|
+
`semanticState`/`landmark`/`containment` and extends `TargetResolution`
|
|
167
|
+
with `selectedLocatorKind`/`selectedLocatorIndex`/`usedFallback`/
|
|
168
|
+
`confidence`/`attempts`. Artifact kind, directory structure, atomic
|
|
169
|
+
persistence, and evidence-state/source vocabularies are unchanged.
|
|
170
|
+
- **Validation on this branch**: `npm run typecheck`, `npm run lint`,
|
|
171
|
+
`npm test`, `npm run test:browser`, `npm run build`, and
|
|
172
|
+
`npm run check:docs` all pass (106 unit tests, 69 real-Chromium tests as
|
|
173
|
+
of this reconciliation; see `docs/DEVELOPMENT.md` for how to reproduce).
|
|
174
|
+
`scripts/dev/builtCliTargetsFileSmoke.mjs` additionally proves the built
|
|
175
|
+
`dist/cli.js` (not just the imported `runCli()` function) performs a real
|
|
176
|
+
semantic `--targets-file` observation end to end.
|
|
177
|
+
|
|
178
|
+
## v0.3 status (Runtime Scrolling, Overflow, and Visibility Behavior) - released as 0.3.0
|
|
179
|
+
|
|
180
|
+
v0.3 is implemented and released as package version `0.3.0`, observation
|
|
181
|
+
schema `1.2.0`. It was validated as a packed npm tarball in a clean
|
|
182
|
+
consumer environment on Windows, Linux, and macOS before release.
|
|
183
|
+
|
|
184
|
+
- **Batch 1** froze the `scrollScenario` request/identity/schema contract:
|
|
185
|
+
`ScrollScenario { action }` with exactly two action kinds
|
|
186
|
+
(`window-scroll-by`, `target-scroll-by`), signed-integer deltas bounded to
|
|
187
|
+
`[-20000, 20000]`, `target-scroll-by.target` referencing an existing stable
|
|
188
|
+
configured target name, scenario configuration participating in
|
|
189
|
+
`requestId` (runtime results never do), and the full bounded runtime
|
|
190
|
+
evidence model (`ScrollRuntimeSnapshot`, `ViewportRelationEvidence`,
|
|
191
|
+
`OverflowEvidence`, scenario transitions, `ScrollOwnerInterpretation`) in
|
|
192
|
+
schema `1.2.0` (up from `1.1.0`).
|
|
193
|
+
- **Batch 2** implemented real `window-scroll-by` execution
|
|
194
|
+
(`src/browser/scrollCapture.ts`, `src/domain/scrollEvidence.ts`): initial/
|
|
195
|
+
final runtime snapshots around an immediate `window.scrollBy({behavior:
|
|
196
|
+
'instant'})` and exactly two `requestAnimationFrame` cycles, real vertical/
|
|
197
|
+
horizontal document scrolling, actual-vs-computed overflow, real viewport
|
|
198
|
+
relation, `enteredViewport`/`leftViewport`, and `document`/`none`
|
|
199
|
+
scroll-owner evidence - with ordinary final `pageEvidence`/`targetEvidence`
|
|
200
|
+
and the screenshot always describing the same final post-action state.
|
|
201
|
+
- **Batch 3** implemented real `target-scroll-by` execution against the same
|
|
202
|
+
canonical `resolveConfiguredTargets` resolution already used by every v0.2
|
|
203
|
+
locator kind: real nested vertical/horizontal element scrolling, boundary
|
|
204
|
+
clamping, non-scrollable/no-movement targets, and the completed
|
|
205
|
+
`document`/`target:<name>`/`none`/`indeterminate` scroll-owner derivation
|
|
206
|
+
(`src/domain/scrollEvidence.ts#deriveScrollOwner`) - proven never to
|
|
207
|
+
attribute ownership from bounding-rectangle movement alone in either
|
|
208
|
+
direction. An unresolved/ambiguous/hidden action target is never scrolled
|
|
209
|
+
and never fabricated as moved; the existing target diagnostics explain it
|
|
210
|
+
honestly and the observation still persists.
|
|
211
|
+
- **Batch 4** exposed the existing contract through the real public CLI:
|
|
212
|
+
`my-frontend-observer observe --scroll-scenario-file <json-file>` (see
|
|
213
|
+
`docs/COMMANDS.md`). The file supplies the `scrollScenario` value directly
|
|
214
|
+
(no wrapper field); the CLI/input layer only validates file readability,
|
|
215
|
+
JSON validity, and a non-array object root - every scenario/action rule
|
|
216
|
+
stays owned by the existing `normalizeRequest()`. Usable with either
|
|
217
|
+
`--target` or `--targets-file` (independent of target configuration, never
|
|
218
|
+
a third mutually-exclusive mode); the scenario-file path is operational
|
|
219
|
+
input only, never persisted and never part of request identity, exactly
|
|
220
|
+
like `--targets-file`'s path. CLI output/exit-code semantics are
|
|
221
|
+
unchanged. Proven via real Chromium (`tests/browser/cliObserve.test.ts`)
|
|
222
|
+
and the built `dist/cli.js` (`scripts/dev/builtCliScrollScenarioSmoke.mjs`).
|
|
223
|
+
|
|
105
224
|
## Not implemented
|
|
106
225
|
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
226
|
+
- Layout/spatial relationship engine, before/after comparison, frontend
|
|
227
|
+
contracts/change scope, source ownership, my-dev-kit runtime/static
|
|
228
|
+
integration, orchestrator/lab product integration, viewer, and annotation
|
|
229
|
+
all remain unimplemented (v0.4+).
|
|
110
230
|
|
|
111
231
|
## Next target
|
|
112
232
|
|
|
113
|
-
v0.1.
|
|
233
|
+
v0.1, v0.2, and v0.3 are implemented, validated, and released (`0.1.0`,
|
|
234
|
+
`0.2.0`, `0.3.0`). v0.4 (Layout Relationships, Dependency Evidence, and
|
|
235
|
+
Before/After Comparison) is the next planned version.
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -21,9 +21,9 @@ npm run check:docs
|
|
|
21
21
|
npm pack --dry-run
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
`npm test` runs the fast unit suite only (`tests/unit/`, currently
|
|
24
|
+
`npm test` runs the fast unit suite only (`tests/unit/`, currently 176
|
|
25
25
|
passing tests). `npm run test:browser` runs the real-Chromium integration
|
|
26
|
-
suite (`tests/browser/`, currently
|
|
26
|
+
suite (`tests/browser/`, currently 88 passing tests) against deterministic
|
|
27
27
|
local fixtures under `tests/fixtures/` and requires the Chromium binary
|
|
28
28
|
above to be installed first; it is kept out of `npm test` because it
|
|
29
29
|
launches a real browser and is slower.
|
|
@@ -62,4 +62,42 @@ It is what `.github/workflows/pre-release-readiness.yml` runs identically on
|
|
|
62
62
|
Windows, Linux, and macOS against one shared candidate tarball (see
|
|
63
63
|
`docs/CI_CD.md`); it can also be run locally the same way the workflow runs
|
|
64
64
|
it. It is readiness/CI infrastructure only, not part of the published
|
|
65
|
-
package and never imported by production code.
|
|
65
|
+
package and never imported by production code. It exercises both the
|
|
66
|
+
legacy CSS-shorthand `--target` packed-observation shape and the
|
|
67
|
+
structured semantic `--targets-file` shape in the same run - see
|
|
68
|
+
`docs/CI_CD.md` for the current v0.2 readiness coverage.
|
|
69
|
+
|
|
70
|
+
`scripts/dev/builtCliTargetsFileSmoke.mjs` is a separate, narrower v0.2
|
|
71
|
+
development smoke, added alongside the `--targets-file` implementation: it
|
|
72
|
+
runs the built `dist/cli.js` directly (`node dist/cli.js observe
|
|
73
|
+
--targets-file ...`) against an inline disposable local HTTP fixture and a
|
|
74
|
+
temporary JSON target file, proving a real semantic observation persists a
|
|
75
|
+
valid schema-`1.2.0` artifact with no packed-tarball step involved. Run it
|
|
76
|
+
locally after `npm run build`:
|
|
77
|
+
|
|
78
|
+
```powershell
|
|
79
|
+
node scripts/dev/builtCliTargetsFileSmoke.mjs
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`scripts/dev/builtCliScrollScenarioSmoke.mjs` is the v0.3 equivalent, added
|
|
83
|
+
alongside the `--scroll-scenario-file` implementation: it runs the built
|
|
84
|
+
`dist/cli.js` directly against an inline disposable local HTTP fixture,
|
|
85
|
+
once with a temporary `window-scroll-by` scenario file and once with a
|
|
86
|
+
temporary structured `--targets-file` plus a `target-scroll-by` scenario
|
|
87
|
+
file, proving both real runtime scroll actions persist a valid
|
|
88
|
+
schema-`1.2.0` artifact with populated `scrollScenarioEvidence`,
|
|
89
|
+
scenario-file path privacy, and target-application immutability. Run it
|
|
90
|
+
locally after `npm run build`:
|
|
91
|
+
|
|
92
|
+
```powershell
|
|
93
|
+
node scripts/dev/builtCliScrollScenarioSmoke.mjs
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Unlike `scripts/ci/runPackedObservationSmoke.mjs`, neither of these dev
|
|
97
|
+
smokes is wired into any CI workflow or is a release gate - they are
|
|
98
|
+
source-checkout development evidence only, proving the built CLI's
|
|
99
|
+
`--targets-file`/`--scroll-scenario-file` behavior without installing a
|
|
100
|
+
packed tarball or requiring cross-platform infrastructure. Neither is part
|
|
101
|
+
of the published package. Cross-platform packed validation of the v0.3
|
|
102
|
+
scroll-scenario behavior is `scripts/ci/runPackedObservationSmoke.mjs`'s
|
|
103
|
+
responsibility (see `docs/CI_CD.md`), and has been completed.
|
package/docs/PROJECT_OVERVIEW.md
CHANGED
|
@@ -15,12 +15,18 @@ The responsibility split is stable:
|
|
|
15
15
|
|
|
16
16
|
## Current repository state
|
|
17
17
|
|
|
18
|
-
v0.1, Runtime Observation Foundation,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
v0.1, Runtime Observation Foundation; v0.2, Stable Semantic Targets and
|
|
19
|
+
Region Identity; and v0.3, Runtime Scrolling, Overflow, and Visibility
|
|
20
|
+
Behavior, are released, published to npm (current version `0.3.0`,
|
|
21
|
+
observation schema `1.2.0`) and validated as a packed npm tarball in a
|
|
22
|
+
clean consumer environment across Windows, Linux, and macOS: a real
|
|
23
|
+
`observe` CLI command launches Chromium, enforces loopback-only safety,
|
|
24
|
+
captures bounded page/target evidence via legacy CSS-shorthand targets,
|
|
25
|
+
structured semantic `--targets-file` targets, or a bounded
|
|
26
|
+
`--scroll-scenario-file` runtime scroll scenario (`window-scroll-by` or
|
|
27
|
+
`target-scroll-by`), and persists one portable local artifact - see
|
|
28
|
+
`docs/CURRENT_STATE.md` for the implementation summary. v0.4–v0.10 remain
|
|
29
|
+
future and unimplemented.
|
|
24
30
|
|
|
25
31
|
The revised dependency path reaches practical coding-agent use before graphical
|
|
26
32
|
interaction:
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -21,7 +21,9 @@ node dist/cli.js observe `
|
|
|
21
21
|
|
|
22
22
|
This launches Chromium, captures a screenshot plus bounded page/target
|
|
23
23
|
evidence, and writes one portable artifact under `observations/<observation-id>/`.
|
|
24
|
-
See [COMMANDS.md](COMMANDS.md) for the full flag reference
|
|
24
|
+
See [COMMANDS.md](COMMANDS.md) for the full flag reference, including the
|
|
25
|
+
`--targets-file` structured semantic-target input and the
|
|
26
|
+
`--scroll-scenario-file` bounded runtime scroll scenario input.
|
|
25
27
|
|
|
26
28
|
To validate the repository itself instead:
|
|
27
29
|
|
package/docs/RELEASE.md
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
# Release
|
|
2
2
|
|
|
3
|
-
`v0.
|
|
3
|
+
`v0.3.0` is published to npm as `my-frontend-observer`, validated on
|
|
4
4
|
Windows, Linux, and macOS as an installed packed-tarball consumer prior to
|
|
5
|
-
publication
|
|
6
|
-
|
|
5
|
+
publication (covering the legacy CSS-shorthand `--target` path, the
|
|
6
|
+
structured semantic `--targets-file` path, and the bounded
|
|
7
|
+
`--scroll-scenario-file` `window-scroll-by`/`target-scroll-by` runtime
|
|
8
|
+
scroll scenario path). No project license has been declared yet; that
|
|
9
|
+
decision remains open for a later explicit task.
|
|
7
10
|
|
|
8
|
-
Observation schema version and package version remain separate:
|
|
9
|
-
`
|
|
11
|
+
Observation schema version and package version remain separate: package
|
|
12
|
+
version is `0.3.0`; observation schema is `1.2.0` and does not change
|
|
13
|
+
automatically with the package version.
|
|
14
|
+
|
|
15
|
+
Prior releases: `v0.2.0` (Stable Semantic Targets and Region Identity),
|
|
16
|
+
`v0.1.0` (Runtime Observation Foundation) - see `CHANGELOG.md`.
|
package/docs/ROADMAP.md
CHANGED
|
@@ -43,6 +43,10 @@ and the concrete dependency/version set before implementation.
|
|
|
43
43
|
|
|
44
44
|
## v0.2 — Stable Semantic Targets and Region Identity
|
|
45
45
|
|
|
46
|
+
Current status: released as `0.2.0`, published to npm and validated as a
|
|
47
|
+
packed npm tarball in a clean consumer environment on Windows, Linux, and
|
|
48
|
+
macOS. See `docs/CURRENT_STATE.md` for the implementation summary.
|
|
49
|
+
|
|
46
50
|
Objective/problem: let humans and consumers refer reliably to conceptual
|
|
47
51
|
rendered regions across observations without brittle selector-only identity.
|
|
48
52
|
Required capabilities include semantic HTML, accessibility role/name, stable
|
|
@@ -56,6 +60,11 @@ identity persistence rules from current evidence.
|
|
|
56
60
|
|
|
57
61
|
## v0.3 — Runtime Scrolling, Overflow, and Visibility Behavior
|
|
58
62
|
|
|
63
|
+
Current status: released as `0.3.0`, published to npm and validated as a
|
|
64
|
+
packed npm tarball in a clean consumer environment on Windows, Linux, and
|
|
65
|
+
macOS (observation schema `1.2.0`). See `docs/CURRENT_STATE.md` for the
|
|
66
|
+
implementation summary.
|
|
67
|
+
|
|
59
68
|
Objective/problem: show which container actually scrolls and what becomes
|
|
60
69
|
visible, clipped, or overflowing after controlled actions. Required capabilities
|
|
61
70
|
are bounded action scenarios, before/after window and target scroll positions,
|