screencast-axi 0.1.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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +555 -0
  3. package/dist/bin/screencast-axi.d.ts +2 -0
  4. package/dist/bin/screencast-axi.js +16 -0
  5. package/dist/bin/screencast-axi.js.map +1 -0
  6. package/dist/src/auth/strategies.d.ts +54 -0
  7. package/dist/src/auth/strategies.js +137 -0
  8. package/dist/src/auth/strategies.js.map +1 -0
  9. package/dist/src/auth/types.d.ts +65 -0
  10. package/dist/src/auth/types.js +2 -0
  11. package/dist/src/auth/types.js.map +1 -0
  12. package/dist/src/browser.d.ts +100 -0
  13. package/dist/src/browser.js +168 -0
  14. package/dist/src/browser.js.map +1 -0
  15. package/dist/src/cli.d.ts +2 -0
  16. package/dist/src/cli.js +160 -0
  17. package/dist/src/cli.js.map +1 -0
  18. package/dist/src/commands/auth.d.ts +4 -0
  19. package/dist/src/commands/auth.js +207 -0
  20. package/dist/src/commands/auth.js.map +1 -0
  21. package/dist/src/commands/check.d.ts +12 -0
  22. package/dist/src/commands/check.js +103 -0
  23. package/dist/src/commands/check.js.map +1 -0
  24. package/dist/src/commands/doctor.d.ts +15 -0
  25. package/dist/src/commands/doctor.js +131 -0
  26. package/dist/src/commands/doctor.js.map +1 -0
  27. package/dist/src/commands/guide.d.ts +6 -0
  28. package/dist/src/commands/guide.js +257 -0
  29. package/dist/src/commands/guide.js.map +1 -0
  30. package/dist/src/commands/home.d.ts +12 -0
  31. package/dist/src/commands/home.js +78 -0
  32. package/dist/src/commands/home.js.map +1 -0
  33. package/dist/src/commands/list.d.ts +6 -0
  34. package/dist/src/commands/list.js +128 -0
  35. package/dist/src/commands/list.js.map +1 -0
  36. package/dist/src/commands/record.d.ts +7 -0
  37. package/dist/src/commands/record.js +266 -0
  38. package/dist/src/commands/record.js.map +1 -0
  39. package/dist/src/commands/scaffold.d.ts +4 -0
  40. package/dist/src/commands/scaffold.js +122 -0
  41. package/dist/src/commands/scaffold.js.map +1 -0
  42. package/dist/src/commands/setup.d.ts +14 -0
  43. package/dist/src/commands/setup.js +137 -0
  44. package/dist/src/commands/setup.js.map +1 -0
  45. package/dist/src/config.d.ts +126 -0
  46. package/dist/src/config.js +275 -0
  47. package/dist/src/config.js.map +1 -0
  48. package/dist/src/director.d.ts +217 -0
  49. package/dist/src/director.js +415 -0
  50. package/dist/src/director.js.map +1 -0
  51. package/dist/src/duration.d.ts +33 -0
  52. package/dist/src/duration.js +68 -0
  53. package/dist/src/duration.js.map +1 -0
  54. package/dist/src/encode.d.ts +67 -0
  55. package/dist/src/encode.js +225 -0
  56. package/dist/src/encode.js.map +1 -0
  57. package/dist/src/errors.d.ts +19 -0
  58. package/dist/src/errors.js +27 -0
  59. package/dist/src/errors.js.map +1 -0
  60. package/dist/src/flags.d.ts +39 -0
  61. package/dist/src/flags.js +130 -0
  62. package/dist/src/flags.js.map +1 -0
  63. package/dist/src/forensics.d.ts +51 -0
  64. package/dist/src/forensics.js +107 -0
  65. package/dist/src/forensics.js.map +1 -0
  66. package/dist/src/hooks.d.ts +9 -0
  67. package/dist/src/hooks.js +20 -0
  68. package/dist/src/hooks.js.map +1 -0
  69. package/dist/src/index.d.ts +18 -0
  70. package/dist/src/index.js +18 -0
  71. package/dist/src/index.js.map +1 -0
  72. package/dist/src/inventory.d.ts +45 -0
  73. package/dist/src/inventory.js +89 -0
  74. package/dist/src/inventory.js.map +1 -0
  75. package/dist/src/manifest.d.ts +89 -0
  76. package/dist/src/manifest.js +137 -0
  77. package/dist/src/manifest.js.map +1 -0
  78. package/dist/src/output.d.ts +8 -0
  79. package/dist/src/output.js +2 -0
  80. package/dist/src/output.js.map +1 -0
  81. package/dist/src/overlay.d.ts +105 -0
  82. package/dist/src/overlay.js +302 -0
  83. package/dist/src/overlay.js.map +1 -0
  84. package/dist/src/reference.d.ts +1 -0
  85. package/dist/src/reference.js +108 -0
  86. package/dist/src/reference.js.map +1 -0
  87. package/dist/src/run.d.ts +82 -0
  88. package/dist/src/run.js +321 -0
  89. package/dist/src/run.js.map +1 -0
  90. package/dist/src/skill.d.ts +12 -0
  91. package/dist/src/skill.js +69 -0
  92. package/dist/src/skill.js.map +1 -0
  93. package/dist/src/toolchain.d.ts +62 -0
  94. package/dist/src/toolchain.js +127 -0
  95. package/dist/src/toolchain.js.map +1 -0
  96. package/dist/src/types.d.ts +88 -0
  97. package/dist/src/types.js +18 -0
  98. package/dist/src/types.js.map +1 -0
  99. package/dist/src/version.d.ts +10 -0
  100. package/dist/src/version.js +11 -0
  101. package/dist/src/version.js.map +1 -0
  102. package/package.json +93 -0
  103. package/skills/screencast-axi/SKILL.md +49 -0
