Follow-ups accepted as Minors by the #383 final whole-branch review + device pass (PR #398, merged 694a57d5; see workspace DECISIONS.md D1292/D1293, BUGS.md B230–B233, ROADMAP 2026-07-02). All small, none behavior-critical; batched to be picked up together.
- Behavioral park regression test.
runFlowParked's deviceId threading (fixed in 26a7bd87, B231) is guarded only by a source-text wiring assertion in gh-383-open-path-surfacing.test.js — but FlowParkOpts.stopFastRunner is a real DI seam. Replace/augment with a behavioral test: inject a capturing stopFastRunner, assert it receives opts.deviceId (survives reformatting).
runIOS mismatch hint parity. The iOS RUNNER_PROTOCOL_MISMATCH failResult from the postCommand v-check carries no hint; the Android twin does (runAndroid catch). Add the rebuild hint.
cdp_status runnerProtocol conflation. deviceSession.runnerProtocol.compatible = liveness === 'alive' conflates health-stale with protocol-incompatible: a wedged-but-current runner reports {expected, compatible:false} with no runner fields. Omit the block when staleReason === 'health', or add a reason field.
decideRunnerSpawn stale-legacy message. The "rn-fast-runner not started and not prebuilt" error is wrong when a stale/legacy runner IS running but no prebuilt artifact exists — say "incompatible runner detected, rebuild required" on that path.
- repair-path udid threading.
repair-action.ts:92 passes getActiveSession()?.deviceId to stopFastRunner rather than the repair-resolved udid — on the session-less smoke path this degrades to a no-op stop (narrow focus-fight window; self-heals).
TEST_RUNNER_ prefix for the port env (latent, behavior-changing — decide deliberately). B230 proved xcodebuild forwards only TEST_RUNNER_-prefixed vars, so RN_FAST_RUNNER_PORT has NEVER reached the Swift runner — RunnerEnv.resolvePort() always returns 0 and the runner binds an ephemeral port; the READY-line parser self-heals. Adding TEST_RUNNER_RN_FAST_RUNNER_PORT would make the documented fixed-port-22088 behavior real for the first time (stable ports for docs/foreign-flow detection) — but flips runners from ephemeral to fixed ports, so land it deliberately with the port-conflict path re-verified.
- Meta-helper duplication.
device-session.ts now imports attachMetaNote (agent-device-wrapper) while having its own wrapWithMeta — near-duplicate meta-merging helpers in one file; unify (they differ on isError/extra-content handling — pick one contract).
Refs. PR #398, final review + task-review Minors (plugin .superpowers/sdd/progress.md); workspace D1292/D1293, B230–B233.
🤖 Generated with Claude Code
Follow-ups accepted as Minors by the #383 final whole-branch review + device pass (PR #398, merged
694a57d5; see workspaceDECISIONS.mdD1292/D1293,BUGS.mdB230–B233, ROADMAP 2026-07-02). All small, none behavior-critical; batched to be picked up together.runFlowParked's deviceId threading (fixed in26a7bd87, B231) is guarded only by a source-text wiring assertion ingh-383-open-path-surfacing.test.js— butFlowParkOpts.stopFastRunneris a real DI seam. Replace/augment with a behavioral test: inject a capturingstopFastRunner, assert it receivesopts.deviceId(survives reformatting).runIOSmismatch hint parity. The iOSRUNNER_PROTOCOL_MISMATCHfailResult from the postCommand v-check carries nohint; the Android twin does (runAndroidcatch). Add the rebuild hint.cdp_statusrunnerProtocol conflation.deviceSession.runnerProtocol.compatible = liveness === 'alive'conflates health-stale with protocol-incompatible: a wedged-but-current runner reports{expected, compatible:false}with no runner fields. Omit the block whenstaleReason === 'health', or add areasonfield.decideRunnerSpawnstale-legacy message. The "rn-fast-runner not started and not prebuilt" error is wrong when a stale/legacy runner IS running but no prebuilt artifact exists — say "incompatible runner detected, rebuild required" on that path.repair-action.ts:92passesgetActiveSession()?.deviceIdtostopFastRunnerrather than the repair-resolved udid — on the session-less smoke path this degrades to a no-op stop (narrow focus-fight window; self-heals).TEST_RUNNER_prefix for the port env (latent, behavior-changing — decide deliberately). B230 proved xcodebuild forwards onlyTEST_RUNNER_-prefixed vars, soRN_FAST_RUNNER_PORThas NEVER reached the Swift runner —RunnerEnv.resolvePort()always returns 0 and the runner binds an ephemeral port; the READY-line parser self-heals. AddingTEST_RUNNER_RN_FAST_RUNNER_PORTwould make the documented fixed-port-22088 behavior real for the first time (stable ports for docs/foreign-flow detection) — but flips runners from ephemeral to fixed ports, so land it deliberately with the port-conflict path re-verified.device-session.tsnow importsattachMetaNote(agent-device-wrapper) while having its ownwrapWithMeta— near-duplicate meta-merging helpers in one file; unify (they differ on isError/extra-content handling — pick one contract).Refs. PR #398, final review + task-review Minors (plugin
.superpowers/sdd/progress.md); workspace D1292/D1293, B230–B233.🤖 Generated with Claude Code