Conversation
Use 127.0.0.1 for the Playwright baseURL/webServer so a foreign dev server bound to ::1:3000 cannot shadow the webpack server, allow 127.0.0.1 in the Supabase approved-domain check (app hard-crashed to a blank page on non-approved hosts), and make the navigation spec's URL assertion host-agnostic.
Qualified-operations arc: morning rounds, customer pass, planned-maintenance handover cycle, thermal trend judgment, rain-fade hold, frequency coordination, and the cascade-failure capstone. Adds TIDEMARK-3 to the satellite roster, registers all eight scenarios in both registries, and validates each with a Playwright full-completion spec. Key corrections made during validation: handovers stage the receiving station cold (the transfer swaps RF authority - dual illumination otherwise), HPA-before-BUC safety sequencing in S16, traffic-owner condition params, receiver IF tuning for ME-02, and S13 thermal/gain math consistent with the BUC model.
… Document engine support Crisis-operations opener: Solar Event (new 'sun-transit' weather type drives an RX-only sky-noise rise/peak/fall on the antenna - demod loss and self-recovery are real), Satellite Anomaly (scenario-local drifting TM-2 variant, step-track contingency), Train the New Hire (new Working Document panel accumulates the quick-reference card from documentLine quiz params), and Dual Outage (multi-site triage with an adversarial rule-out beat). All four validated with full-completion Playwright specs (88 tests); targeted 1-16 regression (S3/S9/S14) green after the engine extensions.
Crisis-operations conclusion: Hostile RF (new InterferenceManager injects a duty-cycled uplink jammer relayed through the transponder; jamming-vs- interference discrimination and the denial-vs-intrusion data-layer check), End-of-Life Planning (Working Document produces a board-level sunset report), Emergency Bypass (new ACU automation-fault flag forces verified manual ops), and the Constellation Crisis capstone (five concurrent tracks under single- operator incident command, Working Document as the incident log). Engine additions are additive and regression-clean (1-16 + S17-20 green): InterferenceManager, antenna isAcuAutomationFaulted gating, and the documentLine/workingDocument plumbing. All four validated with full-completion specs (batch-2 gate 77/77). Campaign plan marked fully Built.
SimulationManager's constructor started the game loop synchronously, which emits Events.UPDATE before getInstance() has assigned the singleton instance_. ObjectivesManager.evaluateCondition_ calls SimulationManager.getInstance() for every condition, so any objective evaluated during that first synchronous tick re-entered the constructor and recursed until 'Maximum call stack size exceeded'. Defer the first tick to requestAnimationFrame so the constructor returns and instance_ is assigned before any UPDATE fires.
The pre-game 'already complete?' check awaits a remote GET that retries failed fetches with exponential backoff (~7s total). Because it is awaited before the mission-control screen transitions, an unreachable or slow backend (offline, or a CORS-blocked dev origin) stalled the Start button for 5-8 seconds. Cap the check at 1.5s via Promise.race and proceed into the scenario on timeout - the worst case is replaying an already-complete scenario. The losing request is caught so it cannot surface as an unhandled rejection.
Passive verification conditions (beacon present, receiver locked, HPA enabled, GPSDO locked, etc.) were satisfied from ambient simulation state, so their checklist rows showed pre-ticked before the operator ever opened the relevant screen - teaching the wrong habit. Add an opt-in observation latch: - Condition param requiresObservation + observationTab: the condition does not count from ambient state alone; it latches satisfied only once the value is true WHILE the operator is viewing the observation tab, then stays checked. - Condition.hidden: a condition still enforced for completion but not rendered as a checklist row - used to require the correct tab on qualified-operator scenarios without spelling out which tab. Applied to Scenario 9 as the reference: every tab-active row hidden (9+ players are expected to know where to look) and each ambient value-condition gated on observation. The objective still completes the instant the operator opens the right tab. observed latches through checkpoint save/restore and resets when an objective is replayed.
Hide every tab-active checklist row on the qualified-operator scenarios (10-24) so the player is not handed which tab to open, and require observation (requiresObservation + observationTab) on the ambient value-conditions in the verify/check/baseline objectives - beacon present, receiver lock, C/N margin, HPA enabled, antenna lock, etc. These rows no longer pre-tick from scenario state; they latch only once the operator views the relevant screen. Gated: S10-S18 verify objectives (the rounds/baseline/anomaly checks where the values are true at activation). Action objectives (power-up, repoint, mode changes, backoff sets) are left alone - those values result from the operator's own action in the same step.
Apply requiresObservation to the ambient value-conditions in the Phase 1 verify/health-check objectives (GPSDO lock, LNB powered/stable/ref-locked, beacon present, receiver lock + C/N) so those rows no longer pre-tick from scenario state. Phase 1 keeps its tab-active rows VISIBLE - Charlie still walks new trainees to each tab - so only the value rows are gated, matched to the tab where each is actually observed (gps-timing / rx-analysis / dashboard). Power-up, acquire, and configure action objectives are left untouched.
Dependency ReviewThe following issues were found:
|
The sun-transit feature added WeatherManager.updateSunTransit_, which calls antenna.updateSkyNoiseDegradation(). The mock antenna lacked that method and the skyNoiseDegradation_dB state field, so 13 tests failed with TypeError. Add both to createMockAntenna so the mock matches the real Antenna interface.
The game loop moved from App into SimulationManager, which defers its first tick to requestAnimationFrame and is torn down by the router when it navigates to the campaign-selection page during init (Router.showPage -> SimulationManager.destroy). App.create() therefore no longer emits UPDATE/DRAW. Replace the stale assertion with a create() contract test (instantiation + window.signalRange + ROUTE_CHANGED) and a dedicated game-loop test that drives one tick on a live SimulationManager.
Use the @app/ alias for any import that reaches outside its own directory and keep ./ for same-directory siblings. Consolidate @engine/ usage outside the engine subtree into @app/engine/ so @app is the single internal alias. This removes the alias-vs-relative duplication footgun where the same module could be referenced two ways (e.g. ./events/event-bus vs @app/events/event-bus), which previously let App and SimulationManager disagree on the same import. 351 imports across 110 files; src/engine/ excluded.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request adds comprehensive end-to-end Playwright test suites for two new simulation scenarios ("Customer Pass" and "Thermal Anomaly") and improves the robustness of navigation tests by making URL matching host-agnostic. The new scenario test files automate realistic operator workflows, validating all objectives and mission completion for each scenario.
New scenario test automation:
scenario10-full-completion.spec.ts, a full test suite for Scenario 10 ("Customer Pass"), automating all mission objectives including antenna tracking mode changes and HPA backoff adjustments. This includes helper functions for scenario-specific actions and checks for mission completion.scenario13-full-completion.spec.ts, a full test suite for Scenario 13 ("Thermal Anomaly"), automating objectives such as BUC gain adjustment and trend analysis, with helper functions for BUC gain configuration and scenario workflow.Navigation test robustness:
navigation.spec.tsto accept bothlocalhostand127.0.0.1as valid hosts, making navigation tests less brittle and more environment-agnostic.## DescriptionTesting
npm test)npm run test:e2e)