Skip to content

refactor: move screen recording onto platform runtime - #1724

Merged
thymikee merged 1 commit into
mainfrom
agent/platform-runtime-recording-cutover
Aug 11, 2026
Merged

refactor: move screen recording onto platform runtime#1724
thymikee merged 1 commit into
mainfrom
agent/platform-runtime-recording-cutover

Conversation

@thymikee

@thymikee thymikee commented Aug 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Route record through the request-bound platform runtime and durable-capture lifecycle while preserving the public CLI and response shape.
  • Preserve exact-owner recovery, fencing, cancellation rollback, provider no-fallback, and platform-specific finalization across Android, Apple, HarmonyOS, and Web.
  • Remove the retired recording backend/provider route, keep trace execution separate, and add the R16 command-atomic cutover gate.

Stacked on #1720. This layer touches 259 files, confined to the screen-recording command family and its shared durable-capture lifecycle.

Validation

  • pnpm check:affected --run: 533 files / 4,522 tests passed; changed-line coverage 1,721/1,941 (88.67%); provider progress 53/53 commands and 67/67 device-observable flags.
  • Android helpers and iOS/macOS XCTest runner builds passed.
  • Live iPhone 17 Pro simulator and Pixel 9 Pro XL emulator flows exercised public start/open/stop, daemon-loss cleanup, replacement start, and playable artifact finalization. On exact head, iOS produced a 31.43-second, 876,761-byte H.264 MP4 and two subsequent starts/stops proved ownership release; earlier Android recovery produced playable H.264 MP4s.
  • Exact-head Web verification exercised public open/start/interaction/stop/close and produced a playable 69,498-byte, 27.7-second VP8 WebM.
  • Live verification exposed and closed exact process-identity regressions for simulator xcrun-to-simctl exec and Android missing/timeout-shaped /proc probes.
  • ADR 0019 records the command-unit cumulative and stack-base budgets. A same-toolchain size/dead-surface/bundler audit removed unreleased unused host fields; current output is 112 B raw and 47 B gzip below the reviewed bound. Bundler A/Bs were rejected when they worsened compressed/tarball size or were byte-neutral.
  • macOS TextEdit opened, but the host XCTest runner never became ready for recording even after a successful runner rebuild; no artifact was claimed. HarmonyOS hardware was unavailable. Both are recorded as residual practical-verification risks while the corresponding focused/package/CI coverage remains green.

No CLI docs or skills changed because public command behavior is preserved; ADR 0019 and structural gates own the internal cutover.

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-08-11 08:25 UTC

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 2.14 MB 2.17 MB +31.9 kB
JS gzip 696.6 kB 709.4 kB +12.8 kB
npm tarball 827.9 kB 836.9 kB +9.0 kB
npm unpacked 2.88 MB 2.91 MB +32.4 kB

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 28.2 ms 27.6 ms -0.7 ms
CLI --help 68.9 ms 66.8 ms -2.1 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/dispatch.js +41.4 kB +12.9 kB
dist/src/runtime2.js +25.3 kB +7.6 kB
dist/src/internal/daemon.js -2.8 kB +842 B
dist/src/sdk-batch-runner.js +1.2 kB +358 B
dist/src/session.js +1.7 kB +335 B

@thymikee

Copy link
Copy Markdown
Member Author

Not ready at exact 2db0a9b0:

  • [P2] Linux/Vega record start now falls through narrowDeviceBinding and reports the internal Runtime operation screenRecordingStart is unavailable with no hint, replacing the prior operator-facing record is not supported on this device. Give the screen-recording unavailability fact/handler a record-specific public message and recovery hint, with a production-route regression.
  • [P2] src/daemon/handlers/__tests__/record-runtime.test.ts is a new 549-line file. AGENTS.md requires extraction above 500 LOC and explicitly says tests are not exempt. Split start from stop/recovery and move the shared runtime harness to a sibling fixture.
  • ADR 0019 says future command units must define and review their own cumulative package budget rather than inherit checkpoint headroom. This unit adds +31.7 kB raw JS, +12.7 kB gzip, +8.9 kB tarball, and +32.1 kB unpacked versus refactor: extract durable capture resource lifecycle #1720, but the PR/ADR records no reviewed recording-unit budget. Reconcile and document that acceptance before readiness; the green per-PR Size job does not make the decision.
  • Practical evidence covers iOS simulator and Android emulator only in summary prose. This cutover changes Apple/macOS, Android, HarmonyOS, Web and provider recording routes. Attach exact-head command/output evidence with artifact/playability, recovery/replacement-start and session cleanup; run the other available changed routes, and explicitly record unavailable HarmonyOS hardware as residual risk.

All exact-head CI checks are green and the architectural cutover otherwise traces coherently. PR is stacked on draft #1720. Do not label ready.

