demobite 1.0.4 → 1.0.5
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/package.json +1 -1
- package/scripts/calibrate.mjs +12 -1
package/package.json
CHANGED
package/scripts/calibrate.mjs
CHANGED
|
@@ -38,6 +38,14 @@ if (!fs.existsSync(manPath)) { console.error(`${manPath} not found. Run record.m
|
|
|
38
38
|
if (!fs.existsSync(clean)) { console.error(`${clean} not found. Run trim.mjs first.`); process.exit(1); }
|
|
39
39
|
const man = JSON.parse(fs.readFileSync(manPath, "utf8"));
|
|
40
40
|
const tb = man.timebase;
|
|
41
|
+
// IDEMPOTENCE (2026-09-02): always measure from the identity base. A previous
|
|
42
|
+
// run may have already applied a hover-anchor shift to `b`; re-running on top
|
|
43
|
+
// of it compounded two shifts (-0.71 then -1.67 on one take) and produced a
|
|
44
|
+
// clock that matched nothing. Re-base first, then anchor once.
|
|
45
|
+
if (tb && typeof man.record_from === "number") {
|
|
46
|
+
tb.a = 1; tb.k = 1; tb.b = -man.record_from; tb.videoRecordFrom = man.record_from;
|
|
47
|
+
tb.method = "identity (raw is wall-rate; see 2026-08-09 four-lane verification)";
|
|
48
|
+
}
|
|
41
49
|
if (!tb || typeof tb.a !== "number" || typeof tb.b !== "number") {
|
|
42
50
|
console.error("manifest.json has no timebase stamp. Run trim.mjs first.");
|
|
43
51
|
process.exit(1);
|
|
@@ -45,7 +53,10 @@ if (!tb || typeof tb.a !== "number" || typeof tb.b !== "number") {
|
|
|
45
53
|
|
|
46
54
|
const FRAME = { w: man.frame?.width ?? 1920, h: man.frame?.height ?? 1080 };
|
|
47
55
|
const clicks = (man.steps ?? [])
|
|
48
|
-
|
|
56
|
+
// A `type` step has no single consequence instant — its pixels keep changing
|
|
57
|
+
// for the whole typing run, so the detector lands at the END of it (+5..7 s
|
|
58
|
+
// every take, 2026-09-02) and poisons the median. Clicks only.
|
|
59
|
+
.filter((s) => typeof s.click_at === "number" && s.action !== "type")
|
|
49
60
|
.map((s) => ({ wall: s.click_at, label: s.label ?? "click" }))
|
|
50
61
|
.sort((x, y) => x.wall - y.wall);
|
|
51
62
|
|