@@ -0,0 +1,257 @@
1
+ import { ScreencastError } from "../errors.js";
2
+ import { parseFlags } from "../flags.js";
3
+ const TOPICS = {
4
+ overview: {
5
+ summary: "What this tool does, and what is built so far",
6
+ body: [
7
+ "screencast-axi records a scripted browser workflow as a watchable clip:",
8
+ "a scenario is a TypeScript file that drives Playwright through a flow,",
9
+ "and the recorder overlays a synthetic cursor and captions, then encodes",
10
+ "the capture to mp4, webm and a poster image.",
11
+ "",
12
+ "The loop is: `init` sets up a project, `scaffold` writes a skeleton, you",
13
+ "fill in the run() body, `rehearse` proves the selectors without",
14
+ "encoding, and `record` shoots the real take and writes the manifest.",
15
+ "",
16
+ "`list` and `show` say what exists, `check` cross-references the manifest",
17
+ "against the scenarios and the files, and `doctor` checks everything a",
18
+ "recording needs in one pass - run it first if a take fails before its",
19
+ "own steps.",
20
+ "",
21
+ "For a page behind a login, see `guide auth`: a person signs in by hand",
22
+ "once and every take afterwards reuses the session.",
23
+ ],
24
+ },
25
+ encoding: {
26
+ summary: "Output formats, why not GIF, and what has to be installed",
27
+ body: [
28
+ "Every take produces an mp4 (h264, faststart), a webm (VP9) and a poster",
29
+ "image. GIF is opt-in and is an export, not a storage format.",
30
+ "",
31
+ "Measured on a real 16.7s app screencast, all at 800px wide and 15fps:",
32
+ " mp4 (h264) 182 KB",
33
+ " animated WebP (q55) 944 KB 5.2x",
34
+ " animated WebP (q70) 1,875 KB 10.3x",
35
+ " GIF (192 colours) 2,034 KB 11.2x",
36
+ "The source mp4 at full 1280px and 30fps is 471 KB - still 4.3x smaller",
37
+ "than the GIF at half the resolution and half the frame rate.",
38
+ "",
39
+ "Quality is not the deciding factor for flat app UI: 192 colours plus",
40
+ "dithering keeps small text legible. Size and capability are. A GIF has",
41
+ "no controls, no seeking, no poster frame, cannot be paused, and ignores",
42
+ "prefers-reduced-motion. Reach for it only where video does not render -",
43
+ "an npm README, an email - and prefer <video autoplay muted loop",
44
+ "playsinline> everywhere else.",
45
+ "",
46
+ "ffmpeg is required and is not bundled: it is 80MB+ per platform, and",
47
+ "which build you have matters. Many builds - Homebrew's among them - ship",
48
+ "without libwebp, so the poster falls back from ffmpeg to cwebp to PNG.",
49
+ "A missing WebP encoder costs you file size, never a recording.",
50
+ "",
51
+ "ffmpeg is looked up in this order: $SCREENCAST_FFMPEG, then an installed",
52
+ "`ffmpeg-static` (add it as a dev dependency if you would rather not",
53
+ "install ffmpeg system-wide), then PATH.",
54
+ ],
55
+ },
56
+ mobile: {
57
+ summary: "Recording a phone or tablet viewport",
58
+ body: [
59
+ "Use a Playwright device preset rather than a bare size:",
60
+ ' screencast-axi record tour --device "iPhone 13" --orientation portrait',
61
+ "",
62
+ "A preset does more than set a width. Its isMobile and hasTouch flags",
63
+ "decide whether the site's own @media (hover: none) and touch rules apply",
64
+ "at all, and it carries the right user agent - so this is the mobile",
65
+ "layout the site actually serves, not a desktop squeezed narrow.",
66
+ "",
67
+ "The video is captured at the CSS viewport, so a phone clip is 390x664",
68
+ "rather than the 1170x1992 the device would render at. That is a",
69
+ "Playwright limit, not a setting: it composites the page into the video",
70
+ "canvas without scaling up, so asking for more just leaves empty space",
71
+ "around the page. deviceScaleFactor still affects how the page renders",
72
+ "and which images it picks, but not the resolution of the recording.",
73
+ "",
74
+ "Playwright ships 140+ presets; the names are its own and are",
75
+ "case-sensitive. `--viewport 390x844` works when no preset fits.",
76
+ ],
77
+ },
78
+ duration: {
79
+ summary: "Aiming a clip at a length",
80
+ body: [
81
+ " screencast-axi record tour --duration 30s",
82
+ "",
83
+ "The recorder runs one measuring pass without encoding, then solves for",
84
+ "the pace that lands near the target and shoots the real take. Accepts",
85
+ "30s, 1m30s, or a bare number of seconds.",
86
+ "",
87
+ "A take is `fixed + pace x scalable`: every pause the recorder controls",
88
+ "scales, and the site's own waits - navigation, network, animation - do",
89
+ "not, because slowing the recorder down does not slow the site down. The",
90
+ "measuring pass reports both halves, so the solve is exact rather than an",
91
+ "assumption that everything scales.",
92
+ "",
93
+ "After navigating, the recorder waits up to 2.5s for the network to go",
94
+ "quiet, then carries on. That ceiling matters: plenty of real sites never",
95
+ "go quiet at all - analytics, websockets, polling - and every second",
96
+ "spent waiting is recorded into the clip. Raise it with",
97
+ "`timeouts.settleMs` if a site genuinely needs longer.",
98
+ "",
99
+ "Pace is clamped to 0.4-2.5. Outside that a clip stops being watchable,",
100
+ "so a target that needs more is reported rather than obeyed: the honest",
101
+ "answer is that the scenario has too much or too little in it for the",
102
+ "length you asked for.",
103
+ ],
104
+ },
105
+ tour: {
106
+ summary: "Multi-page walkthroughs",
107
+ body: [
108
+ "`d.tour(stops)` is the shape most walkthrough requests have. Each stop",
109
+ "navigates, narrates, dwells, and optionally scrolls:",
110
+ "",
111
+ " await d.tour([",
112
+ ' { path: "/", step: 0, scroll: 0.6 },',
113
+ ' { path: "/pricing", step: 1, scroll: 0.5 },',
114
+ ' { path: "/docs", step: 2 },',
115
+ " ]);",
116
+ "",
117
+ "`step` indexes the scenario's `steps`. `scroll` of 1 or less is a share",
118
+ "of the viewport, so it reads the same on a phone and a desktop; larger",
119
+ "values are pixels. `waitFor` holds the narration until something is on",
120
+ "screen, so a slow page does not get a jump cut.",
121
+ "",
122
+ "Paths resolve the way URLs do, not the way you might hope: with a",
123
+ 'baseUrl of `https://site.com/app/`, `goto("/")` goes to the origin and',
124
+ "drops the `/app/`. Keep baseUrl to the origin and put the path in the",
125
+ "goto. (The failure output names the URL it actually reached, so this is",
126
+ "a fast one to spot.)",
127
+ "",
128
+ "`screencast-axi scaffold <id> --tour 5` writes the whole skeleton.",
129
+ "Every pause is pace-scaled, so --duration re-cuts a tour untouched.",
130
+ ],
131
+ },
132
+ auth: {
133
+ summary: "Recording a page that is behind a login",
134
+ body: [
135
+ "The default is signed out. For anything behind a login, the strategy",
136
+ "that needs no code for the site you are recording is `profileAuth()`:",
137
+ "",
138
+ " // screencast.config.ts",
139
+ ' browser: { profileDir: ".screencast/profile" },',
140
+ ' auth: profileAuth({ signedInSelector: "[data-testid=user-menu]" }),',
141
+ "",
142
+ "Then a person runs, once, in their own terminal:",
143
+ " npx -y screencast-axi auth login --interactive",
144
+ "A browser opens, they sign in however that site wants - OAuth, SSO, a",
145
+ "magic link, two-factor - and close the window. The session lives in the",
146
+ "profile and every take reuses it. No credential is handled by this tool.",
147
+ "",
148
+ "`auth login` never reads stdin, so an agent can open the window on the",
149
+ "user's screen rather than making them retype a command. It cannot hang:",
150
+ "the wait is bounded (--wait, default 5m) and it refuses up front where",
151
+ "no window could appear, such as a headless box with no display.",
152
+ "Without --interactive it refuses with NEEDS_HUMAN, so an agent that",
153
+ "reaches for it without meaning to involve a person is told to.",
154
+ "",
155
+ "Also shipped: `storageStateAuth({ path })` for a portable session file",
156
+ "(CI-friendly, but needs an isolated context so it cannot be combined",
157
+ "with profileDir), and `basicAuth({ username, password })` for staging",
158
+ "environments. Anything else is an `AuthStrategy` object written in the",
159
+ "config, which is typed and debuggable.",
160
+ "",
161
+ "Set `signedInSelector` or `signedInCookie`. Without one nothing is",
162
+ 'verified, and "the URL is not /login" is a false pass - a build-error',
163
+ "page satisfies it too.",
164
+ "",
165
+ "Recording a live production site: a scenario that creates or drags",
166
+ "something writes to production. Prefer read-only scenarios there, or",
167
+ "point at staging. The profile holds a real session, so gitignore it.",
168
+ ],
169
+ },
170
+ watching: {
171
+ summary: "Seeing what a scenario does before trusting it",
172
+ body: [
173
+ "A scenario is arbitrary code driving a real browser, often one signed",
174
+ "into your own account. Two ways to see what it does:",
175
+ "",
176
+ " screencast-axi rehearse <id> prints every action it took",
177
+ " screencast-axi rehearse <id> --headed and shows you it happening",
178
+ "",
179
+ "`--headed` opens a real Chrome window instead of running hidden. It",
180
+ "works on `record` too and does not change the output - the clip is",
181
+ "identical either way - so it costs nothing but the window.",
182
+ "",
183
+ "A rehearsal always prints `performed`: every goto, click, typed value,",
184
+ "drag and scroll, in order, with timings. It also prints `hosts`, which",
185
+ "is the short answer to where the script went - a list of one host reads",
186
+ "very differently from a list of nine. `record` prints the same with",
187
+ "`--full`.",
188
+ "",
189
+ "Reading the log beats watching for anything you plan to run more than",
190
+ "once: it can be diffed after an edit, and it does not need you sitting",
191
+ "there. Watching is the better first look at a script someone else wrote.",
192
+ "",
193
+ "Nothing is recorded before `run()` starts, so a sign-in and any setup",
194
+ "are outside the clip.",
195
+ ],
196
+ },
197
+ overlay: {
198
+ summary: "The synthetic cursor, captions and drag ghost, and how to theme them",
199
+ body: [
200
+ "Playwright's video contains no mouse pointer, which makes any clip of a",
201
+ "click or a drag unreadable. The recorder injects an overlay that draws a",
202
+ "pointer following the real one, a click ripple, a drag ghost and a",
203
+ "caption bar - all inside a shadow root, so no page CSS can reach them.",
204
+ "",
205
+ "Everything is themeable: accent colour, pointer shape, caption position,",
206
+ "typography and fade. `hideSelectors` removes page chrome that should not",
207
+ "appear in footage - a framework error badge, a cookie banner, a staging",
208
+ "ribbon.",
209
+ "",
210
+ "The overlay re-mounts itself if the page replaces its document, because",
211
+ "that detaches the overlay while leaving its API in place. Without the",
212
+ "recovery, captions would stop appearing and the take would keep",
213
+ "recording as though nothing were wrong.",
214
+ ],
215
+ },
216
+ };
217
+ /** No flags: it takes a topic and nothing else. */
218
+ export const GUIDE_FLAGS = {};
219
+ export function guideCommand(args) {
220
+ // No flags of its own, but it still goes through the parser so an unknown
221
+ // flag is rejected here exactly as it is everywhere else.
222
+ const { positionals } = parseFlags(args, GUIDE_FLAGS);
223
+ const [topic, ...rest] = positionals;
224
+ if (rest.length > 0) {
225
+ throw new ScreencastError(`Unexpected argument: ${rest[0]}`, "VALIDATION_ERROR", [
226
+ "Run `screencast-axi guide <topic>` with a single topic",
227
+ "Run `screencast-axi guide` to list the topics",
228
+ ]);
229
+ }
230
+ if (!topic) {
231
+ return {
232
+ topics: Object.entries(TOPICS).map(([name, t]) => ({ topic: name, summary: t.summary })),
233
+ help: ["Run `screencast-axi guide overview` to start"],
234
+ };
235
+ }
236
+ const found = TOPICS[topic];
237
+ if (!found) {
238
+ throw new ScreencastError(`Unknown guide topic: ${topic}`, "VALIDATION_ERROR", [
239
+ `Available topics: ${Object.keys(TOPICS).join(", ")}`,
240
+ "Run `screencast-axi guide` to list them with summaries",
241
+ ]);
242
+ }
243
+ return { topic, summary: found.summary, guidance: found.body.join("\n") };
244
+ }
245
+ export function guideHelp() {
246
+ return `${[
247
+ `command: guide`,
248
+ `description: Topic-sized guidance, pulled one topic at a time`,
249
+ ``,
250
+ `usage:`,
251
+ ` screencast-axi guide List the available topics`,
252
+ ` screencast-axi guide <topic> Print one topic`,
253
+ ``,
254
+ `topics: ${Object.keys(TOPICS).join(", ")}`,
255
+ ].join("\n")}\n`;
256
+ }
257
+ //# sourceMappingURL=guide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide.js","sourceRoot":"","sources":["../../../src/commands/guide.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { AxiStructuredOutput } from "../output.js";
2
+ /**
3
+ * The no-argument view: live data, never help text (AXI principle 8).
4
+ *
5
+ * `status` is the aggregate worth pre-computing. Deriving it otherwise means
6
+ * reading the manifest, listing the output directory and diffing both against
7
+ * the scenario list - three round trips to answer the question anyone actually
8
+ * has, which is "what do I need to re-shoot".
9
+ *
10
+ * The SDK prepends `{ bin, description }`, so this returns only the state.
11
+ */
12
+ export declare function homeView(): Promise<AxiStructuredOutput>;
@@ -0,0 +1,78 @@
1
+ import { readManifest } from "../manifest.js";
2
+ import { loadConfig, loadScenarios } from "../config.js";
3
+ /**
4
+ * The no-argument view: live data, never help text (AXI principle 8).
5
+ *
6
+ * `status` is the aggregate worth pre-computing. Deriving it otherwise means
7
+ * reading the manifest, listing the output directory and diffing both against
8
+ * the scenario list - three round trips to answer the question anyone actually
9
+ * has, which is "what do I need to re-shoot".
10
+ *
11
+ * The SDK prepends `{ bin, description }`, so this returns only the state.
12
+ */
13
+ export async function homeView() {
14
+ const config = await loadConfig().catch(() => null);
15
+ if (!config) {
16
+ return {
17
+ config: "none",
18
+ scenarios: [],
19
+ totals: "0 scenarios",
20
+ help: [
21
+ "Create one: `screencast-axi scaffold <id> --url <url>`",
22
+ "Run `screencast-axi guide` for topic-sized guidance",
23
+ ],
24
+ };
25
+ }
26
+ const loaded = await loadScenarios(config).catch(() => []);
27
+ const { entries } = readManifest(config.outDir);
28
+ const byId = new Map(entries.map((e) => [e.id, e]));
29
+ const rows = loaded.map(({ scenario }) => {
30
+ const entry = byId.get(scenario.id);
31
+ const status = !entry
32
+ ? "never-recorded"
33
+ : entry.stepsHash && entry.steps?.join("\u0000") !== scenario.steps?.join("\u0000")
34
+ ? "stale"
35
+ : "recorded";
36
+ return {
37
+ id: scenario.id,
38
+ status,
39
+ steps: scenario.steps?.length ?? 0,
40
+ duration_s: entry ? Number((entry.durationMs / 1000).toFixed(1)) : 0,
41
+ };
42
+ });
43
+ const counts = rows.reduce((acc, r) => ({ ...acc, [r.status]: acc[r.status] + 1 }), { recorded: 0, stale: 0, "never-recorded": 0 });
44
+ const orphans = entries.filter((e) => !loaded.some((l) => l.scenario.id === e.id));
45
+ return {
46
+ config: config.configPath ?? "none",
47
+ out: config.outDir,
48
+ scenarios: rows,
49
+ totals: rows.length === 0
50
+ ? "0 scenarios"
51
+ : `${rows.length} scenarios, ${counts.recorded} recorded, ${counts.stale} stale, ${counts["never-recorded"]} never-recorded`,
52
+ ...(orphans.length > 0 ? { orphaned: orphans.map((o) => o.id) } : {}),
53
+ help: buildHelp(rows, orphans.length),
54
+ };
55
+ }
56
+ function buildHelp(rows, orphans) {
57
+ if (rows.length === 0) {
58
+ return [
59
+ "No scenarios found. Create one: `screencast-axi scaffold <id> --url <url>`",
60
+ "A scenario can also be recorded straight from a path, with no config",
61
+ ];
62
+ }
63
+ const help = [];
64
+ const stale = rows.find((r) => r.status === "stale");
65
+ const never = rows.find((r) => r.status === "never-recorded");
66
+ if (stale) {
67
+ help.push(`\`screencast-axi record ${stale.id}\` - its narration changed since the clip was shot`);
68
+ }
69
+ if (never) {
70
+ help.push(`\`screencast-axi record ${never.id}\` - never recorded`);
71
+ }
72
+ if (orphans > 0) {
73
+ help.push(`${orphans} clip(s) in the output directory have no scenario any more`);
74
+ }
75
+ help.push("Iterate with `rehearse` rather than `record`: it skips the encode");
76
+ return help;
77
+ }
78
+ //# sourceMappingURL=home.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home.js","sourceRoot":"","sources":["../../../src/commands/home.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type FlagSpecs } from "../flags.js";
2
+ import type { AxiStructuredOutput } from "../output.js";
3
+ export declare const LIST_FLAGS: FlagSpecs;
4
+ export declare const SHOW_FLAGS: FlagSpecs;
5
+ export declare function listCommand(args: string[]): Promise<AxiStructuredOutput>;
6
+ export declare function showCommand(args: string[]): Promise<AxiStructuredOutput>;
@@ -0,0 +1,128 @@
1
+ import { statSync } from "node:fs";
2
+ import { relative } from "node:path";
3
+ import { loadConfig } from "../config.js";
4
+ import { buildInventory, filesOf, summarise } from "../inventory.js";
5
+ import { parseFlags } from "../flags.js";
6
+ import { ScreencastError } from "../errors.js";
7
+ export const LIST_FLAGS = {
8
+ config: { kind: "string", description: "Path to a config file", placeholder: "path" },
9
+ full: { kind: "boolean", description: "Every field, not the four-column summary" },
10
+ stale: { kind: "boolean", description: "Only what needs re-shooting" },
11
+ tag: { kind: "string", description: "Filter by scenario tag", placeholder: "name", repeat: true },
12
+ };
13
+ export const SHOW_FLAGS = {
14
+ config: { kind: "string", description: "Path to a config file", placeholder: "path" },
15
+ full: { kind: "boolean", description: "Include untruncated step text" },
16
+ };
17
+ function needsWork(row) {
18
+ return row.status !== "recorded";
19
+ }
20
+ export async function listCommand(args) {
21
+ const { flags } = parseFlags(args, LIST_FLAGS);
22
+ const config = await loadConfig(flags["config"]);
23
+ const inventory = await buildInventory(config);
24
+ const full = flags["full"] === true;
25
+ const rows = flags["stale"] === true ? inventory.rows.filter(needsWork) : inventory.rows;
26
+ if (rows.length === 0) {
27
+ // Principle 5: an explicit nothing, never a blank list.
28
+ return {
29
+ scenarios: [],
30
+ totals: flags["stale"] === true ? "0 scenarios need re-shooting" : "0 scenarios",
31
+ help: inventory.rows.length === 0
32
+ ? ["Create one: `screencast-axi scaffold <id> --url <url>`"]
33
+ : ["Everything is up to date. `screencast-axi list` shows them all"],
34
+ };
35
+ }
36
+ return {
37
+ out: config.outDir,
38
+ scenarios: rows.map((r) => ({
39
+ id: r.id,
40
+ status: r.status,
41
+ steps: r.steps,
42
+ duration_s: Number((r.durationMs / 1000).toFixed(1)),
43
+ ...(full
44
+ ? {
45
+ title: r.title,
46
+ file: relative(process.cwd(), r.file),
47
+ ...(r.staleReason ? { why: r.staleReason } : {}),
48
+ ...(r.missing.length > 0 ? { missing: r.missing } : {}),
49
+ ...(r.entry?.recordedAt ? { recorded: r.entry.recordedAt } : {}),
50
+ }
51
+ : {}),
52
+ })),
53
+ totals: summarise(inventory),
54
+ ...(inventory.orphans.length > 0 ? { orphaned: inventory.orphans.map((o) => o.id) } : {}),
55
+ help: buildHelp(inventory, full),
56
+ };
57
+ }
58
+ function buildHelp(inventory, full) {
59
+ const help = [];
60
+ const first = inventory.rows.find(needsWork);
61
+ if (first) {
62
+ const why = first.status === "incomplete"
63
+ ? `is missing ${first.missing.join(", ")}`
64
+ : first.status === "stale"
65
+ ? `is stale - its ${first.staleReason}`
66
+ : "has never been recorded";
67
+ help.push(`\`screencast-axi record ${first.id}\` - it ${why}`);
68
+ }
69
+ if (inventory.orphans.length > 0) {
70
+ help.push("`screencast-axi check` explains the orphaned entries");
71
+ }
72
+ if (!full)
73
+ help.push("Add `--full` for titles, file paths and recording dates");
74
+ if (help.length === 0)
75
+ help.push("Everything is recorded and current");
76
+ return help;
77
+ }
78
+ export async function showCommand(args) {
79
+ const { positionals, flags } = parseFlags(args, SHOW_FLAGS);
80
+ const id = positionals[0];
81
+ const config = await loadConfig(flags["config"]);
82
+ const inventory = await buildInventory(config);
83
+ if (!id) {
84
+ throw new ScreencastError("Name a scenario", "VALIDATION_ERROR", [
85
+ "Run `screencast-axi show <id>`",
86
+ inventory.rows.length > 0
87
+ ? `This config has: ${inventory.rows.map((r) => r.id).join(", ")}`
88
+ : "No scenarios are configured yet",
89
+ ]);
90
+ }
91
+ const row = inventory.rows.find((r) => r.id === id);
92
+ if (!row) {
93
+ const orphan = inventory.orphans.find((o) => o.id === id);
94
+ throw new ScreencastError(`Unknown scenario: ${id}`, "UNKNOWN_SCENARIO", [
95
+ orphan
96
+ ? `\`${id}\` is in the manifest but has no scenario any more - see \`screencast-axi check\``
97
+ : `This config has: ${inventory.rows.map((r) => r.id).join(", ") || "nothing"}`,
98
+ ]);
99
+ }
100
+ const files = filesOf(row, config.outDir).map((f) => ({
101
+ file: f,
102
+ kb: Math.round(statSync(f).size / 1024),
103
+ }));
104
+ return {
105
+ id: row.id,
106
+ title: row.title,
107
+ status: row.status,
108
+ ...(row.staleReason ? { why: row.staleReason } : {}),
109
+ scenario: relative(process.cwd(), row.file),
110
+ ...(row.entry
111
+ ? {
112
+ description: row.entry.description,
113
+ duration_s: Number((row.entry.durationMs / 1000).toFixed(1)),
114
+ size: `${row.entry.width}x${row.entry.height}`,
115
+ recorded: row.entry.recordedAt,
116
+ ...(row.entry.device ? { device: row.entry.device } : {}),
117
+ ...(row.entry.pace !== undefined ? { pace: row.entry.pace } : {}),
118
+ }
119
+ : {}),
120
+ ...(row.entry?.steps ? { steps: row.entry.steps } : {}),
121
+ ...(files.length > 0 ? { files } : {}),
122
+ ...(row.missing.length > 0 ? { missing: row.missing } : {}),
123
+ help: row.status === "recorded"
124
+ ? [`\`screencast-axi record ${row.id}\` re-shoots it`]
125
+ : [`\`screencast-axi rehearse ${row.id}\` first, then \`record ${row.id}\``],
126
+ };
127
+ }
128
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { type FlagSpecs } from "../flags.js";
2
+ import type { AxiStructuredOutput } from "../output.js";
3
+ import { ScenarioFailure, type RunMode } from "../run.js";
4
+ export declare const RECORD_FLAGS: FlagSpecs;
5
+ export declare const REHEARSE_FLAGS: FlagSpecs;
6
+ export declare function recordCommand(args: string[], mode: RunMode): Promise<AxiStructuredOutput>;
7
+ export { ScenarioFailure };