task: #3615268 Finish the split: lineBookings(), lineCounts() and allLinesPast() still sat on the service that writes orders
Finishes what !182 (merged) started. That MR gave the engine a read-only TransactionLookup but left three reads on TransactionManager, so the split was half-done: docs/architecture.md asserted that reading an order must not depend on the code that writes it, while TransactionSummary still injected TransactionManagerInterface purely to call lineBookings().
What moves
lineBookings(), lineCounts() and allLinesPast() move onto TransactionLookup, all taking an id so the class is uniform. TransactionManagerInterface is down to writes and state transitions only, and TransactionManager injects the lookup for its own internal reads.
allLinesPast() needed BookingManager::isPast(), which would have dragged the write path into the lookup and reopened the cycle. So the predicate moves to where it belongs: Booking::isPast(int $now), beside consumes() and isHeld(), since it only ever read the booking's own slot. BookingManager::isPast() delegates to it, and the lookup needs only storage and the clock. It takes the moment as an argument so an order with many lines reads the clock once, not once per line.
Callers
12 read-only classes swapped to the lookup; 5 mixed classes (BookingCart, RequestBooker, OrderManager, SelectionBooker, CheckinHandler) take both; OrderTransitionActionBase takes both because its subclasses transition through it. Plus 6 create() container gets, 13 service definitions, and the test call sites.
OrderManager::lineBookings(OrderInterface $order) keeps its own signature: it is the order layer's own API and delegates.
Verification
Live container rebuilds and all 15 rewired services instantiate. Green locally: TransactionLookupTest, TransactionTest, TransactionSummaryTest, ExchangeHoldTest, BookingCartTest, CheckoutFreezeTest, BookingModeTest, BookingManagerTest, OrderTest, OrderSummaryBuilderTest, TransactionDeleteCascadeTest, CheckinHandlerTest. phpcs and phpstan clean across the module.
TransactionDeleteCascadeTest::testAllLinesPast caught a real bug in the move: Booking::isPast() referenced BookingSlotInterface without importing it, so it silently returned FALSE for every line.
Not in scope
Nothing further. TransactionManager is write-only by construction after this.