@enricai/barnacle 1.10.0 → 1.11.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.
@@ -11,28 +11,24 @@ export interface PhantomClickSnapshot {
11
11
  url: string;
12
12
  /** `document.body.outerHTML.length`. */
13
13
  bodyHtmlLength: number;
14
- /**
15
- * Fingerprint of client-side selection state across selection-bearing
16
- * controls — `aria-pressed`/`aria-checked`/`aria-selected`, `data-state`
17
- * (excluding `open`/`closed` disclosure values), `data-selected`/
18
- * `data-checked`, and a selected/active/checked class-token hit on an
19
- * interactive element. A multi-select toggle (React state flip) moves this
20
- * without moving network, URL, or byte size — often a NEGATIVE byte delta
21
- * (an `aria-pressed="false"`→`"true"` flip shrinks the HTML), which the
22
- * byte-floor branch can never catch. A pure `disabled`→`enabled` gate with
23
- * no accompanying selection-marker change is intentionally NOT tracked.
24
- * Optional so pre-`selectionStateSignature` snapshots (and this module's own
25
- * tests) stay valid; a defined pre/post pair that differs is a real effect
26
- * (see {@link classifyPhantomClick}). The producer is `snapshotPage`'s
27
- * `DOM_SNAPSHOT_EXPR` in `flow-runner.ts`, which documents the exact shape.
28
- */
29
- selectionStateSignature?: string;
30
14
  }
