rename to core

This commit is contained in:
2025-12-15 13:46:07 +01:00
parent aedf58643d
commit 5c22f8820c
559 changed files with 415 additions and 767 deletions

View File

@@ -38,10 +38,10 @@ Everything else from the concept docs (league/season management, result aggregat
- React renderer: [`App`](apps/companion/renderer/App.tsx), UI components under [`components`](apps/companion/renderer/components).
- Automation & browser integration:
- Domain models around hosted sessions and steps, e.g. [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1), [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1).
- Application layer ports and use-cases, e.g. [`IAutomationEngine`](packages/application/ports/IAutomationEngine.ts:1), [`ISessionRepository`](packages/application/ports/ISessionRepository.ts:1), [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1).
- Playwright-based automation adapter and helpers, e.g. [`PlaywrightAutomationAdapter`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1), [`CheckoutPriceExtractor`](packages/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1).
- Logging, config and in-memory repository implementations, e.g. [`InMemorySessionRepository`](packages/infrastructure/repositories/InMemorySessionRepository.ts:1), [`AutomationConfig`](packages/infrastructure/config/AutomationConfig.ts:1), [`LoggingConfig`](packages/infrastructure/config/LoggingConfig.ts:1), [`PinoLogAdapter`](packages/infrastructure/adapters/logging/PinoLogAdapter.ts:1).
- Domain models around hosted sessions and steps, e.g. [`AutomationSession`](core/domain/entities/AutomationSession.ts:1), [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1).
- Application layer ports and use-cases, e.g. [`IAutomationEngine`](core/application/ports/IAutomationEngine.ts:1), [`ISessionRepository`](core/application/ports/ISessionRepository.ts:1), [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1).
- Playwright-based automation adapter and helpers, e.g. [`PlaywrightAutomationAdapter`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1), [`CheckoutPriceExtractor`](core/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1).
- Logging, config and in-memory repository implementations, e.g. [`InMemorySessionRepository`](core/infrastructure/repositories/InMemorySessionRepository.ts:1), [`AutomationConfig`](core/infrastructure/config/AutomationConfig.ts:1), [`LoggingConfig`](core/infrastructure/config/LoggingConfig.ts:1), [`PinoLogAdapter`](core/infrastructure/adapters/logging/PinoLogAdapter.ts:1).
- Testing:
- Unit tests for domain, application and infrastructure.
@@ -162,14 +162,14 @@ The website under [`apps/website`](apps/website:1) is the primary presentation s
- Read standings, stats snapshots and rating values.
- Submit registrations, complaints and admin actions.
- Trigger or schedule result imports and (where allowed) automation runs.
- These APIs are implemented by the platform application layer and are conceptually separate from the automation-specific ports in `packages/application`.
- These APIs are implemented by the platform application layer and are conceptually separate from the automation-specific ports in `core/application`.
### 2.4 Platform Integration with Automation
The web platform uses the automation & companion subsystem as a hosted-session engine, without coupling to Playwright or Electron details:
- **From league/season data to automation intent**
- The platform aggregates league configuration (series settings, car/track choices, schedule, server settings) and derives a hosted-session configuration structure conceptually equivalent to [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1).
- The platform aggregates league configuration (series settings, car/track choices, schedule, server settings) and derives a hosted-session configuration structure conceptually equivalent to [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1).
- This configuration captures the intent of a single hosted session (or a batch of sessions across a season) in a platform-neutral format.
- **Hand-off to automation**
@@ -207,9 +207,9 @@ This section describes how the automation engine and companion in this repo sit
- **Automation Engine & Domain (this repo)**
- Clean Architecture core for iRacing hosted-session automation:
- Domain and value objects under [`packages/domain`](packages/domain/entities/AutomationSession.ts:1).
- Application use-cases and ports under [`packages/application`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1).
- Infrastructure adapters under [`packages/infrastructure`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1).
- Domain and value objects under [`core/domain`](core/domain/entities/AutomationSession.ts:1).
- Application use-cases and ports under [`core/application`](core/application/use-cases/StartAutomationSessionUseCase.ts:1).
- Infrastructure adapters under [`core/infrastructure`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1).
- Exposes automation capabilities via application ports that can be used both by the companion and by external orchestrators.
- **iRacing Web (members.iracing.com)**
@@ -228,7 +228,7 @@ This section describes how the automation engine and companion in this repo sit
- Shared concept space:
- Both surfaces operate on the competition concepts described in [`CONCEPT.md`](docs/concept/CONCEPT.md), [`ADMINS.md`](docs/concept/ADMINS.md), [`DRIVERS.md`](docs/concept/DRIVERS.md), [`COMPETITION.md`](docs/concept/COMPETITION.md), [`RACING.md`](docs/concept/RACING.md), [`SOCIAL.md`](docs/concept/SOCIAL.md), [`TEAMS.md`](docs/concept/TEAMS.md).
- The automation engine uses [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) as the canonical representation of a hosted-session setup derived from those higher-level concepts.
- The automation engine uses [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) as the canonical representation of a hosted-session setup derived from those higher-level concepts.
- Division of responsibilities:
- The **website** is the primary UI for league management, discovery, stats and rating (core platform concerns).
@@ -245,7 +245,7 @@ At a high level, communication flows are designed around the automation engine a
- Companion App → Application Use-cases → Automation Engine → Playwright Adapter → iRacing Web.
- Hand-off of automation intent:
- Core platform services or the web app can derive a [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) from league data and store it server-side.
- Core platform services or the web app can derive a [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) from league data and store it server-side.
- The companion app or a headless orchestrator retrieves these configs via platform APIs and invokes the automation engine using the same application ports used in this repo.
### 2.4 System context diagram
@@ -300,7 +300,7 @@ The automation strategy is shaped by iRacings platform boundaries and Terms o
- Hooking the sim process or game memory.
- Running any automation that is not clearly aligned with “browser automation of a public web UI”.
The [`PlaywrightAutomationAdapter`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) contains additional safeguards, such as:
The [`PlaywrightAutomationAdapter`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) contains additional safeguards, such as:
- Guardrails around checkout/payment-like buttons using iRacing-specific selector maps.
- Explicit “blocked selector” detection before clicks.
@@ -336,7 +336,7 @@ Inner layers:
**Layer responsibilities**
- **Domain**
- Competition-neutral automation concepts such as [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1), [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1), session and step invariants and validators.
- Competition-neutral automation concepts such as [`AutomationSession`](core/domain/entities/AutomationSession.ts:1), [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1), session and step invariants and validators.
- Independent of Electron, Playwright, HTTP or persistence.
- **Application**
@@ -354,9 +354,9 @@ Inner layers:
**Key rules in this repo**
- `packages/domain/*` has no dependencies on application, infrastructure, or Electron.
- `packages/application/*` depends only on `packages/domain/*` (plus shared types).
- `packages/infrastructure/*` depends on domain and application ports, and on external libraries (Playwright, Pino, etc.).
- `core/domain/*` has no dependencies on application, infrastructure, or Electron.
- `core/application/*` depends only on `core/domain/*` (plus shared types).
- `core/infrastructure/*` depends on domain and application ports, and on external libraries (Playwright, Pino, etc.).
- `apps/companion/*` depends on inner layers and glues application use-cases to Electron UI and IPC.
This keeps the **automation engine** stable and reusable across presentation surfaces (companion today, web or backend orchestrators later), while allowing infrastructure and UI details to evolve without rewriting business logic.
@@ -365,19 +365,19 @@ This keeps the **automation engine** stable and reusable across presentation sur
## 4. Layer-by-Layer Mapping
### 4.1 Domain Layer (`packages/domain/*`)
### 4.1 Domain Layer (`core/domain/*`)
The domain models what an “automation session” is, how it progresses, and which invariants must hold regardless of UI or tooling.
**Core entities**
- [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1)
- [`AutomationSession`](core/domain/entities/AutomationSession.ts:1)
- Represents a single hosted-session automation run.
- Tracks:
- `id`
- `currentStep` (wizard step, via [`StepId`](packages/domain/value-objects/StepId.ts:1))
- `state` (via [`SessionState`](packages/domain/value-objects/SessionState.ts:1))
- immutable [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1)
- `currentStep` (wizard step, via [`StepId`](core/domain/value-objects/StepId.ts:1))
- `state` (via [`SessionState`](core/domain/value-objects/SessionState.ts:1))
- immutable [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1)
- timestamps (`startedAt`, `completedAt`)
- failure information (`errorMessage`).
- Enforces invariants:
@@ -385,44 +385,44 @@ The domain models what an “automation session” is, how it progresses, and wh
- Steps can only move forward and must progress sequentially (`n → n+1`, no skipping or going backwards).
- Terminal states (e.g. `STOPPED_AT_STEP_18`, `FAILED`) cannot be mutated further.
- [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1)
- [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1)
- Describes the admins intended hosted session:
- Required: `sessionName`, `trackId`, `carIds`.
- Optional QoL fields: `serverName`, `password`, `adminPassword`, `maxDrivers`, weather/time-of-day, lengths, damage model, track state, etc.
- Acts as the **canonical session description** that higher layers use to map into iRacings wizard fields.
- [`StepExecution`](packages/domain/entities/StepExecution.ts:1)
- [`StepExecution`](core/domain/entities/StepExecution.ts:1)
- Encapsulates the result of executing a single wizard step, including timing and error data.
**Value objects**
- Session lifecycle and step identity:
- [`SessionState`](packages/domain/value-objects/SessionState.ts:1)
- [`SessionLifetime`](packages/domain/value-objects/SessionLifetime.ts:1)
- [`StepId`](packages/domain/value-objects/StepId.ts:1)
- [`SessionState`](core/domain/value-objects/SessionState.ts:1)
- [`SessionLifetime`](core/domain/value-objects/SessionLifetime.ts:1)
- [`StepId`](core/domain/value-objects/StepId.ts:1)
- Authentication and browser state:
- [`AuthenticationState`](packages/domain/value-objects/AuthenticationState.ts:1)
- [`BrowserAuthenticationState`](packages/domain/value-objects/BrowserAuthenticationState.ts:1)
- [`CookieConfiguration`](packages/domain/value-objects/CookieConfiguration.ts:1)
- [`AuthenticationState`](core/domain/value-objects/AuthenticationState.ts:1)
- [`BrowserAuthenticationState`](core/domain/value-objects/BrowserAuthenticationState.ts:1)
- [`CookieConfiguration`](core/domain/value-objects/CookieConfiguration.ts:1)
- Checkout and pricing safety:
- [`CheckoutPrice`](packages/domain/value-objects/CheckoutPrice.ts:1)
- [`CheckoutState`](packages/domain/value-objects/CheckoutState.ts:1)
- [`CheckoutConfirmation`](packages/domain/value-objects/CheckoutConfirmation.ts:1)
- [`CheckoutPrice`](core/domain/value-objects/CheckoutPrice.ts:1)
- [`CheckoutState`](core/domain/value-objects/CheckoutState.ts:1)
- [`CheckoutConfirmation`](core/domain/value-objects/CheckoutConfirmation.ts:1)
- Overlay/visual integration:
- [`ScreenRegion`](packages/domain/value-objects/ScreenRegion.ts:1)
- [`RaceCreationResult`](packages/domain/value-objects/RaceCreationResult.ts:1)
- [`ScreenRegion`](core/domain/value-objects/ScreenRegion.ts:1)
- [`RaceCreationResult`](core/domain/value-objects/RaceCreationResult.ts:1)
**Domain services**
- [`PageStateValidator`](packages/domain/services/PageStateValidator.ts:1)
- [`PageStateValidator`](core/domain/services/PageStateValidator.ts:1)
- Declaratively describes what it means for the automation to be “on the right wizard page”.
- Evaluates combinations of required/forbidden selectors into a structured result.
- Used by [`PlaywrightAutomationAdapter`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) to avoid driving the wrong UI state.
- Used by [`PlaywrightAutomationAdapter`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) to avoid driving the wrong UI state.
- [`StepTransitionValidator`](packages/domain/services/StepTransitionValidator.ts:1)
- [`StepTransitionValidator`](core/domain/services/StepTransitionValidator.ts:1)
- Enforces legal transitions between wizard steps and session states.
- Centralizes the rules for when it is safe to move to the next step or finalize.
@@ -433,133 +433,133 @@ The domain models what an “automation session” is, how it progresses, and wh
---
### 4.2 Application Layer (`packages/application/*`)
### 4.2 Application Layer (`core/application/*`)
The application layer orchestrates use-cases by coordinating domain entities and calling ports that are implemented in infrastructure.
**Key ports**
- [`IAutomationEngine`](packages/application/ports/IAutomationEngine.ts:1)
- [`IAutomationEngine`](core/application/ports/IAutomationEngine.ts:1)
- `validateConfiguration(config)` → checks whether the intended hosted session is structurally valid and automatable.
- `executeStep(stepId, config)` → drives a single wizard step using the underlying browser automation.
- `stopAutomation()` → halts the current run.
- [`ISessionRepository`](packages/application/ports/ISessionRepository.ts:1)
- Persists [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1) instances for tracking and later inspection.
- [`ISessionRepository`](core/application/ports/ISessionRepository.ts:1)
- Persists [`AutomationSession`](core/domain/entities/AutomationSession.ts:1) instances for tracking and later inspection.
- Screen & browser integration:
- [`IScreenAutomation`](packages/application/ports/IScreenAutomation.ts:1) (implemented by [`PlaywrightAutomationAdapter`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1)).
- [`IAuthenticationService`](packages/application/ports/IAuthenticationService.ts:1) for login/session management.
- [`ICheckoutService`](packages/application/ports/ICheckoutService.ts:1) and [`ICheckoutConfirmationPort`](packages/application/ports/ICheckoutConfirmationPort.ts:1) for safe credits/checkout flows.
- [`IScreenAutomation`](core/application/ports/IScreenAutomation.ts:1) (implemented by [`PlaywrightAutomationAdapter`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1)).
- [`IAuthenticationService`](core/application/ports/IAuthenticationService.ts:1) for login/session management.
- [`ICheckoutService`](core/application/ports/ICheckoutService.ts:1) and [`ICheckoutConfirmationPort`](core/application/ports/ICheckoutConfirmationPort.ts:1) for safe credits/checkout flows.
- Cross-cutting:
- [`ILogger`](packages/application/ports/ILogger.ts:1)
- [`IOverlaySyncPort`](packages/application/ports/IOverlaySyncPort.ts:1)
- [`IAutomationEventPublisher`](packages/application/ports/IAutomationEventPublisher.ts:1)
- [`IUserConfirmationPort`](packages/application/ports/IUserConfirmationPort.ts:1)
- [`ILogger`](core/application/ports/ILogger.ts:1)
- [`IOverlaySyncPort`](core/application/ports/IOverlaySyncPort.ts:1)
- [`IAutomationEventPublisher`](core/application/ports/IAutomationEventPublisher.ts:1)
- [`IUserConfirmationPort`](core/application/ports/IUserConfirmationPort.ts:1)
**Key services**
- [`OverlaySyncService`](packages/application/services/OverlaySyncService.ts:1)
- [`OverlaySyncService`](core/application/services/OverlaySyncService.ts:1)
- Bridges the automation lifecycle (from infrastructure) to overlay/presentation consumers (companion renderer).
- Consumes an [`IAutomationLifecycleEmitter`](packages/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) (implemented by the Playwright adapter) and publishes state to an overlay sync port.
- Consumes an [`IAutomationLifecycleEmitter`](core/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) (implemented by the Playwright adapter) and publishes state to an overlay sync port.
**Key use-cases**
- [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1)
- Creates a new [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1) from a [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1).
- Calls [`IAutomationEngine`](packages/application/ports/IAutomationEngine.ts:1) to perform validation before any browser work starts.
- Persists the session via [`ISessionRepository`](packages/application/ports/ISessionRepository.ts:1).
- [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1)
- Creates a new [`AutomationSession`](core/domain/entities/AutomationSession.ts:1) from a [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1).
- Calls [`IAutomationEngine`](core/application/ports/IAutomationEngine.ts:1) to perform validation before any browser work starts.
- Persists the session via [`ISessionRepository`](core/application/ports/ISessionRepository.ts:1).
- Returns a DTO that the companion app tracks as progress state.
- Authentication:
- [`CheckAuthenticationUseCase`](packages/application/use-cases/CheckAuthenticationUseCase.ts:1)
- [`InitiateLoginUseCase`](packages/application/use-cases/InitiateLoginUseCase.ts:1)
- [`ClearSessionUseCase`](packages/application/use-cases/ClearSessionUseCase.ts:1)
- [`CheckAuthenticationUseCase`](core/application/use-cases/CheckAuthenticationUseCase.ts:1)
- [`InitiateLoginUseCase`](core/application/use-cases/InitiateLoginUseCase.ts:1)
- [`ClearSessionUseCase`](core/application/use-cases/ClearSessionUseCase.ts:1)
- These map the ToS-compliant login flow described in [`CONCEPT.md`](docs/concept/CONCEPT.md) and [`ADMINS.md`](docs/concept/ADMINS.md) into explicit use-cases (no password handling by GridPilot).
- Automation completion & checkout:
- [`CompleteRaceCreationUseCase`](packages/application/use-cases/CompleteRaceCreationUseCase.ts:1)
- [`ConfirmCheckoutUseCase`](packages/application/use-cases/ConfirmCheckoutUseCase.ts:1)
- Uses [`ICheckoutService`](packages/application/ports/ICheckoutService.ts:1) from the Playwright layer to inspect price/state and defers to a UI-side confirmation port to comply with “never surprise-charge the admin”.
- [`CompleteRaceCreationUseCase`](core/application/use-cases/CompleteRaceCreationUseCase.ts:1)
- [`ConfirmCheckoutUseCase`](core/application/use-cases/ConfirmCheckoutUseCase.ts:1)
- Uses [`ICheckoutService`](core/application/ports/ICheckoutService.ts:1) from the Playwright layer to inspect price/state and defers to a UI-side confirmation port to comply with “never surprise-charge the admin”.
- Guarding against stale auth:
- [`VerifyAuthenticatedPageUseCase`](packages/application/use-cases/VerifyAuthenticatedPageUseCase.ts:1) ensures the current page is still authenticated before continuing automation.
- [`VerifyAuthenticatedPageUseCase`](core/application/use-cases/VerifyAuthenticatedPageUseCase.ts:1) ensures the current page is still authenticated before continuing automation.
The application layer is where “admin intent” (start automation, confirm checkout, verify login) is encoded and exposed to the companion, without exposing Playwright or DOM specifics.
---
### 4.3 Infrastructure Layer (`packages/infrastructure/*`)
### 4.3 Infrastructure Layer (`core/infrastructure/*`)
The infrastructure layer implements the ports using concrete tools and services.
**Automation adapters**
- [`PlaywrightAutomationAdapter`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1)
- [`PlaywrightAutomationAdapter`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1)
- Implements:
- [`IScreenAutomation`](packages/application/ports/IScreenAutomation.ts:1)
- [`IAuthenticationService`](packages/application/ports/IAuthenticationService.ts:1)
- [`IAutomationLifecycleEmitter`](packages/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) used by [`OverlaySyncService`](packages/application/services/OverlaySyncService.ts:1).
- [`IScreenAutomation`](core/application/ports/IScreenAutomation.ts:1)
- [`IAuthenticationService`](core/application/ports/IAuthenticationService.ts:1)
- [`IAutomationLifecycleEmitter`](core/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) used by [`OverlaySyncService`](core/application/services/OverlaySyncService.ts:1).
- Responsibilities:
- Managing Playwright browser, context, and page lifecycle (headed/headless, fixture vs real mode).
- Navigating to the iRacing hosted-session wizard, login pages and fixtures.
- Driving wizard steps through an internal [`WizardStepOrchestrator`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1).
- Driving wizard steps through an internal [`WizardStepOrchestrator`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1).
- Injecting and updating the on-page automation overlay.
- Enforcing click safety (blocked selectors, checkout detection).
- Handling authentication flows, cookies and persistent sessions via [`SessionCookieStore`](packages/infrastructure/adapters/automation/auth/SessionCookieStore.ts:1) and [`PlaywrightAuthSessionService`](packages/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.ts:1).
- Validating page state using [`PageStateValidator`](packages/domain/services/PageStateValidator.ts:1).
- Handling authentication flows, cookies and persistent sessions via [`SessionCookieStore`](core/infrastructure/adapters/automation/auth/SessionCookieStore.ts:1) and [`PlaywrightAuthSessionService`](core/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.ts:1).
- Validating page state using [`PageStateValidator`](core/domain/services/PageStateValidator.ts:1).
- [`MockBrowserAutomationAdapter`](packages/infrastructure/adapters/automation/engine/MockBrowserAutomationAdapter.ts:1)
- [`MockBrowserAutomationAdapter`](core/infrastructure/adapters/automation/engine/MockBrowserAutomationAdapter.ts:1)
- Lightweight adapter used in tests to simulate automation without real browser interactions.
- [`FixtureServer`](packages/infrastructure/adapters/automation/engine/FixtureServer.ts:1)
- [`FixtureServer`](core/infrastructure/adapters/automation/engine/FixtureServer.ts:1)
- Serves static HTML fixtures from `html-dumps-optimized/` to exercise the automation logic deterministically in tests and local development.
**DOM helpers**
- [`IRacingDomNavigator`](packages/infrastructure/adapters/automation/dom/IRacingDomNavigator.ts:1)
- [`IRacingDomNavigator`](core/infrastructure/adapters/automation/dom/IRacingDomNavigator.ts:1)
- High-level navigation and waiting logic for wizard steps and key UI elements.
- [`IRacingDomInteractor`](packages/infrastructure/adapters/automation/dom/IRacingDomInteractor.ts:1)
- [`IRacingDomInteractor`](core/infrastructure/adapters/automation/dom/IRacingDomInteractor.ts:1)
- Encapsulates filling fields, clicking elements, handling modals.
- [`SafeClickService`](packages/infrastructure/adapters/automation/dom/SafeClickService.ts:1)
- [`SafeClickService`](core/infrastructure/adapters/automation/dom/SafeClickService.ts:1)
- A safer click abstraction that combines timeouts, modal-dismiss logic and safety checks.
- Selectors and constants:
- [`IRACING_SELECTORS`](packages/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1)
- Additional helper types under `packages/infrastructure/adapters/automation/dom/*`.
- [`IRACING_SELECTORS`](core/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1)
- Additional helper types under `core/infrastructure/adapters/automation/dom/*`.
**Checkout & pricing**
- [`CheckoutPriceExtractor`](packages/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1)
- [`CheckoutPriceExtractor`](core/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1)
- Reads DOM labels and buttons in the iRacing wizard to produce:
- [`CheckoutPrice`](packages/domain/value-objects/CheckoutPrice.ts:1) (if parsable).
- [`CheckoutState`](packages/domain/value-objects/CheckoutState.ts:1) (derived from button classes).
- [`CheckoutPrice`](core/domain/value-objects/CheckoutPrice.ts:1) (if parsable).
- [`CheckoutState`](core/domain/value-objects/CheckoutState.ts:1) (derived from button classes).
- Raw `buttonHtml` for debugging.
- Returns results wrapped in [`Result`](packages/shared/result/Result.ts:1) to avoid throwing during automation.
- Returns results wrapped in [`Result`](core/shared/result/Result.ts:1) to avoid throwing during automation.
**Repositories & configuration**
- [`InMemorySessionRepository`](packages/infrastructure/repositories/InMemorySessionRepository.ts:1)
- Simple in-process implementation of [`ISessionRepository`](packages/application/ports/ISessionRepository.ts:1), used in the companion app and tests.
- [`InMemorySessionRepository`](core/infrastructure/repositories/InMemorySessionRepository.ts:1)
- Simple in-process implementation of [`ISessionRepository`](core/application/ports/ISessionRepository.ts:1), used in the companion app and tests.
- Config:
- [`AutomationConfig`](packages/infrastructure/config/AutomationConfig.ts:1)
- [`AutomationConfig`](core/infrastructure/config/AutomationConfig.ts:1)
- Mode selection: `production`, `development`, `test`.
- Default timeouts and base URLs for fixtures vs live.
- [`BrowserModeConfig`](packages/infrastructure/config/BrowserModeConfig.ts:1)
- Controls headed/headless behavior, with [`BrowserModeConfigLoader`](packages/infrastructure/config/BrowserModeConfig.ts:1) used heavily in [`di-container`](apps/companion/main/di-container.ts:1).
- [`LoggingConfig`](packages/infrastructure/config/LoggingConfig.ts:1)
- [`BrowserModeConfig`](core/infrastructure/config/BrowserModeConfig.ts:1)
- Controls headed/headless behavior, with [`BrowserModeConfigLoader`](core/infrastructure/config/BrowserModeConfig.ts:1) used heavily in [`di-container`](apps/companion/main/di-container.ts:1).
- [`LoggingConfig`](core/infrastructure/config/LoggingConfig.ts:1)
- Logging:
- [`PinoLogAdapter`](packages/infrastructure/adapters/logging/PinoLogAdapter.ts:1)
- [`NoOpLogAdapter`](packages/infrastructure/adapters/logging/NoOpLogAdapter.ts:1) (used in tests to keep noise low).
- [`PinoLogAdapter`](core/infrastructure/adapters/logging/PinoLogAdapter.ts:1)
- [`NoOpLogAdapter`](core/infrastructure/adapters/logging/NoOpLogAdapter.ts:1) (used in tests to keep noise low).
**IPC / UI integration**
- [`ElectronCheckoutConfirmationAdapter`](packages/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter.ts:1)
- [`ElectronCheckoutConfirmationAdapter`](core/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter.ts:1)
- Bridges application-level checkout confirmation flows to the companion renderer via IPC.
This layer is where the “messy reality” of Playwright, Electron, file paths and selectors is implemented, while honoring the constraints defined at the domain/application layers.
@@ -579,22 +579,22 @@ The presentation layer in this repo is currently a **single Electron app** that
- [`di-container`](apps/companion/main/di-container.ts)
- Central wiring for:
- Logger ([`ILogger`](packages/application/ports/ILogger.ts:1)) via `createLogger()` and [`LoggingConfig`](packages/infrastructure/config/LoggingConfig.ts:1).
- Session repository ([`ISessionRepository`](packages/application/ports/ISessionRepository.ts:1)) via [`InMemorySessionRepository`](packages/infrastructure/repositories/InMemorySessionRepository.ts:1).
- Browser automation adapter via `createBrowserAutomationAdapter()` using [`PlaywrightAutomationAdapter`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) or [`MockBrowserAutomationAdapter`](packages/infrastructure/adapters/automation/engine/MockBrowserAutomationAdapter.ts:1) depending on mode.
- [`IAutomationEngine`](packages/application/ports/IAutomationEngine.ts:1) via [`AutomationEngineAdapter`](packages/infrastructure/adapters/automation/engine/AutomationEngineAdapter.ts:1) / [`MockAutomationEngineAdapter`](packages/infrastructure/adapters/automation/engine/MockAutomationEngineAdapter.ts:1).
- Logger ([`ILogger`](core/application/ports/ILogger.ts:1)) via `createLogger()` and [`LoggingConfig`](core/infrastructure/config/LoggingConfig.ts:1).
- Session repository ([`ISessionRepository`](core/application/ports/ISessionRepository.ts:1)) via [`InMemorySessionRepository`](core/infrastructure/repositories/InMemorySessionRepository.ts:1).
- Browser automation adapter via `createBrowserAutomationAdapter()` using [`PlaywrightAutomationAdapter`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) or [`MockBrowserAutomationAdapter`](core/infrastructure/adapters/automation/engine/MockBrowserAutomationAdapter.ts:1) depending on mode.
- [`IAutomationEngine`](core/application/ports/IAutomationEngine.ts:1) via [`AutomationEngineAdapter`](core/infrastructure/adapters/automation/engine/AutomationEngineAdapter.ts:1) / [`MockAutomationEngineAdapter`](core/infrastructure/adapters/automation/engine/MockAutomationEngineAdapter.ts:1).
- Application use-cases:
- [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1)
- [`CheckAuthenticationUseCase`](packages/application/use-cases/CheckAuthenticationUseCase.ts:1)
- [`InitiateLoginUseCase`](packages/application/use-cases/InitiateLoginUseCase.ts:1)
- [`ClearSessionUseCase`](packages/application/use-cases/ClearSessionUseCase.ts:1)
- [`ConfirmCheckoutUseCase`](packages/application/use-cases/ConfirmCheckoutUseCase.ts:1)
- Overlay sync orchestration via [`OverlaySyncService`](packages/application/services/OverlaySyncService.ts:1) and [`IAutomationLifecycleEmitter`](packages/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1).
- [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1)
- [`CheckAuthenticationUseCase`](core/application/use-cases/CheckAuthenticationUseCase.ts:1)
- [`InitiateLoginUseCase`](core/application/use-cases/InitiateLoginUseCase.ts:1)
- [`ClearSessionUseCase`](core/application/use-cases/ClearSessionUseCase.ts:1)
- [`ConfirmCheckoutUseCase`](core/application/use-cases/ConfirmCheckoutUseCase.ts:1)
- Overlay sync orchestration via [`OverlaySyncService`](core/application/services/OverlaySyncService.ts:1) and [`IAutomationLifecycleEmitter`](core/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1).
- Exposes methods like `getStartAutomationUseCase()`, `initializeBrowserConnection()`, `getBrowserModeConfigLoader()`, and `refreshBrowserAutomation()` that are used by IPC handlers and tests.
- [`ipc-handlers`](apps/companion/main/ipc-handlers.ts)
- Translates renderer IPC calls into use-case invocations:
- `startAutomation` → [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1).
- `startAutomation` → [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1).
- `checkAuth` / `initiateLogin` / `clearSession` → authentication use-cases.
- Browser connection initialization and overlay sync wiring.
@@ -607,7 +607,7 @@ The presentation layer in this repo is currently a **single Electron app** that
- [`App`](apps/companion/renderer/App.tsx)
- Controls high-level UI state:
- Authentication state (`AuthState`) and login flow.
- Current [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) passed from the session creation form.
- Current [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) passed from the session creation form.
- Session progress tracking (step, state, errors).
- Checkout confirmation dialog and race creation success views.
- Talks to Electron via `window.electronAPI`:
@@ -618,17 +618,17 @@ The presentation layer in this repo is currently a **single Electron app** that
- Components (selection):
- [`SessionCreationForm`](apps/companion/renderer/components/SessionCreationForm.tsx)
- Collects the data that becomes [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1).
- Collects the data that becomes [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1).
- [`SessionProgressMonitor`](apps/companion/renderer/components/SessionProgressMonitor.tsx)
- Visualizes the current step, completed steps, and error state of the [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1).
- Visualizes the current step, completed steps, and error state of the [`AutomationSession`](core/domain/entities/AutomationSession.ts:1).
- [`LoginPrompt`](apps/companion/renderer/components/LoginPrompt.tsx)
- Renders different messages for `AUTHENTICATED`, `EXPIRED`, `LOGGED_OUT`, `UNKNOWN` states and wires `onLogin`/`onRetry`.
- [`BrowserModeToggle`](apps/companion/renderer/components/BrowserModeToggle.tsx)
- Allows switching between headed/headless behavior in development, talking to the [`BrowserModeConfigLoader`](packages/infrastructure/config/BrowserModeConfig.ts:1) through IPC.
- Allows switching between headed/headless behavior in development, talking to the [`BrowserModeConfigLoader`](core/infrastructure/config/BrowserModeConfig.ts:1) through IPC.
- [`CheckoutConfirmationDialog`](apps/companion/renderer/components/CheckoutConfirmationDialog.tsx)
- Presents a clear, time-bounded dialog where the admin must confirm or cancel a credit purchase-like action.
- [`RaceCreationSuccessScreen`](apps/companion/renderer/components/RaceCreationSuccessScreen.tsx)
- Displays the final result of a successful race creation as modeled by [`RaceCreationResult`](packages/domain/value-objects/RaceCreationResult.ts:1).
- Displays the final result of a successful race creation as modeled by [`RaceCreationResult`](core/domain/value-objects/RaceCreationResult.ts:1).
The companion app is intentionally a **single presentation layer implemented in this repo**, but the application and domain layers are structured so that other presentation layers (web client, backend orchestration service) can reuse the same automation engine via the same ports.
@@ -644,7 +644,7 @@ This subsection summarizes how the GridPilot Web App / Website and the companion
- League and season management, scheduling and calendars.
- Driver and team views, stats, rating, discovery and social features as described in the concept docs.
- Runs in browsers, talking to core platform services over HTTP or GraphQL.
- Produces configuration artifacts such as hosted-session definitions that can be mapped into [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) on the platform side.
- Produces configuration artifacts such as hosted-session definitions that can be mapped into [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) on the platform side.
**GridPilot Companion App (desktop presentation, this repo)**
@@ -657,9 +657,9 @@ This subsection summarizes how the GridPilot Web App / Website and the companion
**Communication pattern between website, platform and companion**
- A typical flow for a scheduled league race:
- The web app and core platform services use competition data (league, calendar, formats) to derive a [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) or equivalent structure server-side.
- The web app and core platform services use competition data (league, calendar, formats) to derive a [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) or equivalent structure server-side.
- The core platform stores and schedules these configs and can expose them via APIs.
- The companion app fetches or receives the relevant configs, calls into the application layer (for example [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1)) and executes them against iRacing through Playwright.
- The companion app fetches or receives the relevant configs, calls into the application layer (for example [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1)) and executes them against iRacing through Playwright.
- Status and results flow back through overlays and events, and can be consumed both by the companion UI and by platform-side stats and rating services.
- This repo provides:
@@ -679,66 +679,66 @@ This section describes how a typical hosted-session automation run flows through
1. **Admin configures a session**
- In the companion UI, the admin fills out [`SessionCreationForm`](apps/companion/renderer/components/SessionCreationForm.tsx).
- The form builds a [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1)-compatible object and calls `window.electronAPI.startAutomation(config)`.
- The form builds a [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1)-compatible object and calls `window.electronAPI.startAutomation(config)`.
2. **IPC → main process**
- The preload script forwards this call to an IPC handler in [`ipc-handlers`](apps/companion/main/ipc-handlers.ts).
- The handler resolves the singleton [`DIContainer`](apps/companion/main/di-container.ts:1) and obtains:
- [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1).
- [`IAutomationEngine`](packages/application/ports/IAutomationEngine.ts:1) and [`ISessionRepository`](packages/application/ports/ISessionRepository.ts:1) behind the scenes.
- [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1).
- [`IAutomationEngine`](core/application/ports/IAutomationEngine.ts:1) and [`ISessionRepository`](core/application/ports/ISessionRepository.ts:1) behind the scenes.
3. **Use-case and domain**
- [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1):
- Creates a new [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1) by calling `AutomationSession.create(config)`, which validates the core invariants (non-empty session name, track, cars).
- [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1):
- Creates a new [`AutomationSession`](core/domain/entities/AutomationSession.ts:1) by calling `AutomationSession.create(config)`, which validates the core invariants (non-empty session name, track, cars).
- Calls `automationEngine.validateConfiguration(config)` to perform more detailed checks (e.g. compatibility with supported wizard flows).
- Persists the new session via [`ISessionRepository`](packages/application/ports/ISessionRepository.ts:1) (implemented by [`InMemorySessionRepository`](packages/infrastructure/repositories/InMemorySessionRepository.ts:1)).
- Persists the new session via [`ISessionRepository`](core/application/ports/ISessionRepository.ts:1) (implemented by [`InMemorySessionRepository`](core/infrastructure/repositories/InMemorySessionRepository.ts:1)).
- Returns a DTO to the IPC handler which is forwarded to the renderer.
4. **Browser and Playwright setup**
- The [`DIContainer`](apps/companion/main/di-container.ts:1) uses [`AutomationConfig`](packages/infrastructure/config/AutomationConfig.ts:1) and [`BrowserModeConfig`](packages/infrastructure/config/BrowserModeConfig.ts:1) to:
- The [`DIContainer`](apps/companion/main/di-container.ts:1) uses [`AutomationConfig`](core/infrastructure/config/AutomationConfig.ts:1) and [`BrowserModeConfig`](core/infrastructure/config/BrowserModeConfig.ts:1) to:
- Decide between `production`, `development`, `test` modes.
- Decide headed vs headless rendering.
- Potentially start a [`FixtureServer`](packages/infrastructure/adapters/automation/engine/FixtureServer.ts:1) in test/fixture modes.
- [`PlaywrightAutomationAdapter`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) connects to a browser and ensures the context is ready via `connect()` / `ensureBrowserContext()`.
- Potentially start a [`FixtureServer`](core/infrastructure/adapters/automation/engine/FixtureServer.ts:1) in test/fixture modes.
- [`PlaywrightAutomationAdapter`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) connects to a browser and ensures the context is ready via `connect()` / `ensureBrowserContext()`.
5. **Authentication and login**
- For real iRacing usage:
- [`CheckAuthenticationUseCase`](packages/application/use-cases/CheckAuthenticationUseCase.ts:1) and [`VerifyAuthenticatedPageUseCase`](packages/application/use-cases/VerifyAuthenticatedPageUseCase.ts:1) verify whether the session is still valid.
- If not, the renderer triggers [`InitiateLoginUseCase`](packages/application/use-cases/InitiateLoginUseCase.ts:1) via IPC.
- [`CheckAuthenticationUseCase`](core/application/use-cases/CheckAuthenticationUseCase.ts:1) and [`VerifyAuthenticatedPageUseCase`](core/application/use-cases/VerifyAuthenticatedPageUseCase.ts:1) verify whether the session is still valid.
- If not, the renderer triggers [`InitiateLoginUseCase`](core/application/use-cases/InitiateLoginUseCase.ts:1) via IPC.
- The Playwright adapter opens a headed browser window, navigates to the login page, and lets the admin log in manually.
- Once login is complete, [`PlaywrightAuthSessionService`](packages/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.ts:1) stores cookies in [`SessionCookieStore`](packages/infrastructure/adapters/automation/auth/SessionCookieStore.ts:1), and future runs reuse them.
- Once login is complete, [`PlaywrightAuthSessionService`](core/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService.ts:1) stores cookies in [`SessionCookieStore`](core/infrastructure/adapters/automation/auth/SessionCookieStore.ts:1), and future runs reuse them.
6. **Step-by-step wizard automation**
- The automation engine (implemented by [`AutomationEngineAdapter`](packages/infrastructure/adapters/automation/engine/AutomationEngineAdapter.ts:1) and backed by [`PlaywrightAutomationAdapter`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1)) proceeds through steps:
- The automation engine (implemented by [`AutomationEngineAdapter`](core/infrastructure/adapters/automation/engine/AutomationEngineAdapter.ts:1) and backed by [`PlaywrightAutomationAdapter`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1)) proceeds through steps:
- Navigate to hosted sessions.
- Open “Create a Race” and the hosted-session wizard.
- For each step (race information, server details, admins, cars, tracks, weather, race options, conditions):
- Ensure the correct page is active using [`PageStateValidator`](packages/domain/services/PageStateValidator.ts:1) and selectors from [`IRACING_SELECTORS`](packages/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1).
- Fill fields and toggles using [`IRacingDomInteractor`](packages/infrastructure/adapters/automation/dom/IRacingDomInteractor.ts:1).
- Click the correct “Next” / “Create Race” / “New Race” buttons, guarded by [`SafeClickService`](packages/infrastructure/adapters/automation/dom/SafeClickService.ts:1) and blocked-selector logic.
- Ensure the correct page is active using [`PageStateValidator`](core/domain/services/PageStateValidator.ts:1) and selectors from [`IRACING_SELECTORS`](core/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1).
- Fill fields and toggles using [`IRacingDomInteractor`](core/infrastructure/adapters/automation/dom/IRacingDomInteractor.ts:1).
- Click the correct “Next” / “Create Race” / “New Race” buttons, guarded by [`SafeClickService`](core/infrastructure/adapters/automation/dom/SafeClickService.ts:1) and blocked-selector logic.
- At each step, the Playwright adapter:
- Updates the overlay via `updateOverlay(step, message)`.
- Emits lifecycle events consumed by [`OverlaySyncService`](packages/application/services/OverlaySyncService.ts:1), which the companion uses to update [`SessionProgressMonitor`](apps/companion/renderer/components/SessionProgressMonitor.tsx).
- Emits lifecycle events consumed by [`OverlaySyncService`](core/application/services/OverlaySyncService.ts:1), which the companion uses to update [`SessionProgressMonitor`](apps/companion/renderer/components/SessionProgressMonitor.tsx).
7. **Checkout and confirmation**
- For flows that involve iRacing credits or non-zero prices:
- [`CheckoutPriceExtractor`](packages/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1) is used by the Playwright adapter to parse price and state from the wizard UI.
- [`ConfirmCheckoutUseCase`](packages/application/use-cases/ConfirmCheckoutUseCase.ts:1) sends a confirmation request to the renderer via [`ElectronCheckoutConfirmationAdapter`](packages/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter.ts:1).
- [`CheckoutPriceExtractor`](core/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1) is used by the Playwright adapter to parse price and state from the wizard UI.
- [`ConfirmCheckoutUseCase`](core/application/use-cases/ConfirmCheckoutUseCase.ts:1) sends a confirmation request to the renderer via [`ElectronCheckoutConfirmationAdapter`](core/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter.ts:1).
- [`CheckoutConfirmationDialog`](apps/companion/renderer/components/CheckoutConfirmationDialog.tsx) shows the admin the price and state, with an explicit timeout and cancel path.
- Only after explicit confirmation does the adapter simulate the checkout sequence (and in real mode, additional safeguards ensure no ToS-violating clicks occur).
8. **Completion and result**
- Once the final step is reached, [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1) transitions into a terminal state (`STOPPED_AT_STEP_18`, `FAILED`, etc.).
- The companion renderer may present a [`RaceCreationResult`](packages/domain/value-objects/RaceCreationResult.ts:1) via [`RaceCreationSuccessScreen`](apps/companion/renderer/components/RaceCreationSuccessScreen.tsx).
- Once the final step is reached, [`AutomationSession`](core/domain/entities/AutomationSession.ts:1) transitions into a terminal state (`STOPPED_AT_STEP_18`, `FAILED`, etc.).
- The companion renderer may present a [`RaceCreationResult`](core/domain/value-objects/RaceCreationResult.ts:1) via [`RaceCreationSuccessScreen`](apps/companion/renderer/components/RaceCreationSuccessScreen.tsx).
- The browser context is closed or re-used based on mode and configuration; debug artifacts may be written by the Playwright adapter for failed runs.
---
@@ -763,7 +763,7 @@ Although this repo focuses on automation and companion, it is deliberately shape
- The automation engine is designed so that a future league platform can:
- Generate [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) from league and calendar data (cars, tracks, formats) defined in the core competition services.
- Generate [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) from league and calendar data (cars, tracks, formats) defined in the core competition services.
- Trigger automation runs at scheduled times, with the admin supervising in the companion app.
- Use consistent, error-free sessions as the basis for reliable result capture and stats, supporting the narratives in [`DRIVERS.md`](docs/concept/DRIVERS.md), [`TEAMS.md`](docs/concept/TEAMS.md), [`RACING.md`](docs/concept/RACING.md) and [`STATS.md`](docs/concept/STATS.md).
@@ -831,7 +831,7 @@ In a future GridPilot platform:
- The **automation engine** in this repo would be used as a **hosted-session execution backend**:
- The platform would derive [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) objects from league/season metadata (cars, tracks, formats) defined in the platform.
- The platform would derive [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) objects from league/season metadata (cars, tracks, formats) defined in the platform.
- It would call into the automation layer via explicit use-cases or IPC/API, using the same ports used by the companion app today.
- The Electron companion may remain the primary operator UI, or an additional headless orchestration mode could be added (still respecting ToS and admin control).
@@ -846,13 +846,13 @@ In a future GridPilot platform:
The automation domain (sessions, steps, validation) is free of Electron/Playwright details, making it straightforward to embed into other hosts.
- **Ports for automation & auth**:
Using [`IAutomationEngine`](packages/application/ports/IAutomationEngine.ts:1), [`IScreenAutomation`](packages/application/ports/IScreenAutomation.ts:1), [`IAuthenticationService`](packages/application/ports/IAuthenticationService.ts:1) means new drivers (or alternative browser runtimes) can be introduced without changing the use-cases.
Using [`IAutomationEngine`](core/application/ports/IAutomationEngine.ts:1), [`IScreenAutomation`](core/application/ports/IScreenAutomation.ts:1), [`IAuthenticationService`](core/application/ports/IAuthenticationService.ts:1) means new drivers (or alternative browser runtimes) can be introduced without changing the use-cases.
- **Explicit checkout/confirmation path**:
The combination of [`CheckoutPrice`](packages/domain/value-objects/CheckoutPrice.ts:1), [`CheckoutState`](packages/domain/value-objects/CheckoutState.ts:1), [`CheckoutConfirmation`](packages/domain/value-objects/CheckoutConfirmation.ts:1) and the UI-side confirmation port aligns with the transparency and fairness requirements in [`ADMINS.md`](docs/concept/ADMINS.md) and [`RACING.md`](docs/concept/RACING.md).
The combination of [`CheckoutPrice`](core/domain/value-objects/CheckoutPrice.ts:1), [`CheckoutState`](core/domain/value-objects/CheckoutState.ts:1), [`CheckoutConfirmation`](core/domain/value-objects/CheckoutConfirmation.ts:1) and the UI-side confirmation port aligns with the transparency and fairness requirements in [`ADMINS.md`](docs/concept/ADMINS.md) and [`RACING.md`](docs/concept/RACING.md).
- **Overlay and lifecycle emitter**:
The overlay and [`IAutomationLifecycleEmitter`](packages/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) abstraction make it easy to:
The overlay and [`IAutomationLifecycleEmitter`](core/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) abstraction make it easy to:
- Drive visual overlays (like those described in admin QoL features) across different frontends.
- Feed telemetry into a central stats/ops UI for debugging, while keeping the engine itself small.

View File

@@ -120,8 +120,8 @@ src/apps/companion/
```
**Reused Layers** (100% unchanged):
- **Domain**: [`AutomationSession`](../src/packages/domain/entities/AutomationSession.ts:1), [`SessionState`](../src/packages/domain/value-objects/SessionState.ts:1), [`StepId`](../src/packages/domain/value-objects/StepId.ts:1)
- **Application**: [`StartAutomationSessionUseCase`](../src/packages/application/use-cases/StartAutomationSessionUseCase.ts:1)
- **Domain**: [`AutomationSession`](../src/core/domain/entities/AutomationSession.ts:1), [`SessionState`](../src/core/domain/value-objects/SessionState.ts:1), [`StepId`](../src/core/domain/value-objects/StepId.ts:1)
- **Application**: [`StartAutomationSessionUseCase`](../src/core/application/use-cases/StartAutomationSessionUseCase.ts:1)
- **Infrastructure**: [`MockBrowserAutomationAdapter`](../src/infrastructure/adapters/automation/MockBrowserAutomationAdapter.ts:1), [`MockAutomationEngineAdapter`](../src/infrastructure/adapters/automation/MockAutomationEngineAdapter.ts:1), [`InMemorySessionRepository`](../src/infrastructure/repositories/InMemorySessionRepository.ts:1)
### IPC Communication Flow

View File

@@ -57,8 +57,8 @@ This track is grounded in the existing code and architecture:
- Hosted wizard flow and step orchestration (see `tests/e2e/steps/*` and `tests/e2e/workflows/*`).
- Auth and cookie/session management.
- Overlay lifecycle via [`IAutomationLifecycleEmitter`](packages/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) and [`OverlaySyncService`](packages/application/services/OverlaySyncService.ts:1).
- Checkout safety via [`CheckoutPriceExtractor`](packages/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1), [`ConfirmCheckoutUseCase`](packages/application/use-cases/ConfirmCheckoutUseCase.ts:1), [`ElectronCheckoutConfirmationAdapter`](packages/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter.ts:1) and the renderer dialog.
- Overlay lifecycle via [`IAutomationLifecycleEmitter`](core/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) and [`OverlaySyncService`](core/application/services/OverlaySyncService.ts:1).
- Checkout safety via [`CheckoutPriceExtractor`](core/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1), [`ConfirmCheckoutUseCase`](core/application/use-cases/ConfirmCheckoutUseCase.ts:1), [`ElectronCheckoutConfirmationAdapter`](core/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter.ts:1) and the renderer dialog.
- Electron companion UI and IPC wiring.
### Phase A: Solid Hosted-Session Engine & Companion Baseline
@@ -68,14 +68,14 @@ This track is grounded in the existing code and architecture:
**Automation (this repo)**
- [ ] Stabilize wizard step orchestration:
- [ ] Review and align wizard-step domain rules with [`StepTransitionValidator`](packages/domain/services/StepTransitionValidator.ts:1).
- [ ] Review and align wizard-step domain rules with [`StepTransitionValidator`](core/domain/services/StepTransitionValidator.ts:1).
- [ ] Ensure `tests/e2e/steps/*` cover all 18 hosted wizard steps end to end.
- [ ] Harden [`WizardStepOrchestrator`](packages/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) behavior for retries and timeouts.
- [ ] Harden [`WizardStepOrchestrator`](core/infrastructure/adapters/automation/core/PlaywrightAutomationAdapter.ts:1) behavior for retries and timeouts.
- [ ] Strengthen page validation:
- [ ] Extend [`PageStateValidator`](packages/domain/services/PageStateValidator.ts:1) to cover edge cases found in real-hosted tests.
- [ ] Ensure selector sets in `packages/infrastructure/adapters/automation/dom/*` match current iRacing UI.
- [ ] Extend [`PageStateValidator`](core/domain/services/PageStateValidator.ts:1) to cover edge cases found in real-hosted tests.
- [ ] Ensure selector sets in `core/infrastructure/adapters/automation/dom/*` match current iRacing UI.
- [ ] Tighten auth/session flows:
- [ ] Verify [`CheckAuthenticationUseCase`](packages/application/use-cases/CheckAuthenticationUseCase.ts:1), [`InitiateLoginUseCase`](packages/application/use-cases/InitiateLoginUseCase.ts:1), and [`VerifyAuthenticatedPageUseCase`](packages/application/use-cases/VerifyAuthenticatedPageUseCase.ts:1) match the constraints in [`CONCEPT.md`](docs/concept/CONCEPT.md) and [`RACING.md`](docs/concept/RACING.md).
- [ ] Verify [`CheckAuthenticationUseCase`](core/application/use-cases/CheckAuthenticationUseCase.ts:1), [`InitiateLoginUseCase`](core/application/use-cases/InitiateLoginUseCase.ts:1), and [`VerifyAuthenticatedPageUseCase`](core/application/use-cases/VerifyAuthenticatedPageUseCase.ts:1) match the constraints in [`CONCEPT.md`](docs/concept/CONCEPT.md) and [`RACING.md`](docs/concept/RACING.md).
- [ ] Confirm cookie handling in `automation/auth/*` matches the lifecycle described in [`ARCHITECTURE.md`](docs/ARCHITECTURE.md).
- [ ] Companion baseline:
- [ ] Ensure the Electron app boots and connects reliably on supported platforms (see smoke tests in `tests/smoke/*`).
@@ -96,8 +96,8 @@ This track is grounded in the existing code and architecture:
**Automation (this repo)**
- [ ] Lifecycle events:
- [ ] Review events emitted by [`IAutomationLifecycleEmitter`](packages/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) and consumed by [`OverlaySyncService`](packages/application/services/OverlaySyncService.ts:1).
- [ ] Ensure all critical state transitions of [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1) are reflected in overlay events.
- [ ] Review events emitted by [`IAutomationLifecycleEmitter`](core/infrastructure/adapters/IAutomationLifecycleEmitter.ts:1) and consumed by [`OverlaySyncService`](core/application/services/OverlaySyncService.ts:1).
- [ ] Ensure all critical state transitions of [`AutomationSession`](core/domain/entities/AutomationSession.ts:1) are reflected in overlay events.
- [ ] Overlay UX:
- [ ] Ensure [`SessionProgressMonitor`](apps/companion/renderer/components/SessionProgressMonitor.tsx:1) clearly maps steps 118 to admin-understandable labels.
- [ ] Align overlay messaging with admin QoL themes in [`ADMINS.md`](docs/concept/ADMINS.md) (less repetitive work, more transparency).
@@ -119,11 +119,11 @@ This track is grounded in the existing code and architecture:
**Automation (this repo)**
- [ ] Enrich checkout detection:
- [ ] Validate selector logic and price parsing in [`CheckoutPriceExtractor`](packages/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1) against current iRacing UI.
- [ ] Ensure [`CheckoutState`](packages/domain/value-objects/CheckoutState.ts:1) covers all relevant button states.
- [ ] Validate selector logic and price parsing in [`CheckoutPriceExtractor`](core/infrastructure/adapters/automation/CheckoutPriceExtractor.ts:1) against current iRacing UI.
- [ ] Ensure [`CheckoutState`](core/domain/value-objects/CheckoutState.ts:1) covers all relevant button states.
- [ ] Harden confirmation logic:
- [ ] Confirm [`ConfirmCheckoutUseCase`](packages/application/use-cases/ConfirmCheckoutUseCase.ts:1) is the *only* entry point for automation that proceeds past a non-zero price.
- [ ] Ensure [`ElectronCheckoutConfirmationAdapter`](packages/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter.ts:1) and [`CheckoutConfirmationDialog`](apps/companion/renderer/components/CheckoutConfirmationDialog.tsx:1) enforce explicit admin confirmation and timeouts.
- [ ] Confirm [`ConfirmCheckoutUseCase`](core/application/use-cases/ConfirmCheckoutUseCase.ts:1) is the *only* entry point for automation that proceeds past a non-zero price.
- [ ] Ensure [`ElectronCheckoutConfirmationAdapter`](core/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter.ts:1) and [`CheckoutConfirmationDialog`](apps/companion/renderer/components/CheckoutConfirmationDialog.tsx:1) enforce explicit admin confirmation and timeouts.
- [ ] Failure paths:
- [ ] Verify that any parsing failure or ambiguous state results in a safe stop, not a blind click.
- [ ] Add tests to cover “weird but possible” UI states observed via fixtures.
@@ -143,11 +143,11 @@ This track is grounded in the existing code and architecture:
- [ ] Map additional hosted workflows:
- [ ] Identify additional iRacing hosted flows that align with admin QoL needs from [`ADMINS.md`](docs/concept/ADMINS.md) (e.g. practice-only, league-specific hosted sessions).
- [ ] Encode them as configurations on top of [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) where feasible.
- [ ] Encode them as configurations on top of [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) where feasible.
- [ ] Workflow templates:
- [ ] Provide a small set of reusable presets (e.g. “standard league race”, “test session”) that can later be populated by external services.
- [ ] Resilience work:
- [ ] Improve behavior under partial UI changes (selectors, labels) using the validation patterns from [`PageStateValidator`](packages/domain/services/PageStateValidator.ts:1).
- [ ] Improve behavior under partial UI changes (selectors, labels) using the validation patterns from [`PageStateValidator`](core/domain/services/PageStateValidator.ts:1).
**Success criteria**
@@ -195,7 +195,7 @@ Each phase is intentionally high-level to avoid going stale; details belong in f
- Implement league identity, schedules and season configuration:
- public league pages, schedules, rules, rosters (see sections 3 and 4 in [`CONCEPT.md`](docs/concept/CONCEPT.md)).
- admin tools for creating seasons, calendars, formats (mirroring [`RACING.md`](docs/concept/RACING.md)).
- Model leagues, seasons and events as first-class entities that can later produce [`HostedSessionConfig`](packages/domain/entities/HostedSessionConfig.ts:1) instances for this repos automation engine.
- Model leagues, seasons and events as first-class entities that can later produce [`HostedSessionConfig`](core/domain/entities/HostedSessionConfig.ts:1) instances for this repos automation engine.
**Success criteria**

View File

@@ -205,7 +205,7 @@ Two candidates meet accessibility and performance requirements:
### npm Workspaces
- **Rationale:** Built-in, zero configuration, dependency hoisting
- **Structure:** `/src/apps/*`, `/src/packages/*`, `/tests/*`
- **Structure:** `/src/apps/*`, `/src/core/*`, `/tests/*`
### Build Orchestration: Under Evaluation

View File

@@ -1131,8 +1131,8 @@ GridPilot's testing strategy ensures:
For the iRacing hosted-session automation, confidence is provided by these concrete suites:
- **Domain/Application unit tests**
- Entities and value objects such as [`AutomationSession`](packages/domain/entities/AutomationSession.ts:1), [`SessionState`](packages/domain/value-objects/SessionState.ts:1), [`CheckoutState`](packages/domain/value-objects/CheckoutState.ts:1), [`CheckoutConfirmation`](packages/domain/value-objects/CheckoutConfirmation.ts:1), and [`RaceCreationResult`](packages/domain/value-objects/RaceCreationResult.ts:1).
- Use cases such as [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1), [`VerifyAuthenticatedPageUseCase`](packages/application/use-cases/VerifyAuthenticatedPageUseCase.ts:1), [`CompleteRaceCreationUseCase`](packages/application/use-cases/CompleteRaceCreationUseCase.ts:1), and [`ConfirmCheckoutUseCase`](packages/application/use-cases/ConfirmCheckoutUseCase.ts:1).
- Entities and value objects such as [`AutomationSession`](core/domain/entities/AutomationSession.ts:1), [`SessionState`](core/domain/value-objects/SessionState.ts:1), [`CheckoutState`](core/domain/value-objects/CheckoutState.ts:1), [`CheckoutConfirmation`](core/domain/value-objects/CheckoutConfirmation.ts:1), and [`RaceCreationResult`](core/domain/value-objects/RaceCreationResult.ts:1).
- Use cases such as [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1), [`VerifyAuthenticatedPageUseCase`](core/application/use-cases/VerifyAuthenticatedPageUseCase.ts:1), [`CompleteRaceCreationUseCase`](core/application/use-cases/CompleteRaceCreationUseCase.ts:1), and [`ConfirmCheckoutUseCase`](core/application/use-cases/ConfirmCheckoutUseCase.ts:1).
- **Infrastructure / automation integration tests**
- Adapter wiring and fixture serving via [`FixtureServer.integration.test.ts`](tests/integration/infrastructure/FixtureServer.integration.test.ts:1).
@@ -1140,13 +1140,13 @@ For the iRacing hosted-session automation, confidence is provided by these concr
- UI/overlay integration via [`renderer-overlay.integration.test.ts`](tests/integration/interface/renderer/renderer-overlay.integration.test.ts:1).
- **Fixture-based step E2E tests (per-step behavior)**
- One test per wizard step under [`tests/e2e/steps`](tests/e2e/steps:1), all using the shared [`StepHarness`](tests/e2e/support/StepHarness.ts:1) and [`FixtureServer`](packages/infrastructure/adapters/automation/engine/FixtureServer.ts:1).
- One test per wizard step under [`tests/e2e/steps`](tests/e2e/steps:1), all using the shared [`StepHarness`](tests/e2e/support/StepHarness.ts:1) and [`FixtureServer`](core/infrastructure/adapters/automation/engine/FixtureServer.ts:1).
- These validate DOM-level selectors / flows for each step (118) against fixture-backed HTML, and are considered canonical for step behavior.
- **Fixture-based workflow E2E tests (button → auth entry → automation → confirmation boundary)**
- Workflow-focused tests under [`tests/e2e/workflows`](tests/e2e/workflows:1) that drive the `PlaywrightAutomationAdapter` + `WizardStepOrchestrator` across multiple steps using the fixture server.
- Example: [`steps-07-09-cars-flow.e2e.test.ts`](tests/e2e/workflows/steps-07-09-cars-flow.e2e.test.ts:1) exercises cross-step cars flow, while [`full-hosted-session.workflow.e2e.test.ts`](tests/e2e/workflows/full-hosted-session.workflow.e2e.test.ts:1) runs a full 118 workflow via [`MockAutomationEngineAdapter`](packages/infrastructure/adapters/automation/engine/MockAutomationEngineAdapter.ts:1) and [`StartAutomationSessionUseCase`](packages/application/use-cases/StartAutomationSessionUseCase.ts:1), asserting final `SessionState` and step position.
- Additional workflow scenarios cover mid-flow failure using [`MockBrowserAutomationAdapter`](packages/infrastructure/adapters/automation/engine/MockBrowserAutomationAdapter.ts:1), ensuring failure states and diagnostics are surfaced without emitting false confirmations.
- Example: [`steps-07-09-cars-flow.e2e.test.ts`](tests/e2e/workflows/steps-07-09-cars-flow.e2e.test.ts:1) exercises cross-step cars flow, while [`full-hosted-session.workflow.e2e.test.ts`](tests/e2e/workflows/full-hosted-session.workflow.e2e.test.ts:1) runs a full 118 workflow via [`MockAutomationEngineAdapter`](core/infrastructure/adapters/automation/engine/MockAutomationEngineAdapter.ts:1) and [`StartAutomationSessionUseCase`](core/application/use-cases/StartAutomationSessionUseCase.ts:1), asserting final `SessionState` and step position.
- Additional workflow scenarios cover mid-flow failure using [`MockBrowserAutomationAdapter`](core/infrastructure/adapters/automation/engine/MockBrowserAutomationAdapter.ts:1), ensuring failure states and diagnostics are surfaced without emitting false confirmations.
- **Opt-in real-world automation smoke tests (legacy)**
- The legacy real iRacing automation suite [`automation.e2e.test.ts`](tests/e2e/automation.e2e.test.ts:1) is now a skipped, documentation-only layer.
@@ -1182,7 +1182,7 @@ The hosted-session automation stack is covered by layered suites that balance re
- **Fixture-backed auto-navigation workflows**
- [`full-hosted-session.autonav.workflow.e2e.test.ts`](tests/e2e/workflows/full-hosted-session.autonav.workflow.e2e.test.ts:1)
- Uses the real Playwright stack (adapter + `WizardStepOrchestrator` + `FixtureServer`) with auto navigation enabled (`__skipFixtureNavigation` forbidden).
- Drives a representative subset of steps (e.g., 1 → 3 → 7 → 9 → 13 → 17) and asserts each step lands on the expected wizard container via [`IRACING_SELECTORS`](packages/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1).
- Drives a representative subset of steps (e.g., 1 → 3 → 7 → 9 → 13 → 17) and asserts each step lands on the expected wizard container via [`IRACING_SELECTORS`](core/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1).
- **Step-level fixture E2Es with explicit mismatch path**
- Existing step suites under [`tests/e2e/steps`](tests/e2e/steps:1) now have two execution paths via [`StepHarness`](tests/e2e/support/StepHarness.ts:1):
@@ -1265,7 +1265,7 @@ These suites assume the same fixture server and Playwright wiring as the rest of
#### Selector ↔ fixture ↔ real DOM guardrail
For hosted-session automation, [`IRACING_SELECTORS`](packages/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1) must match **either**:
For hosted-session automation, [`IRACING_SELECTORS`](core/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1) must match **either**:
- The current `html-dumps-optimized` fixtures under [`html-dumps-optimized/iracing-hosted-sessions`](html-dumps-optimized/iracing-hosted-sessions:1), or
- The real-site DOM as exercised by the hosted-real tests above.
@@ -1287,7 +1287,7 @@ Manual workflow when the iRacing DOM changes:
3. Re-align selectors and tests:
- Update [`IRACING_SELECTORS`](packages/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1) to reflect the new DOM shape.
- Update [`IRACING_SELECTORS`](core/infrastructure/adapters/automation/dom/IRacingSelectors.ts:1) to reflect the new DOM shape.
- Fix any failing step/workflow E2Es under [`tests/e2e/steps`](tests/e2e/steps:1) and [`tests/e2e/workflows`](tests/e2e/workflows:1) so they again describe the canonical behavior.
- Re-run:
- `npm test`