@flemo/devtools 0.2.1 → 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/README.md +7 -9
- package/dist/__tests__/domProtocol.test.d.ts +1 -0
- package/dist/__tests__/overridesRegistry.test.d.ts +1 -0
- package/dist/anomalies.d.ts +0 -4
- package/dist/domProtocol.d.ts +22 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +424 -390
- package/dist/noop.d.ts +1 -1
- package/dist/noop.mjs +147 -100
- package/dist/overrides.d.ts +39 -7
- package/dist/types.d.ts +0 -14
- package/package.json +2 -1
package/dist/noop.d.ts
CHANGED
|
@@ -10,4 +10,4 @@ export declare const attachFlightRecorder: (_options?: FlightRecorderOptions) =>
|
|
|
10
10
|
export declare const attachDevtoolsPanel: (_options?: DevtoolsPanelOptions) => DevtoolsPanelHandle;
|
|
11
11
|
export type { FlemoGlobal } from './recorder';
|
|
12
12
|
export type { DevtoolsPanelHandle, DevtoolsPanelOptions } from './panel';
|
|
13
|
-
export type {
|
|
13
|
+
export type { EnvironmentFingerprint, FlemoReport, FlightDriver, FlightHolds, FlightKind, FlightParticipants, FlightRecord, FlightRecorderHandle, FlightRecorderOptions, FlightTimestamp, FramePhaseStats, FrameSampleStats, LandingAudit, LongTaskSpan, ObservationCapabilities, OverridesSection, PlayerGapStats, UaBrand } from './types';
|
package/dist/noop.mjs
CHANGED
|
@@ -11,7 +11,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
11
11
|
return d.holdReassertedAtMs !== null && n.push(`hold re-asserted ${d.holdReassertedAtMs}ms into the flight, after it had already released (an interleaved commit wrote the stale paused hold attribute over a running flight — the flemo 2026-08-18 release-race signature; the motion pauses while every timing metric stays clean)`), d.pausedAfterRelease && n.push("compiled animation reported playState=paused after its release (the flight was posed and then stopped mid-motion, not merely starved of frames)"), d.longestStallMs >= 48 && n.push(`motion stalled ${d.longestStallMs}ms mid-flight (${d.stalledFrames}/${d.sampledFrames} released frames advanced neither the animation clock nor the pose — freeze, or freeze-then-leap if the flight still landed on time)`), d.sampledFrames === 0 && e.releasedAtMs !== null && n.push("no released frames were sampled (the flight ended at or before its own hold release — the visible motion, if any, was never observed)"), f.completedUnheld > 0 && n.push(`${f.completedUnheld} image(s) finished loading mid-flight without a hold (${f.completedDuringFlight} completed, ${f.heldDuringFlight} held; ${f.loadingAtStart} were loading at t0, ${f.addedDuringFlight} arrived mid-flight) — each decode rasters on the moving layer and costs a present; this is the warm-side image-hold regression`), l.orphanedHolds.length > 0 && n.push(`hold markers left on the page at rest: ${l.orphanedHolds.join("; ")} (whatever they hide has no owner left to reveal it — the permanently-blank-avatar class)`), l.residualInlineTransforms.length > 0 && n.push(`residual inline style after COMPLETED: ${l.residualInlineTransforms.join("; ")} (landing cleanup failure — the landed scope belongs to the compiled rest rules)`), l.offViewportAtRest && n.push("screen resting at from-pose while COMPLETED+active (blank-viewport signature — the flemo PR #259 class: a residual pose left the landed screen parked off-viewport)"), l.stuckStatuses.length > 0 && n.push(`transitional status stuck >${t / 1e3}s: ${l.stuckStatuses.join(", ")} (navigation queue lock or missed animationend — later navigations will be swallowed)`), i === "unknown" && n.push("driver could not be classified (no running flemo-* CSSAnimation and no player inline-style signature observed — zero-duration flight, or the sampler attached after motion ended)"), n;
|
|
12
12
|
}, s = (e) => {
|
|
13
13
|
let n = [];
|
|
14
|
-
if (e.
|
|
14
|
+
if (e.emulationSuspected) {
|
|
15
15
|
let t = /Win/i.test(e.platform) ? " (Windows touch hardware makes this signal ambiguous — confirm the DevTools device toolbar state)" : "";
|
|
16
16
|
n.push("DevTools device emulation suspected — the page composites to a rescaled surface, so visual reports from this session are untrustworthy; judge motion in a plain window or on a real device" + t);
|
|
17
17
|
}
|
|
@@ -98,163 +98,214 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
98
98
|
playerGapMirror: Array.isArray(n?.__flemoPlayerGaps)
|
|
99
99
|
}
|
|
100
100
|
};
|
|
101
|
-
}, h = [
|
|
101
|
+
}, h = "flemo:devtools-panel-height", g = [{
|
|
102
|
+
key: "flemo:devtools",
|
|
103
|
+
storage: "session",
|
|
104
|
+
kind: "opt-in-diagnostic",
|
|
105
|
+
values: "\"on\" / \"off\"",
|
|
106
|
+
fallback: "off",
|
|
107
|
+
effect: "arms this flight recorder in the playground (?devtools=on)"
|
|
108
|
+
}, {
|
|
109
|
+
key: h,
|
|
110
|
+
storage: "session",
|
|
111
|
+
kind: "production-state",
|
|
112
|
+
values: "a pixel height",
|
|
113
|
+
fallback: "(the panel's default height)",
|
|
114
|
+
effect: "the drawer height this panel was last dragged to"
|
|
115
|
+
}], _ = [
|
|
102
116
|
{
|
|
103
|
-
key: "flemo:
|
|
104
|
-
storage: "
|
|
117
|
+
key: "flemo:sixty",
|
|
118
|
+
storage: "session",
|
|
105
119
|
kind: "production-state",
|
|
106
|
-
|
|
120
|
+
values: "\"high\" / a streak count",
|
|
121
|
+
fallback: "(learned)",
|
|
122
|
+
effect: "steady-60 desktop verdict seed — owned by steadySixtyCadence.ts"
|
|
107
123
|
},
|
|
108
124
|
{
|
|
109
|
-
key: "flemo:
|
|
125
|
+
key: "flemo:settle-gate",
|
|
110
126
|
storage: "session",
|
|
111
|
-
kind: "
|
|
112
|
-
|
|
127
|
+
kind: "production-default-with-override",
|
|
128
|
+
values: "\"on\" / \"off\"",
|
|
129
|
+
fallback: "touch WebKit + touch Blink + desktop macOS WebKit + steady-60 desktop",
|
|
130
|
+
effect: "render-settle entry gate, shared by the engine's routing and the binding"
|
|
113
131
|
},
|
|
114
132
|
{
|
|
115
|
-
key: "flemo:
|
|
133
|
+
key: "flemo:arrivalhold",
|
|
116
134
|
storage: "session",
|
|
117
|
-
kind: "production-
|
|
118
|
-
|
|
135
|
+
kind: "production-default-with-override",
|
|
136
|
+
values: "\"off\"",
|
|
137
|
+
fallback: "on",
|
|
138
|
+
effect: "the whole in-flight hold set (arrival, response, invisible animations, images)"
|
|
119
139
|
},
|
|
120
140
|
{
|
|
121
|
-
key: "flemo:
|
|
141
|
+
key: "flemo:deskflip",
|
|
122
142
|
storage: "session",
|
|
123
|
-
kind: "production-
|
|
124
|
-
|
|
143
|
+
kind: "production-default-with-override",
|
|
144
|
+
values: "\"on\" / \"off\"",
|
|
145
|
+
fallback: "desktop macOS WebKit",
|
|
146
|
+
effect: "atomic release flip: the hold attribute flips on the DOM inside the readiness rAF"
|
|
125
147
|
},
|
|
126
148
|
{
|
|
127
|
-
key: "flemo:
|
|
149
|
+
key: "flemo:deskhead",
|
|
128
150
|
storage: "session",
|
|
129
|
-
kind: "production-
|
|
130
|
-
|
|
151
|
+
kind: "production-default-with-override",
|
|
152
|
+
values: "\"on\" / \"off\"",
|
|
153
|
+
fallback: "desktop macOS WebKit",
|
|
154
|
+
effect: "desktop flat-head keyframes; arming it retires the desktop birth anchor"
|
|
131
155
|
},
|
|
132
156
|
{
|
|
133
|
-
key: "flemo:
|
|
157
|
+
key: "flemo:creep",
|
|
134
158
|
storage: "session",
|
|
135
|
-
kind: "
|
|
136
|
-
|
|
159
|
+
kind: "production-default-with-override",
|
|
160
|
+
values: "\"on\" / \"off\"",
|
|
161
|
+
fallback: "touch WebKit",
|
|
162
|
+
effect: "creep head: its end keyframe carries a hair of motion, so the compositor is already carrying the animation at the boundary"
|
|
137
163
|
},
|
|
138
164
|
{
|
|
139
|
-
key: "flemo:
|
|
165
|
+
key: "flemo:relcommit",
|
|
140
166
|
storage: "session",
|
|
141
|
-
kind: "
|
|
142
|
-
|
|
167
|
+
kind: "production-default-with-override",
|
|
168
|
+
values: "\"defer\" / \"sync\"",
|
|
169
|
+
fallback: "touch WebKit",
|
|
170
|
+
effect: "the release's reconcile lands next frame instead of synchronously"
|
|
143
171
|
},
|
|
144
172
|
{
|
|
145
|
-
key: "flemo:
|
|
173
|
+
key: "flemo:imgoffload",
|
|
146
174
|
storage: "session",
|
|
147
175
|
kind: "production-default-with-override",
|
|
148
|
-
|
|
176
|
+
values: "\"on\" / \"off\"",
|
|
177
|
+
fallback: "on — the offloader decides per image, from the source's own size",
|
|
178
|
+
effect: "image decode offloader: an oversized source is fetched and downscaled in a worker so its decode never lands in a paint"
|
|
149
179
|
},
|
|
150
180
|
{
|
|
151
|
-
key: "flemo:
|
|
181
|
+
key: "flemo:governed",
|
|
152
182
|
storage: "session",
|
|
153
|
-
kind: "
|
|
154
|
-
|
|
183
|
+
kind: "production-default-with-override",
|
|
184
|
+
values: "\"on\" / \"off\"",
|
|
185
|
+
fallback: "legacy Android Blink (an old browser, not a slow device)",
|
|
186
|
+
effect: "the governed head kit on touch Blink — a flat head covering a compiled flight's opening. The auto-detection reads browser AGE, so a modern-but-weak phone falls through it; this is how such a device gets measured"
|
|
155
187
|
},
|
|
156
188
|
{
|
|
157
|
-
key: "flemo:
|
|
189
|
+
key: "flemo:imghold",
|
|
158
190
|
storage: "session",
|
|
159
191
|
kind: "opt-in-diagnostic",
|
|
160
|
-
|
|
192
|
+
values: "\"on\" / \"off\"",
|
|
193
|
+
fallback: "off",
|
|
194
|
+
effect: "flight-scoped <img> reveal hold"
|
|
161
195
|
},
|
|
162
196
|
{
|
|
163
|
-
key: "flemo:
|
|
197
|
+
key: "flemo:preraster",
|
|
164
198
|
storage: "session",
|
|
165
199
|
kind: "opt-in-diagnostic",
|
|
166
|
-
|
|
200
|
+
values: "\"on\"",
|
|
201
|
+
fallback: "off",
|
|
202
|
+
effect: "REST-time scope promotion, and the park-over hold variant. Flight-time promotion is the engine's own stamp and needs no flag"
|
|
167
203
|
},
|
|
168
204
|
{
|
|
169
|
-
key: "flemo:
|
|
205
|
+
key: "flemo:layers",
|
|
170
206
|
storage: "session",
|
|
171
|
-
kind: "
|
|
172
|
-
|
|
207
|
+
kind: "opt-in-diagnostic",
|
|
208
|
+
values: "\"resident\" / \"off\"",
|
|
209
|
+
fallback: "off",
|
|
210
|
+
effect: "keep screen layers resident at rest — a resident layer is a PERMANENT stacking context over the consumer's screen"
|
|
173
211
|
},
|
|
174
212
|
{
|
|
175
|
-
key: "flemo:
|
|
213
|
+
key: "flemo:freeze",
|
|
176
214
|
storage: "session",
|
|
177
215
|
kind: "opt-in-diagnostic",
|
|
178
|
-
|
|
216
|
+
values: "\"shallow\"",
|
|
217
|
+
fallback: "off",
|
|
218
|
+
effect: "keep the direct prev screen live instead of freezing it"
|
|
219
|
+
}
|
|
220
|
+
], v = [..._, ...g], y = [
|
|
221
|
+
{
|
|
222
|
+
key: "flemo:motion-driver",
|
|
223
|
+
storage: "local",
|
|
224
|
+
retiredWith: "the per-origin driver demotion ledger (2026-08-19)"
|
|
179
225
|
},
|
|
180
226
|
{
|
|
181
|
-
key: "flemo:
|
|
227
|
+
key: "flemo:motion-driver-force",
|
|
182
228
|
storage: "session",
|
|
183
|
-
|
|
184
|
-
description: "resident screen layers at rest"
|
|
229
|
+
retiredWith: "the hard driver pin, with the rAF player (2026-08-22)"
|
|
185
230
|
},
|
|
186
231
|
{
|
|
187
|
-
key: "flemo:
|
|
232
|
+
key: "flemo:landing-snap",
|
|
188
233
|
storage: "session",
|
|
189
|
-
|
|
190
|
-
description: "keep the direct prev screen live"
|
|
234
|
+
retiredWith: "the integer-device-pixel landing snap, falsified on device (2026-08-22)"
|
|
191
235
|
},
|
|
192
236
|
{
|
|
193
|
-
key: "flemo:
|
|
237
|
+
key: "flemo:handoff",
|
|
194
238
|
storage: "session",
|
|
195
|
-
|
|
196
|
-
description: "promote the entering content layer through the hold"
|
|
239
|
+
retiredWith: "the player's anchored-opening handoff (2026-08-22)"
|
|
197
240
|
},
|
|
198
241
|
{
|
|
199
|
-
key: "flemo:
|
|
242
|
+
key: "flemo:handoffms",
|
|
200
243
|
storage: "session",
|
|
201
|
-
|
|
202
|
-
description: "image decode offloader override"
|
|
244
|
+
retiredWith: "the player's anchored-opening handoff (2026-08-22)"
|
|
203
245
|
},
|
|
204
246
|
{
|
|
205
|
-
key: "flemo:
|
|
247
|
+
key: "flemo:apply",
|
|
206
248
|
storage: "session",
|
|
207
|
-
|
|
208
|
-
|
|
249
|
+
retiredWith: "the scrub-WAAPI value-application tier (2026-08-22)"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
key: "flemo:snap",
|
|
253
|
+
storage: "session",
|
|
254
|
+
retiredWith: "the player's device-pixel snap policy (2026-08-22)"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
key: "flemo:snapband",
|
|
258
|
+
storage: "session",
|
|
259
|
+
retiredWith: "the player's device-pixel snap policy (2026-08-22)"
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
key: "flemo:lat",
|
|
263
|
+
storage: "session",
|
|
264
|
+
retiredWith: "the Low Power Mode release-latency probe (2026-08-22)"
|
|
209
265
|
}
|
|
210
|
-
],
|
|
266
|
+
], b = "(retired — the library no longer reads this)", x = (e) => {
|
|
211
267
|
try {
|
|
212
268
|
let t = e === "session" ? sessionStorage : localStorage;
|
|
213
269
|
return t.length, t;
|
|
214
270
|
} catch {
|
|
215
271
|
return null;
|
|
216
272
|
}
|
|
217
|
-
},
|
|
273
|
+
}, S = (e, t) => {
|
|
218
274
|
try {
|
|
219
275
|
return e ? e.getItem(t) : null;
|
|
220
276
|
} catch {
|
|
221
277
|
return null;
|
|
222
278
|
}
|
|
223
|
-
},
|
|
224
|
-
let e = {}, t =
|
|
225
|
-
for (let r of
|
|
226
|
-
let i =
|
|
279
|
+
}, C = new Set(v.map((e) => e.key)), w = new Set(y.map((e) => e.key)), T = new Set(g.map((e) => e.key)), E = () => {
|
|
280
|
+
let e = {}, t = x("session"), n = x("local");
|
|
281
|
+
for (let r of v) {
|
|
282
|
+
let i = S(r.storage === "session" ? t : n, r.key);
|
|
227
283
|
i !== null && (e[r.key] = i);
|
|
228
284
|
}
|
|
229
|
-
let r
|
|
230
|
-
|
|
285
|
+
for (let r of y) for (let [i, a] of [[t, "sessionStorage"], [n, "localStorage"]]) {
|
|
286
|
+
let t = S(i, r.key);
|
|
287
|
+
t !== null && (e[`${r.key} (${a}) ${b}`] = t);
|
|
288
|
+
}
|
|
231
289
|
for (let [r, i] of [[t, "sessionStorage"], [n, "localStorage"]]) if (r) try {
|
|
232
290
|
for (let t = 0; t < r.length; t += 1) {
|
|
233
291
|
let n = r.key(t);
|
|
234
|
-
!n || !n.startsWith("flemo:") ||
|
|
292
|
+
!n || !n.startsWith("flemo:") || C.has(n) || w.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
|
|
235
293
|
}
|
|
236
294
|
} catch {}
|
|
237
295
|
return e;
|
|
238
|
-
},
|
|
296
|
+
}, D = (e) => {
|
|
239
297
|
let t = [];
|
|
240
298
|
for (let [n, r] of Object.entries(e)) {
|
|
241
|
-
if (n
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
if (n === _) {
|
|
246
|
-
t.push(`${n}=${r} — legacy localStorage driver pin present. The library removes it on sight and never honors it, but its existence means an old A/B session left residue on this profile.`);
|
|
299
|
+
if (n.includes("(retired — the library no longer reads this)")) {
|
|
300
|
+
let e = n.slice(0, n.indexOf(" (")), i = y.find((t) => t.key === e);
|
|
301
|
+
t.push(`${n}=${r} — RETIRED residue: this key went with ${i?.retiredWith ?? "a removed feature"}. The library never reads it, so it cannot explain anything you are seeing. Safe to delete; it is listed only so it does not read as an unexplained lead.`);
|
|
247
302
|
continue;
|
|
248
303
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
continue;
|
|
252
|
-
}
|
|
253
|
-
let e = h.find((e) => n === e.key || n.startsWith(`${e.key} `));
|
|
254
|
-
!e || e.key === "flemo:devtools" || (e.kind === "opt-in-diagnostic" ? t.push(`${n}=${r} — opt-in diagnostic active (${e.description}); behavior differs from stock. Possible left-over A/B toggle from an earlier debugging session.`) : e.kind === "production-default-with-override" && t.push(`${n}=${r} — production default overridden for this session (${e.description}).`));
|
|
304
|
+
let e = v.find((e) => n === e.key || n.startsWith(`${e.key} `));
|
|
305
|
+
!e || T.has(e.key) || (e.kind === "opt-in-diagnostic" ? t.push(`${n}=${r} — opt-in diagnostic active (${e.effect}); behavior differs from stock. Possible left-over A/B toggle from an earlier debugging session.`) : e.kind === "production-default-with-override" && t.push(`${n}=${r} — production default overridden for this session (${e.effect}). Stock behavior here is ${e.fallback}.`));
|
|
255
306
|
}
|
|
256
307
|
return t;
|
|
257
|
-
},
|
|
308
|
+
}, O = (e) => Math.round(e * 10) / 10, k = (e) => {
|
|
258
309
|
if (e.length === 0) return {
|
|
259
310
|
count: 0,
|
|
260
311
|
medianGapMs: 0,
|
|
@@ -264,11 +315,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
264
315
|
let t = [...e].sort((e, t) => e - t);
|
|
265
316
|
return {
|
|
266
317
|
count: e.length,
|
|
267
|
-
medianGapMs:
|
|
268
|
-
maxGapMs:
|
|
318
|
+
medianGapMs: O(t[Math.floor(t.length / 2)]),
|
|
319
|
+
maxGapMs: O(t[t.length - 1]),
|
|
269
320
|
over30Count: e.filter((e) => e >= 30).length
|
|
270
321
|
};
|
|
271
|
-
},
|
|
322
|
+
}, A = (e, t = []) => {
|
|
272
323
|
let n = [...e, ...t];
|
|
273
324
|
return {
|
|
274
325
|
...n.length === 0 ? {
|
|
@@ -279,21 +330,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
279
330
|
let e = [...n].sort((e, t) => e - t);
|
|
280
331
|
return {
|
|
281
332
|
count: n.length,
|
|
282
|
-
medianGapMs:
|
|
283
|
-
maxGapMs:
|
|
333
|
+
medianGapMs: O(e[Math.floor(e.length / 2)]),
|
|
334
|
+
maxGapMs: O(e[e.length - 1])
|
|
284
335
|
};
|
|
285
336
|
})(),
|
|
286
|
-
longGaps: n.filter((e) => e >= 30).map(
|
|
287
|
-
held:
|
|
288
|
-
released:
|
|
337
|
+
longGaps: n.filter((e) => e >= 30).map(O),
|
|
338
|
+
held: k(e),
|
|
339
|
+
released: k(t)
|
|
289
340
|
};
|
|
290
|
-
},
|
|
291
|
-
maxMs:
|
|
341
|
+
}, j = (e) => e.length === 0 ? null : {
|
|
342
|
+
maxMs: O(Math.max(...e)),
|
|
292
343
|
over30Count: e.filter((e) => e >= 30).length
|
|
293
|
-
},
|
|
344
|
+
}, M = (e) => {
|
|
294
345
|
let t = e.playerSuppression || e.playerAdvance;
|
|
295
346
|
return t && e.compiledAnimation ? "mixed" : t ? "player" : e.compiledAnimation ? "compiled" : "unknown";
|
|
296
|
-
},
|
|
347
|
+
}, N = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, P = (e) => {
|
|
297
348
|
let t = /^matrix3d\(([^)]+)\)$/.exec(e.trim());
|
|
298
349
|
if (t) {
|
|
299
350
|
let e = t[1].split(",").map((e) => Number(e.trim()));
|
|
@@ -305,7 +356,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
305
356
|
return e.length === 6 && Number.isFinite(e[4]) ? e[4] : null;
|
|
306
357
|
}
|
|
307
358
|
return null;
|
|
308
|
-
},
|
|
359
|
+
}, F = "2", I = "@flemo/devtools resolved to its production entry: nothing was recorded. Run a development build to collect a real report.", L = () => {}, R = () => ({
|
|
309
360
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
310
361
|
version: "inert",
|
|
311
362
|
environment: {
|
|
@@ -338,19 +389,15 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
338
389
|
},
|
|
339
390
|
overrides: {
|
|
340
391
|
active: {},
|
|
341
|
-
warnings: [
|
|
342
|
-
},
|
|
343
|
-
driverPolicy: {
|
|
344
|
-
demotion: null,
|
|
345
|
-
forcePin: null
|
|
392
|
+
warnings: [I]
|
|
346
393
|
},
|
|
347
394
|
flights: [],
|
|
348
|
-
anomalies: [
|
|
395
|
+
anomalies: [I],
|
|
349
396
|
blindSpots: [],
|
|
350
|
-
judgingProtocol: [
|
|
351
|
-
}),
|
|
352
|
-
detach:
|
|
353
|
-
report:
|
|
354
|
-
}),
|
|
397
|
+
judgingProtocol: [I]
|
|
398
|
+
}), z = (e) => ({
|
|
399
|
+
detach: L,
|
|
400
|
+
report: R
|
|
401
|
+
}), B = (e) => ({ detach: L });
|
|
355
402
|
//#endregion
|
|
356
|
-
export { c as BLIND_SPOTS,
|
|
403
|
+
export { c as BLIND_SPOTS, _ as CORE_FLAGS, g as DEVTOOLS_OWNED_FLAGS, v as FLAG_REGISTRY, e as LONG_GAP_MS, i as MID_FLIGHT_TASK_MS, n as OPENING_WINDOW_LEAD_MS, r as OPENING_WINDOW_TAIL_MS, h as PANEL_HEIGHT_KEY, F as REPORT_SCHEMA_VERSION, y as RETIRED_FLAGS, b as RETIRED_MARKER, a as STALL_MS, t as STUCK_STATUS_MS, B as attachDevtoolsPanel, z as attachFlightRecorder, m as captureEnvironment, M as classifyDriver, A as computeFrameStats, k as computePhaseStats, j as computePlayerGapStats, o as deriveFlightAnomalies, D as deriveOverrideWarnings, s as deriveReportAnomalies, u as detectEngine, d as isEmulationSuspected, N as kindFromStatus, P as parseTranslateX, f as sampleRafCadence, E as snapshotOverrides };
|
package/dist/overrides.d.ts
CHANGED
|
@@ -1,18 +1,50 @@
|
|
|
1
1
|
export type FlagClass = "production-state" | "production-default-with-override" | "opt-in-diagnostic";
|
|
2
|
+
/**
|
|
3
|
+
* The panel's drawer height. Declared HERE rather than in the panel so the
|
|
4
|
+
* registry below can name it: a `flemo:` key the recorder writes but does not
|
|
5
|
+
* declare shows up in its own reports as an unknown key.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PANEL_HEIGHT_KEY = "flemo:devtools-panel-height";
|
|
2
8
|
export interface FlagDescriptor {
|
|
3
9
|
key: string;
|
|
4
10
|
storage: "session" | "local";
|
|
5
11
|
kind: FlagClass;
|
|
6
|
-
|
|
12
|
+
/** Accepted values, for a report to spell out. */
|
|
13
|
+
values: string;
|
|
14
|
+
/** The default when the key is unset. */
|
|
15
|
+
fallback: string;
|
|
16
|
+
/** What arming it changes. */
|
|
17
|
+
effect: string;
|
|
7
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Keys DEVTOOLS itself owns. Core neither reads nor declares them, so they are
|
|
21
|
+
* listed here and excluded from the comparison against core — without a row
|
|
22
|
+
* each one would surface in every report as an unknown key, which is the
|
|
23
|
+
* recorder generating its own false lead.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEVTOOLS_OWNED_FLAGS: readonly FlagDescriptor[];
|
|
26
|
+
/** Every `flemo:*` key the library reads, mirrored from core. */
|
|
27
|
+
export declare const CORE_FLAGS: readonly FlagDescriptor[];
|
|
8
28
|
export declare const FLAG_REGISTRY: readonly FlagDescriptor[];
|
|
9
|
-
/** Marker suffix for the legacy-location residue of the force pin. */
|
|
10
|
-
export declare const LEGACY_LOCAL_PIN_KEY = "flemo:motion-driver-force (localStorage \u2014 legacy location)";
|
|
11
29
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
|
|
30
|
+
* Keys the library once read and no longer does. They are still ENUMERATED so
|
|
31
|
+
* a report can say "this is set, and it does nothing" — residue that is merely
|
|
32
|
+
* unknown reads as a lead worth chasing.
|
|
33
|
+
*/
|
|
34
|
+
export interface RetiredFlag {
|
|
35
|
+
key: string;
|
|
36
|
+
storage: "session" | "local";
|
|
37
|
+
/** What it used to do, and when it stopped doing it. */
|
|
38
|
+
retiredWith: string;
|
|
39
|
+
}
|
|
40
|
+
export declare const RETIRED_FLAGS: readonly RetiredFlag[];
|
|
41
|
+
/** Marker suffix appended to a retired key so a report reads as a verdict. */
|
|
42
|
+
export declare const RETIRED_MARKER = "(retired \u2014 the library no longer reads this)";
|
|
43
|
+
/**
|
|
44
|
+
* Snapshot every `flemo:*` key currently set, from both storages: the live
|
|
45
|
+
* registry keys from their native storage, any RETIRED key still persisted
|
|
46
|
+
* (marked as such), and any UNKNOWN `flemo:`-prefixed key either storage holds
|
|
47
|
+
* (a future flag, or hand-set residue).
|
|
16
48
|
*/
|
|
17
49
|
export declare const snapshotOverrides: () => Record<string, string>;
|
|
18
50
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -238,26 +238,12 @@ export interface OverridesSection {
|
|
|
238
238
|
/** Derived, prominent warnings — read these before trusting anything. */
|
|
239
239
|
warnings: string[];
|
|
240
240
|
}
|
|
241
|
-
export interface DriverPolicySection {
|
|
242
|
-
/**
|
|
243
|
-
* localStorage `flemo:motion-driver` — the learned ledger. "css" means the
|
|
244
|
-
* device earned a persisted player demotion; "raf" means a clean probe.
|
|
245
|
-
*/
|
|
246
|
-
demotion: string | null;
|
|
247
|
-
/**
|
|
248
|
-
* sessionStorage `flemo:motion-driver-force` raw value. NON-NULL MEANS A
|
|
249
|
-
* PIN IS ACTIVE: every transition is forced onto one driver. Almost always
|
|
250
|
-
* A/B residue when found unexpectedly.
|
|
251
|
-
*/
|
|
252
|
-
forcePin: string | null;
|
|
253
|
-
}
|
|
254
241
|
export interface FlemoReport {
|
|
255
242
|
generatedAt: string;
|
|
256
243
|
/** Report schema version (not the package version). */
|
|
257
244
|
version: string;
|
|
258
245
|
environment: EnvironmentFingerprint;
|
|
259
246
|
overrides: OverridesSection;
|
|
260
|
-
driverPolicy: DriverPolicySection;
|
|
261
247
|
flights: FlightRecord[];
|
|
262
248
|
/** Session-level findings (observation traps, active pins, stuck flights). */
|
|
263
249
|
anomalies: string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flemo/devtools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Zero-config flight recorder for flemo screen transitions: captures per-flight driver routing, frame pacing, long tasks, landing residues, active debug overrides, and environment/observation-trap fingerprints into one JSON report readable by humans and coding agents.",
|
|
5
5
|
"main": "./dist/index.mjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"vite": "^8.2.1",
|
|
43
43
|
"vite-plugin-dts": "^5.0.3",
|
|
44
44
|
"vitest": "^4.1.10",
|
|
45
|
+
"@flemo/core": "1.30.0",
|
|
45
46
|
"@flemo/eslint-config": "0.0.0",
|
|
46
47
|
"@flemo/tsconfig": "0.0.0"
|
|
47
48
|
},
|