Skip to content

fix: keep open and foreground capture in one session lifetime - #3145

Closed
thymikee wants to merge 38 commits into
fix/replay-observation-lifetimesfrom
fix/open-session-lifetimes
Closed

thymikee wants to merge 38 commits into
fix/replay-observation-lifetimesfrom
fix/open-session-lifetimes

Conversation

@thymikee

@thymikee thymikee commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Summary

Reopening an app now updates the latest record of its admitted session lifetime. One publication helper preserves resources, recording, claims, creation time and script-authoring behavior; retirement or daemon shutdown refuses a late open result.

Provisional publication retains its existing before-dispatch timing. Final publication follows artifact-directory and response construction. Foreground snapshot composition carries the exact published ref, so it cannot capture or mutate a successor at the same address.

Eleven files changed. Part of #3116, stacked on #3144.

Validation

Validated 52ec7ebd05: 70 focused tests through daemon handlers and the request router. Seven planted regressions fail, then restored source passes. Quick and Fallow checks pass; pnpm check:affected --base fix/replay-observation-lifetimes --run passes all selected runnable gates and 1,628 related tests across 265 files.

Controls cover held native launch, same-lifetime rebuild, retirement with record reuse, provisional replacement, cancellation, shutdown admission, a real blocked artifact directory, and foreground composition after publication. Independent review found no remaining findings. CI and live-provider evidence remain pending on the published head.

Review in cubic

@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
Installed (including dependencies) 4.96 MB 4.96 MB +1.0 kB
Package (unpacked) 4.96 MB 4.96 MB +1.0 kB
Package (download) 1.49 MB 1.49 MB +239 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 23.1 ms 23.9 ms +0.8 ms
CLI --help 68.1 ms 67.7 ms -0.4 ms

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 11 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@thymikee
thymikee added this pull request to stack #3146 October 3, 2026 08:50
@thymikee

thymikee commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

Thanks for the change. At 52ec7eb I found one gap: the changed device path has no live run yet. The PR body says live-provider evidence is still pending, and the new fixtures stub openApplication and runtime facts. This PR changes the device-facing open route, so merge needs a live run of it: session-open-execution.ts#L212 covers reopen publication, fresh publication ordering, the provisional beforeDispatch publication used by replay --record-video, and the fresh open --foreground snapshot. On one live device at this commit, please run three things. (1) A fresh open <app> --platform android --foreground --json: the output must include data.snapshot and no initialSnapshotError. (2) A second open <otherApp> in the same session: session list --json must show one session with an unchanged createdAt, and the recorded actions must include both opens. (3) A replay test --record-video of a script that opens an app: the video artifact must be produced.

Not blocking, and fine to take or leave: the blocked-directory test at session-open-execution-runtime.test.ts#L607 uses a bare .rejects.toThrow(), so any throw before publication passes, and asserting the ENOTDIR or normalized error code would pin it down. Also, composeOpenWithInitialSnapshot checks requireCurrent(ref) but passes only ref.address, so the lifetime binding relies on no await before the snapshot lookup, and passing the SessionRef through SnapshotRuntimeRouteParams would remove that reliance.

Could the size come down? The session-open-state seam is small. Most of the weight is nine requireOpenSessionAdmission calls across handleOpenCommand, completeOpenCommand and openNewSessionWithDeviceClaim, plus wrapping SessionOpenResult at about 25 return sites. If SessionStore.update and publish enforced admission, publishOpenSession would be the single gate, and only the guards before device side effects (claim renewal and prepare) would stay. This depends on #3116 deciding whether SessionStore.update is admitted during daemon shutdown, since finalization and teardown writes may need it.

The earlier cubic-dev-ai thread on session-open-runtime.fixtures.ts does not apply, so you can resolve it: the temp root's sessions path gets created as a file with no ENOENT, and the later mkdir fails with ENOTDIR, which is the failure the test wants. #3145 (comment)

CI is green with 14 checks and none failing, and there are no conflicts. I did not run the focused tests, and I judged the new tests against the old code paths by reading only. I also did not check whether the router already serializes concurrent fresh opens of one session name across devices, since store.publish now throws session_address_occupied where the old code overwrote silently. Before merge, we need the live device evidence at 52ec7eb for the fresh foreground open, the same-session reopen, and replay --record-video.

@thymikee

thymikee commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

Completed the requested live controls at 52ec7ebd05 on the owned emulator-5580, using a fresh checkout build and Android helpers.

Fresh open settings --foreground --json returned data.snapshot, no initialSnapshotError, and android-helper version 0.21.18. A second open to the discovered com.google.android.deskclock returned its initial snapshot too.

Session lists before/after each open contained one entry:

{
  "address": "cwd:bd54d58de95a06c0:android",
  "createdAtBefore": 1791032271520,
  "createdAtAfter": 1791032271520,
  "journalOpenActions": ["Opened settings", "Opened com.google.android.deskclock"]
}

Both action.recorded entries are in the same session event journal. The existing second-open script-authoring abort rule is preserved, as specified in #3116; the proof uses journal entries rather than an export that policy intentionally refuses.

Also ran this separate native script with test --record-video:

context platform=android
open settings
snapshot -i
wait 500
open com.google.android.deskclock
snapshot -i
wait 500
close

Result: one attempt passed, seven steps replayed, no healing or failures. The timing trace records video start before the first open, both successful opens, and successful recording finalization at close. The exported MP4 is playable H.264, 1080×2400, 6.050 seconds; attached below. The owned sessions and isolated daemon were cleaned afterward.

recording.mp4

@thymikee

thymikee commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

Thanks for the live runs at 52ec7eb. They cover all three paths: the fresh open --foreground returned a snapshot, the second open kept one session with the same createdAt and both opens in the journal, and test --record-video produced a playable video. The evidence gap is closed.

One question from my earlier review is still open: could the size come down if SessionStore update and publish enforced admission, so publishOpenSession is the single gate? If you rejected that design, or it must wait for #3116, a short note on why is enough. I will add the ready-for-human label after that.

@thymikee
thymikee force-pushed the fix/replay-observation-lifetimes branch from 5c349ba to 10ff582 Compare October 3, 2026 14:41
@thymikee
thymikee force-pushed the fix/open-session-lifetimes branch from 52ec7eb to 9842be3 Compare October 3, 2026 14:41
@thymikee
thymikee force-pushed the fix/replay-observation-lifetimes branch from 10ff582 to f36994c Compare October 3, 2026 15:16
@thymikee
thymikee force-pushed the fix/open-session-lifetimes branch from 9842be3 to adb93d3 Compare October 3, 2026 15:16
@thymikee
thymikee force-pushed the fix/replay-observation-lifetimes branch from f36994c to 974356e Compare October 3, 2026 16:41
@thymikee
thymikee force-pushed the fix/open-session-lifetimes branch from adb93d3 to 838f115 Compare October 3, 2026 16:41
@thymikee
thymikee force-pushed the fix/replay-observation-lifetimes branch from 974356e to b08a3f6 Compare October 3, 2026 16:56
@thymikee
thymikee force-pushed the fix/open-session-lifetimes branch from 838f115 to 55f0ce9 Compare October 3, 2026 16:56
@thymikee
thymikee force-pushed the fix/replay-observation-lifetimes branch from b08a3f6 to c0cb32f Compare October 3, 2026 17:49
@thymikee
thymikee force-pushed the fix/open-session-lifetimes branch from 55f0ce9 to 14594d1 Compare October 3, 2026 17:49
…eclarations

Daemon session bindings inferred a binding type whose clear result was an
alias the durable-capture entry never exported, so declaration emit failed
with TS2883.
Binding app-log capture through the session capture binding pulled that module
into session-teardown's eager closure. Teardown now imports the app-log
resource only when a session has an app log to stop.
Session teardown imported three per-capture binding modules plus their shared
binding, which grew its eager closure past the merge-base. The audio, perf and
screen-recording bindings now live beside bindSessionCapture.
@thymikee
thymikee removed this pull request from stack #3146 October 3, 2026 19:38
@thymikee
thymikee force-pushed the fix/open-session-lifetimes branch from 14594d1 to 08940db Compare October 3, 2026 19:39
@thymikee
thymikee force-pushed the fix/replay-observation-lifetimes branch from c0cb32f to 0e24d48 Compare October 3, 2026 19:39
@thymikee
thymikee added this pull request to stack #3187 October 3, 2026 19:45
@thymikee
thymikee removed this pull request from stack #3187 October 3, 2026 20:59
@thymikee
thymikee force-pushed the fix/replay-observation-lifetimes branch from 0e24d48 to 7f2e379 Compare October 3, 2026 21:00
@thymikee

thymikee commented Oct 3, 2026

Copy link
Copy Markdown
Member Author

Consolidated into #3144 as part of reducing #3116 to seven PRs. The composition preserves the complete pre-consolidation source tree, including tests and later review corrections. This PR is superseded; its review discussion and native evidence remain available. Outstanding findings transfer to the owning keeper in the implementation record.

@thymikee thymikee closed this Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant