Negotiate is an offline negotiation simulator with a domain-agnostic engine and a V1 UKHousingPack.
- Offline-first simulation (no network, no external APIs)
- Deterministic seeded RNG (
SplitMix64) for reproducibility - Domain-agnostic engine with pluggable
DomainPack - UK housing V1 experience: price + term trades, ask/hold/walk-away, stochastic event cards, delayed callbacks, debrief coaching, NCI progression
- Local JSON persistence in
Application Support
NegotiateApp
-> AppStore (flow + orchestration)
-> Storage (JSON persistence)
-> ScenarioGenerator (domain hook)
-> NegotiationEngine (state machine + utility policy)
-> BeliefModel (player estimates)
-> EventDeck (weighted stochastic shocks)
-> ScoringEngine (debrief + NCI)
-> SwiftUI Views
Home -> ScenarioBrief -> Negotiation -> Debrief
+ History + Settings sheets
Negotiate/ModelsScenario,HiddenState,Archetype,Event,Terms,Action,Outcome,Debrief,DomainPack
Negotiate/EngineNegotiationEngine,BeliefModel,ScenarioGenerator,EventDeck,ScoringEngine
Negotiate/PersistenceStorage
Negotiate/UtilitiesDesignSystem,SeededRNG,HapticsManager
Negotiate/UI- Home/brief/negotiation/feed/meters/intel/debrief/history/settings/sheets/components
SeededRNG uses SplitMix64. Given the same seed and action sequence:
- Scenario generation emits the same scenarios
- Engine stochastic branches (noise/events/callback rolls) are deterministic
- Unit tests can lock behavior against expected outcomes
On first launch:
- Generate first 50 scenarios immediately for quick start.
- Persist that first batch.
- Generate full 1000 in background and replace/persist once complete.
- On decode corruption, scenario file is deleted and regenerated with a user-facing reset alert.
- Create a new pack conforming to
DomainPack. - Provide variable labels, terms schema, scenario generator hook, event deck hook, and coaching templates.
- Implement a generator conforming to
ScenarioGeneratorProtocol. - Optionally implement a custom
EventDeckProtocoltype. - Switch pack in
AppStoreinitializer.
Skeleton:
struct SalaryPack: DomainPack {
let id = "salary_pack"
let name = "Salary Raise"
let description = "Manager-employee compensation negotiations"
let variableLabels: [String: String] = [:]
let termsSchema: [String] = ["bonus", "title", "startDate"]
func makeScenarioGenerator(seed: UInt64) -> any ScenarioGeneratorProtocol {
SalaryScenarioGenerator(seed: seed)
}
func makeEventDeck(for scenario: Scenario, seed: UInt64) -> any EventDeckProtocol {
SalaryEventDeck(seed: seed)
}
func coachingTemplates(for outcome: NegotiationOutcome) -> DebriefTemplateSet {
DebriefTemplateSet(whatWorkedTemplates: [], whatCostTemplates: [])
}
}- Xcode: 15.4+ (recommended latest Xcode 16.x)
- Target: iOS 17.0+
- Device: iPhone-only, portrait
Steps:
- Open
Negotiate.xcodeproj. - Select
Negotiatescheme and an iPhone simulator (e.g., iPhone 15). - Build and run.
- Run tests via Product -> Test.