Repository navigation
refactor(maestro): shape the replay backend as a create(host) plugin - #3623
Conversation
There was a problem hiding this comment.
1 issue found across 32 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/__tests__/eager-closure-budgets.ts">
<violation number="1" location="scripts/__tests__/eager-closure-budgets.ts:140">
P3: This allowance row is authored in the same PR that uses it, and the gate only checks that an `owner` string exists. Please record the owner's sign-off before merge, for example in the PR approval, since the diff itself does not show it.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| issue: '#3377', | ||
| reason: | ||
| 'The Maestro replay backend plugin IS the engine behind `replay --maestro`; the registry reaches it only through a function-scoped import(), and no startup hub evaluates it (cli-startup-import-closure pins that).', | ||
| owner: 'thymikee', |
There was a problem hiding this comment.
P3: This allowance row is authored in the same PR that uses it, and the gate only checks that an owner string exists. Please record the owner's sign-off before merge, for example in the PR approval, since the diff itself does not show it.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At scripts/__tests__/eager-closure-budgets.ts, line 140:
<comment>This allowance row is authored in the same PR that uses it, and the gate only checks that an `owner` string exists. Please record the owner's sign-off before merge, for example in the PR approval, since the diff itself does not show it.</comment>
<file context>
@@ -132,7 +132,14 @@ export const NEW_ENTRY_CEILINGS: Readonly<Record<EntryCategory, number>> = Objec
+ issue: '#3377',
+ reason:
+ 'The Maestro replay backend plugin IS the engine behind `replay --maestro`; the registry reaches it only through a function-scoped import(), and no startup hub evaluates it (cli-startup-import-closure pins that).',
+ owner: 'thymikee',
+ },
+});
</file context>
There was a problem hiding this comment.
No code change: maintainer approval of this PR is the sign-off for the APPROVED_OVER_CEILING row. Leaving this thread open so thymikee sees it.
|
The design holds at 5352eef, and one small test fix is needed before merge: the first inline thread below, where a test name promises suggestNodes but the test never calls it. CI is still pending: all 17 lanes were queued or running and none had failed. The lanes this diff touches are Typecheck & Package, Repo Guards and Integration/Smoke, and they decide whether it can merge. I read the diff but did not run the test suites or the closure-budget and layering gates, and I did not measure the eager-closure size of replay-maestro-backend.ts. I also did not check the CLI startup closure numerically after cli-help moved to replay-port/replay-backend-declarations, though reading the imports it should shrink. I checked the moved tests by reading the diff, not with Not blocking: the host builds Three inline threads on this PR still apply. The first is the test name that promises suggestNodes. The daemon test at lines 342-475 covers the route end to end, so either assert the suggestion source or drop it from the name. The second is the lost first-event ordering check, where Before merge, the CI lanes above need to go green and thymikee needs to approve the APPROVED_OVER_CEILING row. After that, retarget the PR to main once #3622 merges. No conflicts. |
Size Report
Startup median (7 runs, lower is better):
|
|
5352eef to
be07f5b
Compare
|
Both non-blocking notes taken in be07f5b: the host's |
be07f5b to
a12c6ab
Compare
|
The Maestro replay backend now has the create(host) plugin shape. The code at a12c6ab is clean: I found no new problems since the earlier review (#3623 (comment)), and the findings from 5352eef are fixed. I read the code. I did not run the unit suites, the eager-closure budget gate, the layering gate or the startup-closure test, and I did not measure the eager-closure size of replay-maestro-backend.ts, so the over-ceiling margin is unverified. I would like those results before this counts as proven. The Smoke Tests lane failed in the iOS runner XCTest RunnerTests.testNonReadCommandStillLaunchesANotRunningSessionApp, because the fixture /tmp/agent-device-inject-tap-recorded-failure-for-testing was missing. This looks unrelated: the diff from e59514f to a12c6ab has no Swift, runner or Apple files, and the PR only changes Maestro replay packaging. I judged this only from that lack of overlap. I did not compare it with runs of the same test on main. Please rerun the lane. One question on simplicity. Nothing reads ReplayBackendDeclaration.apiVersion, and only provider plugins validate theirs (src/plugins/manifest.ts:63). The registry never reads ReplayBackendPlugin.declaration, because help uses the separate REPLAY_BACKEND_DECLARATIONS table. Should apiVersion and plugin.declaration wait for the installed-plugin loader that would check them? Or should the registry be the one reader: derive the help table from the plugins' declarations and assert that declaration.id and backend.id match the registry key? Either way, the id and the declaration would no longer be registered in parallel with nothing keeping them in step. Of the open review threads, the cubic-dev-ai P3 on scripts/tests/eager-closure-budgets.ts:136-141 still holds (#3623 (comment)). The owner row is self-authored, so it needs no code change, only the owner's approval. The reason text is now true, because isLazyEngineModule covers the plugin subpath. The other two threads are fixed at this head and can be resolved: the failure-suggestion test now compares against collectMaestroFailureSuggestions and asserts a non-empty result (#3623 (comment)), and the observer test uses toHaveBeenNthCalledWith(1, ...) (#3623 (comment)). No conflicts are known. To merge, the Smoke Tests lane needs a green rerun, the owner must approve the APPROVED_OVER_CEILING row, and the PR must be retargeted to main after #3622 merges. |
a12c6ab to
85d588e
Compare
|
At 85d588e the code looks good, but I cannot call it ready: the question from my earlier review (a12c6ab) is still open. All 40 checks pass at 85d588e, including the unit, layering, eager-closure and startup-closure gates that were unverified before. The Smoke Tests failure from a12c6ab is gone, and there are no conflicts. The two Cubic test threads on the failure suggestions and the start-event order are fixed at this head. Is one registration per backend id enough here? REPLAY_BACKEND_DECLARATIONS (https://github.com/callstack/agent-device/blob/85d588e/packages/replay-port/src/daemon-port/replay-backend-declarations.ts#L11) and BUILTIN_REPLAY_BACKEND_PLUGINS (https://github.com/callstack/agent-device/blob/85d588e/packages/replay-port/src/daemon-port/replay-backend-registry.ts#L33) are two id-keyed tables for one backend. Help reads the first. The registry reads the second and never reads plugin.declaration. Nothing in production checks that the ids and apiVersion agree, so a second backend could show help that does not describe the engine that runs. You could keep Not blocking, and you can take or leave it: the duplicated tables above also mean only one identity test for maestro links them. The open Cubic thread on the APPROVED_OVER_CEILING row in eager-closure-budgets.ts (#3623 (comment)) still applies. It needs no code change, only maintainer sign-off. I ran no tests locally and read no CI logs; the gate results are from the 40/40 check summary. I did not measure the eager-closure size of replay-maestro-backend.ts, so the over-ceiling margin rests on that gate passing. How |
…ts id, drop unread fields Both id-keyed tables are mapped over ReplayBackendId, so a declaration or plugin registered under another backend's id fails to type-check. The tables stay apart so the daemon routes that load backends do not evaluate help text. ReplayBackendPlugin.declaration and ReplayBackendDeclaration.apiVersion had no reader; the installed-plugin loader that would check them is not part of #3377 yet.
85d588e to
36d06fa
Compare
|
Registration question answered in a0be641 and the head is rebased onto main at 36d06fa (#3622 merged). The installed-plugin loader is not in scope for #3377 yet, so the unread fields are gone: I tried the single The rebase also dropped the three #3616 |
|
This PR is ready at 36d06fa. The question about one registration per backend id is settled: both tables are now mapped over Smoke Tests is still running, not failed, and this update does not touch the device or runner routes it exercises. The open Cubic P3 thread on the #3377 approval row still holds, but it is a sign-off, not a code defect. Not blocking: one doc-comment line at replay-backend-registry.ts#L10 is about 150 characters and could be rewrapped. |
#3623 put the entry on main, so the merge-base now carries it and the no-growth rule governs it; the stale-row check asks the next PR to remove it.
…e runtime gate (#3631) * refactor(interaction): move the moving-target decision policy into the runtime gate MovingTargetBaseline stays in contracts beside CommandSessionRecord; the window and sample-gap constants, the decision union, and movingTargetGateDecision move into the runtime gate, their only consumer. The decision tests move with them, unchanged. * chore(gates): drop the @agent-device/contracts/moving-target-gate subpath The module is gone; remove its exports-map entry and its line in the contracts export snapshot. * docs(interaction): scope the moving-target gate header to resolved targets and any dispatch * chore(gates): drop the replay-maestro-backend over-ceiling approval #3623 put the entry on main, so the merge-base now carries it and the no-growth rule governs it; the stale-row check asks the next PR to remove it.
…rule the runner runs (#3632) * refactor(apple): reduce SnapshotPresentedSurface to the element-type rule the runner runs The runner's only caller classifies a RawAXNode acquisition, which carries no UIKit class name, so the class-aware branch never ran in production. Keep the element-type vocabulary, the strict Element(<digits>) parse, and the acquisition entry point; the Swift parity test now checks every golden case against classBlindExpected. The TypeScript rule and its two-column parity test are unchanged. * chore(gates): drop the replay-maestro-backend over-ceiling approval #3623 put the entry on main, so the merge-base now carries it and the no-growth rule governs it; the stale-row check asks the next PR to remove it. * docs(contracts): attribute the AX role prefix to accessibility roles, not the runner
Summary
Second half of the #3377 replay-backend prep. Builds on #3622 (merged); based on
main. Behavior, wire shapes, help text and error wording are unchanged; the backend still resolves once per process (ADR 0015).packages/maestro/src/replay-backend/and ships asReplayBackendPlugin = { create(host) }(@agent-device/maestro/replay-backend), with an engine-free declaration (.../replay-backend-declaration).ReplayBackendHost(built inreplay-backend-host.ts) is the only way the adapter reaches process state or daemon policy: trace append, builtin vars, script-source read, target-device resolution, request signal, and the divergence-failure builder from refactor(replay-port): own the replay backend contract in contracts #3622.create(host)once.replay-backend-declarations.tsholds the declaration table, so the registry's eager closure (and every daemon route that loads it) does not grow. Both tables are mapped overReplayBackendId, so a declaration or plugin under another backend's id fails to type-check.help maestroreads its topic from the declaration, socli-helpno longer imports the engine.getReplayBackend('maestro'); two warnings checks became unit tests../daemon-runtime-portexport.@agent-device/maestroin production (scripts/fuzzstill does).32 files touched. Sign-off needed: the
APPROVED_OVER_CEILINGrow forreplay-maestro-backend.tsnames thymikee as owner, so it needs his approval.Refs #3377.
Validation
Tested SHA: 36d06fa (
pnpm check:affected --run).pnpm check:affected --base <layer-1 branch> --run: all runnable checks passed.pnpm check:quickand focused vitest (replay-port, maestro, daemon sessions, CLI help/MCP, startup closure, closure budgets) passed.-M90%stat shows more because several moved files are 80–91% similar after the host rewrite.maestro-differentialare CI-authoritative.🤖 Generated with Claude Code