@hasna/recordings 0.2.13 → 0.3.1
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/Dockerfile.package +4 -5
- package/README.md +113 -8
- package/bun.lock +2 -2
- package/dist/__tests__/helpers/installer-guard-execution.d.ts +22 -0
- package/dist/__tests__/helpers/installer-guard-execution.d.ts.map +1 -0
- package/dist/__tests__/helpers/installer-preflight.d.ts +22 -0
- package/dist/__tests__/helpers/installer-preflight.d.ts.map +1 -0
- package/dist/__tests__/helpers/native-fs-guard.d.ts.map +1 -1
- package/dist/__tests__/helpers/source-assertions.d.ts +169 -0
- package/dist/__tests__/helpers/source-assertions.d.ts.map +1 -0
- package/dist/__tests__/preload.d.ts +1 -4
- package/dist/__tests__/preload.d.ts.map +1 -1
- package/dist/cli/desktop-snapshot.d.ts +20 -0
- package/dist/cli/desktop-snapshot.d.ts.map +1 -0
- package/dist/cli/index.js +2078 -277
- package/dist/cli/macos-permissions.d.ts +72 -0
- package/dist/cli/macos-permissions.d.ts.map +1 -1
- package/dist/cli/macos-shortcut.d.ts +139 -0
- package/dist/cli/macos-shortcut.d.ts.map +1 -0
- package/dist/cli/trigger-probe.d.ts +172 -0
- package/dist/cli/trigger-probe.d.ts.map +1 -0
- package/dist/db/database.d.ts +9 -0
- package/dist/db/database.d.ts.map +1 -1
- package/dist/http/client.d.ts +10 -7
- package/dist/http/client.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +634 -49
- package/dist/lib/capture-probe.d.ts +216 -0
- package/dist/lib/capture-probe.d.ts.map +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/macos-bundle.d.ts +50 -0
- package/dist/lib/macos-bundle.d.ts.map +1 -0
- package/dist/lib/persistence-probe.d.ts +208 -0
- package/dist/lib/persistence-probe.d.ts.map +1 -0
- package/dist/lib/recorder.d.ts.map +1 -1
- package/dist/lib/retired-deployment-modes.d.ts +24 -0
- package/dist/lib/retired-deployment-modes.d.ts.map +1 -0
- package/dist/lib/transcriber.d.ts +60 -0
- package/dist/lib/transcriber.d.ts.map +1 -1
- package/dist/mcp/index.js +140 -56
- package/dist/server/cloud-config.d.ts +25 -3
- package/dist/server/cloud-config.d.ts.map +1 -1
- package/dist/server/cloud-readiness.d.ts.map +1 -1
- package/dist/server/cloud.d.ts +8 -7
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.js +187 -79
- package/dist/server/migrate-command.d.ts.map +1 -1
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +108 -49
- package/dist/store.d.ts +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/package.json +25 -6
- package/scripts/build_native_fs_guard.sh +15 -2
- package/scripts/ci-linux-suite.ts +403 -0
- package/scripts/ci-native-build.ts +402 -0
- package/scripts/enforce_identity_migration.sh +110 -0
- package/scripts/generate-sdk.ts +1 -1
- package/scripts/install_macos_app.sh +138 -24
- package/scripts/macos_artifact.ts +205 -33
- package/scripts/native/realtime-settle-probe/README.md +39 -0
- package/scripts/native/realtime-settle-probe/main.swift +135 -0
- package/scripts/policy/local-only-approved-targets.txt +21 -0
- package/scripts/read_local_only_targets.sh +203 -0
- package/scripts/scan-artifact.ts +40 -0
- package/scripts/set-version.ts +145 -0
- package/scripts/vacuity-manifest-gen.ts +96 -0
- package/scripts/vacuity-manifests/enhancement-screen-mirror.tsv +44 -0
- package/scripts/vacuity-manifests/install-chain.tsv +13 -0
- package/scripts/vacuity-manifests/must-survive-controls.tsv +10 -0
- package/scripts/vacuity-manifests/reorder.tsv +4 -0
- package/scripts/vacuity-manifests/source-side.tsv +15 -0
- package/scripts/vacuity-manifests/variable-operands.tsv +16 -0
- package/scripts/vacuity-manifests/version-sites.tsv +61 -0
- package/scripts/vacuity-mutation-battery.ts +266 -0
- package/src/native/Recordings/App/MenuBarStatusView.swift +14 -7
- package/src/native/Recordings/App/RuntimeSmoke.swift +5 -1
- package/src/native/Recordings/App/SidebarView.swift +1 -1
- package/src/native/Recordings/Package.swift +24 -5
- package/src/native/Recordings/RecordingsLib/EnhancementScreen.swift +91 -0
- package/src/native/Recordings/RecordingsLib/FnKeyMonitor.swift +27 -4
- package/src/native/Recordings/RecordingsLib/Info.plist +2 -2
- package/src/native/Recordings/RecordingsLib/MenuBarPresentation.swift +56 -3
- package/src/native/Recordings/RecordingsLib/NativePCMRecorder.swift +13 -0
- package/src/native/Recordings/RecordingsLib/PasteDeliveryVerification.swift +460 -0
- package/src/native/Recordings/RecordingsLib/RealtimeTranscriptionClient.swift +41 -7
- package/src/native/Recordings/RecordingsLib/RecordingAttemptAlert.swift +36 -0
- package/src/native/Recordings/RecordingsLib/RecordingEngine.swift +1071 -75
- package/src/native/Recordings/RecordingsLib/SettingsView.swift +47 -3
- package/src/native/Recordings/RecordingsLib/VoiceShortcuts.swift +11 -6
- package/src/native/Recordings/RecordingsTests/CLIRunnerTests.swift +3 -3
- package/src/native/Recordings/RecordingsTests/EnhancementScreenTests.swift +191 -0
- package/src/native/Recordings/RecordingsTests/MenuBarPresentationTests.swift +144 -4
- package/src/native/Recordings/RecordingsTests/PasteDeliveryVerificationTests.swift +463 -0
- package/src/native/Recordings/RecordingsTests/PasteTargetTests.swift +33 -20
- package/src/native/Recordings/RecordingsTests/ProjectStoreTests.swift +1 -1
- package/src/native/Recordings/RecordingsTests/RealtimeSettleBenchmark.swift +200 -0
- package/src/native/Recordings/RecordingsTests/RealtimeSettleBudgetTests.swift +80 -0
- package/src/native/Recordings/RecordingsTests/RealtimeTranscriptionTests.swift +22 -4
- package/src/native/Recordings/RecordingsTests/RecordingEngineDeliveryTests.swift +12 -6
- package/src/native/Recordings/RecordingsTests/RecordingEngineHomeIsolationTests.swift +67 -0
- package/src/native/Recordings/RecordingsTests/RecordingStartGateTests.swift +12 -3
- package/src/native/Recordings/RecordingsTests/RecordingStartTimingTests.swift +207 -11
- package/src/native/Recordings/RecordingsTests/SpeechIntentTests.swift +17 -6
- package/src/native/Recordings/RecordingsTests/TestHomeDirectory.swift +23 -0
- package/src/native/Recordings/Updater/Broker/ApplicationProcessQuiescence.swift +7 -1
- package/src/native/Recordings/Updater/Broker/AtomicActivation.swift +10 -10
- package/src/native/Recordings/Updater/Broker/BrokerMain.swift +5 -1
- package/src/native/Recordings/Updater/Broker/HostOSProductVersion.swift +1 -0
- package/src/native/Recordings/Updater/Broker/PeerIdentity.swift +59 -3
- package/src/native/Recordings/Updater/Protocol/UpdateProtocol.swift +21 -2
- package/src/native/Recordings/Updater/ProtocolTests/ExpectationIntegrityTests.swift +60 -0
- package/src/native/Recordings/Updater/ProtocolTests/UpdateXPCInterfaceTests.swift +113 -0
- package/src/native/Recordings/Updater/VerifierLauncher/RecordingsVerifierLauncher.c +106 -5
- package/src/native/Recordings/build.sh +75 -9
- package/scripts/native/prebuilds/darwin-universal/recordings_fs_guard.node +0 -0
package/Dockerfile.package
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# syntax=docker/dockerfile:1
|
|
2
2
|
# Image built from the published @hasna/recordings npm tarball by the ECR image
|
|
3
|
-
# builder (CodeBuild, ARM64). Runs recordings-serve
|
|
4
|
-
# the serve process reads/writes the shared
|
|
5
|
-
#
|
|
3
|
+
# builder (CodeBuild, ARM64). Runs recordings-serve with the `postgresql` data
|
|
4
|
+
# backend: the serve process reads/writes the shared Postgres directly, selected
|
|
5
|
+
# by the presence of HASNA_RECORDINGS_DATABASE_URL. No on-box sqlite/sync in the
|
|
6
|
+
# service.
|
|
6
7
|
|
|
7
8
|
FROM oven/bun:1.3.13-alpine AS runtime
|
|
8
9
|
|
|
9
10
|
ENV NODE_ENV=production \
|
|
10
11
|
HASNA_APP_NAME=recordings \
|
|
11
|
-
HASNA_APP_MODE=self_hosted \
|
|
12
|
-
HASNA_RECORDINGS_STORAGE_MODE=remote \
|
|
13
12
|
HOST=0.0.0.0 \
|
|
14
13
|
PORT=8874 \
|
|
15
14
|
NODE_EXTRA_CA_CERTS=/etc/ssl/certs/rds-global-bundle.pem \
|
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ provides recording controls and access to the main window while it is in the bac
|
|
|
26
26
|
the CLI and MCP write), searchable and filterable by project, mode, and machine, with a
|
|
27
27
|
detail pane (copy, paste-into-front-app, audio playback, metadata).
|
|
28
28
|
- **Projects** — app projects are registered through the same canonical Store before a
|
|
29
|
-
recording can reference them, preserving referential integrity
|
|
29
|
+
recording can reference them, preserving referential integrity on either store.
|
|
30
30
|
- **Settings** (⌘,) — OpenAI key, language, recording shortcut, permissions, projects,
|
|
31
31
|
and voice shortcuts.
|
|
32
32
|
|
|
@@ -59,6 +59,9 @@ recordings app install \
|
|
|
59
59
|
|
|
60
60
|
recordings app open # launch it
|
|
61
61
|
recordings app status # show install state
|
|
62
|
+
recordings app snapshot # write ./desktop-snapshot.png for local UI debugging
|
|
63
|
+
# From this repository, optionally choosing another output path:
|
|
64
|
+
bun run desktop:snapshot -- /tmp/recordings-desktop.png
|
|
62
65
|
/Applications/Recordings.app/Contents/Helpers/recordings-update-client status
|
|
63
66
|
|
|
64
67
|
# Release builds run only as the isolated _recordingsbuild account. Provision these first:
|
|
@@ -115,7 +118,10 @@ RECORDINGS_RELEASE_COMPATIBLE_COHORT_MANIFEST="/Library/Application Support/Hasn
|
|
|
115
118
|
./build.sh release app-update
|
|
116
119
|
|
|
117
120
|
# Explicit local-only alternative when Developer ID credentials are unavailable.
|
|
118
|
-
# Build on a Mac other than the approved target; this does not replace a release
|
|
121
|
+
# Build on a Mac other than the approved target; this does not replace a release.
|
|
122
|
+
# The approved targets are declared once in
|
|
123
|
+
# scripts/policy/local-only-approved-targets.txt, which the builder, the installer,
|
|
124
|
+
# and the artifact tool all read; add a Mac there rather than in any guard:
|
|
119
125
|
RECORDINGS_LOCAL_APPROVED_TARGET="station06" \
|
|
120
126
|
RECORDINGS_LOCAL_APPROVED_TARGET_IDENTITY_KIND="tailscale_node_id_sha256" \
|
|
121
127
|
RECORDINGS_LOCAL_APPROVED_TARGET_IDENTITY_SHA256="AUTHENTICATED_TAILSCALE_NODE_ID_SHA256" \
|
|
@@ -135,6 +141,27 @@ recordings app install \
|
|
|
135
141
|
--approved-target-identity-sha256 AUTHENTICATED_TAILSCALE_NODE_ID_SHA256 \
|
|
136
142
|
--acknowledge-local-signing-and-permissions \
|
|
137
143
|
--launch
|
|
144
|
+
|
|
145
|
+
# Reinstalling or repairing an already-installed local-only app additionally needs
|
|
146
|
+
# --allow-adhoc-identity-migration. Local-only builds are ad-hoc signed, so every rebuild
|
|
147
|
+
# produces a new CDHash; replacing the installed app is therefore a real identity migration
|
|
148
|
+
# and the installer refuses it with exit 1 until you approve it once, explicitly. Approving
|
|
149
|
+
# it voids the Microphone and Accessibility grants held by the replaced app -- macOS keys
|
|
150
|
+
# those to code identity and the installer cannot restore them -- so expect to grant both
|
|
151
|
+
# again afterwards. Run `scripts/install_macos_app.sh --help` for the full argument list.
|
|
152
|
+
recordings app install \
|
|
153
|
+
--artifact /path/to/Recordings-0.2.13-macos-station06-local-only.zip \
|
|
154
|
+
--manifest /path/to/Recordings-0.2.13-macos-station06-local-only.manifest.json \
|
|
155
|
+
--manifest-sha256 AUTHENTICATED_MANIFEST_SHA256 \
|
|
156
|
+
--expected-source-sha APPROVED_40_CHARACTER_COMMIT_SHA \
|
|
157
|
+
--expected-version 0.2.13 \
|
|
158
|
+
--artifact-policy local-only \
|
|
159
|
+
--approved-target station06 \
|
|
160
|
+
--approved-target-identity-kind tailscale_node_id_sha256 \
|
|
161
|
+
--approved-target-identity-sha256 AUTHENTICATED_TAILSCALE_NODE_ID_SHA256 \
|
|
162
|
+
--acknowledge-local-signing-and-permissions \
|
|
163
|
+
--allow-adhoc-identity-migration \
|
|
164
|
+
--launch
|
|
138
165
|
swift test # run the native test suite
|
|
139
166
|
```
|
|
140
167
|
|
|
@@ -236,7 +263,9 @@ signature check. The mutable `/Applications` path is never executed, caller stat
|
|
|
236
263
|
not inherited, and all snapshot paths are removed by normal installer cleanup. The builder applies
|
|
237
264
|
the same checks in its private build directory and removes the snapshot with the rest of the build
|
|
238
265
|
workspace. The status parser then
|
|
239
|
-
requires online `Self`
|
|
266
|
+
requires online `Self` whose hostname equals the caller's `--expected-hostname` — the
|
|
267
|
+
approved target when the installer verifies the target, and the builder's own host when
|
|
268
|
+
the builder verifies itself, which `build.sh` requires to differ from the target —
|
|
240
269
|
requires the single nonempty `Self.ID` to contain no whitespace or NUL, hashes its exact decoded
|
|
241
270
|
bytes without a newline, and compares the digest. Neither raw node ID is written to the manifest,
|
|
242
271
|
build log, or installer log. Older schema-v3 artifacts without an
|
|
@@ -264,6 +293,31 @@ The native app uses OpenAI realtime transcription for the stop-and-paste path: s
|
|
|
264
293
|
unsettled, or cannot be saved. Raw and processed transcript fields are still stored
|
|
265
294
|
separately, so cleanup instructions never replace the verbatim transcript.
|
|
266
295
|
|
|
296
|
+
### What the app reads to confirm a paste
|
|
297
|
+
|
|
298
|
+
Posting a Cmd-V keystroke returns no delivery receipt — `CGEvent.post` returns `Void` — so
|
|
299
|
+
the only way to know whether a transcript actually landed is to look. Around each paste the
|
|
300
|
+
app therefore **reads the text value of whatever field is focused in the target app**, via
|
|
301
|
+
Accessibility, once before the keystroke and once after, and compares them.
|
|
302
|
+
|
|
303
|
+
State this plainly because it is a real change in what a dictation app can see:
|
|
304
|
+
|
|
305
|
+
- The read covers the focused field's full value and its current selection, not only the
|
|
306
|
+
pasted fragment, so text you did not dictate is inside the app's process during the
|
|
307
|
+
comparison.
|
|
308
|
+
- It is **never logged and never persisted.** The comparison happens in memory and only its
|
|
309
|
+
verdict (`pasted` / `not observed` / `unverified` plus a reason) reaches the log.
|
|
310
|
+
- Fields longer than 20,000 characters are reported unverifiable rather than copied and
|
|
311
|
+
scanned.
|
|
312
|
+
- A field that publishes no Accessibility value — terminals, canvas editors, some Electron
|
|
313
|
+
apps — is reported as unverified, never as a success.
|
|
314
|
+
- Reading requires the Accessibility permission the app already needs to post the keystroke.
|
|
315
|
+
No additional permission is requested, which is exactly why this is worth writing down.
|
|
316
|
+
|
|
317
|
+
One known limit, in the safe direction: pasting text identical to the selection it replaces
|
|
318
|
+
leaves the field's value and the occurrence count unchanged, so a genuinely successful paste
|
|
319
|
+
is reported as **not observed**. The app under-claims rather than over-claims.
|
|
320
|
+
|
|
267
321
|
## CLI Usage
|
|
268
322
|
|
|
269
323
|
```bash
|
|
@@ -378,9 +432,23 @@ Endpoints: `GET /health` → `{"status":"ok","name":"recordings"}`, MCP at `/mcp
|
|
|
378
432
|
|
|
379
433
|
## HTTP API (`recordings-serve`)
|
|
380
434
|
|
|
381
|
-
`recordings-serve` is the
|
|
382
|
-
|
|
383
|
-
|
|
435
|
+
`recordings-serve` is the HTTP API. Its data backend is a single two-value
|
|
436
|
+
switch, `HASNA_RECORDINGS_STORAGE_MODE=sqlite | postgresql` (a
|
|
437
|
+
`HASNA_RECORDINGS_DATABASE_URL` on its own implies `postgresql`). On
|
|
438
|
+
`postgresql` the process reads/writes that database directly with API-key auth
|
|
439
|
+
via [`@hasna/contracts`](https://www.npmjs.com/package/@hasna/contracts).
|
|
440
|
+
|
|
441
|
+
There are no deployment modes. `local`, `self-hosted`, `cloud`, `remote` and
|
|
442
|
+
`hybrid` no longer select anything, and passing one is an error that names the
|
|
443
|
+
variable and value to use instead. Where the server runs, and who operates it,
|
|
444
|
+
never changed how it stored data.
|
|
445
|
+
|
|
446
|
+
The CLI and MCP client are a separate, two-value switch:
|
|
447
|
+
`HASNA_RECORDINGS_CLIENT_STORE=sqlite | http`. Setting
|
|
448
|
+
`HASNA_RECORDINGS_API_URL` + `HASNA_RECORDINGS_API_KEY` selects `http` on its
|
|
449
|
+
own; `HASNA_RECORDINGS_CLIENT_STORE=sqlite` forces the on-box file even when
|
|
450
|
+
both are set. The client never opens Postgres — it reaches the shared dataset
|
|
451
|
+
only through this API.
|
|
384
452
|
|
|
385
453
|
```bash
|
|
386
454
|
recordings-serve --port 8874 # start the API
|
|
@@ -401,8 +469,9 @@ Versioned API (`/v1/*`, API-key auth via `x-api-key` or `Authorization: Bearer`)
|
|
|
401
469
|
| GET/POST | `/v1/agents` · GET `/v1/agents/:id` | `recordings:read` / `recordings:write` |
|
|
402
470
|
| GET/POST | `/v1/projects` · GET `/v1/projects/:id` | `recordings:read` / `recordings:write` |
|
|
403
471
|
|
|
404
|
-
Env: `
|
|
405
|
-
|
|
472
|
+
Env: `HASNA_RECORDINGS_STORAGE_MODE` (`sqlite` | `postgresql`),
|
|
473
|
+
`HASNA_RECORDINGS_DATABASE_URL` (PostgreSQL DSN — implies `postgresql`) and
|
|
474
|
+
`HASNA_RECORDINGS_API_SIGNING_KEY` (HMAC signing secret for API-key auth).
|
|
406
475
|
|
|
407
476
|
## SDK
|
|
408
477
|
|
|
@@ -433,6 +502,42 @@ context, `transcriber_prompt` for cleanup instructions, and `post_processing_mod
|
|
|
433
502
|
`off`, `auto`, or `always`. Tool results preserve `raw_text` and return `processed_text`
|
|
434
503
|
only when post-processing actually produced enhanced output.
|
|
435
504
|
|
|
505
|
+
## Releasing
|
|
506
|
+
|
|
507
|
+
The release version is hand-maintained in four places: `package.json`, `src/version.ts`, and both
|
|
508
|
+
`CFBundleShortVersionString` and `CFBundleVersion` in
|
|
509
|
+
`src/native/Recordings/RecordingsLib/Info.plist`. Bump them together, never by hand:
|
|
510
|
+
|
|
511
|
+
```bash
|
|
512
|
+
bun run version:set 0.3.0 # rewrites every hand-maintained site
|
|
513
|
+
bun run generate:sdk # restamps the generated SDK's header
|
|
514
|
+
bun run version:check # exits 1 if any site disagrees with package.json
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
A fifth copy is **generated**, not written: `src/server/openapi.ts` stamps `VERSION` into the
|
|
518
|
+
OpenAPI document and `bun run generate:sdk` bakes it into the `// Source: …` header of
|
|
519
|
+
`src/sdk/v1.generated.ts`. `version:set` leaves that file alone — the generator owns it, and
|
|
520
|
+
patching the stamp by hand would hide real regeneration drift — so regenerate after every bump.
|
|
521
|
+
`src/__tests__/version-site-guard.test.ts` fails when the committed header disagrees with
|
|
522
|
+
`package.json`.
|
|
523
|
+
|
|
524
|
+
`package.json` is the authority because `scripts/build_companion_cli.sh` compares the
|
|
525
|
+
compiled CLI's `--version` against it and exits 1 on a mismatch. That abort propagates
|
|
526
|
+
through `src/native/Recordings/build.sh` (`set -euo pipefail`), so a partial bump does
|
|
527
|
+
not just fail an assertion -- the native app cannot be built at all, and the whole
|
|
528
|
+
`native-app-companion-contract` suite aborts on its first test.
|
|
529
|
+
|
|
530
|
+
Three things enforce it. `.github/workflows/ci.yml` runs the whole TypeScript suite on
|
|
531
|
+
every push, which is what makes the two guards below actually block a branch rather than
|
|
532
|
+
wait for someone to run them locally. `prepack` runs `build:native-fs-guard` first (the
|
|
533
|
+
fail-closed macOS gate), then `version:check`, so a partial bump stops before the build
|
|
534
|
+
rather than deep inside it. And `prepublishOnly` runs `bun test`, which covers the sites
|
|
535
|
+
through `src/__tests__/native-bundle-version.test.ts` and
|
|
536
|
+
`src/__tests__/version-site-guard.test.ts`.
|
|
537
|
+
|
|
538
|
+
The Swift side is not covered: no reachable machine currently runs the Swift suite, so a
|
|
539
|
+
version claim about the app bundle is only as verified as the last macOS build.
|
|
540
|
+
|
|
436
541
|
## Data Directory
|
|
437
542
|
|
|
438
543
|
Data is stored in `~/.hasna/recordings/`.
|
package/bun.lock
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"": {
|
|
6
6
|
"name": "@hasna/recordings",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@hasna/contracts": "^0.4
|
|
8
|
+
"@hasna/contracts": "^0.8.4",
|
|
9
9
|
"@hasna/events": "^0.1.11",
|
|
10
10
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
11
11
|
"chalk": "^5.4.1",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
25
|
"packages": {
|
|
26
|
-
"@hasna/contracts": ["@hasna/contracts@0.4
|
|
26
|
+
"@hasna/contracts": ["@hasna/contracts@0.8.4", "", { "dependencies": { "commander": "^13.1.0", "zod": "^3.25.76" }, "bin": { "contracts": "dist/cli/index.js", "contracts-cli": "dist/cli/contracts-cli.js" } }, "sha512-a/flLzdu8cbCUrScNQT3VBMl2HgwbjUYWrmwQ45x19X6F8FPiOf2gbb43MT0vlKTLUPEonh5jSoEPdjp44nAGw=="],
|
|
27
27
|
|
|
28
28
|
"@hasna/events": ["@hasna/events@0.1.11", "", { "dependencies": { "commander": "^13.1.0" }, "bin": { "events": "dist/cli/index.js", "hasna-events": "dist/cli/index.js" } }, "sha512-X36W9TB8mKxtS5UeW1n2IlvW6nPUcoYCQWNMMV+/JM4YNzlnnk1FRm8Aay02tt1LjQOGICCHF3hz/l//EHEe+Q=="],
|
|
29
29
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const EXISTING_IDENTITY_SHA256: string;
|
|
2
|
+
export declare const CANDIDATE_IDENTITY_SHA256: string;
|
|
3
|
+
export declare const MANIFEST_SHA256: string;
|
|
4
|
+
export type ArtifactPolicy = "local-only" | "release";
|
|
5
|
+
export type IncompatibleDirection = "installed-requirement-vs-candidate" | "candidate-requirement-vs-installed" | "both";
|
|
6
|
+
export type GuardExecutionOptions = {
|
|
7
|
+
identityMigration: boolean;
|
|
8
|
+
incompatibleDirection?: IncompatibleDirection;
|
|
9
|
+
artifactPolicy?: ArtifactPolicy;
|
|
10
|
+
extraArguments?: string[];
|
|
11
|
+
};
|
|
12
|
+
export type GuardExecutionResult = {
|
|
13
|
+
exitCode: number;
|
|
14
|
+
stdout: string;
|
|
15
|
+
stderr: string;
|
|
16
|
+
reachedTransaction: boolean;
|
|
17
|
+
codesignInvocations: string[];
|
|
18
|
+
bunInvocations: string[];
|
|
19
|
+
unstubbedInvocations: string[];
|
|
20
|
+
};
|
|
21
|
+
export declare function runInstallerToIdentityGuard(options: GuardExecutionOptions): GuardExecutionResult;
|
|
22
|
+
//# sourceMappingURL=installer-guard-execution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer-guard-execution.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/installer-guard-execution.ts"],"names":[],"mappings":"AA+DA,eAAO,MAAM,wBAAwB,QAAiB,CAAC;AACvD,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AACxD,eAAO,MAAM,eAAe,QAAiB,CAAC;AAsB9C,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,SAAS,CAAC;AAuFtD,MAAM,MAAM,qBAAqB,GAE7B,oCAAoC,GAGpC,oCAAoC,GAEpC,MAAM,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG;IAKlC,iBAAiB,EAAE,OAAO,CAAC;IAG3B,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAK9C,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IAKf,kBAAkB,EAAE,OAAO,CAAC;IAG5B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAG9B,cAAc,EAAE,MAAM,EAAE,CAAC;IAMzB,oBAAoB,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,qBAAqB,GAC7B,oBAAoB,CAwStB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const POLICY_RELATIVE_PATH = "scripts/policy/local-only-approved-targets.txt";
|
|
2
|
+
export declare const READER_RELATIVE_PATH = "scripts/read_local_only_targets.sh";
|
|
3
|
+
export declare const IDENTITY_GUARD_RELATIVE_PATH = "scripts/enforce_identity_migration.sh";
|
|
4
|
+
export declare const readRepositoryFile: (relativePath: string) => string;
|
|
5
|
+
export type InstallerPreflightOptions = {
|
|
6
|
+
artifactPolicy?: "release" | "local-only";
|
|
7
|
+
approvedTarget?: string;
|
|
8
|
+
hostname?: string;
|
|
9
|
+
extraArguments?: string[];
|
|
10
|
+
policyContents?: string | null;
|
|
11
|
+
removeReader?: boolean;
|
|
12
|
+
removeIdentityGuard?: boolean;
|
|
13
|
+
identityGuardContents?: string;
|
|
14
|
+
symlinkIdentityGuard?: boolean;
|
|
15
|
+
environment?: Record<string, string>;
|
|
16
|
+
};
|
|
17
|
+
export declare function runInstallerPreflight(options?: InstallerPreflightOptions): {
|
|
18
|
+
exitCode: number;
|
|
19
|
+
stdout: string;
|
|
20
|
+
stderr: string;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=installer-preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer-preflight.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/installer-preflight.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,oBAAoB,mDAAmD,CAAC;AACrF,eAAO,MAAM,oBAAoB,uCAAuC,CAAC;AACzE,eAAO,MAAM,4BAA4B,0CAA0C,CAAC;AAEpF,eAAO,MAAM,kBAAkB,GAAI,cAAc,MAAM,KAAG,MACA,CAAC;AAc3D,MAAM,MAAM,yBAAyB,GAAG;IACtC,cAAc,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAG9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAG/B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAG/B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,yBAA8B,GACtC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA8GtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-fs-guard.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/native-fs-guard.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"native-fs-guard.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/native-fs-guard.ts"],"names":[],"mappings":"AA2CA,wBAAgB,wBAAwB,CAAC,cAAc,SAAuC,GAAG,MAAM,CActG"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared assertions for contract tests that read source text.
|
|
3
|
+
*
|
|
4
|
+
* These live here rather than inside one suite because the defect they exist to prevent is
|
|
5
|
+
* repo-wide: a sweep of every `*.test.ts` found 40 ordering assertions written as
|
|
6
|
+
* `indexOf(a) < indexOf(b)`, across 11 files. `indexOf` answers -1 when the needle is absent and
|
|
7
|
+
* `-1 < anything` is true, so such an assertion PASSES when the thing being ordered is DELETED.
|
|
8
|
+
* The same hole exists in `.slice(indexOf(...), indexOf(...))` region bounds, where a -1 silently
|
|
9
|
+
* slices from the end of the file or to its start — a region assertion over the wrong text, or over
|
|
10
|
+
* none of it, reads exactly like a satisfied one.
|
|
11
|
+
*
|
|
12
|
+
* ---------------------------------------------------------------------------------------------
|
|
13
|
+
* BEFORE YOU BUILD A MUTATION BATTERY: three suites are RED ON A CONTENDED STATION, not on Linux.
|
|
14
|
+
*
|
|
15
|
+
* A mutation battery is evidence only when its clean control is GREEN. Include a suite that was
|
|
16
|
+
* already failing and the run was non-zero before you changed anything, so every mutation "looks
|
|
17
|
+
* caught" and every verdict is manufactured. That already produced one wrong all-clear here.
|
|
18
|
+
*
|
|
19
|
+
* These are the three suites it happens to. NO PASS/FAIL SPLIT IS RECORDED FOR THEM ON PURPOSE —
|
|
20
|
+
* see below. `macos-app-lifecycle.test.ts` has 140 tests, `native-app-companion-contract.test.ts`
|
|
21
|
+
* has 14, `config.test.ts` has 44, and how many of those fail is a property of the MACHINE:
|
|
22
|
+
*
|
|
23
|
+
* src/__tests__/macos-app-lifecycle.test.ts
|
|
24
|
+
* src/__tests__/native-app-companion-contract.test.ts
|
|
25
|
+
* src/__tests__/config.test.ts
|
|
26
|
+
*
|
|
27
|
+
* CORRECTED 2026-07-27, and the correction is the useful part. This block used to call them
|
|
28
|
+
* "PERMANENTLY RED on Linux" and attribute fixed environmental causes — BSD `stat -f`, a fixture
|
|
29
|
+
* port reading `NaN`, a `getDataDir` HOME-ancestor assumption. The first CI run this repository
|
|
30
|
+
* ever had (run 30302342895, ubuntu-24.04) re-ran all three on a clean single-tenant runner and
|
|
31
|
+
* every one of them PASSED:
|
|
32
|
+
*
|
|
33
|
+
* macos-app-lifecycle 140 pass / 0 fail (358.85s)
|
|
34
|
+
* native-app-companion-contract 14 pass / 0 fail ( 4.50s)
|
|
35
|
+
* config 44 pass / 0 fail ( 0.10s)
|
|
36
|
+
*
|
|
37
|
+
* So the cause is not the platform. Measure on a quiet machine, or in CI, before recording a suite
|
|
38
|
+
* as red. There were TWO independent station-local causes, and every earlier version of this comment
|
|
39
|
+
* named only one of them. In a 92-fail run of `macos-app-lifecycle.test.ts` on this station the
|
|
40
|
+
* failure messages broke down as 38 × `Home ancestor has an unexpected owner.`, 22 × FIFO
|
|
41
|
+
* synchronisation timeout, 24 × ENOENT on a fixture marker. The first cause is now fixed in the
|
|
42
|
+
* fixture and only the second remains; do not collapse them into one, because a quiet machine with
|
|
43
|
+
* `FORCE_COLOR` set still showed all 38 aborts, so "measure on a quiet machine" was necessary and
|
|
44
|
+
* not sufficient:
|
|
45
|
+
*
|
|
46
|
+
* 1. `FORCE_COLOR` — **FIXED IN THE FIXTURE, no longer a live cause.** The `stat` stub answered
|
|
47
|
+
* `%u` by shelling out to `bun -e '… console.log(statSync(…).uid)'`
|
|
48
|
+
* (`macos-app-lifecycle.test.ts:217`) and spread `...Bun.env` into the installer, so with
|
|
49
|
+
* `FORCE_COLOR` set Bun COLOURED the number: the installer compared `\e[0m\e[33m1000\e[0m`
|
|
50
|
+
* against `id -u`'s `1000` at `install_macos_app.sh:143` and aborted before reaching any gate.
|
|
51
|
+
* `NO_COLOR=1` did NOT help — FORCE_COLOR wins in Bun. The stub now writes bare integers with
|
|
52
|
+
* `process.stdout.write` and `unset FORCE_COLOR`s its own children, which takes that message
|
|
53
|
+
* from 38 to 0 in place, positive-controlled (the same grep still finds 38 in the pre-fix log).
|
|
54
|
+
* Nothing about ancestor MODE was ever involved: `verify_secure_parent` and
|
|
55
|
+
* `verify_safe_home_ancestor` each `stat` only the one path handed to them, the sole call is
|
|
56
|
+
* `verify_safe_home_ancestor "$HOME"`, and the stub hardcodes every `%Lp` answer anyway.
|
|
57
|
+
* Kept here rather than deleted because it is the reason this file's split moved, and because
|
|
58
|
+
* the same trap recurs in any stub that parses `console.log` of a NUMBER: only strings are
|
|
59
|
+
* left uncoloured.
|
|
60
|
+
* 2. CONTENTION. The station routinely runs several full recordings suites at once out of
|
|
61
|
+
* different worktrees, and this suite scans a shared /tmp — the hazard this very comment warns
|
|
62
|
+
* about below. Those were FIFO timeouts at an internal 5000ms budget; the FIFO helper now uses
|
|
63
|
+
* the suite's configured timeout too, so a raised test budget can distinguish load sensitivity
|
|
64
|
+
* from a regression. With `FORCE_COLOR` unset the residual failures scaled with load: 132 pass /
|
|
65
|
+
* 8 fail at load ~20, 114 pass / 26 fail at load 44-60 on the same commit, which is why no split
|
|
66
|
+
* belongs here either. GitHub Actions sets neither `FORCE_COLOR` nor a competing suite, which
|
|
67
|
+
* is why both causes were absent from the only clean measurement.
|
|
68
|
+
*
|
|
69
|
+
* WHY NO SPLIT IS RECORDED. Every split ever written here has gone stale, including two written as
|
|
70
|
+
* corrections. On one unchanged tree, three consecutive runs measured 48/92, 48/92, 49/91; the
|
|
71
|
+
* single test that flips is `runtime smoke timeout does not wait forever on a live open process`
|
|
72
|
+
* (`macos-app-lifecycle.test.ts:3594`), which races a hardcoded internal `Bun.sleep(2_000)` that no
|
|
73
|
+
* `--timeout` flag reaches either. So a count comparison across two trees shows a phantom delta
|
|
74
|
+
* from this file alone — which is the concrete reason for the rule below: compare failing test
|
|
75
|
+
* NAMES, never counts. Two trees whose failing NAME SETS are identical are identical regardless of
|
|
76
|
+
* what the totals say.
|
|
77
|
+
*
|
|
78
|
+
* `@hasna/events` MUST resolve 0.1.11, as `bun.lock` pins it. A plain `bun install` pulls 0.1.14,
|
|
79
|
+
* which dropped a shipped CLI command inside the patch range and fails `cli.test.ts` — and it can
|
|
80
|
+
* drift back mid-session, so re-check it before quoting any cross-tree comparison.
|
|
81
|
+
*
|
|
82
|
+
* Corollary, also corrected: this repo NOW HAS CI. `.github/workflows/ci.yml` gates the whole
|
|
83
|
+
* suite with no exemptions on every pull request, so these suites are no longer gated only by
|
|
84
|
+
* somebody remembering to run them. What CI does NOT cover is the Swift/C half, which does not
|
|
85
|
+
* currently compile; see `.github/native-known-errors.txt`.
|
|
86
|
+
* Compare failing test NAMES, never counts — the suite is nondeterministic at the margin.
|
|
87
|
+
* ---------------------------------------------------------------------------------------------
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* Assert `first` appears before `second`, requiring BOTH to exist.
|
|
91
|
+
*
|
|
92
|
+
* Use this instead of comparing two `indexOf` results directly. `firstMatch: "last"` selects
|
|
93
|
+
* `lastIndexOf` for the first operand, which has the identical -1 hole.
|
|
94
|
+
*/
|
|
95
|
+
export declare function expectOrder(haystack: string, first: string, second: string, options?: {
|
|
96
|
+
firstMatch?: "first" | "last";
|
|
97
|
+
}): void;
|
|
98
|
+
/**
|
|
99
|
+
* Slice between two markers, requiring both to exist and the region to be non-trivial.
|
|
100
|
+
*
|
|
101
|
+
* The length floor matters as much as the -1 checks: `slice(-1)` yields a ONE-CHARACTER string, not
|
|
102
|
+
* an empty one, so a `expect(region.length).toBeGreaterThan(0)` control passes on a region that
|
|
103
|
+
* contains nothing worth asserting about. Any `not.toContain` over such a region is vacuous.
|
|
104
|
+
*/
|
|
105
|
+
export declare function sliceBetween(source: string, open: string, close: string, options?: {
|
|
106
|
+
minimumLength?: number;
|
|
107
|
+
}): string;
|
|
108
|
+
/**
|
|
109
|
+
* Assert a marker occurs exactly once before slicing on it.
|
|
110
|
+
*
|
|
111
|
+
* A duplicated end marker silently extends a region: `let myPID = ProcessInfo…` occurs twice in
|
|
112
|
+
* `RecordingEngine.swift`, so a region bounded by it could stretch ~127 KB and be satisfied by
|
|
113
|
+
* copies of the needle from an unrelated function.
|
|
114
|
+
*/
|
|
115
|
+
export declare function sliceBetweenUnique(source: string, open: string, close: string): string;
|
|
116
|
+
/** Strip Swift line comments so an assertion about code is not defeated by prose. */
|
|
117
|
+
export declare function withoutComments(source: string): string;
|
|
118
|
+
/**
|
|
119
|
+
* Index just past the `close` matching the `open` at `openIndex`, skipping comments and literals.
|
|
120
|
+
*
|
|
121
|
+
* Needed because `lastIndexOf("}")` is not brace matching, and the difference is a live defect: an
|
|
122
|
+
* early exit written between a decision and its use —
|
|
123
|
+
*
|
|
124
|
+
* } // the decision table closes here
|
|
125
|
+
* guard stillOwnsChangeCount else { return }
|
|
126
|
+
* if shouldRestore { … }
|
|
127
|
+
*
|
|
128
|
+
* — puts a NEARER `}` (the `else` block's) between the two, so a "nothing between them" check
|
|
129
|
+
* measured from the last brace saw only whitespace and passed. Counting braces naively fails the
|
|
130
|
+
* other way: one `}` inside a string literal, such as `log("settlement }")`, cancels a real opener.
|
|
131
|
+
* Both were measured surviving at EXIT=0.
|
|
132
|
+
*/
|
|
133
|
+
export declare function matchingDelimiterIndex(source: string, openIndex: number, open: string, close: string): number;
|
|
134
|
+
export declare function withoutAnyComments(source: string): string;
|
|
135
|
+
/**
|
|
136
|
+
* The arms of a Swift `switch` body, as a mapping from each matched case to its expression.
|
|
137
|
+
*
|
|
138
|
+
* Order- and grouping-independent, which matters because pinning an arm by its exact TEXT gets both
|
|
139
|
+
* directions wrong. It false-positives on a pure reorder — `.deliveredUnverified, .deliveryNotObserved`
|
|
140
|
+
* is the same table and failed — and it misses a real defect: splitting one outcome out of a group
|
|
141
|
+
* into its own arm with a different expression leaves the pinned needle intact, so
|
|
142
|
+
* `.targetUnavailable` could be given `false` while the six-outcome needle still matched.
|
|
143
|
+
*
|
|
144
|
+
* `body` is the text between the switch's braces, comments already stripped by the caller.
|
|
145
|
+
*/
|
|
146
|
+
export declare function switchArmsByOutcome(body: string): Map<string, string>;
|
|
147
|
+
/**
|
|
148
|
+
* Evaluate a Swift boolean condition for a given binding of its identifiers.
|
|
149
|
+
*
|
|
150
|
+
* Folded in from PR #43, which pinned the clipboard-restore guard by evaluating it for BOTH values
|
|
151
|
+
* of the decision rather than comparing its text. That is the half worth keeping: an exact
|
|
152
|
+
* `toBe("shouldRestore")` on a captured condition kills the inversion, but it also fails on
|
|
153
|
+
* `(shouldRestore)` and on a trailing comment — reporting refactors as defects while proving
|
|
154
|
+
* nothing about behaviour.
|
|
155
|
+
*
|
|
156
|
+
* Deliberately narrow and fail-CLOSED: `true`, `false`, `!x`, whole-expression parentheses, and
|
|
157
|
+
* identifiers present in `env`. Anything else throws. An added disjunct
|
|
158
|
+
* (`shouldRestore || stillOwnsChangeCount`) is an unevaluatable expression, not a passing one —
|
|
159
|
+
* which is the behaviour that matters, because that disjunct is exactly how the
|
|
160
|
+
* transcript-destroying defect gets reintroduced. Extend the evaluator when a new shape is
|
|
161
|
+
* legitimate; do not loosen the assertion.
|
|
162
|
+
*/
|
|
163
|
+
export declare function evaluateSwiftCondition(condition: string, env: Record<string, boolean>): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Every Swift source under a root, so an absence claim can be made about the app rather than about
|
|
166
|
+
* whichever files were on the reviewer's mind.
|
|
167
|
+
*/
|
|
168
|
+
export declare function swiftSourcesUnder(root: string): Array<[path: string, source: string]>;
|
|
169
|
+
//# sourceMappingURL=source-assertions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-assertions.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/source-assertions.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AAEH;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CAAO,GAC9C,IAAI,CAON;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,MAAM,CAWR;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMtF;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKtD;AAuED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,MAAM,CA0BR;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoEzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBrE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAiC/F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAIrF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preload.d.ts","sourceRoot":"","sources":["../../src/__tests__/preload.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"preload.d.ts","sourceRoot":"","sources":["../../src/__tests__/preload.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const DEFAULT_DESKTOP_SNAPSHOT = "desktop-snapshot.png";
|
|
2
|
+
type CaptureResult = {
|
|
3
|
+
error?: Error;
|
|
4
|
+
status: number | null;
|
|
5
|
+
stderr?: string;
|
|
6
|
+
};
|
|
7
|
+
type DesktopSnapshotDependencies = {
|
|
8
|
+
platform?: NodeJS.Platform;
|
|
9
|
+
cwd?: string;
|
|
10
|
+
capture?: (executable: string, arguments_: string[]) => CaptureResult;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Write a main-display snapshot to a stable caller-visible path.
|
|
14
|
+
*
|
|
15
|
+
* `screencapture` writes into a private sibling directory first so a denied Screen Recording
|
|
16
|
+
* grant or an interrupted capture cannot truncate a useful snapshot from the previous run.
|
|
17
|
+
*/
|
|
18
|
+
export declare function exportDesktopSnapshot(output?: string, dependencies?: DesktopSnapshotDependencies): string;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=desktop-snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"desktop-snapshot.d.ts","sourceRoot":"","sources":["../../src/cli/desktop-snapshot.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAE/D,KAAK,aAAa,GAAG;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,aAAa,CAAC;CACvE,CAAC;AAcF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,SAA2B,EACjC,YAAY,GAAE,2BAAgC,GAC7C,MAAM,CAuDR"}
|