fix(core): correct the dev-client login path refusals and auth-route matching - #997
fix(core): correct the dev-client login path refusals and auth-route matching#997Lykhoyda wants to merge 12 commits into
Conversation
Four independent defects one QA journey walked through in sequence, plus the captain-approved pre-mutation clearState refusal (Option A). None of them changes which authority axes are probed, when, or what proves them; the runner pin, exact-pin refusal, engine-pin refusal and regex fence are unchanged. 1. worktree-inheritance: the LINK_FOREIGN remediation now depends on the regime. With no primary corpus it names the single accepted target (<primary worktree>/.rn-agent/actions), says it does not exist, and lists the two supported shapes; with a primary corpus it names the target it can be re-pointed to. classifyDestination, the allowlist and resolveReadableActionCorpus are untouched. 2. auto-login: isOnAuthScreen compares the whole route chain root->leaf (routeName and params.screen at each level) instead of the leaf only, so `__root > auth > intro` is an auth screen without adding any app-specific name; the negative reason carries the observed chain. 3. action-engine-compat: the regex-selector fence is evaluated before the enginePin header refusal, so an unpinned regex action gets its terminal reason instead of being sent to migrate-actions, which refuses it; the header refusal now says what an `incompatible` migration result means. 4. maestro-run: a METRO_ORIGIN_MISMATCH raised after a flow-owned launchApp relaunch is attributed to that relaunch (message + meta.flowRelaunch); the SessionAuthorityError instance, code, axis, and the GH #708 abort-vs-defer control flow are unchanged. 5. run-action (Option A): on a managed dev-client session (install binding buildKind expo or devClientUrl) a flow containing clearState is refused with DEV_CLIENT_CLEARSTATE_REFUSED before any runner call, origin claim or park. cdp_login_prologue inherits it. Bare React Native sessions and unmanaged replay keep GH #705 behaviour. 6. creating-actions skill + rn-agent README: single accepted inheritance target; dev-client login actions must be warm with id/literal selectors. Each defect has a test that fails on the previous dist and passes now: gh-993-auth-route-chain, gh-993-dev-client-clearstate-refusal (zero runner invocations, unchanged sidecar), gh-708-mid-flow-relaunch (D2.b/D2.e), action-engine-compat (unpinned regex ordering), worktree-inheritance (S1/S2).
…stall-binding read GH #993 reads the install binding for every clearState flow to decide the dev-client refusal, so the GH #705 test now pins the invariant it guards — explicit appFile wins and auto-resolution never runs — and the new suite pins that an explicit appFile does not bypass DEV_CLIENT_CLEARSTATE_REFUSED.
…ttribution owners
…ms.screen, WRONG_TYPE wording
…learState refusal ahead of preflight
…aunch attribution
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
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. |
QA Report — PR #997 / GH #993Date: 2026-09-09 ConflictsResolved against VerdictPass — merge as-is for GH #993. All four independent defects hold on the product path. No foreign-corpus allow path. Nested What was tested
Live evidence (quoted)LINK_FOREIGN, primary has no corpus: LINK_FOREIGN, primary owns a corpus: clearState Option A (managed Expo receipt): Regex before migrate-actions: Auth-route chain (live, this app’s tree — not the reported
Out of scope / environment
Residual riskLow. Axis A/B probing, CleanupTemp probe YAML deleted. |
Intent
Captain (2026-09-07): "take next" on the architect -> dev -> QA workflow, then on the one open policy question: "A".
Substance of what those refer to. Two user-filed issues describe a login path that does not work:
An architect stage investigated both and its accepted report's verdict: these are FOUR INDEPENDENT defects that one QA journey happened to walk through in sequence, not a chain; only the LINK_FOREIGN one is pooled-worktree specific; and issue 990 overlaps issue 993 on exactly two of them, so both issues are one piece of work. The report's implementation plan, which the captain's "take next" dispatches, is: (1) in the linked-worktree inheritance planner, make the LINK_FOREIGN remediation depend on the regime — when the primary worktree has no corpus, say the only accepted target is the primary worktree's .rn-agent/actions, that it does not exist, and that the supported shapes are a real actions directory in this worktree or creating the corpus in the primary; when the primary has a corpus, keep the re-point wording but name the target — without changing the destination classifier, the allowlist, or the single corpus resolver; (2) in cdp_auto_login, replace leaf-only route matching with a walk over the nested route chain root-to-leaf (routeName at each level and params.screen where present), matching if any level matches the existing auth patterns, without adding "intro" or any app-specific name to the patterns, and make the negative reason carry the observed route chain; (3) in the replay compatibility preflight, evaluate the regex-selector fence before the enginePin header refusal (runtime pin still first) so an unpinned regex action gets the terminal reason instead of being told to run migrate-actions, which would refuse it; (4) when a flow contains a launchApp stage and the subsequent origin claim or completion fails with METRO_ORIGIN_MISMATCH, annotate the failure so the result names the flow's own launchApp (with clearState if present) relaunch as the cause and points to device_reset_state and the EG_DEV_CLIENT_CLEARSTATE rule, keeping the original code and axis — message and metadata only, no change to the probe, its order, or its result; (5) the pre-mutation clearState refusal decided below; (6) host-neutral skills and the rn-agent template README state the single accepted inheritance target and that login learned actions on a dev client must be warm (start attached, no relaunch) and use id or literal selectors. The report's boundary: no change to axis A or B probing, claimOrigin, relaunchSessionRuntime, connectExactSessionTarget, pinExactDevClient, or tool profiles; no relaxation of the runner pin, the exact-pin refusal, the engine-pin refusal, or the GH #750 regex fence; no foreign-corpus allow path, confirmation flag, or second corpus resolver; no app-specific names in the auth route patterns; no product-shipped login flow for any specific app; the project-side corpus rewrite belongs to the app's own lane, not to rn-dev-agent; the issue 990 secondary findings (one-launch-per-Metro bundle binding, native logs gated on axis B, cdp_connect relaunches, fingerprint cache persistence, the dev-client picker RECENTLY OPENED row, device_screenshot default path, the postflight envelope hint, any readiness-timeout change) are deliberately omitted. Ship as one PR, core source only, with a changeset bumping rn-dev-agent-plugin and rn-dev-agent-core; each of the four defects gets a test that fails on the current code and passes after the change.
The captain's answer "A" settles the one question the report escalated: managed dev-client replay through cdp_run_action and cdp_login_prologue must REFUSE flows containing clearState true BEFORE executing anything, fail-closed and side-effect-free, matching the position cdp_auto_login already takes. The captain accepted the stated consequence: flows that currently limp through will fail outright instead.
What Changed
cdp_run_action(andcdp_login_prologuethrough it) now refuses a flow containingclearStateon a managed dev-client session with the newDEV_CLIENT_CLEARSTATE_REFUSEDcode, before the compat preflight and before any runner call, origin claim, or park; the refusal reads the signedbuildKind === 'expo'install binding and decides on parsed commands via a singlecontainsClearStatepredicate now shared withcdp_auto_login. The replay compat preflight also evaluates the regex-selector fence ahead of theenginePinheader refusal, so an unpinned regex action gets the terminal reason instead of being pointed atmigrate-actions.cdp_auto_loginwalks the nested route chain root-to-leaf (routeNameper level plusparams.screenon unmounted navigators) instead of matching only the leaf, treating a level with a mounted child as a container that must match a whole pattern, and the negative reason now carries the observed chain.maestro_runtracks flow-ownedlaunchApprelaunches at runtime across partitioned iOS segments and the deferred completion; when aMETRO_ORIGIN_MISMATCHfollows an unclaimed relaunch, the error is re-issued with the same code, holder, and axis plus a cause message,details.nextAction, andmeta.flowRelaunch. Linked-worktreeLINK_FOREIGNremediation now names the single accepted target and whether it is missing or not a directory, and the skills, rn-agent template README,AGENTS.md, and docs site record the warm-login and dev-client constraints; a changeset patchesrn-dev-agent-coreandrn-dev-agent-plugin, with regression tests per defect.Risk Assessment
✅ Low: All six intent items are implemented within the stated boundary with behavioral (not source-grepping) regression tests, the new refusal is fail-closed and pre-mutation, the relaunch attribution only decorates error messages while preserving code/holder/details/meta and never alters control flow, and the only surviving findings are an unavoidable consequence of a decision the user already made plus one dead export.
Testing
I ran the seven targeted test files covering the four defects plus the clearState refusal and the GH #705/auto-login neighbours (149/149 green), and proved they are genuine regressions by rebuilding from the base source, where five of them fail. Beyond unit tests I captured the actual end-user surfaces: the
worktree-inheritance planCLI output in all three source regimes, thecdp_auto_loginresult for the exact nav state reported in issue #993, thecdp_run_actionandcdp_login_prologueJSON envelopes (with runner/origin-claim/relaunch counters proving the dev-client clearState refusal is side-effect-free), and themaestro_runMETRO_ORIGIN_MISMATCH message and metadata after a flow-ownedlaunchApp. The same script run against the base build gives a line-by-line before/after diff of that operator-visible text. This change ships no rendered UI — the product surface is an MCP tool envelope and a CLI — so the evidence is CLI transcripts and JSON envelopes rather than screenshots. The doc-only part of the intent (skills / rn-agent template README wording) is not independently exercisable and was not separately tested. One incidental issue: five unrelatedmigrateLearnedActionstests fail on a default macOS TMPDIR because their fixtures do not realpath the temp root; setting TMPDIR to its realpath makes the whole file pass. Worktree left clean; all evidence written to the run's evidence directory.Evidence: Before/after summary of the five user-visible surfaces
Evidence: Branch build: product transcript of all five surfaces
Evidence: Base build: same script, same fixtures (the reported failures)
~/.no-mistakes/evidence/01M1YNGNSR3E9QZVV2BR8JXYZG/defect-surfaces.mjs)Evidence: Key before → after deltas
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
packages/rn-dev-agent-core/src/tools/run-action.ts:166-flowCommandsClearStateonly matches the bare string command'clearState'or a nested key whose value is exactlytrue, so the documented Maestro spelling- clearState: <appId>slips through the new fail-closed refusal. Concrete path: an action containing- launchApp: {stopApp: false}/- clearState: com.test.appparses cleanly (clearStateis in ALLOWED_COMMANDS at maestro-validator.ts:107, andvalidateValueaccepts the scalar), sopreflightCommandsholds{clearState: 'com.test.app'};optionsClearStatesees keyclearStatebutnested !== true, then recurses into the string and returns false. On abuildKind: 'expo'session the refusal at run-action.ts:719 does not fire, the flow runs, the dev client's stored Metro URL is wiped, and the caller gets the METRO_ORIGIN_MISMATCH that Option A exists to prevent — the exact bug: no working login path on a pooled worktree - corpus LINK_FOREIGN, prologue tears down axis A, auto-login misreads auth route, warm action engine-incompatible #993 symptom, fail-open.cdp_auto_login's pre-existingcontainsClearState(auto-login.ts:172) already catches this spelling, so the two owners now disagree, and AGENTS.md claims the refusal covers "a bareclearState". Smallest remedy inside the existing helper: treat a command-rootclearStatekey with any value as clearing state, while keeping the nested=== truerule solaunchApp: {clearState: false}stays allowed..changeset/login-path-corrections.md:6- The changeset body is four sentences covering all four defects. The standing convention for changesets is a single-sentence summary, because the body is published verbatim into the package CHANGELOG for external consumers; the per-defect detail belongs in the PR description. Recommend collapsing to one sentence (e.g. the dev-client clearState refusal plus the relaunch attribution) and moving the rest to the PR body. Flagged as ask-user because it is the author's published release note, not a mechanical defect.🔧 Fix: dedupe clearState predicate, close appId-spelling bypass
2 warnings still open:
packages/rn-dev-agent-core/src/domain/maestro-validator.ts:141-containsClearStatematches an object key namedclearStateregardless of its value, so- launchApp:\n clearState: false— a valid, explicit Maestro spelling that clears nothing — is treated as a clearState flow. Concrete path: on anEXPO_INSTALLdev-client session,run-action.ts:703seescontainsClearState(preflightCommands) === trueand returnsDEV_CLIENT_CLEARSTATE_REFUSEDwith a message asserting "The clearState relaunch uninstalls the app and strands the dev client at its picker", which is false for that flow; the action becomes unreplayable until the author deletes a key that was already safe. The same PR uses two narrower spellings of the same concept —flowRelaunchFactsrequireslaunch.clearState === true(maestro-run.ts:307) and the GH bug: launchApp clearState reinstall breaks strict install identity - every corpus auth flow unrunnable #705 helper requires/clearState:\s*true\b/(resolve-ios-app-file.ts:14) — so the three owners now disagree onclearState: false. This is a side effect of the round-1 instruction to widen the predicate to catch- clearState: <appId>; that widening is still needed for the bare-command spelling. Narrower form that keeps the appId fix:key === 'clearState' && nested !== false. Flagged ask-user because the broad form was the author's explicit instruction and because narrowing it also relaxescdp_auto_login, which shares the predicate.packages/rn-dev-agent-core/src/tools/run-action.ts:150- Simplification:isDevClientLaunchShapeaccepts two spellings of "this is a dev client" —buildKind === 'expo'andtypeof devClientUrl === 'string'. The intent requires the refusal for "managed dev-client replay"; every Expo dev-client session carriesbuildKind: 'expo'(set at prepare-build, rn-session.ts:787/860, and preserved byreissueInstallBinding), so the first spelling alone satisfies the requirement. The second widens the refusal to abare-react-nativesession that merely declared adevClientUrl(the session schema accepts one independently, index.ts:1467) — a case no intent requirement names, and the only case thedevClientUrlbranch adds. It is fail-closed, so the risk is a false refusal rather than a bypass. Recommended remedy is removing thedevClientUrldisjunct and keeping the exactbuildKind === 'expo'test (and dropping the corresponding assertion in bug: no working login path on a pooled worktree - corpus LINK_FOREIGN, prologue tears down axis A, auto-login misreads auth route, warm action engine-incompatible #993-dev-client-clearstate-refusal.test.ts), not hardening it.🔧 Fix: narrow clearState predicate and dev-client launch shape
2 infos still open:
packages/rn-dev-agent-core/src/domain/maestro-validator.ts:138-containsClearStatereturns true for the bare string'clearState'in ANY position, not just as a command. Because the walk recurses into every object value,- tapOn:\n id: "clearState"reachescontainsClearState('clearState')via theidvalue and matches. Concrete path: on anEXPO_INSTALLdev-client session, a learned action that taps a debug element whose testID is literallyclearStatehitsrun-action.ts:702and returnsDEV_CLIENT_CLEARSTATE_REFUSEDwith a message asserting "The clearState relaunch uninstalls the app and strands the dev client at its picker" — for a flow that contains no clearState command at all, and the action becomes unreplayable. This is the third over-match found in the same predicate (afterclearState: <appId>andclearState: false); the string branch exists only to catch the bare- clearStatecommand form, which the validator does accept (ALLOWED_COMMANDS,maestro-validator.ts:180) and which always appears as an ARRAY element. Narrower form that keeps every currently-required match: test=== 'clearState'only for array elements (value.some((c) => c === 'clearState' || containsClearState(c))) and drop the top-level string check. Flagged ask-user because the predicate is shared withcdp_auto_login, so narrowing it also relaxes that tool's legacy.maestro/refusal — the same coupling the author decided on explicitly in the previous round.packages/rn-dev-agent-core/src/tools/run-action.ts:125-RunActionInstallReceipt.devClientUrlis declared and documented ("Present when the managed launch opens the app through a dev-client URL") but never read anywhere in the file — it is leftover from thetypeof devClientUrl === 'string'disjunct that the previous fix round removed fromisDevClientLaunchShape(now exactlybuildKind === 'expo'). Structural typing means no call site depends on it either. Dead declaration; remove the field and its comment. (platform,deviceId,appId,buildKindare all genuinely read.)🔧 Fix: make clearState match positional, drop dead receipt field
2 infos still open:
packages/rn-dev-agent-core/src/tools/auto-login.ts:126-isAuthRouteChainmatches AUTH_ROUTE_PATTERNS against every level of the chain, and the same predicate is reused as the post-login exit condition at auto-login.ts:373 (stillOnAuth = await isOnAuthScreen(client)). Because the patterns are substring matches, an ancestor navigator whose name merely contains one (e.g. anAuthenticated/AuthenticatedStackroot that stays mounted after login) now makes a logged-in app read as on-auth at both ends:handleAutoLoginproceeds to replay the login flow, and after a successful replay the 5s loop reportsloggedIn: false, "still on an auth screen". Before the change only the leaf was compared, so an ancestor name could not do this. Both outcomes fail loudly (the login flow's assertVisible steps fail; the verification returns a failure), so nothing is silently wrong. Flagged only because the intent mandates the widening — "matching if any level matches the existing auth patterns" and "no app-specific names in the auth route patterns" — so narrowing (e.g. keeping the leaf-only test for the post-replay exit check, or requiring an exact pattern match rather than substring) is the author's product call, not a repair. No change required if the author accepts the tradeoff.packages/rn-dev-agent-core/src/tools/maestro-run.ts:296-flowRelaunchFacts(line 296),relaunchesApp(line 320) andattributeOriginFailureToFlowRelaunch(line 365) are exported but consumed only inside maestro-run.ts — no other src module and no test imports them (tests importcreateFlowRelaunchTrackerandFLOW_RELAUNCH_NEXT_ACTIONonly). They widen the module's public surface with no requirement. Drop theexporton those three functions.FlowRelaunchFactsandFlowRelaunchTrackermust stay exported (they appear in the exportedcreateFlowRelaunchTrackerreturn type andMaestroRunArgs.flowRelaunches).🔧 Fix: match auth ancestors exactly, unexport relaunch helpers
2 warnings still open:
packages/rn-dev-agent-core/src/tools/auto-login.ts:105- Appendingparams.screento the chain (line 91) moves the routeName that carried it out of the leaf position, whereisAuthRouteChain(line 105) then applies exact-segment matching instead of substring matching. Concrete state, exactly the windowparams.screenexists to serve (a nested navigator that has not yet mounted its child, sonestedis absent):{routeName:'AuthStack', params:{screen:'Intro'}}-> chain['AuthStack','Intro']-> leafintromatches nothing, ancestorauthstackis not exactly any AUTH_ROUTE_PATTERN -> isAuthRouteChain false. Before this branch,getDeepestRouteNamereturnedAuthStackandmatchesAuthPatternsubstring-matchedauth-> true. Same foronboardingStack/loginStack/SignUpStack+params.screen. handleAutoLogin then returns{loggedIn:false, reason:'App is not on an auth screen (route: AuthStack › Intro)'}, whichautoLoginToolResult(line 401) wraps in okResult, so the caller proceeds as if no login were needed while the app sits on the login screen - a wrong result with no error, in the exact defect (2) this change fixes. This is a false negative, materially different from theAuthenticatedfalse positive settled in the previous round, and the exact-ancestor rule itself is the recorded decision, so the narrowing is the author's call: substring-match the deepest observedrouteNameand anyparams.screenappended after it (leaf-equivalent), reserving exact matching for levels that have a mounted child below them. Empty chain and the__root › auth › introcase stay as they are.packages/rn-dev-agent-core/src/tools/maestro-run.ts:476- Simplification:throw relaunches.attribute(error)in therelaunchManagedAppcatch is a third attribution site beyond the intent, which scopes the annotation to 'the subsequent origin claim or completion fails with METRO_ORIGIN_MISMATCH' - the claim site (line 460) and the completion site (line 498) already satisfy that. It is also unreachable through the wired gate: the real 'relaunched but did not re-register' failure comes out ofconnectExactSessionTarget(src/session/connect-exact-session-target.ts:221-465) as a plainError, whichattributeleaves untouched and which the GH bug: maestro_run aborts a passing flow at mid-flow launchApp - re-register check kills relaunch-in-flow patterns #708 deferral path already owns; andauthority.relaunch(src/session/authority-gate.ts:2007-2024) raises a METRO_ORIGIN_MISMATCH SessionAuthorityError only whendependencies.relaunchBoundRuntimeis unwired, which production wires at src/index.ts:626 (the runtime's own unavailable codes are AUTHORITY_STORE_UNAVAILABLE / SESSION_NOT_INITIALIZED / SESSION_OWNER_LOST, never METRO_ORIGIN_MISMATCH). Were it reachable, it would assert a runtime fact that did not happen - 'relaunched the app and it did not re-register on the authority-bound Metro' for a relaunch the gate refused before performing - and would replace the correct axis-repair nextAction. Remedy is removal, not hardening: restorethrow errorat that catch and keep attribution on the claim and completion sites only. TestGH#993 D2.ein test/unit/bug: maestro_run aborts a passing flow at mid-flow launchApp - re-register check kills relaunch-in-flow patterns #708-mid-flow-relaunch.test.ts asserts this branch and would need to drop the attribution assertion (its GH bug: maestro_run aborts a passing flow at mid-flow launchApp - re-register check kills relaunch-in-flow patterns #708 abort-semantics assertions stand).🔧 Fix: judge unmounted navigators as screens, drop relaunch attribution
2 infos still open:
packages/rn-dev-agent-core/src/tools/auto-login.ts:115- Accepted tradeoff, no action needed. The round-5 rule judges any level with no mounted child by substring (matchesAuthPattern), so{routeName:'AuthenticatedStack', params:{screen:'Home'}}with nonested(the window right after login, before the authenticated navigator's state lands on the parent route) matchesauthand reads as on-auth; under the round-4 rule that state was an ancestor and read false. This is not fixable in a narrower form: the recorded decision requires{routeName:'AuthStack', params:{screen:'Intro'}}to be on-auth, andAuthStack/AuthenticatedStackare indistinguishable under substring matching, so any rule satisfying the required case admits this one. The mounted-child cases the decision enumerated (AuthenticatedStack › Home,Root(params.screen=Login) › Home) are correctly false, and the reported__root › auth › introis correctly true. Recording it so the boundary is explicit rather than rediscovered later.packages/rn-dev-agent-core/src/tools/run-action.ts:150-DEV_CLIENT_CLEARSTATE_REFUSALis exported but consumed only at its single call site inside run-action.ts (line 701) — no other src module and no test imports it (the refusal tests assert on the returned envelope'serrortext via regex, and import onlyisDevClientLaunchShape). It widens the module's public surface with no requirement, the same class of finding the round-4 fix applied toflowRelaunchFacts/relaunchesApp/attributeOriginFailureToFlowRelaunchin maestro-run.ts. Drop theexportkeyword; keepRunActionInstallReceiptandisDevClientLaunchShapeexported (the former appears in the exportedRunActionDeps.installReceiptreturn type, the latter is exercised directly by a test).packages/rn-dev-agent-core/test/unit/action-engine-compat.test.ts:564- Pre-existing, unrelated to this change: fivemigrateLearnedActionstests in packages/rn-dev-agent-core/test/unit/action-engine-compat.test.ts fail on a default macOS TMPDIR because their fixtures usemkdtempSync(join(tmpdir(), ...))while the corpus guards comparerealpathSyncpaths (/var/folders/...vs/private/var/folders/...). They pass with TMPDIR set to the realpath. Wrapping the fixture roots inrealpathSync(...), as the worktree-inheritance fixtures already do, would remove the host dependency.node --test test/unit/gh-993-auth-route-chain.test.ts test/unit/gh-993-dev-client-clearstate-refusal.test.ts test/unit/gh-708-mid-flow-relaunch.test.ts test/unit/action-engine-compat.test.ts test/unit/session/worktree-inheritance.test.ts test/unit/gh-705-clearstate-appfile-forwarding.test.ts test/unit/auto-login-authority.test.ts— 149/149 pass on the branch buildFail-before check:git checkout 7f33f73b -- packages/rn-dev-agent-core/src && corepack yarn build:core, then the same defect tests — 5 fail (GH#993: LINK_FOREIGN remediation names the accepted target per regime,GH#993: unpinned regex action gets the terminal regex refusal, not the migrate remedy, plus gh-993-auth-route-chain / gh-993-dev-client-clearstate-refusal / gh-708-mid-flow-relaunch failing wholesale on the not-yet-existing exports); source restored and rebuilt, worktree left cleanManual product transcriptnode defect-surfaces.mjsrun against both the base and branch builds, driving the realdist/worktree-inheritance.js planCLI as a subprocess over a git-worktree fixture in all three source regimes (D1);handleAutoLogin/isOnAuthScreenover the exact__root › auth › intronav state from issue #993, an unmountedAuthStack + params.screen, and a logged-inAuthenticatedStack › Home(D2);cdp_run_actionon an unpinned regex warm-login action (D3);executeMaestroAuthorityStages+authorityErrorMetafor a METRO_ORIGIN_MISMATCH after a flow-ownedlaunchApp {clearState:true}and after a warmlaunchApp {stopApp:false}(D4);cdp_run_actionandcdp_login_prologueenvelopes plus runner/claim/relaunch side-effect counters for a clearState flow on a dev-client session, the same flow on a bare React Native session, and a warm action on the dev client (D5)corepack yarn build:core— rebuilt dist from HEAD source before and after the fail-before experiment✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.