@goliapkg/sentori-react-native 5.1.2 → 5.1.4

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.
@@ -120,7 +120,8 @@ object SentoriReplayCapture {
120
120
  val nodes = JSONArray()
121
121
  val rootLoc = IntArray(2).also { root.getLocationInWindow(it) }
122
122
  val ctx = WalkContext(rootLoc = rootLoc, maskedSet = maskedSet)
123
- walk(root, depth = 0, parentMasked = false, ctx = ctx, nodes = nodes)
123
+ val rootClip = android.graphics.Rect(0, 0, root.width, root.height)
124
+ walk(root, depth = 0, parentMasked = false, ctx = ctx, clip = rootClip, nodes = nodes)
124
125
 
125
126
  val payload = JSONObject().apply {
126
127
  put("ts", System.currentTimeMillis())
@@ -173,6 +174,7 @@ object SentoriReplayCapture {
173
174
  depth: Int,
174
175
  parentMasked: Boolean,
175
176
  ctx: WalkContext,
177
+ clip: android.graphics.Rect,
176
178
  nodes: JSONArray,
177
179
  ) {
178
180
  if (nodes.length() >= MAX_NODES) return
@@ -188,68 +190,94 @@ object SentoriReplayCapture {
188
190
  val w = view.width
189
191
  val h = view.height
190
192
 
193
+ // Insight 2026-08-01: nothing was clipped here at all — a
194
+ // scroll container's full content width shipped as-is and
195
+ // drew past the device in the replay. `clip` accumulates
196
+ // every clipping ancestor (clipChildren defaults to true, so
197
+ // scroll viewports narrow it); a node ships as its visible
198
+ // intersection, an invisible one not at all. This is the
199
+ // root-cause fix the 05-18 decorView→content anchor swap
200
+ // only sidestepped.
201
+ var childClip = clip
202
+
191
203
  // Emit a node ONLY when the view has visual extent. A zero-
192
204
  // size view contributes nothing to render but its subtree
193
- // might; recurse below regardless.
205
+ // might; recurse below regardless (and without narrowing the
206
+ // clip — transient zero-size Fabric wrappers do not really
207
+ // clip their laid-out descendants).
194
208
  if (w > 0 && h > 0) {
195
209
  val loc = IntArray(2)
196
210
  view.getLocationInWindow(loc)
197
211
  val x = loc[0] - ctx.rootLoc[0]
198
212
  val y = loc[1] - ctx.rootLoc[1]
199
213
 
200
- val node = JSONObject().apply {
201
- put("x", x)
202
- put("y", y)
203
- put("w", w)
204
- put("h", h)
214
+ val selfRect = android.graphics.Rect(x, y, x + w, y + h)
215
+ val visible = android.graphics.Rect(selfRect)
216
+ if (!visible.intersect(clip)) {
217
+ // Fully outside every clipping ancestor: the view
218
+ // shows nothing, and if it clips its own children the
219
+ // whole subtree is gone with it.
220
+ if (view is ViewGroup && view.clipChildren) return
221
+ visible.setEmpty()
205
222
  }
206
-
207
- var kindEmitted = false
208
- when {
209
- masked -> {
210
- node.put("kind", "mask")
211
- kindEmitted = true
212
- }
213
- view is TextView && !view.text.isNullOrEmpty() -> {
214
- node.put("kind", "text")
215
- val text = view.text.toString().let { if (it.length > 200) it.substring(0, 200) else it }
216
- node.put("text", text)
217
- node.put("color", colorToHex(view.currentTextColor))
218
- kindEmitted = true
219
- }
220
- view is EditText -> {
221
- node.put("kind", "text")
222
- val text = (view.text ?: "").toString().let { if (it.length > 200) it.substring(0, 200) else it }
223
- node.put("text", text)
224
- kindEmitted = true
225
- }
226
- view is ImageView -> {
227
- node.put("kind", "image")
228
- kindEmitted = true
223
+ if (view is ViewGroup && view.clipChildren) {
224
+ childClip = android.graphics.Rect(visible)
225
+ }
226
+ if (!visible.isEmpty) {
227
+ val node = JSONObject().apply {
228
+ put("x", visible.left)
229
+ put("y", visible.top)
230
+ put("w", visible.width())
231
+ put("h", visible.height())
229
232
  }
230
- view.background != null -> {
231
- // rc.8 — backgrounds backed by a BitmapDrawable
232
- // (a View whose backgroundImage / drawable
233
- // resource is a raster) emit as `image` kind so
234
- // the dashboard renders them as a media region,
235
- // not as a grey rect. Everything else stays
236
- // `rect` and tries to extract a fill colour.
237
- val bg = view.background
238
- if (bg is BitmapDrawable) {
233
+
234
+ var kindEmitted = false
235
+ when {
236
+ masked -> {
237
+ node.put("kind", "mask")
238
+ kindEmitted = true
239
+ }
240
+ view is TextView && !view.text.isNullOrEmpty() -> {
241
+ node.put("kind", "text")
242
+ val text = view.text.toString().let { if (it.length > 200) it.substring(0, 200) else it }
243
+ node.put("text", text)
244
+ node.put("color", colorToHex(view.currentTextColor))
245
+ kindEmitted = true
246
+ }
247
+ view is EditText -> {
248
+ node.put("kind", "text")
249
+ val text = (view.text ?: "").toString().let { if (it.length > 200) it.substring(0, 200) else it }
250
+ node.put("text", text)
251
+ kindEmitted = true
252
+ }
253
+ view is ImageView -> {
239
254
  node.put("kind", "image")
240
- } else {
241
- node.put("kind", "rect")
242
- val color = extractDrawableColor(bg)
243
- if (color != null && (color shr 24 and 0xff) != 0) {
244
- node.put("color", colorToHex(color))
255
+ kindEmitted = true
256
+ }
257
+ view.background != null -> {
258
+ // rc.8 — backgrounds backed by a BitmapDrawable
259
+ // (a View whose backgroundImage / drawable
260
+ // resource is a raster) emit as `image` kind so
261
+ // the dashboard renders them as a media region,
262
+ // not as a grey rect. Everything else stays
263
+ // `rect` and tries to extract a fill colour.
264
+ val bg = view.background
265
+ if (bg is BitmapDrawable) {
266
+ node.put("kind", "image")
267
+ } else {
268
+ node.put("kind", "rect")
269
+ val color = extractDrawableColor(bg)
270
+ if (color != null && (color shr 24 and 0xff) != 0) {
271
+ node.put("color", colorToHex(color))
272
+ }
245
273
  }
274
+ kindEmitted = true
246
275
  }
247
- kindEmitted = true
248
276
  }
249
- }
250
277
 
251
- if (kindEmitted) {
252
- nodes.put(node)
278
+ if (kindEmitted) {
279
+ nodes.put(node)
280
+ }
253
281
  }
254
282
  }
255
283
 
@@ -257,7 +285,7 @@ object SentoriReplayCapture {
257
285
  // descendants (the rc.3 fix).
258
286
  if (!masked && view is ViewGroup) {
259
287
  for (i in 0 until view.childCount) {
260
- walk(view.getChildAt(i), depth + 1, masked, ctx, nodes)
288
+ walk(view.getChildAt(i), depth + 1, masked, ctx, childClip, nodes)
261
289
  }
262
290
  }
263
291
  }
@@ -74,6 +74,7 @@ import UIKit
74
74
  parentMasked: false,
75
75
  maskedIds: maskedIds,
76
76
  window: window,
77
+ clip: window.bounds,
77
78
  nodes: &nodes
78
79
  )
79
80
  lastDiagNodes = nodes.count
@@ -195,6 +196,7 @@ import UIKit
195
196
  parentMasked: Bool,
196
197
  maskedIds: Set<String>,
197
198
  window: UIWindow,
199
+ clip: CGRect,
198
200
  nodes: inout [[String: Any]]
199
201
  ) {
200
202
  if nodes.count >= MAX_NODES { return }
@@ -207,17 +209,29 @@ import UIKit
207
209
  .map { maskedIds.contains($0) } ?? false
208
210
  let masked = parentMasked || isThisMasked
209
211
 
212
+ // Insight 2026-08-01: the old check culled only nodes FULLY
213
+ // outside the window, so a 2000pt scroll ruler shipped at
214
+ // 2000pt and drew past the phone. `clip` accumulates every
215
+ // clipping ancestor (scroll views, clipsToBounds containers)
216
+ // from the window down; a node ships as the part of it that
217
+ // is actually visible, and a subtree behind a clipping edge
218
+ // ships not at all. This replaces the 05-18 anchor-swap class
219
+ // of fix: clipping is the root cause, anchors were symptoms.
210
220
  let frame = view.convert(view.bounds, to: window)
211
- // Skip nodes outside the window bounds (off-screen recyclers).
212
- if !frame.intersects(window.bounds) {
213
- return
221
+ let visible = frame.intersection(clip)
222
+ let clipsChildren = view.clipsToBounds
223
+ if visible.isNull || visible.isEmpty {
224
+ // Nothing of this view shows. Its children can still show
225
+ // when this view does not clip them (transform-heavy or
226
+ // zero-size wrappers); a clipping view ends the subtree.
227
+ if clipsChildren { return }
214
228
  }
215
229
 
216
230
  var node: [String: Any] = [
217
- "x": Double(frame.origin.x),
218
- "y": Double(frame.origin.y),
219
- "w": Double(frame.size.width),
220
- "h": Double(frame.size.height),
231
+ "x": Double(visible.origin.x),
232
+ "y": Double(visible.origin.y),
233
+ "w": Double(visible.size.width),
234
+ "h": Double(visible.size.height),
221
235
  ]
222
236
 
223
237
  if masked {
@@ -239,11 +253,14 @@ import UIKit
239
253
  }
240
254
  // else: invisible container — skip emitting but recurse.
241
255
 
242
- if node["kind"] != nil {
256
+ if node["kind"] != nil, !visible.isNull, !visible.isEmpty {
243
257
  nodes.append(node)
244
258
  }
245
259
 
246
260
  if !masked {
261
+ // A clipping view narrows the clip for everything below
262
+ // it; a non-clipping one passes the inherited clip on.
263
+ let childClip = clipsChildren ? visible : clip
247
264
  // Don't expose internals of masked subtrees.
248
265
  for sub in view.subviews {
249
266
  walk(
@@ -253,6 +270,7 @@ import UIKit
253
270
  parentMasked: masked,
254
271
  maskedIds: maskedIds,
255
272
  window: window,
273
+ clip: childClip,
256
274
  nodes: &nodes
257
275
  )
258
276
  }
package/lib/replay.d.ts CHANGED
@@ -18,12 +18,40 @@ export type ReplayOptions = {
18
18
  };
19
19
  export declare function startReplay(opts: ReplayOptions): void;
20
20
  export declare function stopReplay(): void;
21
+ /**
22
+ * Identity = geometry + occurrence index in walk order.
23
+ *
24
+ * Geometry alone is NOT identity: a page root and the fullscreen
25
+ * overlay covering it share x/y/w/h, and keying a Map on that
26
+ * collapsed them into one node — the overlay inherited the root's
27
+ * z-position and the replay drew the page THROUGH it (insight
28
+ * 2026-08-01). The occurrence suffix keeps every stacked layer its
29
+ * own entry, and stays stable across ticks because the native walk
30
+ * order is deterministic for a stable tree.
31
+ */
32
+ export declare function indexNodes(nodes: Node[]): Map<string, {
33
+ node: Node;
34
+ at: number;
35
+ }>;
21
36
  type Delta = {
22
- added: Node[];
23
- changed: Node[];
24
- removed: Pick<Node, 'x' | 'y' | 'w' | 'h'>[];
37
+ added: (Node & {
38
+ at: number;
39
+ id: string;
40
+ })[];
41
+ changed: (Node & {
42
+ id: string;
43
+ })[];
44
+ removed: (Pick<Node, 'x' | 'y' | 'w' | 'h'> & {
45
+ id: string;
46
+ })[];
25
47
  };
26
- export declare function computeDelta(prev: Map<string, Node>, curr: Map<string, Node>): Delta;
48
+ export declare function computeDelta(prev: Map<string, {
49
+ node: Node;
50
+ at: number;
51
+ }>, curr: Map<string, {
52
+ node: Node;
53
+ at: number;
54
+ }>): Delta;
27
55
  export declare function isReplayRunning(): boolean;
28
56
  /** Drain the ring as NDJSON (keyframe or delta per line). Empty
29
57
  * string when the ring is empty. Resets state so the next session's
@@ -1 +1 @@
1
- {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AAyDA,KAAK,IAAI,GAAG;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAkBF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,KAAK,GAAG,WAAW,CAAC;IAC3B;;mCAE+B;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAIF,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CA2BrD;AAED,wBAAgB,UAAU,IAAI,IAAI,CAajC;AAiHD,KAAK,KAAK,GAAG;IAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,CAAA;CAAE,CAAC;AAE9F,wBAAgB,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,KAAK,CAsBpF;AA8DD,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;2CAE2C;AAC3C,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAED;mEACmE;AACnE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAO1D"}
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AAyDA,KAAK,IAAI,GAAG;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAkBF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,KAAK,GAAG,WAAW,CAAC;IAC3B;;mCAE+B;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAIF,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CA2BrD;AAED,wBAAgB,UAAU,IAAI,IAAI,CAajC;AAmHD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAUjF;AAED,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,CAAC,IAAI,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;IAC7C,OAAO,EAAE,CAAC,IAAI,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;IACnC,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CACjE,CAAC;AAEF,wBAAgB,YAAY,CAC1B,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7C,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5C,KAAK,CAsBP;AA8DD,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;2CAE2C;AAC3C,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAED;mEACmE;AACnE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAO1D"}
package/lib/replay.js CHANGED
@@ -129,9 +129,7 @@ function captureTick() {
129
129
  }
130
130
  }
131
131
  function encodeAndPush(snapshot) {
132
- const currentState = new Map();
133
- for (const n of snapshot.nodes)
134
- currentState.set(fingerprint(n), n);
132
+ const currentState = indexNodes(snapshot.nodes);
135
133
  const ts = snapshot.ts;
136
134
  const isCold = _lastFrameState === null;
137
135
  const keyframeOverdue = ts - _lastKeyframeTs >= _keyframeIntervalMs;
@@ -190,25 +188,47 @@ function evictRing(nowTs) {
190
188
  function fingerprint(n) {
191
189
  return `${n.x | 0},${n.y | 0},${n.w | 0},${n.h | 0}`;
192
190
  }
191
+ /**
192
+ * Identity = geometry + occurrence index in walk order.
193
+ *
194
+ * Geometry alone is NOT identity: a page root and the fullscreen
195
+ * overlay covering it share x/y/w/h, and keying a Map on that
196
+ * collapsed them into one node — the overlay inherited the root's
197
+ * z-position and the replay drew the page THROUGH it (insight
198
+ * 2026-08-01). The occurrence suffix keeps every stacked layer its
199
+ * own entry, and stays stable across ticks because the native walk
200
+ * order is deterministic for a stable tree.
201
+ */
202
+ export function indexNodes(nodes) {
203
+ const out = new Map();
204
+ const seen = new Map();
205
+ nodes.forEach((n, at) => {
206
+ const base = fingerprint(n);
207
+ const occ = seen.get(base) ?? 0;
208
+ seen.set(base, occ + 1);
209
+ out.set(`${base}#${occ}`, { node: n, at });
210
+ });
211
+ return out;
212
+ }
193
213
  export function computeDelta(prev, curr) {
194
214
  const added = [];
195
215
  const changed = [];
196
216
  const removed = [];
197
- for (const [fp, node] of curr) {
198
- const p = prev.get(fp);
217
+ for (const [id, { node, at }] of curr) {
218
+ const p = prev.get(id);
199
219
  if (!p) {
200
- added.push(node);
220
+ added.push({ ...node, at, id });
201
221
  continue;
202
222
  }
203
- if ((p.kind ?? '') !== (node.kind ?? '') ||
204
- (p.color ?? '') !== (node.color ?? '') ||
205
- (p.text ?? '') !== (node.text ?? '')) {
206
- changed.push(node);
223
+ if ((p.node.kind ?? '') !== (node.kind ?? '') ||
224
+ (p.node.color ?? '') !== (node.color ?? '') ||
225
+ (p.node.text ?? '') !== (node.text ?? '')) {
226
+ changed.push({ ...node, id });
207
227
  }
208
228
  }
209
- for (const [fp, node] of prev) {
210
- if (!curr.has(fp))
211
- removed.push({ x: node.x, y: node.y, w: node.w, h: node.h });
229
+ for (const [id, { node }] of prev) {
230
+ if (!curr.has(id))
231
+ removed.push({ x: node.x, y: node.y, w: node.w, h: node.h, id });
212
232
  }
213
233
  return { added, changed, removed };
214
234
  }
package/lib/replay.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"replay.js","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"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"}
package/lib/transport.js CHANGED
@@ -15,7 +15,7 @@ const MAX_RETRY = 3;
15
15
  const STORAGE_KEY = '@sentori/pending';
16
16
  const MAX_PERSISTED = 1000;
17
17
  // Pinned to package.json by a test — bump both together.
18
- const SDK_VERSION = '5.1.2';
18
+ const SDK_VERSION = '5.1.4';
19
19
  let _queue = [];
20
20
  let _assertStats = new Map();
21
21
  let _flushTimer = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goliapkg/sentori-react-native",
3
- "version": "5.1.2",
3
+ "version": "5.1.4",
4
4
  "description": "Sentori SDK for React Native \u2014 JS-layer error capture, native crash handlers (iOS / Android), batched transport, fetch + react-navigation tracing.",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "author": "GOLIA K.K. <takagi@golia.jp> (https://golia.jp)",
@@ -5,6 +5,7 @@ import {
5
5
  __resetReplayForTests,
6
6
  computeDelta,
7
7
  drainReplay,
8
+ indexNodes,
8
9
  } from '../replay';
9
10
 
10
11
  // Unit coverage for the rc.9 v2 replay encoder.
@@ -206,9 +207,7 @@ describe('rc.9 encoder — keyframe vs delta', () => {
206
207
  });
207
208
 
208
209
  describe('computeDelta', () => {
209
- function asMap(nodes: Node[]): Map<string, Node> {
210
- return new Map(nodes.map((n) => [`${n.x | 0},${n.y | 0},${n.w | 0},${n.h | 0}`, n]));
211
- }
210
+ const asMap = (nodes: Node[]) => indexNodes(nodes);
212
211
 
213
212
  test('empty-vs-empty produces all-empty delta', () => {
214
213
  const d = computeDelta(new Map(), new Map());
@@ -234,4 +233,32 @@ describe('computeDelta', () => {
234
233
  expect(d.changed.length).toBe(0);
235
234
  expect(d.removed.length).toBe(0);
236
235
  });
236
+
237
+ test('stacked same-geometry layers keep separate identities (insight overlay bug)', () => {
238
+ // A page root and a fullscreen opaque overlay: identical x/y/w/h.
239
+ const pageRoot: Node = { x: 0, y: 0, w: 400, h: 800, kind: 'rect', color: '#101014FF' };
240
+ const overlay: Node = { x: 0, y: 0, w: 400, h: 800, kind: 'rect', color: '#FFFFFFFF' };
241
+ const m = indexNodes([pageRoot, overlay]);
242
+ // Both survive indexing…
243
+ expect(m.size).toBe(2);
244
+ expect([...m.keys()]).toEqual(['0,0,400,800#0', '0,0,400,800#1']);
245
+ // …and z-order info rides along.
246
+ expect(m.get('0,0,400,800#1')?.at).toBe(1);
247
+ });
248
+
249
+ test('delta entries carry ids; overlay removal targets the right layer', () => {
250
+ const pageRoot: Node = { x: 0, y: 0, w: 400, h: 800, kind: 'rect', color: '#101014FF' };
251
+ const overlay: Node = { x: 0, y: 0, w: 400, h: 800, kind: 'rect', color: '#FFFFFFFF' };
252
+ const withOverlay = indexNodes([pageRoot, overlay]);
253
+ const without = indexNodes([pageRoot]);
254
+
255
+ const closed = computeDelta(withOverlay, without);
256
+ expect(closed.removed.length).toBe(1);
257
+ expect(closed.removed[0]?.id).toBe('0,0,400,800#1');
258
+
259
+ const opened = computeDelta(without, withOverlay);
260
+ expect(opened.added.length).toBe(1);
261
+ expect(opened.added[0]?.id).toBe('0,0,400,800#1');
262
+ expect(opened.added[0]?.at).toBe(1);
263
+ });
237
264
  });
package/src/replay.ts CHANGED
@@ -76,7 +76,7 @@ let _running = false;
76
76
  /** Last emit's reconstructed state — fingerprint → node. Null until
77
77
  * the first keyframe lands; reset on drain so the next session
78
78
  * starts with a fresh keyframe. */
79
- let _lastFrameState: Map<string, Node> | null = null;
79
+ let _lastFrameState: Map<string, { node: Node; at: number }> | null = null;
80
80
  let _lastKeyframeTs = 0;
81
81
 
82
82
  let _nativeMod: ReplayNativeModule | null = null;
@@ -182,8 +182,7 @@ function captureTick(): void {
182
182
  }
183
183
 
184
184
  function encodeAndPush(snapshot: NativeFrame): void {
185
- const currentState = new Map<string, Node>();
186
- for (const n of snapshot.nodes) currentState.set(fingerprint(n), n);
185
+ const currentState = indexNodes(snapshot.nodes);
187
186
 
188
187
  const ts = snapshot.ts;
189
188
  const isCold = _lastFrameState === null;
@@ -195,7 +194,10 @@ function encodeAndPush(snapshot: NativeFrame): void {
195
194
  line = encodeKeyframe(snapshot);
196
195
  _lastKeyframeTs = ts;
197
196
  } else {
198
- const delta = computeDelta(_lastFrameState as Map<string, Node>, currentState);
197
+ const delta = computeDelta(
198
+ _lastFrameState as Map<string, { node: Node; at: number }>,
199
+ currentState,
200
+ );
199
201
  const totalChanged = delta.added.length + delta.changed.length + delta.removed.length;
200
202
  if (totalChanged === 0) {
201
203
  // No-op heartbeat — drop. Keep _lastFrameState as-is (identical).
@@ -248,28 +250,58 @@ function fingerprint(n: Node): string {
248
250
  return `${n.x | 0},${n.y | 0},${n.w | 0},${n.h | 0}`;
249
251
  }
250
252
 
251
- type Delta = { added: Node[]; changed: Node[]; removed: Pick<Node, 'x' | 'y' | 'w' | 'h'>[] };
253
+ /**
254
+ * Identity = geometry + occurrence index in walk order.
255
+ *
256
+ * Geometry alone is NOT identity: a page root and the fullscreen
257
+ * overlay covering it share x/y/w/h, and keying a Map on that
258
+ * collapsed them into one node — the overlay inherited the root's
259
+ * z-position and the replay drew the page THROUGH it (insight
260
+ * 2026-08-01). The occurrence suffix keeps every stacked layer its
261
+ * own entry, and stays stable across ticks because the native walk
262
+ * order is deterministic for a stable tree.
263
+ */
264
+ export function indexNodes(nodes: Node[]): Map<string, { node: Node; at: number }> {
265
+ const out = new Map<string, { node: Node; at: number }>();
266
+ const seen = new Map<string, number>();
267
+ nodes.forEach((n, at) => {
268
+ const base = fingerprint(n);
269
+ const occ = seen.get(base) ?? 0;
270
+ seen.set(base, occ + 1);
271
+ out.set(`${base}#${occ}`, { node: n, at });
272
+ });
273
+ return out;
274
+ }
275
+
276
+ type Delta = {
277
+ added: (Node & { at: number; id: string })[];
278
+ changed: (Node & { id: string })[];
279
+ removed: (Pick<Node, 'x' | 'y' | 'w' | 'h'> & { id: string })[];
280
+ };
252
281
 
253
- export function computeDelta(prev: Map<string, Node>, curr: Map<string, Node>): Delta {
254
- const added: Node[] = [];
255
- const changed: Node[] = [];
256
- const removed: Pick<Node, 'x' | 'y' | 'w' | 'h'>[] = [];
257
- for (const [fp, node] of curr) {
258
- const p = prev.get(fp);
282
+ export function computeDelta(
283
+ prev: Map<string, { node: Node; at: number }>,
284
+ curr: Map<string, { node: Node; at: number }>,
285
+ ): Delta {
286
+ const added: Delta['added'] = [];
287
+ const changed: Delta['changed'] = [];
288
+ const removed: Delta['removed'] = [];
289
+ for (const [id, { node, at }] of curr) {
290
+ const p = prev.get(id);
259
291
  if (!p) {
260
- added.push(node);
292
+ added.push({ ...node, at, id });
261
293
  continue;
262
294
  }
263
295
  if (
264
- (p.kind ?? '') !== (node.kind ?? '') ||
265
- (p.color ?? '') !== (node.color ?? '') ||
266
- (p.text ?? '') !== (node.text ?? '')
296
+ (p.node.kind ?? '') !== (node.kind ?? '') ||
297
+ (p.node.color ?? '') !== (node.color ?? '') ||
298
+ (p.node.text ?? '') !== (node.text ?? '')
267
299
  ) {
268
- changed.push(node);
300
+ changed.push({ ...node, id });
269
301
  }
270
302
  }
271
- for (const [fp, node] of prev) {
272
- if (!curr.has(fp)) removed.push({ x: node.x, y: node.y, w: node.w, h: node.h });
303
+ for (const [id, { node }] of prev) {
304
+ if (!curr.has(id)) removed.push({ x: node.x, y: node.y, w: node.w, h: node.h, id });
273
305
  }
274
306
  return { added, changed, removed };
275
307
  }
package/src/transport.ts CHANGED
@@ -20,7 +20,7 @@ const STORAGE_KEY = '@sentori/pending';
20
20
  const MAX_PERSISTED = 1000;
21
21
 
22
22
  // Pinned to package.json by a test — bump both together.
23
- const SDK_VERSION = '5.1.2';
23
+ const SDK_VERSION = '5.1.4';
24
24
 
25
25
  let _queue: WireEvent[] = [];
26
26
  let _assertStats = new Map<string, AssertStat>();