@thymikee
thymikee force-pushed the agent/platform-runtime-recording-cutover branch 2 times, most recently from b64bf33 to e5dc29c Compare August 11, 2026 06:23
@thymikee

Copy link
Copy Markdown
Member Author

Reviewed exact head e5dc29c. The two prior code findings are resolved: Linux/Vega now receive record-specific unsupported guidance through the fact-only admission path with handler/router coverage, and the 549-line test was split into focused 67/125-line suites plus a 231-line fixture. No new source finding. Readiness remains blocked on evidence: ADR 0019 explicitly requires an exact-head acceptance comment for the new recording budget; quote red-before output for the new production-route unsupported regression; and attach exact-head command/output/artifact evidence for available macOS/Web/provider recording routes plus an explicit HarmonyOS hardware residual-risk note. All completed checks are green; iOS Smoke is still authoritative/in progress.

@thymikee

Copy link
Copy Markdown
Member Author

Addressed the readiness review at exact head e5dc29c98ec57135de39958d923e41c49f325c92:

  1. Linux/Vega unsupported starts now retain the public record-specific message/hint and machine-readable details.reason. The regression runs through the real request router and composed Linux/Vega runtime facts, proving screenRecordingStart is not invoked.
  2. The former 549-line record-runtime test is split 1:1 into record-runtime-start.test.ts (4 tests), record-runtime-stop-recovery.test.ts (5 tests), and the sibling shared fixture. The moved discovery count remains 9/9.
  3. ADR 0019 now records this command unit's original-baseline cumulative bound and immediate stack-base delta. The table is auditable at this acceptance head: reviewed bounds are 2,166,159 B raw / 708,776 B gzip / 836,426 B tar / 2,913,430 B unpacked. A same-toolchain dead-surface and bundler A/B pass then removed unused unreleased Web/Apple host fields. Actual exact-head output is 2,166,047 B raw / 708,729 B gzip / 836,419 B tar / 2,913,318 B unpacked, respectively 112 / 47 / 7 / 112 B below the bound. Removing chunk groups worsened gzip/tar; moduleSideEffects:false also grew them; Node 22 targeting and disabling shims were byte-identical, so no unsafe bundler change landed.
  4. Practical route evidence:
    • iOS simulator, exact head, iPhone 17 Pro 6044A251-23C2-4584-B7DB-87A16B787757: public open → record start → real Settings/General navigation → record stop produced /private/tmp/pr1724-e5dc-ios-primary.mp4; ffprobe reports H.264, 220×480, 30 fps, 31.433333s, 876,761 B. Two subsequent public start/stop cycles succeeded, proving the durable slot was released. Session close and isolated daemon cleanup succeeded.
    • Web, exact head: public open https://example.com → record start → settled Learn more navigation → record stop → close produced /private/tmp/pr1724-e5dc-web-example.webm. JSON reported recordingBackend:"agent-browser", recordingScope:"app"; ffprobe reports Matroska/WebM, VP8 1280×578, 27.700s, 69,498 B. Session and isolated daemon cleanup succeeded.
    • Android emulator evidence on the preceding behavior head already covers public start/stop, dead-daemon exact-owner cleanup, replacement start and playable H.264 artifacts; the final head changes only remove unused Apple/Web host projections, and exact-head Android package, provider, affected-coverage, and CI smoke checks cover the unchanged Android path.
    • macOS residual: public TextEdit open succeeded, but exact-head recording never reached XCTest runner readiness or produced an artifact, even after pnpm build:xcuitest succeeded. The isolated client/daemon cleaned with known confidence and no retained claims. HarmonyOS hardware was unavailable. These are recorded as residual practical-verification risks, not represented as passes.

The full local pnpm check:affected --run passed (533 files / 4,522 tests; 88.67% changed-line coverage). The exact-head GitHub rollup has one remaining red iOS smoke workflow: attempt 1 hit runner_main_thread_execution_timeout in the pre-existing alert accept E2E step; its single failed-workflow retry reached a different pre-existing targeted XCTest and observed partial hardware-keyboard text (h/hardwar instead of hardware-keyboard). No recording assertion failed, but I am keeping the PR draft while that CI result is classified rather than representing the rollup as green.

@thymikee

Copy link
Copy Markdown
Member Author

Follow-up for the requested seen-red production-route evidence:

I restored only the pre-fix direct required-operation bind in an isolated detached e5dc29c98 worktree, leaving the new real-router Linux/Vega test intact, then ran:

pnpm exec vitest run src/daemon/__tests__/request-router-record-runtime-lock.test.ts

src/daemon/__tests__/request-router-record-runtime-lock.test.ts (3 tests | 2 failed)
  ✓ fresh default-device recording starts serialize before durable admission
  × record start on 'linux' routes real unavailable runtime facts into public guidance
  × record start on 'vega' routes real unavailable runtime facts into public guidance

