@hraness/slopcamera 3.2.7 → 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.
- package/NOTICE.md +1 -7
- package/PRIVACY.md +16 -7
- package/README.md +37 -12
- package/apps/desktop/README.md +14 -130
- package/apps/desktop/application/context.ts +0 -9
- package/apps/desktop/application/default-registry.ts +0 -10
- package/apps/desktop/application/operation.ts +1 -5
- package/apps/desktop/application/operations/index.ts +0 -1
- package/apps/desktop/cli/args.ts +14 -86
- package/apps/desktop/cli/command-host-resources.ts +2 -1
- package/apps/desktop/cli/commands.ts +28 -67
- package/apps/desktop/cli/help.ts +12 -18
- package/apps/desktop/cli/html-scene.ts +139 -28
- package/apps/desktop/cli/io.ts +2 -1
- package/apps/desktop/cli/main.ts +23 -47
- package/apps/desktop/cli/menubar.ts +244 -0
- package/apps/desktop/cli/music-analysis-service.ts +61 -0
- package/apps/desktop/cli/portable-surface.ts +12 -4
- package/apps/desktop/code/application-node-planner.ts +0 -47
- package/apps/desktop/code/host-source-layout.ts +46 -0
- package/apps/desktop/code/public.ts +0 -1
- package/apps/desktop/code/runtime-identity.ts +50 -8
- package/apps/desktop/code/semantic-builder.ts +0 -43
- package/apps/desktop/code/source-bundle.ts +23 -6
- package/apps/desktop/code/source-typecheck.ts +131 -43
- package/apps/desktop/code/worker-client.ts +14 -2
- package/apps/desktop/core/music-analysis.ts +124 -1
- package/apps/desktop/dist/cli/main.js +244 -250
- package/apps/desktop/html-overlay/audio-reactivity.ts +127 -0
- package/apps/desktop/html-overlay/index.ts +9 -0
- package/apps/desktop/html-overlay/runtime.ts +2 -0
- package/apps/desktop/html-overlay/scene.ts +29 -0
- package/dist/cli.js +83 -81
- package/dist/{index-rvghzt7b.js → index-7131pg1c.js} +43 -236
- package/dist/{index-mcy8z0br.js → index-fava6pge.js} +1 -1
- package/dist/{index-z7239b4h.js → index-h1k0fnjq.js} +1 -1
- package/dist/{index-p63wavx0.js → index-zfnddgay.js} +1 -1
- package/dist/index.js +4 -18
- package/dist/operations.js +2 -2
- package/dist/vectorize/worker.js +1 -1
- package/dist/workflow.js +3 -3
- package/docs/README.md +1 -1
- package/docs/studio.md +1 -1
- package/package.json +6 -21
- package/skills/slopcamera/SKILL.md +8 -0
- package/skills/slopcamera/references/diagrams.md +5 -14
- package/skills/slopcamera/references/install.md +1 -1
- package/skills/slopcamera/references/music-video.md +23 -3
- package/skills/slopcamera/references/reference-led-3d.md +1 -1
- package/skills/slopcamera/references/support.md +25 -0
- package/skills/slopcamera/references/web-media-excerpts.md +120 -0
- package/src/cli.ts +28 -98
- package/src/index.ts +0 -23
- package/src/support-completion.ts +16 -0
- package/src/support.ts +42 -0
- package/src/version.ts +1 -1
- package/apps/desktop/application/operations/recording/index.ts +0 -5
- package/apps/desktop/application/operations/recording/pause.ts +0 -34
- package/apps/desktop/application/operations/recording/resume.ts +0 -34
- package/apps/desktop/application/operations/recording/shared.ts +0 -199
- package/apps/desktop/application/operations/recording/start.ts +0 -169
- package/apps/desktop/application/operations/recording/stop.ts +0 -34
- package/apps/desktop/capture/protocol.ts +0 -689
- package/apps/desktop/cli/capture-bundle.ts +0 -1117
- package/apps/desktop/cli/recording-controller.ts +0 -1567
- package/apps/desktop/cli/recording-daemon.ts +0 -931
- package/src/desktop.ts +0 -253
package/NOTICE.md
CHANGED
|
@@ -3,18 +3,12 @@
|
|
|
3
3
|
Slopcamera is an independent project and is not affiliated with or endorsed by
|
|
4
4
|
tldraw, Inc.
|
|
5
5
|
|
|
6
|
-
The runtime package does not include the tldraw SDK
|
|
6
|
+
The runtime package does not include the tldraw SDK. It writes
|
|
7
7
|
the documented `.tldr` JSON interchange format so that users can import a
|
|
8
8
|
diagram into compatible tldraw software. The development test suite optionally
|
|
9
9
|
uses the upstream `tldraw` package to check compatibility; that package remains
|
|
10
10
|
under the [tldraw license](https://tldraw.dev/community/license).
|
|
11
11
|
|
|
12
|
-
The optional `slopcamera canvas install` command downloads an unmodified installer
|
|
13
|
-
from the official
|
|
14
|
-
[`tldraw/tldraw-offline`](https://github.com/tldraw/tldraw-offline) GitHub
|
|
15
|
-
release and verifies the SHA-256 digest published by GitHub. tldraw Offline is
|
|
16
|
-
not open source and remains subject to its own terms.
|
|
17
|
-
|
|
18
12
|
tldraw and its associated marks are trademarks of tldraw, Inc.
|
|
19
13
|
|
|
20
14
|
Raster output uses
|
package/PRIVACY.md
CHANGED
|
@@ -5,12 +5,11 @@ operator owns or is authorized to record, import, edit, analyze, and publish.
|
|
|
5
5
|
This document describes the data it can capture, the local execution boundary,
|
|
6
6
|
and the selected media that can leave the machine.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
audio,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
collection is enabled.
|
|
8
|
+
Slopcamera imports finished recording bundles that can contain display video,
|
|
9
|
+
system audio, camera and microphone tracks, and interaction metadata such as
|
|
10
|
+
cursor positions, clicks, key activity, focused-input bounds, display topology,
|
|
11
|
+
and window snapshots. It reads that evidence locally and never records new
|
|
12
|
+
input itself.
|
|
14
13
|
|
|
15
14
|
Slopcamera can also read caller-selected local media and project files, invoke
|
|
16
15
|
bounded local browser and media subprocesses, analyze faces locally without
|
|
@@ -23,10 +22,20 @@ than sandboxed input.
|
|
|
23
22
|
Generation and model-backed media analysis can send an explicit prompt and
|
|
24
23
|
caller-selected media to Vercel AI Gateway. Local media upload requires the
|
|
25
24
|
matching command acknowledgement. Local vectorization, face detection,
|
|
26
|
-
ordinary media editing, diagram rendering
|
|
25
|
+
ordinary media editing, and diagram rendering remain local. Slopcamera does
|
|
27
26
|
not provide an account service and does not upload a project to a Slopcamera
|
|
28
27
|
service.
|
|
29
28
|
|
|
29
|
+
Optional support notices are local. After useful command-line work, the
|
|
30
|
+
`slopcamera` executable can print a short discovery notice to stderr and, on
|
|
31
|
+
request, an optional support offer that names the shared Hraness support page.
|
|
32
|
+
Opening that page and any payment are explicit human choices in a browser. The notice preferences,
|
|
33
|
+
throttles, and last presentation are stored only in local JSON files under
|
|
34
|
+
`$XDG_STATE_HOME/hraness/support` (by default `~/.local/state/hraness/support`),
|
|
35
|
+
shared with other Hraness tools for the same user. No email address, task
|
|
36
|
+
output, or project data is collected or sent, and
|
|
37
|
+
`HRANESS_SUPPORT_AUDIENCE=off` disables the notices.
|
|
38
|
+
|
|
30
39
|
Use Slopcamera only on devices, accounts, displays, conversations, and media that you
|
|
31
40
|
are entitled and permitted to capture or process. Obtain any consent required
|
|
32
41
|
by law, contract, workplace policy, or platform rules. Do not use Slopcamera to
|
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ project database.
|
|
|
33
33
|
|
|
34
34
|
## Install Slopcamera
|
|
35
35
|
|
|
36
|
-
The source tree prepares v3.2.
|
|
36
|
+
The source tree prepares v3.2.8 with optional support in the CLI, agent skill, native menu, and public footer.
|
|
37
37
|
The install below stays on the verified v3.2.6 release until publication completes.
|
|
38
38
|
|
|
39
39
|
Install [Bun 1.3.14 or newer](https://bun.sh), then install the verified
|
|
@@ -77,6 +77,15 @@ Native engines install separately. The [source-install guide](docs/how-to/use-cu
|
|
|
77
77
|
explains workspace placement and durable-run identity; the
|
|
78
78
|
[capability reference](docs/reference/capabilities.md) names runtime requirements.
|
|
79
79
|
|
|
80
|
+
Slopcamera is a CLI. On macOS, an optional unbundled menu-bar companion can show
|
|
81
|
+
the files in the agent outputs directory; `slopcamera menubar` runs a prebuilt
|
|
82
|
+
companion directly and does not install or launch an application bundle. The
|
|
83
|
+
companion is a thin product binary over the shared
|
|
84
|
+
[desktop-foundation](https://github.com/hraness/desktop-foundation) crate, pinned
|
|
85
|
+
by immutable tag. Build it explicitly with
|
|
86
|
+
`cargo build --release --manifest-path desktop/menubar/Cargo.toml`
|
|
87
|
+
when working from source.
|
|
88
|
+
|
|
80
89
|
<details>
|
|
81
90
|
<summary>Historical Atet release evidence</summary>
|
|
82
91
|
|
|
@@ -183,19 +192,18 @@ uploading local references requires the matching explicit acknowledgement.
|
|
|
183
192
|
|
|
184
193
|
### Edit footage and deliver finished videos
|
|
185
194
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
195
|
+
Import existing footage or recording bundles. Remove pauses and filler words,
|
|
196
|
+
align sound, reframe speakers, zoom into screen actions, and add captions,
|
|
197
|
+
graphics, color, and audio treatment. Preview candidates before selecting a
|
|
198
|
+
result, then export clean and captioned versions in 16:9, 9:16, 1:1, and 4:5
|
|
199
|
+
from the same edit.
|
|
191
200
|
|
|
192
201
|
> Edit my product demo: cut the pauses, zoom into each important click, keep the
|
|
193
202
|
> speaker framed, add captions and `logo.svg`, and show a preview before export.
|
|
194
203
|
|
|
195
|
-
Recording
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
[`PRIVACY.md`](PRIVACY.md) before recording sensitive material.
|
|
204
|
+
Recording bundles can carry clicks, cursor movement, key activity, and
|
|
205
|
+
focused-input information. Read [`PRIVACY.md`](PRIVACY.md) before editing
|
|
206
|
+
sensitive material.
|
|
199
207
|
|
|
200
208
|
Start with [Edit a video](docs/how-to/edit-video.md) or inspect a reusable recipe:
|
|
201
209
|
|
|
@@ -234,8 +242,8 @@ declarative graphs, approvals, and resuming work.
|
|
|
234
242
|
|
|
235
243
|
## Important limitations
|
|
236
244
|
|
|
237
|
-
- **Runtime support varies.** The CLI uses Bun on macOS, Linux, and Windows
|
|
238
|
-
|
|
245
|
+
- **Runtime support varies.** The CLI uses Bun on macOS, Linux, and Windows.
|
|
246
|
+
Media, browser, GPU, and native studio profiles
|
|
239
247
|
have additional requirements. Use the capability reference and `slopcamera doctor`.
|
|
240
248
|
- **Interchange preserves a supported subset.** Native rigs and simulations do
|
|
241
249
|
not become editable Three scenes by exporting a GLB. An image or video on a
|
|
@@ -320,3 +328,20 @@ changing a package or runtime boundary. Report vulnerabilities through
|
|
|
320
328
|
## License
|
|
321
329
|
|
|
322
330
|
[MIT](LICENSE), with third-party notices in [`NOTICE`](NOTICE).
|
|
331
|
+
|
|
332
|
+
## Optional support
|
|
333
|
+
|
|
334
|
+
All features remain available without payment. `slopcamera support` opens no browser
|
|
335
|
+
and shows an optional way to support continued development. Agents can read
|
|
336
|
+
`slopcamera support protocol --json` at closeout and request `support offer --json`
|
|
337
|
+
once after useful work. A quiet result needs no mention. Unknown callers, including
|
|
338
|
+
PTYs, receive separately throttled stderr discovery without changing task stdout or
|
|
339
|
+
claiming an invitation. Imported CLI functions and SDK/MCP workflows stay quiet.
|
|
340
|
+
|
|
341
|
+
Acknowledge with `support shown <id>` only after a persistent human-visible invitation
|
|
342
|
+
has been emitted. In final-only hosts, include it once in the final answer without
|
|
343
|
+
an acknowledgment; the unacknowledged offer expires after ten minutes and does not
|
|
344
|
+
consume the weekly shown cooldown. `support dismiss` opts out across the local suite;
|
|
345
|
+
`support snooze` pauses for 30 days. `HRANESS_SUPPORT_AUDIENCE=off` disables ambient
|
|
346
|
+
notices and claimed offers. Payment is an explicit human choice on the shared support
|
|
347
|
+
page; Slopcamera has no product-updates mailing list or account-status lookup.
|
package/apps/desktop/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Slopcamera
|
|
1
|
+
# Slopcamera local host and CLI
|
|
2
2
|
|
|
3
|
-
Slopcamera
|
|
3
|
+
Slopcamera reads finished recording bundles from repository-local directories, combines independent camera and audio takes on one typed project clock, then applies non-destructive edits through the `slopcamera` CLI. The CLI is the product surface for agents. An optional unbundled `slopcamera menubar` companion surfaces the agent outputs directory in the macOS menu bar; it carries no capture or editing authority.
|
|
4
4
|
|
|
5
5
|
## Recording bundles
|
|
6
6
|
|
|
7
|
-
The default root is `artifacts/slopcamera/recordings/`, resolved from the Slopcamera checkout. `artifacts/` is gitignored and excluded from Vercel uploads. Slopcamera never falls back to an external data directory.
|
|
7
|
+
The default root is `artifacts/slopcamera/recordings/`, resolved from the Slopcamera checkout. `artifacts/` is gitignored and excluded from Vercel uploads. Slopcamera never falls back to an external data directory. Bundles are produced outside this CLI and arrive as finished, immutable directories.
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
10
|
rec_<id>/
|
|
@@ -25,9 +25,9 @@ rec_<id>/
|
|
|
25
25
|
└── renders/
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
Each
|
|
28
|
+
Each display occupies its own track. System audio, microphone audio, and webcam video remain independently addressable logical tracks even when a native container carries multiple streams. Each synchronized segment is immutable once finalized.
|
|
29
29
|
|
|
30
|
-
Cursor, click, key activity, focused-input bounds, window geometry, display topology, and lifecycle metadata use integer source-time microseconds plus native monotonic timestamps.
|
|
30
|
+
Cursor, click, key activity, focused-input bounds, window geometry, display topology, and lifecycle metadata use integer source-time microseconds plus native monotonic timestamps.
|
|
31
31
|
|
|
32
32
|
## Multi-asset projects
|
|
33
33
|
|
|
@@ -62,16 +62,8 @@ changes instead of detaching from the pixels they annotate.
|
|
|
62
62
|
Run commands from the repository root:
|
|
63
63
|
|
|
64
64
|
```sh
|
|
65
|
-
#
|
|
65
|
+
# Inspect an existing recording bundle and render it.
|
|
66
66
|
slopcamera doctor
|
|
67
|
-
slopcamera record start
|
|
68
|
-
slopcamera record start \
|
|
69
|
-
--display <display-id> \
|
|
70
|
-
--camera-device <camera-id> \
|
|
71
|
-
--microphone-device <microphone-id>
|
|
72
|
-
slopcamera record pause
|
|
73
|
-
slopcamera record resume
|
|
74
|
-
slopcamera record stop
|
|
75
67
|
slopcamera recordings list --json
|
|
76
68
|
slopcamera inspect <recording>
|
|
77
69
|
slopcamera events <recording> --kind click --around 12.5s --jsonl
|
|
@@ -137,13 +129,6 @@ slopcamera project render plan <project> --json
|
|
|
137
129
|
slopcamera project render run <project> --output renders/final.mp4
|
|
138
130
|
```
|
|
139
131
|
|
|
140
|
-
`record start` defaults to every connected display, system audio, the default
|
|
141
|
-
camera, and the default microphone. `doctor --json` exposes the exact selectable
|
|
142
|
-
IDs. Repeat `--display` for a bounded display subset, or pass
|
|
143
|
-
`--camera-device`/`--microphone-device` to pin a device instead of following the
|
|
144
|
-
system default. Duplicate IDs, unavailable IDs, and selections above the
|
|
145
|
-
16-display capture bound fail before media starts.
|
|
146
|
-
|
|
147
132
|
Read commands default to a bounded text summary and accept `--json`; event queries also accept `--jsonl`. Mutations write atomically and return a normalized plan hash. Camera mutation receipts additionally return the created move ID, keyframe count, bounded face selection when applicable, and exact `camera show`/`camera remove` next commands.
|
|
148
133
|
|
|
149
134
|
### Agent code mode
|
|
@@ -486,9 +471,9 @@ workflow outputs, or inspect the persisted evidence with
|
|
|
486
471
|
remain an explicit local `slopcamera analyze scenes ... --execute
|
|
487
472
|
--allow-cloud-upload` action.
|
|
488
473
|
|
|
489
|
-
The scheduler runs dependency-ready nodes concurrently while obeying the stricter of `--jobs`, the four-worker hard cap, and host resource pools for FFmpeg, Vision, local I/O, paid calls, output publication, project publication
|
|
474
|
+
The scheduler runs dependency-ready nodes concurrently while obeying the stricter of `--jobs`, the four-worker hard cap, and host resource pools for FFmpeg, Vision, local I/O, paid calls, output publication, and project publication. Parallel analyses bind an append-only project edit basis, so one sibling may publish while another is paused without authorizing structural or prior-evidence drift. Mutable edits join into one ordered recoverable project transaction. Rendering first freezes the complete project and edit documents into an immutable geometry-bound revision, resolves an exact tool, media, and recording-metadata-bound plan, and publishes video plus receipt through an output-specific lease and durable precommit. Landscape, square, and portrait branches therefore remain independent.
|
|
490
475
|
|
|
491
|
-
Every run is durable under `artifacts/slopcamera/private/workflow-runs/<run-id>/`. Inspect it with `runs list` and `runs show`; use `runs resume`, `runs approve`, or `runs cancel` when the bounded summary provides that next action. A normal resume reconstructs unfinished host operations from the persisted graph without evaluating the workflow bundle. Exact canonical analysis orphans and output-only render commits are adopted only through their run-bound recovery evidence. An interrupted arbitrary compute callback becomes `ambiguous-code` and requires an exact node-specific replay acknowledgement. Attached cancellation first aborts that callback's real signal, then force-retires an uncooperative worker after a bounded grace period. A paid request uses an exact request ID and durable dispatch journal; an unknown post-dispatch outcome is never submitted again automatically. Live recording actions reconcile against the same controller used by the
|
|
476
|
+
Every run is durable under `artifacts/slopcamera/private/workflow-runs/<run-id>/`. Inspect it with `runs list` and `runs show`; use `runs resume`, `runs approve`, or `runs cancel` when the bounded summary provides that next action. A normal resume reconstructs unfinished host operations from the persisted graph without evaluating the workflow bundle. Exact canonical analysis orphans and output-only render commits are adopted only through their run-bound recovery evidence. An interrupted arbitrary compute callback becomes `ambiguous-code` and requires an exact node-specific replay acknowledgement. Attached cancellation first aborts that callback's real signal, then force-retires an uncooperative worker after a bounded grace period. A paid request uses an exact request ID and durable dispatch journal; an unknown post-dispatch outcome is never submitted again automatically. Live recording actions reconcile against the same controller used by the local host and are never automatically replayed.
|
|
492
477
|
|
|
493
478
|
Custom code mode is trusted code, not a sandbox. Module top-level code and explicitly replayed compute callbacks run as the current user and can use ambient filesystem, process and network authority. Slopcamera keeps its own credentials and privileged handles out of the worker, but it cannot contain malicious repository code. Review custom source before `code check`, `code plan`, or `code run`.
|
|
494
479
|
|
|
@@ -733,7 +718,7 @@ the moved tree closed a second time before cleanup. Normal teardown
|
|
|
733
718
|
rechecks the complete runtime manifest and every direct child, then
|
|
734
719
|
atomically changes its held active lease to a released marker before removing
|
|
735
720
|
validated children; that marker is unlinked last, so an interrupted cleanup is
|
|
736
|
-
recoverable even while the
|
|
721
|
+
recoverable even while the local host process remains alive. These gates prevent
|
|
737
722
|
deletion from colliding with a new render container or a swapped peer subtree.
|
|
738
723
|
The signed snapshot is prepared once per render request and shared by every
|
|
739
724
|
frame in that sequence; callers should submit a complete loop or overlay range
|
|
@@ -822,7 +807,7 @@ For a normalized video-layer layout, face following records the declared output
|
|
|
822
807
|
|
|
823
808
|
## Development
|
|
824
809
|
|
|
825
|
-
Use Bun 1.3.14. Portable checks do not compile native
|
|
810
|
+
Use Bun 1.3.14. Portable checks do not compile native helpers:
|
|
826
811
|
|
|
827
812
|
```sh
|
|
828
813
|
bun test apps/desktop
|
|
@@ -834,16 +819,11 @@ bun run test:html-overlay
|
|
|
834
819
|
bun run benchmark:code-concurrency
|
|
835
820
|
```
|
|
836
821
|
|
|
837
|
-
|
|
822
|
+
The optional Rust menu-bar companion lives under `desktop/` at the repository root and builds with Cargo:
|
|
838
823
|
|
|
839
824
|
```sh
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
bun run apps/desktop/analysis/build.ts
|
|
843
|
-
bun run dev:desktop
|
|
844
|
-
bun run build:desktop:macos
|
|
845
|
-
bun run package:desktop:macos
|
|
846
|
-
bun run verify:html-overlay:macos
|
|
825
|
+
cargo build --manifest-path desktop/menubar/Cargo.toml
|
|
826
|
+
slopcamera menubar
|
|
847
827
|
```
|
|
848
828
|
|
|
849
829
|
`test:html-overlay` is portable and leaves the real-browser tests registered as
|
|
@@ -867,100 +847,4 @@ The compiled smoke copies the executable away from the checkout and proves
|
|
|
867
847
|
diagram initialization/rendering plus PNG-to-SVG vectorization without
|
|
868
848
|
`node_modules`.
|
|
869
849
|
|
|
870
|
-
Screen recording, microphone, camera, Input Monitoring, and Accessibility are separate macOS permissions. A missing optional source becomes a typed diagnostic; strict-input mode fails before recording begins.
|
|
871
|
-
|
|
872
|
-
### Real capture hardware smoke
|
|
873
|
-
|
|
874
|
-
The real hardware smoke is deliberately outside portable and ordinary macOS
|
|
875
|
-
checks. Without the exact confirmation below it is registered as skipped and
|
|
876
|
-
does not build or probe the helper, inspect permissions, or create artifact
|
|
877
|
-
directories:
|
|
878
|
-
|
|
879
|
-
```sh
|
|
880
|
-
SLOPCAMERA_CAPTURE_HARDWARE_CONFIRM=record-local-displays-and-selected-inputs \
|
|
881
|
-
bun run test:capture:hardware:macos
|
|
882
|
-
```
|
|
883
|
-
|
|
884
|
-
The default profile records every connected display twice, with a pause between
|
|
885
|
-
the two immutable segments. It leaves system audio, camera, microphone, and
|
|
886
|
-
typed text disabled. Enable selected inputs explicitly:
|
|
887
|
-
|
|
888
|
-
```sh
|
|
889
|
-
SLOPCAMERA_CAPTURE_HARDWARE_CONFIRM=record-local-displays-and-selected-inputs \
|
|
890
|
-
SLOPCAMERA_CAPTURE_HARDWARE_SYSTEM_AUDIO=true \
|
|
891
|
-
SLOPCAMERA_CAPTURE_HARDWARE_CAMERA=true \
|
|
892
|
-
SLOPCAMERA_CAPTURE_HARDWARE_MICROPHONE=true \
|
|
893
|
-
SLOPCAMERA_CAPTURE_HARDWARE_MIN_DISPLAYS=2 \
|
|
894
|
-
bun run test:capture:hardware:macos
|
|
895
|
-
```
|
|
896
|
-
|
|
897
|
-
Add `SLOPCAMERA_CAPTURE_HARDWARE_INTERACTIONS=true` for the owned interaction
|
|
898
|
-
fixture. The fixture activates its nonce-titled window, performs one fixed
|
|
899
|
-
public → secure → public exercise against its own fields, and remains open with
|
|
900
|
-
neutral focus until capture stops. It can post only the built-in `a`, `s`, and
|
|
901
|
-
`b` canaries to its own PID at verified coordinates inside its focused window;
|
|
902
|
-
it accepts no arbitrary text, key, coordinate, or target from the caller. Do
|
|
903
|
-
not type, click, or switch applications until the command exits because doing
|
|
904
|
-
so can disturb focus or fixture timing. The fixture-PID event tap excludes
|
|
905
|
-
clicks and keys delivered to other applications from the exact evidence gate.
|
|
906
|
-
The profile binds the fixture's native-clock receipt to exact ordered click/key
|
|
907
|
-
pairs, display identity, fixture process identity, public and secure focus
|
|
908
|
-
transitions, and one native `focused` window transition. With the default
|
|
909
|
-
typed-text opt-out, the stopped bundle must contain no `typing.input` event and
|
|
910
|
-
no key cadence from the secure phase.
|
|
911
|
-
|
|
912
|
-
Set `SLOPCAMERA_CAPTURE_HARDWARE_TYPED_TEXT=true` together with the interaction
|
|
913
|
-
profile to verify explicit typed-text capture. That profile accepts exactly the
|
|
914
|
-
public `a` and `b` canaries in metadata; a native focus-identity allowlist binds
|
|
915
|
-
text persistence to the fixture's nonce-derived field ID, PID, window ID, and
|
|
916
|
-
nonce title. Text from any other input remains unpersisted, and the secure `s`
|
|
917
|
-
canary must remain absent. Failed typed-text evidence is deleted regardless of
|
|
918
|
-
the artifact retention setting. Typed-text hardware verification is
|
|
919
|
-
unavailable without the owned fixture.
|
|
920
|
-
|
|
921
|
-
Before capture, the smoke performs the helper's read-only strict probe. Screen
|
|
922
|
-
Recording, Input Monitoring, Accessibility, and window metadata must already be
|
|
923
|
-
authorized; each selected optional input must also be authorized and present.
|
|
924
|
-
An explicitly requested run fails before `start` when a prerequisite is
|
|
925
|
-
missing, so it cannot open a surprise permission prompt. Grant permissions by
|
|
926
|
-
running Slopcamera interactively first. Strict capture also creates and disables
|
|
927
|
-
the listen-only input event tap before starting any media recorder, then waits
|
|
928
|
-
for the tap's run-loop thread to confirm that it is enabled. Metadata writes
|
|
929
|
-
display, focus, window, and cursor boundary snapshots only after that handshake
|
|
930
|
-
and before a recorder can emit its first sample. At pause or stop, the
|
|
931
|
-
user-visible clock freezes, every recorder drains, all metadata pollers are
|
|
932
|
-
cancelled and joined on one serial queue, and metadata takes a final boundary
|
|
933
|
-
snapshot; finalization latency therefore does not become blank footage.
|
|
934
|
-
Tap creation or activation failure aborts the strict segment instead of
|
|
935
|
-
silently losing clicks and keys. Window focus comes from the frontmost
|
|
936
|
-
application's actual Accessibility-focused window matched back to its
|
|
937
|
-
positioned Core Graphics record, not the first enumerated window owned by that
|
|
938
|
-
process.
|
|
939
|
-
|
|
940
|
-
The smoke writes to a unique directory below
|
|
941
|
-
`artifacts/slopcamera/recordings/.hardware-smoke/`, verifies that Git ignores the
|
|
942
|
-
directory, drives the real start/pause/resume/stop controller, probes every
|
|
943
|
-
finalized media stream with FFprobe, and validates verified `capture-sync-v1`
|
|
944
|
-
sample-clock measurements in the manifest. Controller-lifecycle and
|
|
945
|
-
container-length checks are supplemental diagnostics, not substitutes for
|
|
946
|
-
sample timing. It also re-hashes every physical media file, streams and
|
|
947
|
-
re-hashes every event file through the production event parser, checks its
|
|
948
|
-
declared record count and time interval, and requires real cursor, display
|
|
949
|
-
topology, positioned-window, focus, and exact pause/resume lifecycle events.
|
|
950
|
-
For both active segments, opening lifecycle and environment snapshots must
|
|
951
|
-
precede the earliest retained sample across every selected display, system
|
|
952
|
-
audio, camera, and microphone stream, while a closing cursor and lifecycle
|
|
953
|
-
marker must follow the latest retained sample across that same complete
|
|
954
|
-
envelope.
|
|
955
|
-
Any native dropped-event diagnostic fails the run. Typed-text opt-out and any
|
|
956
|
-
observed secure-focus interval are checked directly against the parsed input
|
|
957
|
-
events.
|
|
958
|
-
|
|
959
|
-
Failed evidence is retained by default and its absolute path is printed. Set
|
|
960
|
-
`SLOPCAMERA_CAPTURE_HARDWARE_KEEP_ARTIFACTS=never` to remove every run or `always`
|
|
961
|
-
to keep successful runs too. Optional-input values must be exactly `true` or
|
|
962
|
-
`false`; the minimum-display value is bounded from 1 through 16.
|
|
963
|
-
|
|
964
|
-
## Direct
|
|
965
|
-
|
|
966
|
-
`bun run direct:slopcamera` opens the deterministic recorder and project-evidence lab without native capture, FFmpeg, whisper.cpp, Python, or cloud calls. It exposes compact fixtures for multi-angle placement, alignment, music, scene boundaries/descriptions, speech fillers, synchronized edits, and all overlay kinds. Permission, analyzer, and project worlds are fixture evidence, not claims about live native execution. `bun run verify:slopcamera:direct` drives every declared browser scenario and writes agent-readable evidence.
|
|
850
|
+
Screen recording, microphone, camera, Input Monitoring, and Accessibility are separate macOS permissions. A missing optional source becomes a typed diagnostic; strict-input mode fails before recording begins. Slopcamera ships as a CLI with an unbundled menu-bar companion; it does not produce, install, sign, or notarize a desktop application.
|
|
@@ -52,14 +52,6 @@ export interface ApplicationCapability {
|
|
|
52
52
|
readonly version?: string;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
export interface ApplicationRecordingController {
|
|
56
|
-
execute(
|
|
57
|
-
action: "pause" | "resume" | "start" | "stop",
|
|
58
|
-
options?: unknown,
|
|
59
|
-
): Promise<unknown>;
|
|
60
|
-
status(): Promise<unknown>;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
55
|
export interface ApplicationClock {
|
|
64
56
|
readonly now: () => Date;
|
|
65
57
|
readonly timestampMilliseconds: () => number;
|
|
@@ -92,6 +84,5 @@ export interface ApplicationContext {
|
|
|
92
84
|
/** Per-user host state shared by repository worktrees for mutation leases. */
|
|
93
85
|
readonly machineStateRoot?: string;
|
|
94
86
|
readonly paths: ApplicationPaths;
|
|
95
|
-
readonly recordingController?: ApplicationRecordingController;
|
|
96
87
|
readonly runner: ApplicationProcessRunner;
|
|
97
88
|
}
|
|
@@ -39,11 +39,6 @@ import {
|
|
|
39
39
|
projectRenderOperationDefinitionV3,
|
|
40
40
|
projectRenderOperationDefinitionV4,
|
|
41
41
|
projectSnapshotOperationDefinition,
|
|
42
|
-
recordingPauseOperationDefinition,
|
|
43
|
-
recordingResumeOperationDefinition,
|
|
44
|
-
recordingStartOperationDefinition,
|
|
45
|
-
recordingStartOperationDefinitionV1,
|
|
46
|
-
recordingStopOperationDefinition,
|
|
47
42
|
slopcameraDiagramCheckOperationDefinition,
|
|
48
43
|
slopcameraDiagramRenderOperationDefinition,
|
|
49
44
|
slopcameraImageVectorizeOperationDefinition,
|
|
@@ -131,11 +126,6 @@ export function createApplicationOperationRegistry(
|
|
|
131
126
|
registry.register(projectRenderOperationDefinitionV3);
|
|
132
127
|
registry.register(projectRenderOperationDefinitionV4);
|
|
133
128
|
registry.register(materializeVariantSelectionOperationDefinition);
|
|
134
|
-
registry.register(recordingStartOperationDefinitionV1);
|
|
135
|
-
registry.register(recordingStartOperationDefinition);
|
|
136
|
-
registry.register(recordingPauseOperationDefinition);
|
|
137
|
-
registry.register(recordingResumeOperationDefinition);
|
|
138
|
-
registry.register(recordingStopOperationDefinition);
|
|
139
129
|
registry.register(slopcameraDiagramCheckOperationDefinition);
|
|
140
130
|
registry.register(slopcameraDiagramRenderOperationDefinition);
|
|
141
131
|
registry.register(slopcameraImageVectorizeOperationDefinition);
|
|
@@ -4,7 +4,7 @@ import type { z } from "zod";
|
|
|
4
4
|
|
|
5
5
|
import type { ApplicationContext } from "./context";
|
|
6
6
|
|
|
7
|
-
export const SLOPCAMERA_APPLICATION_TOOL_VERSION = "slopcamera-3.2.
|
|
7
|
+
export const SLOPCAMERA_APPLICATION_TOOL_VERSION = "slopcamera-3.2.8" as const;
|
|
8
8
|
|
|
9
9
|
export const OPERATION_KINDS = [
|
|
10
10
|
"scene.inspect",
|
|
@@ -50,10 +50,6 @@ export const OPERATION_KINDS = [
|
|
|
50
50
|
"gateway.video",
|
|
51
51
|
"gateway.speech",
|
|
52
52
|
"gateway.transcription",
|
|
53
|
-
"recording.start",
|
|
54
|
-
"recording.pause",
|
|
55
|
-
"recording.resume",
|
|
56
|
-
"recording.stop",
|
|
57
53
|
"slopcamera.diagram.check",
|
|
58
54
|
"slopcamera.diagram.render",
|
|
59
55
|
"slopcamera.image.vectorize",
|
|
@@ -18,7 +18,6 @@ export * from "./iteration/select";
|
|
|
18
18
|
export * from "./project/commit-edits";
|
|
19
19
|
export * from "./project/promote-selection";
|
|
20
20
|
export * from "./project/snapshot";
|
|
21
|
-
export * from "./recording";
|
|
22
21
|
export * from "./render/bind-candidate-output";
|
|
23
22
|
export * from "./render/project-plan";
|
|
24
23
|
export * from "./render/project";
|
package/apps/desktop/cli/args.ts
CHANGED
|
@@ -271,6 +271,8 @@ export type CliCommand =
|
|
|
271
271
|
readonly tint: number | undefined;
|
|
272
272
|
readonly videoStreamIndex: number;
|
|
273
273
|
} & JsonOption)
|
|
274
|
+
| ({ readonly kind: "menubar"; readonly action: "run" | "install" | "uninstall" | "status"; readonly mode: "foreground" | "background" } & JsonOption)
|
|
275
|
+
| ({ readonly kind: "outputs" } & JsonOption)
|
|
274
276
|
| ({ readonly kind: "recordings-list"; readonly limit: number } & JsonOption)
|
|
275
277
|
| ({ readonly kind: "projects-list"; readonly limit: number } & JsonOption)
|
|
276
278
|
| ({
|
|
@@ -490,20 +492,6 @@ export type CliCommand =
|
|
|
490
492
|
readonly recording: string;
|
|
491
493
|
readonly to: string | undefined;
|
|
492
494
|
})
|
|
493
|
-
| ({
|
|
494
|
-
readonly action: "start";
|
|
495
|
-
readonly cameraDeviceId: string | undefined;
|
|
496
|
-
readonly displays: readonly string[];
|
|
497
|
-
readonly microphone: boolean;
|
|
498
|
-
readonly microphoneDeviceId: string | undefined;
|
|
499
|
-
readonly strictInputs: boolean;
|
|
500
|
-
readonly systemAudio: boolean;
|
|
501
|
-
readonly typedText: boolean;
|
|
502
|
-
readonly webcam: boolean;
|
|
503
|
-
} & JsonOption & { readonly kind: "record" })
|
|
504
|
-
| ({ readonly action: "pause" | "resume" | "stop" | "status" } & JsonOption & {
|
|
505
|
-
readonly kind: "record";
|
|
506
|
-
})
|
|
507
495
|
| ({
|
|
508
496
|
readonly edit: EditCommand;
|
|
509
497
|
readonly fps: number | undefined;
|
|
@@ -799,22 +787,6 @@ function strictBoolean(value: string | undefined, name: string, defaults: boolea
|
|
|
799
787
|
fail(`${name} must be true or false.`);
|
|
800
788
|
}
|
|
801
789
|
|
|
802
|
-
function captureSourceId(
|
|
803
|
-
value: string | undefined,
|
|
804
|
-
name: string,
|
|
805
|
-
maximumUTF8Bytes: number,
|
|
806
|
-
): string | undefined {
|
|
807
|
-
if (value === undefined) return undefined;
|
|
808
|
-
if (
|
|
809
|
-
value.length === 0
|
|
810
|
-
|| value.includes("\0")
|
|
811
|
-
|| new TextEncoder().encode(value).byteLength > maximumUTF8Bytes
|
|
812
|
-
) {
|
|
813
|
-
fail(`${name} must be a non-empty, non-NUL source ID of at most ${maximumUTF8Bytes} UTF-8 bytes.`);
|
|
814
|
-
}
|
|
815
|
-
return value;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
790
|
function oneOf<T extends string>(
|
|
819
791
|
value: string | undefined,
|
|
820
792
|
name: string,
|
|
@@ -1825,61 +1797,6 @@ function parseEvents(argv: readonly string[]): CliCommand {
|
|
|
1825
1797
|
};
|
|
1826
1798
|
}
|
|
1827
1799
|
|
|
1828
|
-
function parseRecord(argv: readonly string[]): CliCommand {
|
|
1829
|
-
const action = argv[0];
|
|
1830
|
-
if (action === "start") {
|
|
1831
|
-
const parsed = parseOptions(argv.slice(1), {
|
|
1832
|
-
...JSON_SPEC,
|
|
1833
|
-
"--camera-device": "value",
|
|
1834
|
-
"--display": "repeat",
|
|
1835
|
-
"--microphone": "value",
|
|
1836
|
-
"--microphone-device": "value",
|
|
1837
|
-
"--strict-inputs": "flag",
|
|
1838
|
-
"--system-audio": "value",
|
|
1839
|
-
"--typed-text": "value",
|
|
1840
|
-
"--webcam": "value",
|
|
1841
|
-
});
|
|
1842
|
-
exactPositionals(parsed, 0, "slopcamera record start [options]");
|
|
1843
|
-
const displays = optionStrings(parsed, "--display").map((displayId) =>
|
|
1844
|
-
captureSourceId(displayId, "--display", 64)!
|
|
1845
|
-
);
|
|
1846
|
-
if (displays.length > 16) fail("--display may be specified at most 16 times.");
|
|
1847
|
-
if (new Set(displays).size !== displays.length) fail("--display IDs must be unique.");
|
|
1848
|
-
const microphone = strictBoolean(optionString(parsed, "--microphone"), "--microphone", true);
|
|
1849
|
-
const webcam = strictBoolean(optionString(parsed, "--webcam"), "--webcam", true);
|
|
1850
|
-
const cameraDeviceId = captureSourceId(optionString(parsed, "--camera-device"), "--camera-device", 256);
|
|
1851
|
-
const microphoneDeviceId = captureSourceId(
|
|
1852
|
-
optionString(parsed, "--microphone-device"),
|
|
1853
|
-
"--microphone-device",
|
|
1854
|
-
256,
|
|
1855
|
-
);
|
|
1856
|
-
if (!webcam && cameraDeviceId !== undefined) {
|
|
1857
|
-
fail("--camera-device cannot be combined with --webcam false.");
|
|
1858
|
-
}
|
|
1859
|
-
if (!microphone && microphoneDeviceId !== undefined) {
|
|
1860
|
-
fail("--microphone-device cannot be combined with --microphone false.");
|
|
1861
|
-
}
|
|
1862
|
-
return {
|
|
1863
|
-
action,
|
|
1864
|
-
cameraDeviceId,
|
|
1865
|
-
displays,
|
|
1866
|
-
json: optionFlag(parsed, "--json"),
|
|
1867
|
-
kind: "record",
|
|
1868
|
-
microphone,
|
|
1869
|
-
microphoneDeviceId,
|
|
1870
|
-
strictInputs: optionFlag(parsed, "--strict-inputs"),
|
|
1871
|
-
systemAudio: strictBoolean(optionString(parsed, "--system-audio"), "--system-audio", true),
|
|
1872
|
-
typedText: strictBoolean(optionString(parsed, "--typed-text"), "--typed-text", false),
|
|
1873
|
-
webcam,
|
|
1874
|
-
};
|
|
1875
|
-
}
|
|
1876
|
-
if (action === "pause" || action === "resume" || action === "stop" || action === "status") {
|
|
1877
|
-
const parsed = parseOptions(argv.slice(1), JSON_SPEC);
|
|
1878
|
-
exactPositionals(parsed, 0, `slopcamera record ${action} [--json]`);
|
|
1879
|
-
return { action, json: optionFlag(parsed, "--json"), kind: "record" };
|
|
1880
|
-
}
|
|
1881
|
-
fail("Usage: slopcamera record <start|pause|resume|stop|status> [options]");
|
|
1882
|
-
}
|
|
1883
1800
|
|
|
1884
1801
|
const TIME_RANGE_SPEC = {
|
|
1885
1802
|
"--end": "value",
|
|
@@ -3175,7 +3092,18 @@ export function parseCliArgs(argv: readonly string[]): CliCommand {
|
|
|
3175
3092
|
case "project": return parseProject(argv.slice(1));
|
|
3176
3093
|
case "inspect": return parseInspect(argv.slice(1));
|
|
3177
3094
|
case "events": return parseEvents(argv.slice(1));
|
|
3178
|
-
case "
|
|
3095
|
+
case "menubar": {
|
|
3096
|
+
const parsed = parseOptions(argv.slice(1), { ...JSON_SPEC, "--foreground": "flag", "--background": "flag" });
|
|
3097
|
+
const positionals = parsed.positionals;
|
|
3098
|
+
if (positionals.length > 1 || (positionals[0] !== undefined && !["install", "uninstall", "status"].includes(positionals[0]))) throw new CliError("usage", "Use slopcamera menubar [--foreground|--background] | install|uninstall|status");
|
|
3099
|
+
if (positionals[0] !== undefined && (optionFlag(parsed, "--foreground") || optionFlag(parsed, "--background"))) throw new CliError("usage", "Choose a menu-bar action or a run mode, not both.");
|
|
3100
|
+
return { kind: "menubar", action: (positionals[0] as "install" | "uninstall" | "status" | undefined) ?? "run", mode: optionFlag(parsed, "--background") ? "background" : "foreground", json: optionFlag(parsed, "--json") };
|
|
3101
|
+
}
|
|
3102
|
+
case "outputs": {
|
|
3103
|
+
const parsed = parseOptions(argv.slice(1), JSON_SPEC);
|
|
3104
|
+
exactPositionals(parsed, 0, "slopcamera outputs [--json]");
|
|
3105
|
+
return { kind: "outputs", json: optionFlag(parsed, "--json") };
|
|
3106
|
+
}
|
|
3179
3107
|
case "edit": return parseEdit(argv.slice(1));
|
|
3180
3108
|
case "analyze": return parseAnalyze(argv.slice(1));
|
|
3181
3109
|
case "faces": return parseFaces(argv.slice(1));
|
|
@@ -226,15 +226,16 @@ export function commandHostResourceClaims(
|
|
|
226
226
|
case "fillers-list":
|
|
227
227
|
case "help":
|
|
228
228
|
case "inspect":
|
|
229
|
+
case "menubar":
|
|
229
230
|
case "operations-list":
|
|
230
231
|
case "operations-show":
|
|
232
|
+
case "outputs":
|
|
231
233
|
case "project-camera-edit":
|
|
232
234
|
case "project-edit":
|
|
233
235
|
case "project-inspect":
|
|
234
236
|
case "project-metadata-edit":
|
|
235
237
|
case "projects-create":
|
|
236
238
|
case "projects-list":
|
|
237
|
-
case "record":
|
|
238
239
|
case "recordings-list":
|
|
239
240
|
case "runs-approve":
|
|
240
241
|
case "runs-cancel":
|