@crouton-kit/capture 1.3.7 → 1.3.8

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.
Files changed (40) hide show
  1. package/bin/capture +2807 -1312
  2. package/package.json +4 -1
  3. package/src/capture.ts +10 -0
  4. package/src/cdp/args.ts +99 -10
  5. package/src/cdp/bridge/protocol.ts +99 -0
  6. package/src/cdp/bridge/server.ts +105 -43
  7. package/src/cdp/bridge/spawn.ts +62 -0
  8. package/src/cdp/commands/bridge-serve.ts +28 -3
  9. package/src/cdp/commands/cdp.ts +30 -2
  10. package/src/cdp/commands/measure/census.ts +31 -0
  11. package/src/cdp/commands/measure/check.ts +35 -0
  12. package/src/cdp/commands/measure/diff.ts +32 -0
  13. package/src/cdp/commands/measure/explain.ts +31 -0
  14. package/src/cdp/commands/measure/index.ts +114 -0
  15. package/src/cdp/commands/measure/map-focus.ts +24 -0
  16. package/src/cdp/commands/measure/map-layers.ts +25 -0
  17. package/src/cdp/commands/measure/map-scroll.ts +24 -0
  18. package/src/cdp/commands/measure/snap.ts +36 -0
  19. package/src/cdp/commands/measure/sweep.ts +30 -0
  20. package/src/cdp/commands/motion/index.ts +60 -0
  21. package/src/cdp/commands/motion/jank.ts +22 -0
  22. package/src/cdp/commands/motion/mask.ts +23 -0
  23. package/src/cdp/commands/motion/rec.ts +33 -0
  24. package/src/cdp/commands/motion/response.ts +26 -0
  25. package/src/cdp/commands/motion/timeline.ts +27 -0
  26. package/src/cdp/coordinates.ts +158 -0
  27. package/src/cdp/dispatch.ts +4 -0
  28. package/src/cdp/domains.ts +75 -0
  29. package/src/cdp/recorder-bridge.ts +521 -0
  30. package/src/cdp/source-map.ts +309 -0
  31. package/src/cdp/timing.ts +82 -0
  32. package/src/cdp/types.ts +66 -0
  33. package/src/cdp/usage.ts +2 -0
  34. package/src/output/artifact.ts +520 -0
  35. package/src/output/diff.ts +111 -0
  36. package/src/output/render.ts +593 -0
  37. package/src/output/selector.ts +185 -0
  38. package/src/session/artifacts.ts +229 -0
  39. package/src/session/commands.ts +119 -15
  40. package/src/session-context.ts +48 -8
@@ -0,0 +1,31 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure census [--snap <id>]... [--url <url>]... [--set-file <path>] --axis <axis>
5
+
6
+ Value distributions and token audits across one or more snapshots. Each
7
+ --snap/--url is repeatable to build a cross-page distribution; a --url
8
+ target creates a one-shot snap first.
9
+
10
+ Options:
11
+ --snap <id> Existing snapshot id/path (repeatable)
12
+ --url <url> URL to snap first (repeatable)
13
+ --set-file <path> File listing additional snap/url targets, one per line
14
+ --viewport <WxH> Viewport to snap at (repeatable)
15
+ --axis <axis> color|font|spacing|radius|shadow|animation|geometry|media|queries
16
+
17
+ Not yet implemented.`;
18
+
19
+ export async function cmdMeasureCensus(parsed: ParsedArgs, _args: string[]): Promise<void> {
20
+ if (parsed.help) {
21
+ console.log(USAGE);
22
+ process.exit(0);
23
+ }
24
+ const result: RenderableResult = {
25
+ tag: 'error',
26
+ attrs: { command: 'measure census', status: 'not_implemented' },
27
+ summary: fact`\`measure census\` is not implemented yet.`,
28
+ };
29
+ emitResult(result, { json: parsed.json });
30
+ process.exit(1);
31
+ }
@@ -0,0 +1,35 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure check [url|snap] [--for <checks>] [--viewport <WxH>]... [--gate]
5
+
6
+ Threshold/fact checks over a settled snapshot's substrate: overlap,
7
+ offscreen, overflow, tap-target size, contrast, hit-test receiver,
8
+ truncation, form visibility, media/replaced anomalies, and animation
9
+ facts. A URL target creates a one-shot snap first.
10
+
11
+ Options:
12
+ --for <checks> Comma-separated check names (e.g.
13
+ overlap,offscreen,overflow,tap-targets,contrast,
14
+ hit-test,truncation) or a category
15
+ (geometry|content|targetability|forms|animation|all).
16
+ Omit for every check.
17
+ --viewport <WxH> Viewport to check at (repeatable, for a discrete
18
+ multi-viewport sweep)
19
+ --gate Exit 2 if any check finds something (default: exit 0)
20
+
21
+ Not yet implemented.`;
22
+
23
+ export async function cmdMeasureCheck(parsed: ParsedArgs, _args: string[]): Promise<void> {
24
+ if (parsed.help) {
25
+ console.log(USAGE);
26
+ process.exit(0);
27
+ }
28
+ const result: RenderableResult = {
29
+ tag: 'error',
30
+ attrs: { command: 'measure check', status: 'not_implemented' },
31
+ summary: fact`\`measure check\` is not implemented yet.`,
32
+ };
33
+ emitResult(result, { json: parsed.json });
34
+ process.exit(1);
35
+ }
@@ -0,0 +1,32 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure diff --before <snap> --after <snap> [--pixels] [--full] [--gate]
5
+
6
+ Structured before/after diff over two snapshots: style/geometry/text/form/
7
+ media deltas, cascade provenance, and reflow attribution. No positional
8
+ target — both snapshots must already exist.
9
+
10
+ Options:
11
+ --before <snap> Earlier snapshot id/path (required)
12
+ --after <snap> Later snapshot id/path (required)
13
+ --pixels Also report raster regions not explained by geometry
14
+ --full Expand to state-matrix deltas and complete per-element
15
+ change records
16
+ --gate Exit 2 if any element changed (default: exit 0)
17
+
18
+ Not yet implemented.`;
19
+
20
+ export async function cmdMeasureDiff(parsed: ParsedArgs, _args: string[]): Promise<void> {
21
+ if (parsed.help) {
22
+ console.log(USAGE);
23
+ process.exit(0);
24
+ }
25
+ const result: RenderableResult = {
26
+ tag: 'error',
27
+ attrs: { command: 'measure diff', status: 'not_implemented' },
28
+ summary: fact`\`measure diff\` is not implemented yet.`,
29
+ };
30
+ emitResult(result, { json: parsed.json });
31
+ process.exit(1);
32
+ }
@@ -0,0 +1,31 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure explain <snap> --selector <sel> [--size] [--text] [--form]
5
+
6
+ Per-element cascade/stacking/clipping explanation over one snapshot, plus
7
+ optional detail sections.
8
+
9
+ Options:
10
+ --selector <sel> Element selector (required)
11
+ --size Include size/layout provenance (flex/grid/intrinsic)
12
+ --text Include text/line-box/wrap detail
13
+ --form Include form/caret/selection/autofill detail (redacted)
14
+
15
+ With no detail flag, returns the standard compact element explanation.
16
+
17
+ Not yet implemented.`;
18
+
19
+ export async function cmdMeasureExplain(parsed: ParsedArgs, _args: string[]): Promise<void> {
20
+ if (parsed.help) {
21
+ console.log(USAGE);
22
+ process.exit(0);
23
+ }
24
+ const result: RenderableResult = {
25
+ tag: 'error',
26
+ attrs: { command: 'measure explain', status: 'not_implemented' },
27
+ summary: fact`\`measure explain\` is not implemented yet.`,
28
+ };
29
+ emitResult(result, { json: parsed.json });
30
+ process.exit(1);
31
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * `capture measure` branch router.
3
+ *
4
+ * Shifts the consumed leaf token(s) out of `parsed.positional` before
5
+ * handing off, so every leaf command still finds its own primary target
6
+ * (a URL, a snap id, ...) at `positional[0]` exactly as every other capture
7
+ * command does — leaf commands never need to know they're nested under a
8
+ * branch.
9
+ */
10
+ import { type ParsedArgs } from '../../types.js';
11
+ import { cmdMeasureSnap } from './snap.js';
12
+ import { cmdMeasureCheck } from './check.js';
13
+ import { cmdMeasureDiff } from './diff.js';
14
+ import { cmdMeasureCensus } from './census.js';
15
+ import { cmdMeasureExplain } from './explain.js';
16
+ import { cmdMeasureSweep } from './sweep.js';
17
+ import { cmdMeasureMapFocus } from './map-focus.js';
18
+ import { cmdMeasureMapScroll } from './map-scroll.js';
19
+ import { cmdMeasureMapLayers } from './map-layers.js';
20
+
21
+ export const MEASURE_USAGE = `capture measure — enriched snapshot substrate + read-only queries over it.
22
+
23
+ \`snap\` drives the page (or a base snapshot) and writes one settled artifact
24
+ directory; every other leaf below is a cheap read over that artifact and
25
+ never re-drives the browser unless it explicitly accepts a URL target.
26
+
27
+ Leaves:
28
+ snap [url|snap] Drive + write a settled snapshot substrate
29
+ [--freeze-animations] [--settle-timeout <ms>] [--capture-unsettled]
30
+ [--pixels] [--state <state[:selector]>]...
31
+
32
+ check [url|snap] [--for <checks>] [--viewport <WxH>]... [--gate]
33
+ Threshold/fact checks over a snapshot
34
+
35
+ diff --before <snap> --after <snap> [--pixels] [--full] [--gate]
36
+ Structured before/after snapshot diff
37
+
38
+ census [--snap <id>]... [--url <url>]... [--set-file <path>] --axis <axis>
39
+ Value distributions across one or more snapshots
40
+ (--snap/--url repeatable)
41
+
42
+ explain <snap> --selector <sel> [--size] [--text] [--form]
43
+ Per-element cascade/stacking/clipping/size/text/form explanation
44
+
45
+ sweep [url] --axis <axis> [--from <val>] [--to <val>] [--viewport-height <val>]
46
+ Responsive/environment sampling
47
+
48
+ map focus|scroll|layers [url|snap] Read one facet of a snapshot's substrate
49
+ (see \`capture measure map --help\`)
50
+
51
+ Every leaf defaults to rendered prose; --json mirrors the same result as JSON.
52
+ Exit codes: 0 by default — findings are a report, not a failure.
53
+ --gate exits 2 on findings/changes; only \`check\` and \`diff\` accept it.
54
+
55
+ capture measure <leaf> --help Per-leaf usage`;
56
+
57
+ export const MEASURE_MAP_USAGE = `capture measure map — read one facet of a snapshot's substrate (no browser re-drive).
58
+
59
+ Leaves:
60
+ focus [url|snap] Keyboard traversal order (focus.json)
61
+ scroll [url|snap] Scroll-container topology (scroll.json)
62
+ layers [url|snap] Paint/compositor layer map (layers.json)
63
+
64
+ A URL target first creates a snap; a snap target reads its existing artifact.
65
+
66
+ capture measure map <leaf> --help Per-leaf usage`;
67
+
68
+ export async function measureMain(parsed: ParsedArgs, args: string[]): Promise<void> {
69
+ const leaf = parsed.positional[0];
70
+ const rest: ParsedArgs = { ...parsed, positional: parsed.positional.slice(1) };
71
+
72
+ switch (leaf) {
73
+ case 'snap':
74
+ return cmdMeasureSnap(rest, args);
75
+ case 'check':
76
+ return cmdMeasureCheck(rest, args);
77
+ case 'diff':
78
+ return cmdMeasureDiff(rest, args);
79
+ case 'census':
80
+ return cmdMeasureCensus(rest, args);
81
+ case 'explain':
82
+ return cmdMeasureExplain(rest, args);
83
+ case 'sweep':
84
+ return cmdMeasureSweep(rest, args);
85
+ case 'map':
86
+ return measureMapMain(rest, args);
87
+ case undefined:
88
+ console.log(MEASURE_USAGE);
89
+ return;
90
+ default:
91
+ console.error(`Unknown measure leaf: ${leaf}\n\n${MEASURE_USAGE}`);
92
+ process.exit(1);
93
+ }
94
+ }
95
+
96
+ async function measureMapMain(parsed: ParsedArgs, args: string[]): Promise<void> {
97
+ const sub = parsed.positional[0];
98
+ const rest: ParsedArgs = { ...parsed, positional: parsed.positional.slice(1) };
99
+
100
+ switch (sub) {
101
+ case 'focus':
102
+ return cmdMeasureMapFocus(rest, args);
103
+ case 'scroll':
104
+ return cmdMeasureMapScroll(rest, args);
105
+ case 'layers':
106
+ return cmdMeasureMapLayers(rest, args);
107
+ case undefined:
108
+ console.log(MEASURE_MAP_USAGE);
109
+ return;
110
+ default:
111
+ console.error(`Unknown measure map leaf: ${sub}\n\n${MEASURE_MAP_USAGE}`);
112
+ process.exit(1);
113
+ }
114
+ }
@@ -0,0 +1,24 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure map focus [url|snap]
5
+
6
+ Keyboard traversal order recorded in a snapshot's focus.json: forward and
7
+ reverse Tab sequence, rects, scroll jumps, focus-visible facts, and
8
+ unreached focusable elements. A URL target creates a snap first.
9
+
10
+ Not yet implemented.`;
11
+
12
+ export async function cmdMeasureMapFocus(parsed: ParsedArgs, _args: string[]): Promise<void> {
13
+ if (parsed.help) {
14
+ console.log(USAGE);
15
+ process.exit(0);
16
+ }
17
+ const result: RenderableResult = {
18
+ tag: 'error',
19
+ attrs: { command: 'measure map focus', status: 'not_implemented' },
20
+ summary: fact`\`measure map focus\` is not implemented yet.`,
21
+ };
22
+ emitResult(result, { json: parsed.json });
23
+ process.exit(1);
24
+ }
@@ -0,0 +1,25 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure map layers [url|snap]
5
+
6
+ Paint/compositor layer map recorded in a snapshot's layers.json: layers,
7
+ bounds, compositing reasons, paint order, per-node membership, and source
8
+ provenance for layer-affecting declarations. A URL target creates a snap
9
+ first.
10
+
11
+ Not yet implemented.`;
12
+
13
+ export async function cmdMeasureMapLayers(parsed: ParsedArgs, _args: string[]): Promise<void> {
14
+ if (parsed.help) {
15
+ console.log(USAGE);
16
+ process.exit(0);
17
+ }
18
+ const result: RenderableResult = {
19
+ tag: 'error',
20
+ attrs: { command: 'measure map layers', status: 'not_implemented' },
21
+ summary: fact`\`measure map layers\` is not implemented yet.`,
22
+ };
23
+ emitResult(result, { json: parsed.json });
24
+ process.exit(1);
25
+ }
@@ -0,0 +1,24 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure map scroll [url|snap]
5
+
6
+ Scroll-container topology recorded in a snapshot's scroll.json: containers,
7
+ ranges, current/max offsets, sticky/fixed occupancy, snap points, and
8
+ visual/layout viewport facts. A URL target creates a snap first.
9
+
10
+ Not yet implemented.`;
11
+
12
+ export async function cmdMeasureMapScroll(parsed: ParsedArgs, _args: string[]): Promise<void> {
13
+ if (parsed.help) {
14
+ console.log(USAGE);
15
+ process.exit(0);
16
+ }
17
+ const result: RenderableResult = {
18
+ tag: 'error',
19
+ attrs: { command: 'measure map scroll', status: 'not_implemented' },
20
+ summary: fact`\`measure map scroll\` is not implemented yet.`,
21
+ };
22
+ emitResult(result, { json: parsed.json });
23
+ process.exit(1);
24
+ }
@@ -0,0 +1,36 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure snap [url|snap] [--freeze-animations] [--settle-timeout <ms>] [--capture-unsettled] [--pixels] [--state <state[:selector]>]... [--viewport <WxH>]...
5
+
6
+ Drive the page (or re-capture states over a base snapshot) and write one
7
+ settled snapshot substrate directory: geometry, styles, hit-test, text,
8
+ forms, animation, ax, queries, focus, scroll, layers, and (with --pixels)
9
+ per-element crops. Every other measure/motion query leaf reads this
10
+ artifact instead of re-driving the browser.
11
+
12
+ Options:
13
+ --freeze-animations Pause CSS/WAAPI animation before capture
14
+ --settle-timeout <ms> Override the default 5000ms settle wait
15
+ --capture-unsettled Write full substrate despite non-settlement,
16
+ marking unstable regions
17
+ --pixels Also write per-element raster crops
18
+ --state <state[:selector]> Force a pseudo-state or real control state
19
+ (repeatable)
20
+ --viewport <WxH> Viewport to snap at (repeatable)
21
+
22
+ Not yet implemented.`;
23
+
24
+ export async function cmdMeasureSnap(parsed: ParsedArgs, _args: string[]): Promise<void> {
25
+ if (parsed.help) {
26
+ console.log(USAGE);
27
+ process.exit(0);
28
+ }
29
+ const result: RenderableResult = {
30
+ tag: 'error',
31
+ attrs: { command: 'measure snap', status: 'not_implemented' },
32
+ summary: fact`\`measure snap\` is not implemented yet.`,
33
+ };
34
+ emitResult(result, { json: parsed.json });
35
+ process.exit(1);
36
+ }
@@ -0,0 +1,30 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture measure sweep [url] --axis <axis> [--from <val>] [--to <val>] [--viewport-height <val>]
5
+
6
+ Responsive/environment sampling: repeated snap captures across an axis
7
+ (width, dpr, zoom, color-scheme, reduced-motion, ...), binary-searched to
8
+ find transition points and piecewise-stable ranges.
9
+
10
+ Options:
11
+ --axis <axis> The sampled axis (default: width)
12
+ --from <val> Range start (axis-dependent: width px, dpr, zoom, ...)
13
+ --to <val> Range end (axis-dependent)
14
+ --viewport-height <val> Fixed viewport height while sweeping width/dpr/zoom
15
+
16
+ Not yet implemented.`;
17
+
18
+ export async function cmdMeasureSweep(parsed: ParsedArgs, _args: string[]): Promise<void> {
19
+ if (parsed.help) {
20
+ console.log(USAGE);
21
+ process.exit(0);
22
+ }
23
+ const result: RenderableResult = {
24
+ tag: 'error',
25
+ attrs: { command: 'measure sweep', status: 'not_implemented' },
26
+ summary: fact`\`measure sweep\` is not implemented yet.`,
27
+ };
28
+ emitResult(result, { json: parsed.json });
29
+ process.exit(1);
30
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * `capture motion` branch router.
3
+ *
4
+ * Shifts the consumed leaf token out of `parsed.positional` before handing
5
+ * off, so every leaf command still finds its own primary target (a URL, a
6
+ * recording id, ...) at `positional[0]` exactly as every other capture
7
+ * command does.
8
+ */
9
+ import { type ParsedArgs } from '../../types.js';
10
+ import { cmdMotionRec } from './rec.js';
11
+ import { cmdMotionMask } from './mask.js';
12
+ import { cmdMotionTimeline } from './timeline.js';
13
+ import { cmdMotionJank } from './jank.js';
14
+ import { cmdMotionResponse } from './response.js';
15
+
16
+ export const MOTION_USAGE = `capture motion — recorder lifecycle + read-only queries over a finalized recording.
17
+
18
+ \`rec\` drives (and records) the browser, one-shot or composed across
19
+ intervening commands; every other leaf below is a cheap read over the
20
+ finalized recording artifact.
21
+
22
+ Leaves:
23
+ rec [url] --do <action> [--duration <ms>] One-shot: drive one action, record it
24
+ rec --start Composed: arm the recorder (needs an active session)
25
+ rec --stop Composed: finalize the recorder
26
+
27
+ mask <rec> Motion-diff composite image + per-region facts
28
+ timeline <rec> --element <sel> [--prop <prop>]
29
+ Per-frame geometry/scroll/property timeline
30
+ jank <rec> Dropped-frame/long-task/layout-shift facts
31
+ response <rec> [--action <action>] Input-to-settled response timeline
32
+
33
+ Every leaf defaults to rendered prose; --json mirrors the same result as JSON.
34
+ Exit codes: 0 always — findings are a report, not a failure. No leaf accepts --gate.
35
+
36
+ capture motion <leaf> --help Per-leaf usage`;
37
+
38
+ export async function motionMain(parsed: ParsedArgs, args: string[]): Promise<void> {
39
+ const leaf = parsed.positional[0];
40
+ const rest: ParsedArgs = { ...parsed, positional: parsed.positional.slice(1) };
41
+
42
+ switch (leaf) {
43
+ case 'rec':
44
+ return cmdMotionRec(rest, args);
45
+ case 'mask':
46
+ return cmdMotionMask(rest, args);
47
+ case 'timeline':
48
+ return cmdMotionTimeline(rest, args);
49
+ case 'jank':
50
+ return cmdMotionJank(rest, args);
51
+ case 'response':
52
+ return cmdMotionResponse(rest, args);
53
+ case undefined:
54
+ console.log(MOTION_USAGE);
55
+ return;
56
+ default:
57
+ console.error(`Unknown motion leaf: ${leaf}\n\n${MOTION_USAGE}`);
58
+ process.exit(1);
59
+ }
60
+ }
@@ -0,0 +1,22 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture motion jank <rec>
5
+
6
+ Dropped-frame/long-task/layout-shift facts over a finalized recording.
7
+
8
+ Not yet implemented.`;
9
+
10
+ export async function cmdMotionJank(parsed: ParsedArgs, _args: string[]): Promise<void> {
11
+ if (parsed.help) {
12
+ console.log(USAGE);
13
+ process.exit(0);
14
+ }
15
+ const result: RenderableResult = {
16
+ tag: 'error',
17
+ attrs: { command: 'motion jank', status: 'not_implemented' },
18
+ summary: fact`\`motion jank\` is not implemented yet.`,
19
+ };
20
+ emitResult(result, { json: parsed.json });
21
+ process.exit(1);
22
+ }
@@ -0,0 +1,23 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture motion mask <rec>
5
+
6
+ Motion-diff composite image over a finalized recording, plus per-region
7
+ area/distance/velocity facts and element attribution where resolvable.
8
+
9
+ Not yet implemented.`;
10
+
11
+ export async function cmdMotionMask(parsed: ParsedArgs, _args: string[]): Promise<void> {
12
+ if (parsed.help) {
13
+ console.log(USAGE);
14
+ process.exit(0);
15
+ }
16
+ const result: RenderableResult = {
17
+ tag: 'error',
18
+ attrs: { command: 'motion mask', status: 'not_implemented' },
19
+ summary: fact`\`motion mask\` is not implemented yet.`,
20
+ };
21
+ emitResult(result, { json: parsed.json });
22
+ process.exit(1);
23
+ }
@@ -0,0 +1,33 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture motion rec [url] --do <action> [--duration <ms>]
5
+ capture motion rec --start
6
+ capture motion rec --stop [--rec-id <id>]
7
+
8
+ One-shot (\`--do\`): drives one scripted action and records it end to end.
9
+ Composed (\`--start\` ... intervening commands ... \`--stop\`): records
10
+ whatever the active session does across multiple independent commands.
11
+
12
+ Options:
13
+ --do <action> One-shot action to drive and record (e.g. click:SEL)
14
+ --duration <ms> Recording duration override
15
+ --start Arm the composed recorder (requires an active session)
16
+ --stop Finalize the composed recorder
17
+ --rec-id <id> Explicit recording id (default: the session's active recording)
18
+
19
+ Not yet implemented.`;
20
+
21
+ export async function cmdMotionRec(parsed: ParsedArgs, _args: string[]): Promise<void> {
22
+ if (parsed.help) {
23
+ console.log(USAGE);
24
+ process.exit(0);
25
+ }
26
+ const result: RenderableResult = {
27
+ tag: 'error',
28
+ attrs: { command: 'motion rec', status: 'not_implemented' },
29
+ summary: fact`\`motion rec\` is not implemented yet.`,
30
+ };
31
+ emitResult(result, { json: parsed.json });
32
+ process.exit(1);
33
+ }
@@ -0,0 +1,26 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture motion response <rec> [--action <action>]
5
+
6
+ Input-to-settled response timeline over a finalized recording:
7
+ input -> mutation -> layout -> paint -> network -> settle.
8
+
9
+ Options:
10
+ --action <action> Narrow to one recorded action
11
+
12
+ Not yet implemented.`;
13
+
14
+ export async function cmdMotionResponse(parsed: ParsedArgs, _args: string[]): Promise<void> {
15
+ if (parsed.help) {
16
+ console.log(USAGE);
17
+ process.exit(0);
18
+ }
19
+ const result: RenderableResult = {
20
+ tag: 'error',
21
+ attrs: { command: 'motion response', status: 'not_implemented' },
22
+ summary: fact`\`motion response\` is not implemented yet.`,
23
+ };
24
+ emitResult(result, { json: parsed.json });
25
+ process.exit(1);
26
+ }
@@ -0,0 +1,27 @@
1
+ import { type ParsedArgs } from '../../types.js';
2
+ import { emitResult, fact, type RenderableResult } from '../../../output/render.js';
3
+
4
+ const USAGE = `Usage: capture motion timeline <rec> --element <sel> [--prop <prop>]
5
+
6
+ Per-frame geometry/scroll/property values for one element across a
7
+ finalized recording.
8
+
9
+ Options:
10
+ --element <sel> Element selector to track (required)
11
+ --prop <prop> Additional CSS/computed property to sample per frame
12
+
13
+ Not yet implemented.`;
14
+
15
+ export async function cmdMotionTimeline(parsed: ParsedArgs, _args: string[]): Promise<void> {
16
+ if (parsed.help) {
17
+ console.log(USAGE);
18
+ process.exit(0);
19
+ }
20
+ const result: RenderableResult = {
21
+ tag: 'error',
22
+ attrs: { command: 'motion timeline', status: 'not_implemented' },
23
+ summary: fact`\`motion timeline\` is not implemented yet.`,
24
+ };
25
+ emitResult(result, { json: parsed.json });
26
+ process.exit(1);
27
+ }