@vosjs/cli 0.45.1 → 0.46.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/dist/{chunk-RDQYYRWN.js → chunk-ID4OUS5L.js} +62 -2
- package/dist/chunk-ID4OUS5L.js.map +1 -0
- package/dist/{chunk-4HW2XR5K.js → chunk-UE66DC2K.js} +21 -11
- package/dist/chunk-UE66DC2K.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/index.d.ts +25 -0
- package/dist/index.js +2 -2
- package/dist/{run-S4EZ5OIT.js → run-2OZS25ER.js} +3 -3
- package/dist/{shotList-FYDHO5AI.js → shotList-JC4A3FBT.js} +2 -2
- package/package.json +3 -3
- package/dist/chunk-4HW2XR5K.js.map +0 -1
- package/dist/chunk-RDQYYRWN.js.map +0 -1
- /package/dist/{run-S4EZ5OIT.js.map → run-2OZS25ER.js.map} +0 -0
- /package/dist/{shotList-FYDHO5AI.js.map → shotList-JC4A3FBT.js.map} +0 -0
|
@@ -90,6 +90,63 @@ function paceLine(r) {
|
|
|
90
90
|
const slow = r.slow.length ? `; slow: ${r.slow.map((x) => `#${x.step} ${x.do} ${s(x.wallMs)} for ${s(x.askedMs)} asked`).join(", ")}` : "";
|
|
91
91
|
return `pace: the script asked ${s(r.askedMs)}, the gestures added ${s(r.gestureMs)}, the take ran ${s(r.wallMs)} (${r.overheadPct} % overhead${slow})`;
|
|
92
92
|
}
|
|
93
|
+
var READ_BEAT_MS = { page: 1e3, control: 600 };
|
|
94
|
+
var DEAD_STRETCH_WARN_MS = 1500;
|
|
95
|
+
var DEAD_SHARE_WARN_PCT = 20;
|
|
96
|
+
function deadTime(steps, frames, events, durationMs) {
|
|
97
|
+
const out = [];
|
|
98
|
+
let ms = 0;
|
|
99
|
+
let longestMs = 0;
|
|
100
|
+
for (const s of steps) {
|
|
101
|
+
const t0 = s.tStart * 1e3;
|
|
102
|
+
const t1 = s.tEnd * 1e3;
|
|
103
|
+
if (!(t1 > t0)) continue;
|
|
104
|
+
const press = events.find(
|
|
105
|
+
(e) => e.type === "down" && e.t >= t0 && e.t <= t1
|
|
106
|
+
);
|
|
107
|
+
const act = press ? press.t : t0;
|
|
108
|
+
let last = act;
|
|
109
|
+
for (const f of frames) {
|
|
110
|
+
if (f.tMs > act && f.tMs <= t1) last = f.tMs;
|
|
111
|
+
}
|
|
112
|
+
const settledMs = Math.round(last - act);
|
|
113
|
+
const heldMs = Math.round(t1 - last);
|
|
114
|
+
const moved = events.some(
|
|
115
|
+
(e) => (e.type === "move" || e.type === "scroll") && e.t > last && e.t <= t1
|
|
116
|
+
);
|
|
117
|
+
const beat = s.navigated || s.step === 0 ? READ_BEAT_MS.page : READ_BEAT_MS.control;
|
|
118
|
+
const deadMs = moved ? 0 : Math.max(0, heldMs - beat);
|
|
119
|
+
if (deadMs > 0) {
|
|
120
|
+
out.push({
|
|
121
|
+
step: s.step,
|
|
122
|
+
...s.id ? { id: s.id } : {},
|
|
123
|
+
do: s.do,
|
|
124
|
+
settledMs,
|
|
125
|
+
heldMs,
|
|
126
|
+
deadMs
|
|
127
|
+
});
|
|
128
|
+
ms += deadMs;
|
|
129
|
+
longestMs = Math.max(longestMs, deadMs);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
ms,
|
|
134
|
+
pct: durationMs > 0 ? Math.round(ms / durationMs * 100) : 0,
|
|
135
|
+
steps: out,
|
|
136
|
+
longestMs
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function deadWarns(r) {
|
|
140
|
+
return r.pct >= DEAD_SHARE_WARN_PCT || r.longestMs >= DEAD_STRETCH_WARN_MS;
|
|
141
|
+
}
|
|
142
|
+
function deadLine(r) {
|
|
143
|
+
const s = (ms) => `${(ms / 1e3).toFixed(1)} s`;
|
|
144
|
+
if (!r.steps.length) return "dead time: none";
|
|
145
|
+
const parts = r.steps.map(
|
|
146
|
+
(d) => `#${d.step}${d.id ? ` (${d.id})` : ""} ${d.do} held ${s(d.heldMs)} after it settled, ${s(d.deadMs)} past the beat`
|
|
147
|
+
);
|
|
148
|
+
return `dead time: ${s(r.ms)} (${r.pct} %), a still frame under a parked cursor past the reading beat: ${parts.join("; ")}. Cut those steps' ms; a hold is what it takes to read what changed.`;
|
|
149
|
+
}
|
|
93
150
|
|
|
94
151
|
export {
|
|
95
152
|
PRESS_LEAD_MS,
|
|
@@ -102,6 +159,9 @@ export {
|
|
|
102
159
|
clockTyping,
|
|
103
160
|
askedMs,
|
|
104
161
|
paceReport,
|
|
105
|
-
paceLine
|
|
162
|
+
paceLine,
|
|
163
|
+
deadTime,
|
|
164
|
+
deadWarns,
|
|
165
|
+
deadLine
|
|
106
166
|
};
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
167
|
+
//# sourceMappingURL=chunk-ID4OUS5L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugin/pace.ts"],"sourcesContent":["/**\n * The recorder's pace — the pure parts.\n *\n * A take of a scripted flow should run as long as the script asks, plus the\n * gestures a person makes between the asks (the pointer's travel, the press,\n * the settle after it) and no more. Measured before this module (§4.5 of\n * the utility-clip retrospective), hovers ran 2× their ask, drags 4.8× and\n * a 25 s script recorded 42 s, for two reasons the numbers here answer:\n *\n * - The motion loops counted STEPS (one per 16 ms of the asked duration)\n * and awaited a `mouse.move` round trip per step, so a page that\n * re-renders per move (a slider) stretched every gesture by the round\n * trip. A gesture is now driven by the CLOCK: its position is a function\n * of the elapsed time, and it ends when the asked duration has elapsed,\n * however many samples the page allowed.\n * - The settles after a gesture were fixed sleeps (500 ms after a click,\n * 250 after every selector lookup). A settle is DATA: `ms` on the step\n * overrides a small default, and the script's own `wait` steps carry\n * the intended pauses.\n */\n\n/** Pointer travel: ms per CSS px, floor and ceiling — a person's hand. */\nexport const POINTER_MS_PER_PX = 0.7\nexport const POINTER_MIN_MS = 250\nexport const POINTER_MAX_MS = 800\n/** The sample cadence a motion loop aims for. */\nexport const MOTION_TICK_MS = 16\n\n/** The settle after a gesture when the step names none, by verb. */\nexport const SETTLE_MS = {\n click: 150,\n type: 150,\n scroll: 200,\n drag: 80,\n} as const\n\n/** The press: the pause before the button goes down, and the hold. */\nexport const PRESS_LEAD_MS = 80\nexport const PRESS_HOLD_MS = 70\n/** The pause between a selector lookup that scrolled the page and the move. */\nexport const SCROLL_SETTLE_MS = 120\n/** The hold after the last step, so the take does not cut on a press. */\nexport const TRAILING_HOLD_MS = 400\n\n/** How long the pointer takes to travel `dist` CSS px. */\nexport function pointerTravelMs(dist: number): number {\n return Math.min(\n POINTER_MAX_MS,\n Math.max(POINTER_MIN_MS, Math.round(dist * POINTER_MS_PER_PX)),\n )\n}\n\n/** The settle after a step: its own `ms` when it names one, else the verb's. */\nexport function settleMs(step: { do: string; ms?: number }): number {\n if (typeof step.ms === 'number' && step.ms >= 0) return step.ms\n const d = step.do as keyof typeof SETTLE_MS\n return SETTLE_MS[d] ?? 0\n}\n\nexport const easeInOutCubic = (u: number): number =>\n u < 0.5 ? 4 * u * u * u : 1 - Math.pow(-2 * u + 2, 3) / 2\n\n/**\n * Drive a motion by the clock: `at(u)` is called with the eased progress\n * for each sample, and the loop ends when `dur` ms have elapsed, with the\n * last call at u = 1 exactly. Between samples it sleeps to the next tick\n * only when the sample came back early; a slow sample (a page busy\n * re-rendering) is followed at once, so the gesture keeps its length and\n * loses samples, never the other way round.\n */\nexport async function clockMotion(\n dur: number,\n at: (u: number) => Promise<void>,\n clock: { now: () => number; sleep: (ms: number) => Promise<void> },\n): Promise<number> {\n const start = clock.now()\n let samples = 0\n for (;;) {\n const elapsed = clock.now() - start\n if (elapsed >= dur) break\n await at(easeInOutCubic(Math.min(1, elapsed / dur)))\n samples++\n const next =\n start + Math.ceil((clock.now() - start) / MOTION_TICK_MS) * MOTION_TICK_MS\n const wait = Math.min(next, start + dur) - clock.now()\n if (wait > 0) await clock.sleep(wait)\n }\n await at(1)\n return samples + 1\n}\n\n/**\n * Typing paced by the clock: the i-th character is due at `start + i·delay`;\n * after each keystroke the loop sleeps to the next due time only if the\n * keystroke came back early. A slow field (an editor re-rendering per key)\n * types as fast as it can and says so in the pace report.\n */\nexport async function clockTyping(\n chars: readonly string[],\n delay: number,\n type: (ch: string, index: number) => Promise<void>,\n clock: { now: () => number; sleep: (ms: number) => Promise<void> },\n): Promise<void> {\n const start = clock.now()\n for (let i = 0; i < chars.length; i++) {\n await type(chars[i], i)\n const due = start + (i + 1) * delay\n const wait = due - clock.now()\n if (wait > 0 && i < chars.length - 1) await clock.sleep(wait)\n }\n}\n\n/** One step's pace: what the script asked for it and what it took. */\nexport interface StepPace {\n step: number\n do: string\n /** The script's own ask: a wait's ms, a hover's dwell, a drag's ms, typing's chars × delay; 0 for a click or a scroll. */\n askedMs: number\n /** The gesture the recorder adds by design: pointer travel, the press, the settle. */\n gestureMs: number\n wallMs: number\n}\n\nexport interface PaceReport {\n askedMs: number\n gestureMs: number\n wallMs: number\n /** Wall time neither asked nor a gesture: what the page and the round trips cost. */\n overheadMs: number\n overheadPct: number\n /** The steps whose wall ran past their ask plus gesture by more than a third. */\n slow: { step: number; do: string; askedMs: number; wallMs: number }[]\n}\n\n/** What a script asks of a step, in ms: the part of its wall time that is the author's. */\nexport function askedMs(step: {\n do: string\n ms?: number\n text?: string\n delayMs?: number\n}): number {\n switch (step.do) {\n case 'wait':\n return step.ms ?? 0\n case 'hover':\n return step.ms ?? 700\n case 'drag':\n return step.ms ?? 700\n case 'type':\n return (step.text?.length ?? 0) * (step.delayMs ?? 40)\n default:\n return 0\n }\n}\n\nexport function paceReport(steps: readonly StepPace[]): PaceReport {\n const askedMs = steps.reduce((a, s) => a + s.askedMs, 0)\n const gestureMs = steps.reduce((a, s) => a + s.gestureMs, 0)\n const wallMs = steps.reduce((a, s) => a + s.wallMs, 0)\n const overheadMs = Math.max(0, wallMs - askedMs - gestureMs)\n const slow = steps\n .filter((s) => s.wallMs > (s.askedMs + s.gestureMs) * 1.34 + 60)\n .map((s) => ({\n step: s.step,\n do: s.do,\n askedMs: s.askedMs,\n wallMs: s.wallMs,\n }))\n return {\n askedMs,\n gestureMs,\n wallMs,\n overheadMs,\n overheadPct: wallMs > 0 ? Math.round((overheadMs / wallMs) * 100) : 0,\n slow,\n }\n}\n\n/** The pace in one line for the log. */\nexport function paceLine(r: PaceReport): string {\n const s = (ms: number) => `${(ms / 1000).toFixed(1)} s`\n const slow = r.slow.length\n ? `; slow: ${r.slow.map((x) => `#${x.step} ${x.do} ${s(x.wallMs)} for ${s(x.askedMs)} asked`).join(', ')}`\n : ''\n return `pace: the script asked ${s(r.askedMs)}, the gestures added ${s(r.gestureMs)}, the take ran ${s(r.wallMs)} (${r.overheadPct} % overhead${slow})`\n}\n\n/**\n * DEAD TIME, the smoothness fact that replaces the freeze share as the\n * warning. A still frame is not a defect: a page the viewer is reading is\n * content, and a workspace tour is mostly still. What is dead is a still\n * frame under a PARKED cursor past the beat it takes to read what changed:\n * after that the picture, the pointer and the camera all hold and nothing\n * is being said. So the derivation reads, per step, when the page settled\n * after the step's act, how long the settled frame was held, and whether\n * the cursor moved in that hold; a hold past the reading beat is dead.\n *\n * The beat is longer after a page changed (a navigation shows a whole new\n * page to take in) than after a control changed (one thing to see).\n */\nexport const READ_BEAT_MS = { page: 1000, control: 600 } as const\n/** A dead stretch this long is a warning on its own, whatever the share. */\nexport const DEAD_STRETCH_WARN_MS = 1500\n/** The share of the take past which dead time is a warning. */\nexport const DEAD_SHARE_WARN_PCT = 20\n\nexport interface DeadStep {\n step: number\n id?: string\n do: string\n /** ms from the step's act (its press, else its start) to the last frame change in the step. */\n settledMs: number\n /** ms the settled frame was held before the step ended. */\n heldMs: number\n /** the hold past the reading beat, while the cursor was parked; 0 when the hold was read or the pointer moved. */\n deadMs: number\n}\n\nexport interface DeadReport {\n ms: number\n pct: number\n /** the steps that carried any dead time, in order. */\n steps: DeadStep[]\n /** the longest single dead hold. */\n longestMs: number\n}\n\nexport function deadTime(\n steps: readonly {\n step: number\n id?: string\n do: string\n tStart: number\n tEnd: number\n navigated?: boolean\n }[],\n frames: readonly { tMs: number }[],\n events: readonly { t: number; type: string }[],\n durationMs: number,\n): DeadReport {\n const out: DeadStep[] = []\n let ms = 0\n let longestMs = 0\n for (const s of steps) {\n const t0 = s.tStart * 1000\n const t1 = s.tEnd * 1000\n if (!(t1 > t0)) continue\n // The act: the step's first press, else its start (a wait, a move).\n const press = events.find(\n (e) => e.type === 'down' && e.t >= t0 && e.t <= t1,\n )\n const act = press ? press.t : t0\n // The last visual change inside the step, after the act.\n let last = act\n for (const f of frames) {\n if (f.tMs > act && f.tMs <= t1) last = f.tMs\n }\n const settledMs = Math.round(last - act)\n const heldMs = Math.round(t1 - last)\n // Parked: no pointer motion while the settled frame was held.\n const moved = events.some(\n (e) =>\n (e.type === 'move' || e.type === 'scroll') && e.t > last && e.t <= t1,\n )\n // The opening step shows a page the viewer has not seen: a page beat.\n const beat =\n s.navigated || s.step === 0 ? READ_BEAT_MS.page : READ_BEAT_MS.control\n const deadMs = moved ? 0 : Math.max(0, heldMs - beat)\n if (deadMs > 0) {\n out.push({\n step: s.step,\n ...(s.id ? { id: s.id } : {}),\n do: s.do,\n settledMs,\n heldMs,\n deadMs,\n })\n ms += deadMs\n longestMs = Math.max(longestMs, deadMs)\n }\n }\n return {\n ms,\n pct: durationMs > 0 ? Math.round((ms / durationMs) * 100) : 0,\n steps: out,\n longestMs,\n }\n}\n\n/** Whether a dead report earns a warning: the share, or one long hold. */\nexport function deadWarns(r: DeadReport): boolean {\n return r.pct >= DEAD_SHARE_WARN_PCT || r.longestMs >= DEAD_STRETCH_WARN_MS\n}\n\n/** The dead time in words, naming the steps and what to cut. */\nexport function deadLine(r: DeadReport): string {\n const s = (ms: number) => `${(ms / 1000).toFixed(1)} s`\n if (!r.steps.length) return 'dead time: none'\n const parts = r.steps.map(\n (d) =>\n `#${d.step}${d.id ? ` (${d.id})` : ''} ${d.do} held ${s(d.heldMs)} after it settled, ${s(d.deadMs)} past the beat`,\n )\n return `dead time: ${s(r.ms)} (${r.pct} %), a still frame under a parked cursor past the reading beat: ${parts.join('; ')}. Cut those steps' ms; a hold is what it takes to read what changed.`\n}\n"],"mappings":"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","names":["askedMs"]}
|
|
@@ -14,11 +14,14 @@ import {
|
|
|
14
14
|
askedMs,
|
|
15
15
|
clockMotion,
|
|
16
16
|
clockTyping,
|
|
17
|
+
deadLine,
|
|
18
|
+
deadTime,
|
|
19
|
+
deadWarns,
|
|
17
20
|
paceLine,
|
|
18
21
|
paceReport,
|
|
19
22
|
pointerTravelMs,
|
|
20
23
|
settleMs
|
|
21
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-ID4OUS5L.js";
|
|
22
25
|
|
|
23
26
|
// src/plugin/run.ts
|
|
24
27
|
import { mkdir as mkdir10, readFile as readFile15, rm as rm5 } from "fs/promises";
|
|
@@ -391,7 +394,8 @@ import {
|
|
|
391
394
|
resolvePins,
|
|
392
395
|
spanOutputExtent,
|
|
393
396
|
zoomCoversRect,
|
|
394
|
-
cameraModel
|
|
397
|
+
cameraModel,
|
|
398
|
+
unionFitLevel
|
|
395
399
|
} from "@vosjs/studio-core";
|
|
396
400
|
import { TYPEFACE_CATALOG, findFontFamily, findTypeface } from "@vosjs/shared";
|
|
397
401
|
var STEP_KINDS_ALL = [
|
|
@@ -1792,8 +1796,14 @@ function framingWarnings(docIn, doc, zoom, overlays, warnings) {
|
|
|
1792
1796
|
0.02,
|
|
1793
1797
|
cameraModel(docIn.frame)
|
|
1794
1798
|
)) {
|
|
1799
|
+
const together = unionFitLevel(
|
|
1800
|
+
{ x: x0 * w, y: y0 * h, w: rect.w * w, h: rect.h * h },
|
|
1801
|
+
w,
|
|
1802
|
+
h
|
|
1803
|
+
);
|
|
1804
|
+
const fix = together < 1.2 ? `the ${under.length} presses under it do not share one window at any zoom, so split it, one span per press (vos plan replans auto spans)` : together < z.level ? `lower the level to ${together.toFixed(2)}\xD7 or below, or split the span` : `move cx/cy toward it`;
|
|
1795
1805
|
warnings.push(
|
|
1796
|
-
`${spanName("zoom", z)}: points beside what was clicked at ${under[0].t.toFixed(1)}s \u2014 the target (center ${((x0 + x1) / 2).toFixed(2)}, ${((y0 + y1) / 2).toFixed(2)}) sits outside the visible window;
|
|
1806
|
+
`${spanName("zoom", z)}: points beside what was clicked at ${under[0].t.toFixed(1)}s \u2014 the target (center ${((x0 + x1) / 2).toFixed(2)}, ${((y0 + y1) / 2).toFixed(2)}) sits outside the visible window; ${fix}`
|
|
1797
1807
|
);
|
|
1798
1808
|
}
|
|
1799
1809
|
}
|
|
@@ -7410,11 +7420,8 @@ async function recordTake(browser, url, actions, paths, log, opts = {}) {
|
|
|
7410
7420
|
}
|
|
7411
7421
|
const frozenMs = freezes.reduce((sum, f) => sum + f.ms, 0);
|
|
7412
7422
|
const freezePct = durationMs > 0 ? Math.round(frozenMs / durationMs * 100) : 0;
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
` WARNING: ${freezePct}% of the take is visually frozen (${freezes.length} freezes, longest ${Math.max(...freezes.map((f) => f.ms))}ms) \u2014 keep motion in frame or trim these spans in doc.json`
|
|
7416
|
-
);
|
|
7417
|
-
}
|
|
7423
|
+
const dead = deadTime(stepSpans, frames, events, durationMs);
|
|
7424
|
+
if (deadWarns(dead)) log(` WARNING: ${deadLine(dead)}`);
|
|
7418
7425
|
const pace = paceReport(paces);
|
|
7419
7426
|
if (!dry) {
|
|
7420
7427
|
await writeJson(paths.cursor, events);
|
|
@@ -7435,6 +7442,7 @@ async function recordTake(browser, url, actions, paths, log, opts = {}) {
|
|
|
7435
7442
|
masks: exposureLog.masks(masks),
|
|
7436
7443
|
freezes,
|
|
7437
7444
|
freezePct,
|
|
7445
|
+
dead,
|
|
7438
7446
|
capped
|
|
7439
7447
|
};
|
|
7440
7448
|
}
|
|
@@ -10726,7 +10734,7 @@ function summary(result) {
|
|
|
10726
10734
|
async function cmdActionsScript(input, flags) {
|
|
10727
10735
|
const r = createReporter(flags.json === true);
|
|
10728
10736
|
const { readFile: readFile16 } = await import("fs/promises");
|
|
10729
|
-
const { shotList, formatShotList } = await import("./shotList-
|
|
10737
|
+
const { shotList, formatShotList } = await import("./shotList-JC4A3FBT.js");
|
|
10730
10738
|
const raw = JSON.parse(await readFile16(resolve8(input), "utf8"));
|
|
10731
10739
|
const errors = validateActions(raw);
|
|
10732
10740
|
if (errors.length) throw new UsageError(`${input}:
|
|
@@ -11279,6 +11287,7 @@ ${lines.join("\n")}
|
|
|
11279
11287
|
navTimeout: rec.navTimeout,
|
|
11280
11288
|
freezes: rec.freezes,
|
|
11281
11289
|
freezePct: rec.freezePct,
|
|
11290
|
+
dead: rec.dead,
|
|
11282
11291
|
capped: rec.capped,
|
|
11283
11292
|
pace: rec.pace,
|
|
11284
11293
|
...rec.wall ? { wall: rec.wall } : {},
|
|
@@ -11287,7 +11296,7 @@ ${lines.join("\n")}
|
|
|
11287
11296
|
...strictFail ? { strictFailed: true } : {}
|
|
11288
11297
|
},
|
|
11289
11298
|
strictFail ? `STRICT: take recorded but incomplete \u2014 ${strictReason(rec)}; fix the flow and re-record.${skippedNote}${exposureNote(rec)}` : `Take ready: ${outDir}
|
|
11290
|
-
${(rec.meta.durationMs / 1e3).toFixed(1)}s \xB7 ${rec.frames.length} frames \xB7 ${rec.events.length} cursor events \xB7 ${clicks} clicks \xB7 ${plan.doc.zoom.length} zoom spans planned \xB7 ${rec.freezePct}% frozen${rec.
|
|
11299
|
+
${(rec.meta.durationMs / 1e3).toFixed(1)}s \xB7 ${rec.frames.length} frames \xB7 ${rec.events.length} cursor events \xB7 ${clicks} clicks \xB7 ${plan.doc.zoom.length} zoom spans planned \xB7 ${rec.freezePct}% frozen \xB7 ${rec.dead.pct}% dead${deadWarns(rec.dead) ? " \u26A0 " + deadLine(rec.dead) : ""}${skippedNote}
|
|
11291
11300
|
Next: edit ${join19(outDir, "doc.json")} (optional), then: vos render ${outDir}${exposureNote(rec)}`
|
|
11292
11301
|
);
|
|
11293
11302
|
return strictFail ? EXIT_USAGE : EXIT_OK;
|
|
@@ -11411,6 +11420,7 @@ async function cmdCreate2(argv) {
|
|
|
11411
11420
|
navTimeout: rec.navTimeout,
|
|
11412
11421
|
freezes: rec.freezes,
|
|
11413
11422
|
freezePct: rec.freezePct,
|
|
11423
|
+
dead: rec.dead,
|
|
11414
11424
|
exposures: rec.exposures,
|
|
11415
11425
|
...rec.masks.length ? { masks: rec.masks } : {},
|
|
11416
11426
|
...flags.draft === true ? { draft: true } : {}
|
|
@@ -12666,4 +12676,4 @@ export {
|
|
|
12666
12676
|
verbHelp,
|
|
12667
12677
|
run
|
|
12668
12678
|
};
|
|
12669
|
-
//# sourceMappingURL=chunk-
|
|
12679
|
+
//# sourceMappingURL=chunk-UE66DC2K.js.map
|