feat(macos): W5 player-build launch handoff (#1322)#1430
Conversation
Additive Mac-side launch path that hands the active campaign off to the standalone Unity player build, mirroring AppProcessService's env-dict handoff idiom (RENDER-DELIVERY-DECISION.md: player launched BESIDE the app; renderer = pure consumer; input = existing POST /move kinds only). CONTRACT (env vars set on the launched player process): WORLDOS_ENGINE_BASE_URL engine/viewer origin the player consumes WORLDOS_CAMPAIGN_ID active campaign to render (omitted when none) Player .app located via the new 'playerAppPath' preference; blank falls back to ~/Applications then /Applications/WorldOSPlayer.app. No player installed -> .notConfigured no-op (today's behavior byte-identical). Launched via NSWorkspace.openApplication with createsNewApplicationInstance = false (idempotent relaunch) as an INDEPENDENT process, so player exit never touches the engine (no termination handler wired to viewer/provider). Zero new engine endpoints, zero new writers. XCTest run in CI (host lacks XCTest); swift build + qa/fast_gate.sh (257 passed) green locally.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 26 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
evaOS review status: closed or merged before reviewPR: #1430 - feat(macos): W5 player-build launch handoff (#1322) evaOS review stopped because the PR closed or merged before this queued head could be reviewed. Automation note: agents should wait for this comment to reach PR URL: #1430 Details: state=closed |
…guards, config env vars) (#1432) Adds BuildMacOSPlayer.cs (Tools/WorldOS/Build/macOS Player (Universal) MenuItem) that builds a Universal (x64+AppleSilicon) macOS standalone player from the current-best combat scene (M1CombatV1_canonical.unity), sets company/product/bundle id to worldos/WorldOSPlayer, and registers the scene in EditorBuildSettings (was empty). Guards 4 legacy editor-only scripts (AnimFrameCapture, IntegrationBuilder, TavernTier1Builder, SetupPainterlyScene) that referenced UnityEditor/[MenuItem] outside Assets/Editor/ with #if UNITY_EDITOR, so the player build compiles clean (0 errors). CombatSurfaceClient now resolves WORLDOS_ENGINE_BASE_URL / WORLDOS_CAMPAIGN_ID from the process environment before falling back to today's hardcoded defaults (byte-identical when absent), per the app-host launch contract (NSWorkspace configuration.environment, PR #1430). Build evidence (report, bundle listing, log tail, structural findings) in qa/evidence/1322-build/. Built + verified on the GEX44 box; .app delivered to the Mac out of band (not committed, binary). Co-authored-by: Eva <arncalso@gmail.com>
…urfaceClient live (#1435) - Commit WorldOS/OccluderDepth as a build-included .shader asset (was runtime ShaderUtil CreateShaderAsset -> stripped from the player build -> magenta occluder cubes). paint_combat_v1 prefers the committed shader (runtime fallback keeps the editor capture flow byte-identical). - CombatSurfaceClient: resolve actors by Actor_<token.id> registry naming (was stale HeroFighter/ MonsterGoblin lookups); cell<->world mirrors paint_combat_v1 (grid from surface, cell 2.0, row-flip); click -> POST /move with the existing kinds only (move_to_cell / on-turn attack), payloads byte-exact to qa/drive_gfx_combat.py. Attached to M1CombatV1_canonical via the W5bWireScene migration MenuItem. - Evidence in qa/evidence/1433/ (build report + shader-inclusion log + before-magenta smoke frame). Refs #1322, PR #1430, PR #1432. Co-authored-by: Eva <arncalso@gmail.com>
What
Additive Mac-side launch path that hands the active campaign off to the standalone Unity player build, mirroring
AppProcessService's existing env-dict handoff idiom. Formalizesdocs/roadmap/RENDER-DELIVERY-DECISION.md: the player is launched beside the app; renderer = pure consumer; input = the existingPOST /movekinds only. Part 2 of W5a (issue #1322).The GEX44 box build lane delivers
WorldOSPlayer.appin parallel — this PR is built against the documented contract below and a faked.app(injectedfileExists) so it lands independent of that artifact.THE CONTRACT (so the build lane aligns)
The app hands the campaign off via environment variables set on the launched player process (the same mechanism
AppProcessService.launchManagedProcessalready uses to hand campaign id + roots to the viewer/provider). The player reads these at startup (System.Environment.GetEnvironmentVariable(...)):WORLDOS_ENGINE_BASE_URL/combat-surface,/events,POST /move(e.g.http://127.0.0.1:8765)WORLDOS_CAMPAIGN_IDAbsent → the player shows its own idle / no-campaign state. It NEVER writes engine state and defines NO new endpoint.
Player
.applocation: new additiveplayerAppPathpreference. Blank → default~/Applications/WorldOSPlayer.app, then/Applications/WorldOSPlayer.app. None present →.notConfiguredno-op (today's behavior byte-identical).Launch mechanism:
NSWorkspace.openApplication(at:configuration:)withconfiguration.environmentcarrying the contract andcreatesNewApplicationInstance = false→ idempotent relaunch (an already-running player is activated, not duplicated). The player is an independent LaunchServices process; no termination handler is wired to the viewer/provider, so player exit never touches the engine.Chose env vars over a plist/config-file beside the
.app: mirrors the existing bridge idiom, writes nothing to disk (no stale-config hazard / no cleanup / no reconcile-on-relaunch), and keeps the pure-consumer invariant crisp.Invariants
maintoday.Tests
PlayerLauncherTests(XCTest, hermetic — mocks.apppresence + captures the launch invocation/env payload): contract env payload, default-path fallback, configured-over-default, campaign omission, byte-identity.notConfiguredno-op, single-invocation seam, idempotent relaunch.swift buildwarning-clean;qa/fast_gate.sh= 257 passed (engine byte-identical — zero Python touched).macOS SwiftCI job (this dev host is CommandLineTools-only, no XCTest — documented in the workflow).Merge
Auto-merge armed; not merging here. Admin-merge per #1389 once
macOS SwiftCI (build + XCTest) is green.Closes part 2 of #1322.