- Expected: message "record is not supported on this device"
- Received: message "Runtime operation screenRecordingStart is unavailable"
- Expected: hint "Select an Apple, Android, physical HarmonyOS, or web target that supports screen recording."
- Received: hint "This command is not available for the selected platform/device."

Test Files  1 failed (1)
Tests       2 failed | 1 passed (3)

The unchanged exact-head tree is green on the same command:

Test Files  1 passed (1)
Tests       3 passed (3)

The failing assertions run through createRequestHandler, the real composed platform runtime gateway, and the Linux/Vega runtime facts; they do not replace the router with a handler mock.

The iOS red is separately classified as pre-existing lane flakiness, not recording behavior: attempt 1 passed targeted XCTest/preflight/Settings smoke before alert accept timed out; attempt 2 failed the unchanged hardware-keyboard XCTest with the known partial-text h/hardwar symptom. The only Swift production delta is the recordStop branch at line 1537. Recent main iOS workflows also fail at unrelated fixture steps with successes interleaved. Per the one-retry policy I am not retrying again or inflating timeouts, and #1724 remains draft while that authoritative check is red.

Base automatically changed from agent/platform-runtime-recording to main August 11, 2026 08:08

Copy link
Copy Markdown
Member Author

Heads-up on a conflict with #1719 (refactor(record): derive session recording from the publication lifecycle), which removes SessionState.recordSession and derives recording from the script-publication aggregate. Posting the resolution here so whichever of us merges second can apply it directly.

Merge dry-run of #1724 4e057e4f against #1719 4872feb: six files overlap, four auto-merge clean (session-state.ts, session-close.ts, types.ts, session-close-shutdown.test.ts). Two conflict:

1. scripts/layering/daemon-modularity.ts — R7 ratchet. Neither side's number survives.

We each remove a different SessionState field, so this doesn't resolve by picking a side:

writerOwnedFields ownerFileClaims
main 23 29
#1724 22 28
#1719 22 26
merged 21 25

Verified by counting the auto-merged SESSION_STATE_FIELD_OWNERS (21 entries / 25 owner claims), not by arithmetic. The guard recomputes from the manifest so a wrong value fails loudly, but 21/25 is what it wants.

2. src/daemon/handlers/record-trace-recording.ts — modify/delete. Your deletion wins.

#1719's only change in that file is a one-line doc comment that stopped naming the removed recordSession field. Take the delete.

Also worth knowing: this branch's scripts/layering/session-state.ts still has the recordSession manifest entry because it predates #1712/#1719. The auto-merge removes it correctly, so no manual edit is needed — just don't re-add it when resolving.

#1719 is green and standalone; I'm deliberately not stacking it on this branch, so no action needed from you unless this lands first.


Generated by Claude Code

@thymikee
thymikee marked this pull request as ready for review August 11, 2026 08:22
@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Aug 11, 2026
@thymikee

Copy link
Copy Markdown
Member Author

Readiness follow-up after #1720 merged: #1724 is now rebased onto main at c7242f8, with exact head 4e057e4. The recording layer is patch-equivalent to the reviewed e5dc29c head (the only range-diff context shift is the newer main host-process helper), so the acceptance, seen-red, size-budget, and practical-route evidence above remain applicable. The fresh rebased-head CI rollup is fully green, including iOS Smoke (targeted runner regressions, public CLI preflight, Settings replay, and fixture-backed simulator E2E), Android/macOS/Linux/Web smokes, coverage, FreeRange, layering, typecheck, package, size, and CodeQL. The full comment/thread audit has no submitted reviews or unresolved inline threads. Marked ready for review and labeled ready-for-human.

@thymikee
thymikee merged commit 1b2e786 into main Aug 11, 2026
33 checks passed
@thymikee
thymikee deleted the agent/platform-runtime-recording-cutover branch August 11, 2026 08:24
thymikee pushed a commit that referenced this pull request Aug 11, 2026
…anch

Two conflicts, both resolved as posted on the PR before the merge landed.

`scripts/layering/daemon-modularity.ts` — the R7 ratchet. #1724 and this
branch each remove a different `SessionState` field, so neither side's
baseline survives. Note git only flagged `ownerFileClaims` (26 vs 28);
`writerOwnedFields: 22` merged silently because both sides wrote 22, yet
the merged manifest holds 21. Counted the auto-merged
`SESSION_STATE_FIELD_OWNERS` rather than doing the subtraction: 21 entries,
25 owner claims. The layering guard confirms — R10 now pins R7 at 21/25.

`src/daemon/handlers/record-trace-recording.ts` — modify/delete. #1724
deletes the module; this branch's only change in it was a doc comment that
stopped naming the removed `recordSession` field, so the deletion wins.
Nothing references the path any more.

`session-state.ts` auto-merged correctly: #1724 predates #1712/#1719 and
still carried the `recordSession` manifest entry, and the merge drops it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PFW9gJqz1wEHoowkdd1nFW
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant