fix(devtools): isolate replay execution lifetimes - #3326
Conversation
Give timers and asynchronous handlers generation-scoped ownership so stop, seek and dispose revoke stale continuations. Prevent duplicate play scheduling, preserve pause/resume semantics, guard reentrant state delivery, and add focused lifecycle regression coverage.
|
Publication/qualification checkpoint for exact head
The source, lifecycle regression and evidence-note blobs all match the locally verified Git object identities. This is a draft checkpoint, not exact-head qualification or merge approval; keep the PR draft until the complete hosted matrix and independent review are inspected. |
|
Exact-head qualification is complete for
The PR is being moved to ready-for-review. Green CI is qualification evidence, not merge authorization; independent review remains required. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Chris0Jeky
left a comment
There was a problem hiding this comment.
Fresh-context review completed on the full replay implementation, canonical lifecycle tests and discussion. Timer generation and activeExecution identity jointly revoke stale settlement; pause preserves the pending action, while stop/seek/dispose revoke it. Reentrant state callbacks are checked before delivering later observers or scheduling successors. Tests assert delivery counts, state and timers rather than merely checking callbacks. External effects already started by handlers are correctly documented as non-cancellable. No blocking finding in this bounded change.
Re-read exact-head Required CI 35596118244, Self-Test 35596117841 and Extended results: all successful. Codex completed at b51fd55 with no findings in the discussion. Normal head-pinned merge under the maintainer's current instruction; no local full-suite execution claimed.
Summary
Hardens the internal trace replay engine around one explicit execution lifetime.
Previously, repeated
play()calls could schedule duplicate delivery, while an async action handler could settle afterstop(),seekTo()ordispose()and still advance state, emit an error or schedule further work. Pause/resume could also invoke one pending action twice, and a reentrant state listener could leave later observers seeing an obsolete state.This change:
Scope
Three files only. Public method signatures remain unchanged. This cannot cancel or roll back an external effect already started inside a handler; it suppresses obsolete engine continuations. No application data, backend, schema, dependency, workflow, authorization or route change.
Base:
307c3b8b50bec1cb0bfaea3e570a942bcb1d4451Exact source head:
b51fd55fbcc477b15503f428f3cbab64a93b4414Red/green evidence
A supplemental runner imports the actual production replay module:
main: 17 expected behavioral failures, 5 controls passing;The coverage includes duplicate Play, late resolve/reject after replacement, Stop/Seek/Dispose ownership, pending-action pause/resume, handler-chain interruption, completion seeks, invalid controls and reentrant state observers.
Verification
35596117841: success.35596118320: success.35596118244: success across Linux/Windows frontend lint, typecheck, build and full coverage tests; backend unit/API integration on both platforms; architecture, migrations, containers, dependency/SAST/secret scans, docs governance, worktree contracts and E2E smoke.Ready for independent review. Green CI is not merge authorization. Review should focus on pending-handler pause/resume semantics, reentrant state callbacks, stale error suppression and final disposal.
No rollback migration is required. Observer exceptions and validation of externally mutated Trace objects remain outside this slice.