# The whole operation: 13 needs, 6 roles, 10 aggregates, overlapping Plan: `plans/contractor-full.yaml`. Built with no model, walked dry (every route of every aggregate), and replayed through portal's real aggregate engine on a throwaway NATS. | | | |---|---| | Verifier | 13 of 13 needs met, 28 pages, by construction | | Routes walked | 40, of which 6 are relays between roles | | Real engine | 40 aggregates created, 78 transitions accepted, 0 refused, 118 events | Who holds buttons on what, as built: - `enquiries`: project managers (6), site managers (mark surveyed; otherwise watch) - `claims`: site managers inspect and fix, project managers accept or reject - `change_orders`: project managers price, **the client approves or declines through their own link**, site managers complete - `material_orders`: site managers order, the crew confirms delivery - `site_issues`: site managers or the safety officer take in hand, only the safety officer closes; project managers watch - `job_requests`: project managers award; **subcontractors watch**, which is how they see what there is to bid on What this plan exposed, none of it fixed yet: 1. **The project managers' desk is one page with 9 aggregates and 32 buttons.** The builder puts every aggregate a role touches on one desk page. Past a handful it has to tier: a hub that lists the aggregates with what is waiting in each, and a page per aggregate. 2. **The front door offers 6 alternatives**, one over the page-load limit. It wants a first question ("a building of yours", "work with us", "a site of ours next door") and a second page under each. 3. **Aggregates do not know about each other.** A bid names its job in a free-text field; a change request names its job by address. Nothing says "a bid belongs to a job request" or "a change order exists only while an enquiry is won". That is the tiering between state machines still to be designed: a need that arises when a record elsewhere reaches a state, and carries its id. 4. **A shared button is walked by one role only.** Where two roles both hold `open -> surveyed`, the dry run presses it as the first of them. 5. **Anyone in `clients` opens the change-request form**, and portal has no per-record ownership beyond the submitter's link, so a client group sees nothing of its own cases afterwards.