@hraness/slopcamera 3.2.6 → 3.2.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 (78) hide show
  1. package/NOTICE.md +1 -7
  2. package/PRIVACY.md +16 -7
  3. package/README.md +41 -13
  4. package/apps/desktop/README.md +14 -130
  5. package/apps/desktop/application/context.ts +0 -9
  6. package/apps/desktop/application/default-registry.ts +0 -10
  7. package/apps/desktop/application/operation.ts +1 -5
  8. package/apps/desktop/application/operations/index.ts +0 -1
  9. package/apps/desktop/cli/args.ts +22 -86
  10. package/apps/desktop/cli/command-host-resources.ts +5 -1
  11. package/apps/desktop/cli/commands.ts +37 -67
  12. package/apps/desktop/cli/help.ts +24 -20
  13. package/apps/desktop/cli/html-scene.ts +479 -0
  14. package/apps/desktop/cli/io.ts +2 -1
  15. package/apps/desktop/cli/main.ts +28 -47
  16. package/apps/desktop/cli/media-ingest-model.ts +2 -0
  17. package/apps/desktop/cli/media-ingest-program.ts +9 -4
  18. package/apps/desktop/cli/menubar.ts +244 -0
  19. package/apps/desktop/cli/music-analysis-service.ts +61 -0
  20. package/apps/desktop/cli/portable-surface.ts +13 -4
  21. package/apps/desktop/cli/root-help-intro.ts +14 -0
  22. package/apps/desktop/code/application-node-planner.ts +0 -47
  23. package/apps/desktop/code/host-source-layout.ts +46 -0
  24. package/apps/desktop/code/public.ts +0 -1
  25. package/apps/desktop/code/runtime-identity.ts +50 -8
  26. package/apps/desktop/code/semantic-builder.ts +0 -43
  27. package/apps/desktop/code/source-bundle.ts +23 -6
  28. package/apps/desktop/code/source-typecheck.ts +131 -43
  29. package/apps/desktop/code/worker-client.ts +14 -2
  30. package/apps/desktop/core/music-analysis.ts +124 -1
  31. package/apps/desktop/dist/cli/main.js +261 -248
  32. package/apps/desktop/html-overlay/audio-reactivity.ts +127 -0
  33. package/apps/desktop/html-overlay/contracts.ts +3 -0
  34. package/apps/desktop/html-overlay/index.ts +28 -0
  35. package/apps/desktop/html-overlay/music-clock.ts +126 -0
  36. package/apps/desktop/html-overlay/rigged-glb.ts +429 -0
  37. package/apps/desktop/html-overlay/runtime.ts +4 -0
  38. package/apps/desktop/html-overlay/scaffolds.ts +2 -1
  39. package/apps/desktop/html-overlay/scene.ts +76 -0
  40. package/dist/cli.js +83 -81
  41. package/dist/{index-jchqst8w.js → index-7131pg1c.js} +43 -236
  42. package/dist/{index-mcy8z0br.js → index-fava6pge.js} +1 -1
  43. package/dist/{index-z7239b4h.js → index-h1k0fnjq.js} +1 -1
  44. package/dist/{index-p63wavx0.js → index-zfnddgay.js} +1 -1
  45. package/dist/index.js +4 -18
  46. package/dist/operations.js +2 -2
  47. package/dist/vectorize/worker.js +1 -1
  48. package/dist/workflow.js +3 -3
  49. package/docs/README.md +2 -1
  50. package/docs/studio.md +1 -1
  51. package/examples/html/music-video.html +514 -0
  52. package/examples/html/music-video.json +16 -0
  53. package/package.json +8 -21
  54. package/skills/slopcamera/SKILL.md +10 -1
  55. package/skills/slopcamera/references/diagrams.md +5 -14
  56. package/skills/slopcamera/references/install.md +2 -2
  57. package/skills/slopcamera/references/music-video.md +169 -0
  58. package/skills/slopcamera/references/reference-led-3d.md +1 -1
  59. package/skills/slopcamera/references/support.md +25 -0
  60. package/skills/slopcamera/references/video-projects.md +6 -2
  61. package/skills/slopcamera/references/web-media-excerpts.md +120 -0
  62. package/skills/slopcamera/references/workflows-sdk.md +1 -1
  63. package/src/cli.ts +28 -98
  64. package/src/index.ts +0 -23
  65. package/src/support-completion.ts +16 -0
  66. package/src/support.ts +42 -0
  67. package/src/version.ts +1 -1
  68. package/apps/desktop/application/operations/recording/index.ts +0 -5
  69. package/apps/desktop/application/operations/recording/pause.ts +0 -34
  70. package/apps/desktop/application/operations/recording/resume.ts +0 -34
  71. package/apps/desktop/application/operations/recording/shared.ts +0 -199
  72. package/apps/desktop/application/operations/recording/start.ts +0 -169
  73. package/apps/desktop/application/operations/recording/stop.ts +0 -34
  74. package/apps/desktop/capture/protocol.ts +0 -689
  75. package/apps/desktop/cli/capture-bundle.ts +0 -1117
  76. package/apps/desktop/cli/recording-controller.ts +0 -1567
  77. package/apps/desktop/cli/recording-daemon.ts +0 -931
  78. package/src/desktop.ts +0 -253
@@ -1,3 +1,4 @@
1
+ import { reportUsefulResult, type UsefulResultObserver } from "../../../src/support-completion";
1
2
  import { createDirectingBlobSession } from "./directing-blob";
2
3
  import { assembleDirectingClips, extractDirectingEndpoint, importDirectingAnchor } from "./directing-media";
3
4
  import { executeDirectingCommand } from "./directing-service";
@@ -133,7 +134,9 @@ import { resolveEmojiAsset, searchEmojiAssets, inspectEmojiAssets } from "./emoj
133
134
  import { asCliError, CliError, EXIT_CODE } from "./errors";
134
135
  import { commandHelp, completions } from "./help";
135
136
  import { PlaywrightHtmlOverlayRenderer } from "./html-overlay-renderer";
137
+ import { executeHtmlSceneCommand } from "./html-scene";
136
138
  import { BunProcessRunner, processIo, writeJson, writeLine, type CliIo, type ProcessRunner } from "./io";
139
+ import { launchMenubar, manageMenubar, reportOutputsRoot } from "./menubar";
137
140
  import {
138
141
  codePreparationHostResourceClaims,
139
142
  combineHostResourceClaims,
@@ -174,12 +177,6 @@ import {
174
177
  type OpenProject,
175
178
  } from "./project-service";
176
179
  import { resolveVerifiedProjectMedia } from "./project-media-integrity";
177
- import {
178
- executeRecordingAction,
179
- type RecordingController,
180
- type RecordingSnapshot,
181
- type RecordingStartOptions,
182
- } from "./recording-controller";
183
180
  import { buildFfmpegInvocation, prepareOverlaySources } from "./renderer";
184
181
  import { buildProjectFfmpegInvocation } from "./project-renderer";
185
182
  import {
@@ -300,7 +297,7 @@ import {
300
297
  workflowRunStore,
301
298
  } from "./workflow-runs";
302
299
 
303
- export const SLOPCAMERA_VERSION = "3.2.6";
300
+ export const SLOPCAMERA_VERSION = "3.2.8";
304
301
 
305
302
  // Legacy direct renders predate per-target output contracts. Keep them
306
303
  // bounded generously enough for long-form production while preventing one
@@ -309,6 +306,7 @@ const MAXIMUM_LEGACY_RECORDING_RENDER_OUTPUT_BYTES = 32 * 1024 * 1024 * 1024;
309
306
  const MAXIMUM_LEGACY_PROJECT_RENDER_OUTPUT_BYTES = 32 * 1024 * 1024 * 1024;
310
307
 
311
308
  export interface CliDependencies {
309
+ readonly onUsefulResult?: UsefulResultObserver;
312
310
  readonly abortSignal?: AbortSignal;
313
311
  readonly stateRoot?: string;
314
312
  readonly clock?: () => number;
@@ -319,7 +317,6 @@ export interface CliDependencies {
319
317
  readonly hostResourceCoordinator?: HostResourceCoordinator;
320
318
  readonly io?: CliIo;
321
319
  readonly paths?: RepositoryPaths;
322
- readonly recordingController?: RecordingController;
323
320
  readonly runner?: ProcessRunner;
324
321
  readonly sceneProviderFactory?: (options: GatewaySceneProviderOptions) => SceneDescriptionProvider;
325
322
  readonly sleep?: (milliseconds: number) => Promise<void>;
@@ -346,7 +343,6 @@ interface CommandContext {
346
343
  readonly hostResourceCoordinator: HostResourceCoordinator;
347
344
  readonly io: CliIo;
348
345
  readonly paths: RepositoryPaths;
349
- readonly recordingController: RecordingController | undefined;
350
346
  readonly runner: ProcessRunner;
351
347
  readonly sceneProviderFactory: (options: GatewaySceneProviderOptions) => SceneDescriptionProvider;
352
348
  readonly sleep: (milliseconds: number) => Promise<void>;
@@ -540,7 +536,6 @@ function applicationContext(
540
536
  context: CommandContext,
541
537
  providerOptions?: GatewayProviderOptions,
542
538
  ): ApplicationContext {
543
- const recordingController = context.recordingController;
544
539
  const toApplicationCapability = (capability: Capability) => ({
545
540
  available: capability.available,
546
541
  ...(capability.command === undefined ? {} : { command: capability.command }),
@@ -571,21 +566,6 @@ function applicationContext(
571
566
  : { hostResourceLease: context.hostResourceLease }),
572
567
  machineStateRoot: context.stateRoot,
573
568
  paths: context.paths,
574
- ...(recordingController === undefined
575
- ? {}
576
- : {
577
- recordingController: {
578
- execute: async (
579
- action: "pause" | "resume" | "start" | "stop",
580
- options?: unknown,
581
- ) => await executeRecordingAction(
582
- recordingController,
583
- action,
584
- options as RecordingStartOptions | undefined,
585
- ),
586
- status: async () => await recordingController.status(),
587
- },
588
- }),
589
569
  runner: context.runner,
590
570
  };
591
571
  return {
@@ -1714,11 +1694,6 @@ async function handleRender(
1714
1694
  writeValue(context.io, command.json, completed, () => `rendered ${output.outputPath}; plan=${artifactPath}`);
1715
1695
  }
1716
1696
 
1717
- function snapshotHuman(snapshot: RecordingSnapshot): string {
1718
- if (snapshot.state === "idle") return "idle";
1719
- return `${snapshot.state} ${snapshot.recordingId ?? "unknown"} ${humanTime(snapshot.logicalTimeUs)} segments=${snapshot.completedSegmentCount}`;
1720
- }
1721
-
1722
1697
  async function handleProjectEdit(
1723
1698
  context: CommandContext,
1724
1699
  command: Extract<CliCommand, { readonly kind: "project-edit" }>,
@@ -5761,6 +5736,13 @@ async function handleMediaColor(
5761
5736
 
5762
5737
  async function dispatch(context: CommandContext, command: CliCommand): Promise<void> {
5763
5738
  switch (command.kind) {
5739
+ case "html-render": {
5740
+ const output = await executeHtmlSceneCommand(applicationContext(context), command,
5741
+ context.abortSignal ?? new AbortController().signal,
5742
+ { progress: stage => context.io.stderr(`HTML scene: ${stage}\n`) });
5743
+ writeValue(context.io, command.json, output, () => JSON.stringify(output, null, 2));
5744
+ return;
5745
+ }
5764
5746
  case "studio": {
5765
5747
  const output = await executeStudioCommand(applicationContext(context), command, context.abortSignal ?? new AbortController().signal);
5766
5748
  writeValue(context.io, command.json, output, () => JSON.stringify(output, null, 2));
@@ -6252,18 +6234,14 @@ async function dispatch(context: CommandContext, command: CliCommand): Promise<v
6252
6234
  for (const completion of completions(command.words)) writeLine(context.io, completion);
6253
6235
  return;
6254
6236
  case "doctor": {
6255
- const [capabilities, emoji, active, macVersion] = await Promise.all([
6237
+ const [capabilities, emoji, macVersion] = await Promise.all([
6256
6238
  context.capabilities(),
6257
6239
  inspectEmojiAssets(context.paths.repositoryRoot),
6258
- context.recordingController === undefined
6259
- ? Promise.resolve(null)
6260
- : context.recordingController.status(),
6261
6240
  context.io.platform === "darwin"
6262
6241
  ? context.runner.run(["/usr/bin/sw_vers", "-productVersion"], { maxOutputBytes: 4_096 })
6263
6242
  : Promise.resolve({ exitCode: 0, stderr: "", stdout: "not-macos" }),
6264
6243
  ]);
6265
6244
  const output = {
6266
- activeRecording: active,
6267
6245
  artifactRoot: displayPath(context.paths.repositoryRoot, context.paths.artifactRoot),
6268
6246
  gatewayCredential: inspectGatewayCredential(context.io.env),
6269
6247
  emoji: {
@@ -6282,7 +6260,6 @@ async function dispatch(context: CommandContext, command: CliCommand): Promise<v
6282
6260
  `artifacts ${output.artifactRoot}`,
6283
6261
  `platform ${output.platform.name} ${output.platform.macOSVersion}`,
6284
6262
  ...capabilities.map((item) => `${item.name} ${item.available ? item.version ?? item.command : "unavailable"}`),
6285
- `recording ${active === null ? "controller-unavailable" : snapshotHuman(active)}`,
6286
6263
  `emoji ${emoji.provenance} ${emoji.installedCount}/${emoji.catalogCount}; generate: ${emoji.generationCommand}`,
6287
6264
  ].join("\n"));
6288
6265
  return;
@@ -6318,6 +6295,15 @@ async function dispatch(context: CommandContext, command: CliCommand): Promise<v
6318
6295
  case "ai-transcribe": await handleAiTranscribe(context, command); return;
6319
6296
  case "media-audio": await handleMediaAudio(context, command); return;
6320
6297
  case "media-color": await handleMediaColor(context, command); return;
6298
+ case "menubar": {
6299
+ if (command.action === "run") await launchMenubar(context.io, context.paths.repositoryRoot, command.json, command.mode);
6300
+ else await manageMenubar(context.io, context.paths.repositoryRoot, command.action, command.json);
6301
+ return;
6302
+ }
6303
+ case "outputs": {
6304
+ await reportOutputsRoot(context.io, context.stateRoot, command.json);
6305
+ return;
6306
+ }
6321
6307
  case "recordings-list": {
6322
6308
  const directories = (await listRecordingDirectories(context.paths.artifactRoot)).slice(0, command.limit);
6323
6309
  const recordings = await Promise.all(directories.map(async ({ id }) => {
@@ -6501,32 +6487,6 @@ async function dispatch(context: CommandContext, command: CliCommand): Promise<v
6501
6487
  ).join("\n"));
6502
6488
  return;
6503
6489
  }
6504
- case "record": {
6505
- if (context.recordingController === undefined) throw new CliError("unavailable", "Recording controller is unavailable.");
6506
- const options = command.action === "start"
6507
- ? {
6508
- camera: !command.webcam
6509
- ? { kind: "disabled" as const }
6510
- : command.cameraDeviceId === undefined
6511
- ? { kind: "default" as const }
6512
- : { deviceId: command.cameraDeviceId, kind: "device" as const },
6513
- displays: command.displays.length === 0
6514
- ? { kind: "all" as const }
6515
- : { displayIds: command.displays, kind: "selected" as const },
6516
- microphone: !command.microphone
6517
- ? { kind: "disabled" as const }
6518
- : command.microphoneDeviceId === undefined
6519
- ? { kind: "default" as const }
6520
- : { deviceId: command.microphoneDeviceId, kind: "device" as const },
6521
- strictInputs: command.strictInputs,
6522
- systemAudio: command.systemAudio,
6523
- typedText: command.typedText,
6524
- }
6525
- : undefined;
6526
- const snapshot = await executeRecordingAction(context.recordingController, command.action, options);
6527
- writeValue(context.io, command.json, snapshot, () => snapshotHuman(snapshot));
6528
- return;
6529
- }
6530
6490
  case "edit": await handleEdit(context, command); return;
6531
6491
  case "analyze-inactivity": await handleInactivity(context, command); return;
6532
6492
  case "analyze-faces": await handleFaceAnalysis(context, command); return;
@@ -6581,6 +6541,7 @@ type MutationReference =
6581
6541
 
6582
6542
  function commandMutationReference(command: CliCommand): MutationReference | undefined {
6583
6543
  switch (command.kind) {
6544
+ case "html-render": return undefined; // A fresh retained attempt owns its publication lease.
6584
6545
  case "studio": return undefined; // Native jobs and the machine custody marker own explicit leases.
6585
6546
  case "directing": return undefined; // The directing store owns its explicit lease.
6586
6547
  case "spatial-world": return undefined; // Immutable world attempts and imports own their publication custody.
@@ -6653,11 +6614,12 @@ function commandMutationReference(command: CliCommand): MutationReference | unde
6653
6614
  case "fillers-list":
6654
6615
  case "emoji-search":
6655
6616
  case "emoji-resolve":
6617
+ case "menubar":
6618
+ case "outputs":
6656
6619
  case "complete": return undefined;
6657
- // These write outside an existing mutable bundle: fresh projects publish by
6658
- // atomic rename and capture has its own controller.
6659
- case "projects-create":
6660
- case "record": return undefined;
6620
+ // Fresh projects write outside an existing mutable bundle and publish by
6621
+ // atomic rename.
6622
+ case "projects-create": return undefined;
6661
6623
  }
6662
6624
  }
6663
6625
 
@@ -6799,7 +6761,6 @@ export async function runCli(argv: readonly string[], dependencies: CliDependenc
6799
6761
  ?? createDefaultHostResourceCoordinator(),
6800
6762
  io,
6801
6763
  paths,
6802
- recordingController: dependencies.recordingController,
6803
6764
  runner,
6804
6765
  sceneProviderFactory: dependencies.sceneProviderFactory
6805
6766
  ?? (options => createGatewaySceneProvider(options)),
@@ -6819,6 +6780,15 @@ export async function runCli(argv: readonly string[], dependencies: CliDependenc
6819
6780
  await dispatch(admittedContext, command);
6820
6781
  });
6821
6782
  });
6783
+ if (command.kind === "projects-create" || command.kind === "project-inspect"
6784
+ || command.kind === "project-add" || command.kind === "inspect"
6785
+ || command.kind === "project-edit" || command.kind === "project-camera-edit"
6786
+ || command.kind === "project-metadata-edit" || command.kind === "project-overlay-edit"
6787
+ || command.kind === "edit"
6788
+ || command.kind === "render-run" && !command.dryRun
6789
+ || command.kind === "project-render" && command.action === "run" && !command.dryRun) {
6790
+ reportUsefulResult(dependencies.onUsefulResult);
6791
+ }
6822
6792
  return 0;
6823
6793
  } catch (error) {
6824
6794
  const failure = asCliError(error);
@@ -17,17 +17,20 @@ Commands:
17
17
  studio init|bundle|plan|probe|run|encode|asset|assemble|inspect|reconcile
18
18
  Author and render retained Blender, CAD and Manim productions
19
19
  image vectorize|generate Create a local SVG or generated image file
20
- html catalog|scaffold Inspect or create a transparent HTML overlay starter
20
+ html catalog|scaffold|render Author HTML scenes and export video with local audio
21
21
  workflows list|show|plan|run Plan or run a reviewed reusable workflow
22
22
  code init|check|plan|run Author, preflight, and run trusted TypeScript workflows
23
23
  runs list|show|resume|approve|cancel
24
24
  Inspect and control durable workflow runs
25
- doctor Check local capture, render, and asset capabilities
25
+ doctor Check local render and asset capabilities
26
26
  ai models|image|video|speech|transcribe
27
27
  Discover and run Vercel AI Gateway media models
28
28
  media audio|color Apply local non-destructive audio and video effects
29
- record start|pause|resume|stop|status
30
- Control the repository-local capture session
29
+ menubar [--background] Run the prebuilt menu-bar companion
30
+ menubar install|uninstall|status Manage its per-user LaunchAgent
31
+ support [--json|protocol --json|offer --json|shown <id>|release <id>|dismiss|snooze|enable|status --json]
32
+ Optional support; no feature requires payment
33
+ outputs Print the agent outputs directory
31
34
  recordings list List recording bundles
32
35
  projects list|create List projects or create one from a recording
33
36
  project inspect|add|edit|render
@@ -43,6 +46,10 @@ Commands:
43
46
  render plan|run <recording> Resolve or execute a render plan
44
47
  assets emoji search|resolve Find checked local emoji overlays
45
48
 
49
+ Agents: after useful work, read slopcamera support protocol --json for the optional
50
+ closeout protocol. Discovery uses stderr; it does not claim an invitation.
51
+ HRANESS_SUPPORT_AUDIENCE=off suppresses offers and incidental discovery.
52
+
46
53
  Run slopcamera help <command> for command-specific help.`;
47
54
 
48
55
  const HELP: Readonly<Record<string, string>> = {
@@ -162,12 +169,21 @@ content-addressed \`ai image generate\` lane and returns project-composable cont
162
169
  html: `Usage:
163
170
  slopcamera html catalog [--json]
164
171
  slopcamera html scaffold <${HTML_OVERLAY_SCAFFOLD_KIND_HELP}> --output <file.html>
172
+ slopcamera html render --input <scene.json> [--dry-run] [--json]
165
173
 
166
174
  Catalog lists the closed scaffold profiles in stable order with their primary jobs, render
167
175
  substrates, and current exact browser-library versions. Scaffold creates a complete transparent
168
176
  HTML overlay without overwriting an existing file. Scaffolds use the existing
169
177
  @hraness/slopcamera/local/html-overlay API and exact locked import maps. Render the document through
170
- workflow.media.htmlOverlay to receive a deterministic transparent video layer.`,
178
+ workflow.media.htmlOverlay to receive a deterministic transparent video layer.
179
+
180
+ Render accepts a slopcamera.html-scene source, retains its HTML, declared resources and
181
+ optional local soundtrack, and returns an H.264/AAC MP4 plus an ordinary editable project
182
+ with separate scene-video and original-audio tracks. Device dimensions must be even integers.
183
+ Duration rounds up to whole frames; audio starts at zero and is trimmed or padded to that
184
+ duration. Soundtracks encode as 48 kHz stereo AAC at 320 kb/s. Dry run checks source and
185
+ workload bounds without launching a browser, importing audio, or writing project state.
186
+ Progress uses stderr; --json keeps stdout machine-readable.`,
171
187
  operations: `Usage:
172
188
  slopcamera operations list [--json]
173
189
  slopcamera operations show <kind>[@<version>] [--json]
@@ -410,19 +426,6 @@ Apply accepts only candidates with safe acoustic boundaries and current placemen
410
426
  [--min-duration <time>] [--min-confidence <0..1>] [--limit <1..1000>] [--json]
411
427
 
412
428
  Face track IDs describe local geometry continuity inside one immutable analysis. They do not identify a person.`,
413
- record: `Usage:
414
- slopcamera record start [--display <id> ...]
415
- [--camera-device <id>] [--microphone-device <id>]
416
- [--webcam <true|false>] [--microphone <true|false>]
417
- [--system-audio <true|false>] [--typed-text <true|false>]
418
- [--strict-inputs] [--json]
419
- slopcamera record pause|resume|stop|status [--json]
420
-
421
- Capture defaults to every current display, system audio, the default microphone,
422
- and the default camera. Repeat --display to record an exact non-empty subset.
423
- Device IDs select the exact camera or microphone reported by slopcamera doctor;
424
- unknown or duplicate IDs fail closed. Typed-text capture remains opt-in with
425
- --typed-text true.`,
426
429
  recordings: `Usage: slopcamera recordings list [--limit <n>] [--json]`,
427
430
  projects: `Usage:
428
431
  slopcamera projects list [--limit <n>] [--json]
@@ -472,10 +475,12 @@ export function commandHelp(topic: readonly string[]): string {
472
475
 
473
476
  export function completions(words: readonly string[]): readonly string[] {
474
477
  const topLevel = [
475
- "operations", "diagram", "direct", "studio", "image", "workflows", "code", "runs", "doctor", "ai", "media", "record", "recordings", "projects", "project", "inspect", "events", "edit", "analyze", "align", "faces", "fillers", "render", "assets",
478
+ "operations", "diagram", "direct", "studio", "image", "html", "workflows", "code", "runs", "doctor", "ai", "media", "menubar", "support", "outputs", "recordings", "projects", "project", "inspect", "events", "edit", "analyze", "align", "faces", "fillers", "render", "assets",
476
479
  ];
477
480
  if (words.length <= 1) return topLevel;
478
481
  const command = words[0];
482
+ if (command === "support") return ["protocol", "offer", "shown", "release", "dismiss", "snooze", "enable", "status"];
483
+ if (command === "html") return ["catalog", "scaffold", "render"];
479
484
  if (command === "direct") return ["init", "anchor", "plan", "start", "inspect", "revise", "generate", "resume", "review", "assemble", "cleanup"];
480
485
  if (command === "studio") return words[2] === "assets" || words[1] === "assets" ? ["search", "describe", "plan", "import"] : ["init", "bundle", "plan", "probe", "run", "encode", "asset", "assemble", "inspect", "reconcile", "assets"];
481
486
  if (command === "operations") return ["list", "show"];
@@ -484,7 +489,6 @@ export function completions(words: readonly string[]): readonly string[] {
484
489
  if (command === "workflows") return ["list", "show", "plan", "run"];
485
490
  if (command === "code") return ["init", "check", "plan", "run"];
486
491
  if (command === "runs") return ["list", "show", "resume", "approve", "cancel"];
487
- if (command === "record") return ["start", "pause", "resume", "stop", "status"];
488
492
  if (command === "recordings") return ["list"];
489
493
  if (command === "projects") return ["list", "create"];
490
494
  if (command === "project") return ["inspect", "add", "edit", "render"];