31
15
  export interface PhantomClickAttempt {
32
16
  /** Stagehand's own verdict for the attempt — did it believe it acted? */
33
17
  actResultSuccess: boolean | null;
34
18
  pre: PhantomClickSnapshot;
35
19
  post: PhantomClickSnapshot;
20
+ /**
21
+ * True when the resolved element's OWN committed selection state changed
22
+ * across the click — the authoritative, element-scoped signal `verifyDomEffect`
23
+ * computes from the pre/post per-element fingerprint baseline
24
+ * (`StepSnapshot.selectionStateByXpath`). A design-system option/toggle (Base
25
+ * Web `kind` flip, hashed-class swap, ARIA, native `checked`) registers here
26
+ * with no network, no URL change, and a trivial/negative byte delta that the
27
+ * byte-floor branch can never catch. Element-scoped, so a state change on any
28
+ * OTHER element on the page can never lift this verdict off `phantom`.
29
+ * Optional so callers/tests that don't supply it default to `false`.
30
+ */
31
+ elementStateChanged?: boolean;
36
32
  /**
37
33
  * True when the step is submit-shaped (a final/submit click). A submit must
38
34
  * show a REAL effect (network/URL) to count as effective — a mere selection-
@@ -1 +1 @@
1
- {"version":3,"file":"phantom-click.d.ts","sourceRoot":"","sources":["../../src/scraper/phantom-click.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,qFAAqF;AACrF,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;;;;OAcG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,gBAAgB,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,GAAG,EAAE,oBAAoB,CAAC;IAC1B,IAAI,EAAE,oBAAoB,CAAC;IAC3B;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,MAAM,mBAAmB;AAC7B,0FAA0F;AACxF,SAAS;AACX,mEAAmE;GACjE,WAAW;AACb,kKAAkK;GAChK,YAAY,CAAC;AAEjB;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CA2BtF"}
1
+ {"version":3,"file":"phantom-click.d.ts","sourceRoot":"","sources":["../../src/scraper/phantom-click.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,qFAAqF;AACrF,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,gBAAgB,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,GAAG,EAAE,oBAAoB,CAAC;IAC1B,IAAI,EAAE,oBAAoB,CAAC;IAC3B;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,MAAM,mBAAmB;AAC7B,0FAA0F;AACxF,SAAS;AACX,mEAAmE;GACjE,WAAW;AACb,kKAAkK;GAChK,YAAY,CAAC;AAEjB;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAuBtF"}
@@ -31,22 +31,19 @@ function classifyPhantomClick(attempt) {
31
31
  const networkDelta = attempt.post.networkCount - attempt.pre.networkCount;
32
32
  const bytesDelta = attempt.post.bodyHtmlLength - attempt.pre.bodyHtmlLength;
33
33
  const urlChanged = attempt.post.url !== attempt.pre.url;
34
- // A client-side selection toggle (aria-pressed/checked/selected, data-state,
35
- // or a selected/active/checked class) is a real effect regardless of byte
36
- // size the byte floor below rejects it because the delta is trivial or
37
- // negative. Only credit when BOTH signatures are defined (an older snapshot
38
- // without the field mustn't read undefined === undefined as a change) and
39
- // they differ. NOT on a submit-shaped step: a submit must prove itself via
40
- // network/URL, and letting a stray selection flip mark it "effective" would
41
- // defeat the cascade's phantom-verdict-driven escalation to the deep submit
42
- // locator.
43
- const selectionStateChanged = !attempt.isSubmitShapedStep &&
44
- attempt.pre.selectionStateSignature !== undefined &&
45
- attempt.post.selectionStateSignature !== undefined &&
46
- attempt.pre.selectionStateSignature !== attempt.post.selectionStateSignature;
34
+ // The resolved element's OWN committed selection state changed across the
35
+ // click a design-system option/toggle (Base Web `kind` flip, hashed-class
36
+ // swap, ARIA, native `checked`) registers here with no network, no URL, and a
37
+ // trivial/negative byte delta the byte floor can never catch. Authoritative
38
+ // and element-scoped (`verifyDomEffect` read it off the clicked element, not a
39
+ // page-wide fingerprint), so an unrelated element's change can't fake it. NOT
40
+ // on a submit-shaped step: a submit must prove itself via network/URL, or the
41
+ // cascade's phantom-verdict-driven escalation to the deep submit locator would
42
+ // be defeated by a stray self-toggle on the submit button.
43
+ const elementStateChanged = !attempt.isSubmitShapedStep && attempt.elementStateChanged === true;
47
44
  const hasEffect = networkDelta !== 0 ||
48
45
  urlChanged ||
49
- selectionStateChanged ||
46
+ elementStateChanged ||
50
47
  bytesDelta >= exports.TRIVIAL_DOM_DELTA_BYTES;
51
48
  return hasEffect ? "effective" : "phantom";
52
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"phantom-click.js","sourceRoot":"","sources":["../../src/scraper/phantom-click.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;AAmDH;;;;;;GAMG;AACU,QAAA,uBAAuB,GAAG,GAAG,CAAC;AAE3C;;;;;;;GAOG;AACH,8BAAqC,OAA4B;IAC/D,IAAI,OAAO,CAAC,gBAAgB,KAAK,IAAI;QAAE,OAAO,YAAY,CAAC;IAE3D,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC1E,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC5E,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;IACxD,6EAA6E;IAC7E,0EAA0E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,0EAA0E;IAC1E,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,WAAW;IACX,MAAM,qBAAqB,GACzB,CAAC,OAAO,CAAC,kBAAkB;QAC3B,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,SAAS;QACjD,OAAO,CAAC,IAAI,CAAC,uBAAuB,KAAK,SAAS;QAClD,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC;IAE/E,MAAM,SAAS,GACb,YAAY,KAAK,CAAC;QAClB,UAAU;QACV,qBAAqB;QACrB,UAAU,IAAI,QAAA,uBAAuB,CAAC;IACxC,OAAO,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7C,CAAC"}
1
+ {"version":3,"file":"phantom-click.js","sourceRoot":"","sources":["../../src/scraper/phantom-click.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;AA+CH;;;;;;GAMG;AACU,QAAA,uBAAuB,GAAG,GAAG,CAAC;AAE3C;;;;;;;GAOG;AACH,8BAAqC,OAA4B;IAC/D,IAAI,OAAO,CAAC,gBAAgB,KAAK,IAAI;QAAE,OAAO,YAAY,CAAC;IAE3D,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC1E,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC5E,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;IACxD,0EAA0E;IAC1E,4EAA4E;IAC5E,8EAA8E;IAC9E,4EAA4E;IAC5E,+EAA+E;IAC/E,8EAA8E;IAC9E,8EAA8E;IAC9E,+EAA+E;IAC/E,2DAA2D;IAC3D,MAAM,mBAAmB,GAAG,CAAC,OAAO,CAAC,kBAAkB,IAAI,OAAO,CAAC,mBAAmB,KAAK,IAAI,CAAC;IAEhG,MAAM,SAAS,GACb,YAAY,KAAK,CAAC;QAClB,UAAU;QACV,mBAAmB;QACnB,UAAU,IAAI,QAAA,uBAAuB,CAAC;IACxC,OAAO,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7C,CAAC"}
@@ -2293,10 +2293,10 @@ function deriveProducerBoundaryBindings(actions, alreadyBound) {
2293
2293
  *
2294
2294
  * WHY before {@link interpolateStateValues} and not via its payload pass: a
2295
2295
  * composite coordinate like a jobLocation `"Torrington, Connecticut, United
2296
- * States"` or a jobSeqNo `"HHKHHEUS26158515EXTERNALENUS"` contains inner tokens a
2296
+ * States"` or a jobSeqNo `"AAA0000000000EXTERNALENUS"` contains inner tokens a
2297
2297
  * genuinely-prior step produces as its own state var (a `label`, a `refNum`).
2298
2298
  * Pass-1 state threading would fragment the string (`"Torrington, ${label}"`,
2299
- * `"${refNum}26158515EXTERNALENUS"`) before the length-descending payload pass
2299
+ * `"${refNum}0000000000EXTERNALENUS"`) before the length-descending payload pass
2300
2300
  * could match the full literal — and the collision guard then refuses to bind the
2301
2301
  * embedded remainder, stranding it frozen. Binding the whole coordinate first —
2302
2302
  * the same "swallow whole before inner passes reach in" discipline as
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enricai/barnacle",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "Site-agnostic browser automation engine. POST a structured payload to a typed endpoint; Barnacle drives a Steel + Stagehand session through the target site and returns a structured result.",
5
5
  "license": "MIT",
6
6
  "author": "Enricai",