eih — a product as an assay, grown from assays/eih.lean

import Witness
import Roster
open Room Face Witness Roster
set_option autoImplicit false

namespace Eih.Treaty

structure Request where
  channel : Nat
  audience : List Nat
  sender : Nat
  confirmed : List Nat

def asked (q : Request) : List Nat := q.audience.filter (fun m => !(Nat.beq m q.sender))

def tally (q : Request) : Nat := (q.confirmed.filter (enrolled Nat.beq (asked q))).length

def heardBy (q : Request) (m : Nat) : List Nat := cond (enrolled Nat.beq q.audience m) q.confirmed []

def confirm (q : Request) (m : Nat) : Request := { q with confirmed := m :: q.confirmed }

def settled (q : Request) : Bool := everyone Nat.beq (asked q) q.confirmed

def unanswered (qs : List Request) : List Request := qs.filter (fun q => !(settled q))

def inChannel (qs : List Request) (ch : Nat) : List Nat :=
  joinMap (fun q => q.confirmed) (qs.filter (fun q => Nat.beq q.channel ch))

structure Room where
  guests : List Party
  delivered : List Nat
  ledger : List (Nat × Nat × Nat)
  timeline : List Nat
  bach : List Nat
  requests : List Request

def deliver (r : Room) : Room := { r with delivered := sheet r.guests }

def withGuests (r : Room) (gl : List Party) : Room := { r with guests := gl }

def withBach (r : Room) (b : List Nat) : Room := { r with bach := b }

def confirmIn (r : Room) (ch m : Nat) : Room :=
  { r with requests := r.requests.map (fun q => cond (Nat.beq q.channel ch) (confirm q m) q) }

def ask (r : Room) (ch : Nat) (audience : List Nat) (sender : Nat) : Room :=
  { r with requests := ⟨ch, audience, sender, []⟩ :: r.requests }

def withLine (r : Room) (e : Nat × Nat × Nat) : Room := { r with ledger := e :: r.ledger }

def allClear (r : Room) : Prop :=
  r.delivered = sheet r.guests ∧ unanswered r.requests = []

inductive Ask where
  | guests | sheet | ledger | timeline | bach | confirmed | vendorRoom

def Ask.code : Ask → Nat
  | .guests => 0 | .sheet => 1 | .ledger => 2 | .timeline => 3 | .bach => 4 | .confirmed => 5 | .vendorRoom => 6

def Ask.beq (a b : Ask) : Bool := Nat.beq a.code b.code

def readRoom (r : Room) : Ask → List Nat
  | .guests => r.guests.map (·.name)
  | .sheet => r.delivered
  | .ledger => r.ledger.map (·.2.2)
  | .timeline => r.timeline
  | .bach => r.bach
  | .confirmed => inChannel r.requests 0
  | .vendorRoom => inChannel r.requests 1

def roomFace : Face := ⟨Room, Ask, List Nat, readRoom⟩

def roomSeat : List Ask := [.guests, .sheet, .ledger, .timeline, .bach, .confirmed, .vendorRoom]

def coupleSeat : List Ask := [.guests, .sheet, .ledger, .timeline, .confirmed]

def lindaSeat : List Ask := [.guests, .timeline, .confirmed]

def bestManSeat : List Ask := [.timeline, .bach, .confirmed]

def catererSeat : List Ask := [.timeline, .sheet, .confirmed, .vendorRoom]

def humanSeats : List (List Ask) := [coupleSeat, lindaSeat, bestManSeat, catererSeat]

def coupleSideSeats : List (List Ask) := [coupleSeat, lindaSeat, bestManSeat]

inductive VendorAsk where
  | timeline | mine

def vendorFace (v : Nat) : Face :=
  ⟨Room, VendorAsk, List Nat, fun r q => match q with
    | .timeline => r.timeline
    | .mine => (r.ledger.filter (fun e => Nat.beq e.1 v)).map (·.2.2)⟩

def makerFace : Face := ⟨Room, Unit, Nat, fun r _ => r.guests.length⟩

structure Channel where
  audience : List Nat

structure File where
  channel : Channel

def visible (f : File) (m : Nat) : Prop := m ∈ f.channel.audience

def canSee (f : File) (m : Nat) : Bool := enrolled Nat.beq f.channel.audience m

inductive Role where
  | couple | planner | vendor | venue | party

def Role.code : Role → Nat
  | .couple => 0 | .planner => 1 | .vendor => 2 | .venue => 3 | .party => 4

def Role.beq (a b : Role) : Bool := Nat.beq a.code b.code

def joinsFree : Role → Bool := fun _ => true

def pays : Role → Bool
  | .couple => true | .vendor => true | .planner => true | .venue => true | .party => false

def samePage (qs : List Request) (v : Nat) : Nat :=
  ((qs.filter (fun q => enrolled Nat.beq q.audience v)).map tally).sum

inductive Thing where
  | wedding | season

def owner : Thing → Role
  | .wedding => .couple | .season => .vendor

structure Bill where
  thing : Thing
  payer : Role

def lawful (b : Bill) : Bool := Role.beq b.payer (owner b.thing) || (Role.beq b.payer .vendor && Role.beq (owner b.thing) .couple)

inductive Page where
  | floorPlan | guestList | samePage | invoices | budget | guests | site | team | dayOf | tasks

def Page.code : Page → Nat
  | .floorPlan => 0 | .guestList => 1 | .samePage => 2 | .invoices => 3 | .budget => 4
  | .guests => 5 | .site => 6 | .team => 7 | .dayOf => 8 | .tasks => 9

def Page.beq (a b : Page) : Bool := Nat.beq a.code b.code

def roles : List Role := [.couple, .planner, .vendor, .venue, .party]

def pages : List Page := [.floorPlan, .guestList, .samePage, .invoices, .budget, .guests, .site, .team, .dayOf, .tasks]

def seen : Role → List Page
  | .couple => pages
  | .planner => [.floorPlan, .guestList, .samePage, .invoices, .team, .dayOf, .tasks]
  | .vendor => [.floorPlan, .samePage, .invoices, .team, .dayOf, .tasks]
  | .venue => [.floorPlan, .samePage, .invoices, .team, .dayOf, .tasks]
  | .party => [.floorPlan, .guestList, .samePage, .team, .dayOf, .tasks]

def edited : Role → List Page
  | .couple => pages
  | .planner => [.floorPlan, .guestList, .invoices, .team, .dayOf, .tasks]
  | .vendor => [.invoices, .dayOf, .tasks]
  | .venue => [.floorPlan, .invoices, .dayOf, .tasks]
  | .party => [.floorPlan, .guestList, .dayOf, .tasks]

def sees (ρ : Role) (p : Page) : Bool := enrolled Page.beq (seen ρ) p

def edits (ρ : Role) (p : Page) : Bool := enrolled Page.beq (edited ρ) p

def withinSight : Bool := roles.all (fun ρ => pages.all (fun p => !(edits ρ p) || sees ρ p))

structure Member where
  user : Nat
  role : Role
  kind : Nat
  dayLane : Bool
  arrival : Nat
  phone : Nat

def vendorSide (m : Member) : Bool :=
  Role.beq m.role .vendor || (Role.beq m.role .venue || Role.beq m.role .planner)

def vendorRoomMembers (roster : List Member) : List Member := roster.filter vendorSide

def vendorRoomAudience (roster : List Member) : List Nat := (vendorRoomMembers roster).map (·.user)

def channelAudience (roster : List Member) (p : Member → Bool) : List Nat := (roster.filter p).map (·.user)

def vendorRoomRequestOf (roster : List Member) (sender : Nat) (confirmed : List Nat) : Request :=
  ⟨1, vendorRoomAudience roster, sender, confirmed⟩

structure Task where
  owner : Nat
  assignee : Nat
  done : Bool

def mayClose (m : Member) (t : Task) : Bool :=
  Nat.beq m.user t.owner || (Role.beq m.role .couple || Role.beq m.role .planner)

def close (t : Task) : Task := { t with done := true }

def assign (t : Task) (to : Nat) : Task := { t with assignee := to }

def mayOpen (_ : Member) : Bool := true

def memberSees (m : Member) (p : Page) : Bool := sees m.role p && !(m.dayLane && Page.beq p .tasks)

def memberEdits (m : Member) (p : Page) : Bool := edits m.role p && memberSees m p

def dayOfIsEveryones : Bool := roles.all (fun ρ => !(sees ρ .dayOf) || edits ρ .dayOf)

structure DayOfEdit where
  who : Nat
  row : Nat
  before : Nat
  after : Nat

def dayOfLog : Machine DayOfEdit (List DayOfEdit) := ledger DayOfEdit

def undo : List Nat → List Nat
  | [] => []
  | [_] => []
  | x :: y :: w => x :: undo (y :: w)

structure Table where
  shape : Nat
  occupants : List Nat

def venueTable (t : Table) : Nat × Nat := (t.shape, t.occupants.length)

def venueChart (c : List Table) : List (Nat × Nat) := c.map venueTable

def seasonView (rs : List Room) (v : Nat) : List (List Nat) := rs.map (fun r => (vendorFace v).obs r .mine)

def seasonOwed (rs : List Room) (v : Nat) : Nat := (joinMap (fun r => (vendorFace v).obs r .mine) rs).sum

def rose : Party := ⟨1, true, [2, 3]⟩

def linda : Party := ⟨2, true, [1]⟩

def cousin : Party := ⟨3, false, [1, 1]⟩

def guestList : List Party := [linda, cousin, rose]

def everyoneChannel : Request := ⟨0, [1, 2, 7, 8, 9], 1, [7, 8]⟩

def vendorRoomRequest : Request := ⟨1, [7, 8, 9], 9, [7]⟩

def demo : Room := ⟨guestList, [], [(7, 1, 900), (8, 1, 1200)], [10, 11, 12], [42], [everyoneChannel, vendorRoomRequest]⟩
#guard readRoom demo .confirmed == [7, 8]
#guard readRoom demo .vendorRoom == [7]

#guard sheet guestList == [1, 2, 3]
#guard heads guestList == 3
#guard (deliver demo).delivered == [1, 2, 3]
#guard demo.delivered == []
#guard readRoom (deliver demo) .sheet == [1, 2, 3]
#guard readRoom demo .guests == [2, 3, 1]

def floristSees : List Nat := (vendorFace 7).obs demo .mine
#guard floristSees == [900]

def djSees : List Nat := (vendorFace 8).obs demo .mine
#guard djSees == [1200]

def catererSees : List (List Nat) := reads roomFace catererSeat (deliver demo)
#guard catererSees == [[10, 11, 12], [1, 2, 3], [7, 8], [7]]

def lindaSees : List (List Nat) := reads roomFace lindaSeat demo
#guard lindaSees == [[2, 3, 1], [10, 11, 12], [7, 8]]

def bestManSees : List (List Nat) := reads roomFace bestManSeat demo
#guard bestManSees == [[10, 11, 12], [42], [7, 8]]

def coupleSees : List (List Nat) := reads roomFace coupleSeat demo
#guard coupleSees == [[2, 3, 1], [], [900, 1200], [10, 11, 12], [7, 8]]

def roomSees : List (List Nat) := reads roomFace roomSeat demo
#guard roomSees.length == 7

def makerSees : Nat := makerFace.obs demo ()
#guard makerSees == 3
#guard joinsFree .party && !(pays .party)

def moreGuests : Room := withGuests demo (rose :: guestList)

def makerSeesMore : Nat := makerFace.obs moreGuests ()
#guard makerSeesMore == 4

def catererSeesMore : List (List Nat) := reads roomFace catererSeat moreGuests
#guard catererSeesMore == reads roomFace catererSeat demo

def newBach : Room := withBach demo [43]

def bestManSeesNew : List (List Nat) := reads roomFace bestManSeat newBach
#guard bestManSeesNew == [[10, 11, 12], [43], [7, 8]]

def coupleSeesNew : List (List Nat) := reads roomFace coupleSeat newBach
#guard coupleSeesNew == coupleSees

def allConfirmed : Room := confirmIn (confirmIn demo 0 2) 0 9
#guard readRoom allConfirmed .confirmed == [9, 2, 7, 8]

def roomSeesConfirmed : List (List Nat) := reads roomFace roomSeat allConfirmed
#guard roomSeesConfirmed != roomSees

def lindaSeesConfirmed : List (List Nat) := reads roomFace lindaSeat allConfirmed
#guard lindaSeesConfirmed != lindaSees

def vendorConfirmed : Room := confirmIn demo 1 8
#guard readRoom vendorConfirmed .vendorRoom == [8, 7]

def lindaSeesVendorConfirmed : List (List Nat) := reads roomFace lindaSeat vendorConfirmed
#guard lindaSeesVendorConfirmed == lindaSees

def coupleSeesVendorConfirmed : List (List Nat) := reads roomFace coupleSeat vendorConfirmed
#guard coupleSeesVendorConfirmed == coupleSees

def catererSeesDemo : List (List Nat) := reads roomFace catererSeat demo

def catererSeesVendorConfirmed : List (List Nat) := reads roomFace catererSeat vendorConfirmed
#guard catererSeesVendorConfirmed != catererSeesDemo
#guard settled everyoneChannel == false
#guard settled (confirm (confirm everyoneChannel 2) 9)
#guard (unanswered demo.requests).length == 2
#guard (unanswered allConfirmed.requests).length == 1
#guard (unanswered (confirmIn allConfirmed 1 8).requests).length == 0

def withInvoice : Room := withLine demo (9, 1, 300)

def lindaSeesInvoice : List (List Nat) := reads roomFace lindaSeat withInvoice
#guard lindaSeesInvoice == lindaSees

def humanEars : List Ask := earshot roomFace humanSeats
#guard humanEars.length == 15
#guard enrolled Ask.beq humanEars .confirmed == true
#guard enrolled Ask.beq humanEars .ledger == true
#guard enrolled Ask.beq humanEars .vendorRoom == true

def coupleSideEars : List Ask := earshot roomFace coupleSideSeats
#guard enrolled Ask.beq coupleSideEars .vendorRoom == false
#guard everyone Nat.beq (asked everyoneChannel) (confirm (confirm everyoneChannel 2) 9).confirmed
#guard !(everyone Nat.beq (asked everyoneChannel) everyoneChannel.confirmed)

def maya : Nat := 1

def jordan : Nat := 7
#guard asked everyoneChannel == [2, 7, 8, 9]
#guard tally everyoneChannel == 2
#guard heardBy everyoneChannel jordan == [7, 8]
#guard heardBy everyoneChannel maya == [7, 8]
#guard heardBy vendorRoomRequest maya == []
#guard heardBy vendorRoomRequest jordan == [7]
#guard tally (confirm everyoneChannel 2) == 3
#guard samePage [everyoneChannel, vendorRoomRequest] maya == 2
#guard samePage [everyoneChannel, vendorRoomRequest] jordan == 3

def coveredWedding : Bill := ⟨.wedding, .vendor⟩

def ownWedding : Bill := ⟨.wedding, .couple⟩

def strayBill : Bill := ⟨.season, .couple⟩
#guard lawful coveredWedding && lawful ownWedding && !(lawful strayBill)
#guard Role.beq (owner coveredWedding.thing) .couple
#guard withinSight
#guard sees .venue .floorPlan && edits .venue .floorPlan && !(sees .venue .guestList)
#guard sees .vendor .floorPlan && !(edits .vendor .floorPlan)
#guard pays .venue && joinsFree .venue && !(pays .party)

def vendorRoomChannel : Channel := ⟨[7, 8, 9]⟩

def vendorRoomFile : File := ⟨vendorRoomChannel⟩
#guard !(canSee vendorRoomFile maya)
#guard canSee vendorRoomFile jordan

def mayaM : Member := ⟨1, .couple, 0, false, 15, 0⟩

def lindaM : Member := ⟨2, .party, 0, true, 14, 0⟩

def jordanM : Member := ⟨7, .vendor, 1, false, 12, 0⟩

def djM : Member := ⟨8, .vendor, 2, false, 13, 0⟩

def sofiaM : Member := ⟨9, .vendor, 3, false, 11, 0⟩

def roster : List Member := [mayaM, lindaM, jordanM, djM, sofiaM]
#guard vendorRoomAudience roster == [7, 8, 9]
#guard !(enrolled Nat.beq (vendorRoomAudience roster) 1)
#guard !(enrolled Nat.beq (vendorRoomAudience roster) 2)
#guard (vendorRoomRequestOf roster 9 [7]).audience == vendorRoomRequest.audience
#guard vendorRoomAudience [mayaM, lindaM, jordanM] == [7]

def loadIn : Task := ⟨7, 7, false⟩
#guard mayClose jordanM loadIn && mayClose mayaM loadIn && !(mayClose sofiaM loadIn)
#guard (close loadIn).done
#guard (assign loadIn 9).assignee == 9
#guard mayOpen sofiaM && mayOpen lindaM
#guard !(memberSees lindaM .tasks) && memberSees lindaM .dayOf && memberEdits lindaM .dayOf
#guard memberSees jordanM .tasks && memberEdits jordanM .tasks
#guard !(memberEdits lindaM .tasks)
#guard pages.all (fun p => !(memberSees lindaM p) || sees .party p)
#guard dayOfIsEveryones
#guard undo [1, 2, 3] == [1, 2]
#guard undo [1] == []

def firstEdit : DayOfEdit := ⟨9, 3, 100, 130⟩

def secondEdit : DayOfEdit := ⟨7, 5, 600, 615⟩
#guard (behavior dayOfLog [firstEdit, secondEdit]).length == 2
#guard (behavior dayOfLog [firstEdit, secondEdit]).map (·.who) == [9, 7]

def headTable : Table := ⟨0, [1, 2, 3]⟩

def table2 : Table := ⟨1, [4]⟩
#guard venueChart [headTable, table2] == [(0, 3), (1, 1)]
#guard venueChart [⟨0, [4, 5, 6]⟩, table2] == venueChart [headTable, table2]
#guard seasonView [demo, withInvoice] 7 == [[900], [900]]
#guard seasonView [demo, withInvoice] 9 == [[], [300]]
#guard seasonOwed [demo, withInvoice] 7 == 1800
#guard seasonOwed [demo, withInvoice] 9 == 300

theorem the_delivery_is_the_sheet (r : Room) : (deliver r).delivered = sheet r.guests :=
  rfl

/-- info: 'Eih.Treaty.the_delivery_is_the_sheet' does not depend on any axioms -/
#guard_msgs in #print axioms the_delivery_is_the_sheet

theorem the_delivery_moves_no_guest (r : Room) : (deliver r).guests = r.guests :=
  rfl

/-- info: 'Eih.Treaty.the_delivery_moves_no_guest' does not depend on any axioms -/
#guard_msgs in #print axioms the_delivery_moves_no_guest

theorem everyone_clear_means_every_request_settled (r : Room) (h : allClear r) :
    ∀ q, q ∈ r.requests → settled q = true := fun q hq => by
  cases hs : settled q with
  | true => rfl
  | false =>
      have hm : q ∈ unanswered r.requests :=
        mem_filter_intro r.requests hq (by show (!(settled q)) = true; rw [hs]; rfl)
      rw [h.2] at hm
      exact nomatch hm

/-- info: 'Eih.Treaty.everyone_clear_means_every_request_settled' does not depend on any axioms -/
#guard_msgs in #print axioms everyone_clear_means_every_request_settled

theorem a_line_touches_only_the_ledger (r : Room) (e : Nat × Nat × Nat) :
    differOnly roomFace (withLine r e) r .ledger :=
  fun q hq => by cases q <;> first | rfl | exact absurd rfl hq

/-- info: 'Eih.Treaty.a_line_touches_only_the_ledger' does not depend on any axioms -/
#guard_msgs in #print axioms a_line_touches_only_the_ledger

theorem the_bach_touches_only_the_bach (r : Room) (b : List Nat) :
    differOnly roomFace (withBach r b) r .bach :=
  fun q hq => by cases q <;> first | rfl | exact absurd rfl hq

/-- info: 'Eih.Treaty.the_bach_touches_only_the_bach' does not depend on any axioms -/
#guard_msgs in #print axioms the_bach_touches_only_the_bach

theorem a_confirmation_elsewhere_leaves_a_channel (ch ch' m : Nat) (h : Nat.beq ch ch' = false) :
    ∀ qs : List Request,
      (qs.map (fun q => cond (Nat.beq q.channel ch) (confirm q m) q)).filter (fun q => Nat.beq q.channel ch')
        = qs.filter (fun q => Nat.beq q.channel ch')
  | [] => rfl
  | q :: qs => by
      show (cond (Nat.beq q.channel ch) (confirm q m) q :: qs.map (fun q => cond (Nat.beq q.channel ch) (confirm q m) q)).filter (fun q => Nat.beq q.channel ch')
        = (q :: qs).filter (fun q => Nat.beq q.channel ch')
      cases hc : Nat.beq q.channel ch with
      | true =>
          have hq : q.channel = ch := eq_of_beq _ _ hc
          have hn : Nat.beq q.channel ch' = false := by rw [hq]; exact h
          show (confirm q m :: qs.map (fun q => cond (Nat.beq q.channel ch) (confirm q m) q)).filter (fun q => Nat.beq q.channel ch')
            = (q :: qs).filter (fun q => Nat.beq q.channel ch')
          rw [List.filter_cons_of_neg (p := fun q => Nat.beq q.channel ch') (a := confirm q m) (ne_true_of_eq_false hn),
              List.filter_cons_of_neg (p := fun q => Nat.beq q.channel ch') (a := q) (ne_true_of_eq_false hn)]
          exact a_confirmation_elsewhere_leaves_a_channel ch ch' m h qs
      | false =>
          show (q :: qs.map (fun q => cond (Nat.beq q.channel ch) (confirm q m) q)).filter (fun q => Nat.beq q.channel ch')
            = (q :: qs).filter (fun q => Nat.beq q.channel ch')
          cases hc' : Nat.beq q.channel ch' with
          | true =>
              rw [List.filter_cons_of_pos (p := fun q => Nat.beq q.channel ch') (a := q) hc',
                  List.filter_cons_of_pos (p := fun q => Nat.beq q.channel ch') (a := q) hc',
                  a_confirmation_elsewhere_leaves_a_channel ch ch' m h qs]
          | false =>
              rw [List.filter_cons_of_neg (p := fun q => Nat.beq q.channel ch') (a := q) (ne_true_of_eq_false hc'),
                  List.filter_cons_of_neg (p := fun q => Nat.beq q.channel ch') (a := q) (ne_true_of_eq_false hc'),
                  a_confirmation_elsewhere_leaves_a_channel ch ch' m h qs]

/-- info: 'Eih.Treaty.a_confirmation_elsewhere_leaves_a_channel' does not depend on any axioms -/
#guard_msgs in #print axioms a_confirmation_elsewhere_leaves_a_channel

theorem the_guests_touch_only_the_guests (r : Room) (gl : List Party) :
    differOnly roomFace (withGuests r gl) r .guests :=
  fun q hq => by cases q <;> first | rfl | exact absurd rfl hq

/-- info: 'Eih.Treaty.the_guests_touch_only_the_guests' does not depend on any axioms -/
#guard_msgs in #print axioms the_guests_touch_only_the_guests

theorem a_vendor_never_sees_anothers_invoice (v w : Nat) (hvw : Nat.beq w v = false) (r : Room)
    (amount to : Nat) :
    alike (vendorFace v) (withLine r (w, to, amount)) r := by
  intro q
  cases q with
  | timeline => rfl
  | mine =>
      show ((( w, to, amount) :: r.ledger).filter (fun e => Nat.beq e.1 v)).map (·.2.2)
        = (r.ledger.filter (fun e => Nat.beq e.1 v)).map (·.2.2)
      rw [List.filter, hvw]

/-- info: 'Eih.Treaty.a_vendor_never_sees_anothers_invoice' does not depend on any axioms -/
#guard_msgs in #print axioms a_vendor_never_sees_anothers_invoice

theorem an_ask_reads_itself : ∀ q : Ask, Ask.beq q q = true :=
  by (intros; (apply Room.beq_self <;> fail))

/-- info: 'Eih.Treaty.an_ask_reads_itself' does not depend on any axioms -/
#guard_msgs in #print axioms an_ask_reads_itself

theorem a_vendor_sees_only_their_own (v : Nat) (r : Room) :
    (vendorFace v).obs r .mine = (r.ledger.filter (fun e => Nat.beq e.1 v)).map (·.2.2) :=
  rfl

/-- info: 'Eih.Treaty.a_vendor_sees_only_their_own' does not depend on any axioms -/
#guard_msgs in #print axioms a_vendor_sees_only_their_own

theorem linda_never_sees_the_ledger (r : Room) (e : Nat × Nat × Nat) :
    reads roomFace lindaSeat (withLine r e) = reads roomFace lindaSeat r :=
  rfl

/-- info: 'Eih.Treaty.linda_never_sees_the_ledger' does not depend on any axioms -/
#guard_msgs in #print axioms linda_never_sees_the_ledger

theorem the_caterer_never_sees_the_ledger (r : Room) (e : Nat × Nat × Nat) :
    reads roomFace catererSeat (withLine r e) = reads roomFace catererSeat r :=
  rfl

/-- info: 'Eih.Treaty.the_caterer_never_sees_the_ledger' does not depend on any axioms -/
#guard_msgs in #print axioms the_caterer_never_sees_the_ledger

theorem the_caterer_never_sees_the_guests (r : Room) (gl : List Party) :
    reads roomFace catererSeat (withGuests r gl) = reads roomFace catererSeat r :=
  rfl

/-- info: 'Eih.Treaty.the_caterer_never_sees_the_guests' does not depend on any axioms -/
#guard_msgs in #print axioms the_caterer_never_sees_the_guests

theorem the_bach_parts_the_best_man (r : Room) (b : List Nat) (hb : b ≠ r.bach) :
    reads roomFace bestManSeat (withBach r b) ≠ reads roomFace bestManSeat r :=
  by
    (intros;
      (apply Witness.the_seat_that_hears_it_reads_it (p := Ask.bach) <;>
          first
          | assumption
          | (apply List.Mem.tail; exact List.Mem.head _)))

/-- info: 'Eih.Treaty.the_bach_parts_the_best_man' does not depend on any axioms -/
#guard_msgs in #print axioms the_bach_parts_the_best_man

theorem a_confirmation_parts_the_audience (r : Room) (m : Nat)
    (h : readRoom (confirmIn r 0 m) .confirmed ≠ readRoom r .confirmed) :
    reads roomFace coupleSeat (confirmIn r 0 m) ≠ reads roomFace coupleSeat r :=
  by
    (intros;
      (apply Witness.the_seat_that_hears_it_reads_it (p := Ask.confirmed) <;>
          first
          | assumption
          |
            (apply List.Mem.tail;
              (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _))))))

/-- info: 'Eih.Treaty.a_confirmation_parts_the_audience' does not depend on any axioms -/
#guard_msgs in #print axioms a_confirmation_parts_the_audience

theorem the_room_covers_itself : covers roomFace [roomSeat] :=
  by
    (intros; (try dsimp only [roomSeat, Witness.covers, roomFace] at *); intro x; induction x;
      all_goals
        (intros;
          first
          | (apply Room.mem_joinMap_intro <;> exact List.Mem.head _)
          |
            (apply Room.mem_joinMap_intro <;>
                first
                | exact List.Mem.head _
                | (apply List.Mem.tail; exact List.Mem.head _))
          |
            (apply Room.mem_joinMap_intro <;>
                first
                | exact List.Mem.head _
                | (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _)))
          |
            (apply Room.mem_joinMap_intro <;>
                first
                | exact List.Mem.head _
                | (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _))))
          |
            (apply Room.mem_joinMap_intro <;>
                first
                | exact List.Mem.head _
                |
                  (apply List.Mem.tail;
                    (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _)))))
          |
            (apply Room.mem_joinMap_intro <;>
                first
                | exact List.Mem.head _
                |
                  (apply List.Mem.tail;
                    (apply List.Mem.tail;
                      (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _))))))
          |
            (apply Room.mem_joinMap_intro <;>
                first
                | exact List.Mem.head _
                |
                  (apply List.Mem.tail;
                    (apply List.Mem.tail;
                      (apply List.Mem.tail;
                        (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _)))))))))

/-- info: 'Eih.Treaty.the_room_covers_itself' does not depend on any axioms -/
#guard_msgs in #print axioms the_room_covers_itself

theorem the_room_witnesses_the_license (x y : Room)
    (hw : witnessed roomFace [roomSeat] x y) : alike roomFace x y :=
  by
    (intros; (try dsimp only [Witness.witnessed, roomSeat, Room, roomFace] at *); intro x; induction x;
      all_goals
        (intros;
          first
          |
            (apply Witness.speak_now <;>
                first
                | assumption
                | exact List.Mem.head _)
          |
            (apply Witness.speak_now <;>
                first
                | assumption
                | (apply List.Mem.tail; exact List.Mem.head _))
          |
            (apply Witness.speak_now <;>
                first
                | assumption
                | (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _)))
          |
            (apply Witness.speak_now <;>
                first
                | assumption
                | (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _))))
          |
            (apply Witness.speak_now <;>
                first
                | assumption
                |
                  (apply List.Mem.tail;
                    (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _)))))
          |
            (apply Witness.speak_now <;>
                first
                | assumption
                |
                  (apply List.Mem.tail;
                    (apply List.Mem.tail;
                      (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _))))))
          |
            (apply Witness.speak_now <;>
                first
                | assumption
                |
                  (apply List.Mem.tail;
                    (apply List.Mem.tail;
                      (apply List.Mem.tail;
                        (apply List.Mem.tail; (apply List.Mem.tail; (apply List.Mem.tail; exact List.Mem.head _)))))))))

/-- info: 'Eih.Treaty.the_room_witnesses_the_license' does not depend on any axioms -/
#guard_msgs in #print axioms the_room_witnesses_the_license

theorem the_caterer_reads_the_delivery (r : Room) :
    readRoom (deliver r) .sheet = sheet r.guests :=
  rfl

/-- info: 'Eih.Treaty.the_caterer_reads_the_delivery' does not depend on any axioms -/
#guard_msgs in #print axioms the_caterer_reads_the_delivery

theorem a_file_is_never_wider_than_its_channel (f : File) (m : Nat) :
    visible f m ↔ m ∈ f.channel.audience :=
  Iff.rfl

/-- info: 'Eih.Treaty.a_file_is_never_wider_than_its_channel' does not depend on any axioms -/
#guard_msgs in #print axioms a_file_is_never_wider_than_its_channel

theorem a_vendor_room_file_is_absent_from_the_couples_files (f : File) (couple : Nat)
    (h : canSee f couple = false) : ¬ visible f couple :=
  by
    (intros;
      (apply Room.the_unenrolled_are_no_member <;>
          first
          | (apply Room.beq_self <;> fail)
          | assumption))

/-- info: 'Eih.Treaty.a_vendor_room_file_is_absent_from_the_couples_files' does not depend on any axioms -/
#guard_msgs in #print axioms a_vendor_room_file_is_absent_from_the_couples_files

theorem join_and_pay_are_unrelated : ∀ ρ : Role, joinsFree ρ = true :=
  fun _ => rfl

/-- info: 'Eih.Treaty.join_and_pay_are_unrelated' does not depend on any axioms -/
#guard_msgs in #print axioms join_and_pay_are_unrelated

theorem the_party_never_pays : pays .party = false :=
  rfl

/-- info: 'Eih.Treaty.the_party_never_pays' does not depend on any axioms -/
#guard_msgs in #print axioms the_party_never_pays

theorem lanes_shrink_never_lock (m : Member) (p : Page) (h : memberSees m p = true) : sees m.role p = true :=
  (and_reads _ _ h).1

/-- info: 'Eih.Treaty.lanes_shrink_never_lock' does not depend on any axioms -/
#guard_msgs in #print axioms lanes_shrink_never_lock

theorem the_day_lane_sees_no_task_list (m : Member) (h : m.dayLane = true) : memberSees m .tasks = false := by
  show (sees m.role .tasks && !(m.dayLane && Page.beq .tasks .tasks)) = false
  rw [h]
  cases sees m.role .tasks <;> rfl

/-- info: 'Eih.Treaty.the_day_lane_sees_no_task_list' does not depend on any axioms -/
#guard_msgs in #print axioms the_day_lane_sees_no_task_list

theorem the_day_lane_keeps_the_day_of_sheet (m : Member) (h : m.role = .party) : memberSees m .dayOf = true := by
  show (sees m.role .dayOf && !(m.dayLane && Page.beq .dayOf .tasks)) = true
  rw [h]
  cases m.dayLane <;> rfl

/-- info: 'Eih.Treaty.the_day_lane_keeps_the_day_of_sheet' does not depend on any axioms -/
#guard_msgs in #print axioms the_day_lane_keeps_the_day_of_sheet

theorem an_edit_is_within_the_lane (m : Member) (p : Page) (h : memberEdits m p = true) : memberSees m p = true :=
  (and_reads _ _ h).2

/-- info: 'Eih.Treaty.an_edit_is_within_the_lane' does not depend on any axioms -/
#guard_msgs in #print axioms an_edit_is_within_the_lane

theorem the_maker_sees_shape_not_content (r : Room) (gl gl' : List Party)
    (h : gl.length = gl'.length) : alike makerFace (withGuests r gl) (withGuests r gl') :=
  by
    (intros; (try dsimp only [Roster.Party, Room, withGuests, makerFace] at *); intro x; induction x;
      all_goals (intros; assumption))

/-- info: 'Eih.Treaty.the_maker_sees_shape_not_content' does not depend on any axioms -/
#guard_msgs in #print axioms the_maker_sees_shape_not_content

theorem everyone_clear_means_rose_ate (r : Room) (h : allClear r)
    {p : Party} (hp : p ∈ r.guests) (hr : p.rsvp = true) {m : Nat} (hm : m ∈ p.meals) :
    m ∈ r.delivered := by
  rw [h.1]
  exact a_yes_reaches_the_sheet hp hr hm

/-- info: 'Eih.Treaty.everyone_clear_means_rose_ate' does not depend on any axioms -/
#guard_msgs in #print axioms everyone_clear_means_rose_ate

theorem the_audience_hears_the_receipt_by_name (q : Request) (m : Nat)
    (h : enrolled Nat.beq q.audience m = true) : heardBy q m = q.confirmed :=
  by (intros; (try dsimp only [heardBy, Request] at *); intros; (rw [h]; rfl))

/-- info: 'Eih.Treaty.the_audience_hears_the_receipt_by_name' does not depend on any axioms -/
#guard_msgs in #print axioms the_audience_hears_the_receipt_by_name

theorem outside_the_audience_hears_no_receipt (q : Request) (m x : Nat)
    (h : enrolled Nat.beq q.audience m = false) : heardBy (confirm q x) m = heardBy q m :=
  by (intros; (try dsimp only [confirm, heardBy, Request] at *); intros; (rw [h]; rfl))

/-- info: 'Eih.Treaty.outside_the_audience_hears_no_receipt' does not depend on any axioms -/
#guard_msgs in #print axioms outside_the_audience_hears_no_receipt

theorem the_sender_is_never_asked (q : Request) : ¬ q.sender ∈ asked q := by
  intro h
  have hq := filter_holds q.audience h
  have hs : (!(Nat.beq q.sender q.sender)) = true := hq
  rw [beq_self] at hs
  exact nomatch hs

/-- info: 'Eih.Treaty.the_sender_is_never_asked' does not depend on any axioms -/
#guard_msgs in #print axioms the_sender_is_never_asked

theorem the_same_page_counts_only_within_earshot (q : Request) (qs : List Request) (v : Nat)
    (h : enrolled Nat.beq q.audience v = false) : samePage (q :: qs) v = samePage qs v := by
  show (((q :: qs).filter (fun q => enrolled Nat.beq q.audience v)).map tally).sum
    = ((qs.filter (fun q => enrolled Nat.beq q.audience v)).map tally).sum
  rw [List.filter_cons_of_neg (p := fun q => enrolled Nat.beq q.audience v) (a := q) (ne_true_of_eq_false h)]

/-- info: 'Eih.Treaty.the_same_page_counts_only_within_earshot' does not depend on any axioms -/
#guard_msgs in #print axioms the_same_page_counts_only_within_earshot

theorem the_same_page_hears_its_own_earshot (q : Request) (qs : List Request) (v : Nat)
    (h : enrolled Nat.beq q.audience v = true) : samePage (q :: qs) v = tally q + samePage qs v := by
  show (((q :: qs).filter (fun q => enrolled Nat.beq q.audience v)).map tally).sum
    = tally q + ((qs.filter (fun q => enrolled Nat.beq q.audience v)).map tally).sum
  rw [List.filter_cons_of_pos (p := fun q => enrolled Nat.beq q.audience v) (a := q) h]
  exact rfl

/-- info: 'Eih.Treaty.the_same_page_hears_its_own_earshot' does not depend on any axioms -/
#guard_msgs in #print axioms the_same_page_hears_its_own_earshot

theorem a_covered_wedding_is_still_the_couples (b : Bill) (h : b.thing = .wedding) : owner b.thing = .couple := by
  rw [h]
  rfl

/-- info: 'Eih.Treaty.a_covered_wedding_is_still_the_couples' does not depend on any axioms -/
#guard_msgs in #print axioms a_covered_wedding_is_still_the_couples

theorem the_payer_is_the_owner_or_the_host (b : Bill) (h : lawful b = true) :
    Role.beq b.payer (owner b.thing) = true ∨ (Role.beq b.payer .vendor = true ∧ Role.beq (owner b.thing) .couple = true) := by
  cases hp : Role.beq b.payer (owner b.thing) with
  | true => exact Or.inl rfl
  | false =>
      have h' : (Role.beq b.payer (owner b.thing) || (Role.beq b.payer .vendor && Role.beq (owner b.thing) .couple)) = true := h
      rw [hp] at h'
      exact Or.inr (and_reads _ _ h')

/-- info: 'Eih.Treaty.the_payer_is_the_owner_or_the_host' does not depend on any axioms -/
#guard_msgs in #print axioms the_payer_is_the_owner_or_the_host

theorem edit_is_within_sight : withinSight = true :=
  rfl

/-- info: 'Eih.Treaty.edit_is_within_sight' does not depend on any axioms -/
#guard_msgs in #print axioms edit_is_within_sight

theorem the_venue_edits_the_floor_and_never_sees_the_list :
    edits .venue .floorPlan = true ∧ sees .venue .guestList = false :=
  by decide

/-- info: 'Eih.Treaty.the_venue_edits_the_floor_and_never_sees_the_list' does not depend on any axioms -/
#guard_msgs in #print axioms the_venue_edits_the_floor_and_never_sees_the_list

theorem a_vendor_sees_the_floor_and_edits_nothing_there :
    sees .vendor .floorPlan = true ∧ edits .vendor .floorPlan = false :=
  by decide

/-- info: 'Eih.Treaty.a_vendor_sees_the_floor_and_edits_nothing_there' does not depend on any axioms -/
#guard_msgs in #print axioms a_vendor_sees_the_floor_and_edits_nothing_there

theorem the_couple_is_never_in_the_vendor_room (roster : List Member) (m : Member) (hc : m.role = .couple) :
    ¬ m ∈ vendorRoomMembers roster := fun h => by
  have hp : vendorSide m = true := filter_holds roster h
  have hf : vendorSide m = false := by
    cases m with
    | mk u r k l a p =>
        cases r with
        | couple => rfl
        | planner => exact nomatch hc
        | vendor => exact nomatch hc
        | venue => exact nomatch hc
        | party => exact nomatch hc
  exact nomatch (hf.symm.trans hp)

/-- info: 'Eih.Treaty.the_couple_is_never_in_the_vendor_room' does not depend on any axioms -/
#guard_msgs in #print axioms the_couple_is_never_in_the_vendor_room

theorem the_wedding_party_is_never_in_the_vendor_room (roster : List Member) (m : Member) (hc : m.role = .party) :
    ¬ m ∈ vendorRoomMembers roster := fun h => by
  have hp : vendorSide m = true := filter_holds roster h
  have hf : vendorSide m = false := by
    cases m with
    | mk u r k l a p =>
        cases r with
        | couple => exact nomatch hc
        | planner => exact nomatch hc
        | vendor => exact nomatch hc
        | venue => exact nomatch hc
        | party => rfl
  exact nomatch (hf.symm.trans hp)

/-- info: 'Eih.Treaty.the_wedding_party_is_never_in_the_vendor_room' does not depend on any axioms -/
#guard_msgs in #print axioms the_wedding_party_is_never_in_the_vendor_room

theorem a_vendor_is_in_the_vendor_room (roster : List Member) (m : Member) (hm : m ∈ roster) (hv : m.role = .vendor) :
    m ∈ vendorRoomMembers roster :=
  mem_filter_intro roster hm (by
    cases m with
    | mk u r k l a p =>
        cases r with
        | couple => exact nomatch hv
        | planner => exact nomatch hv
        | vendor => rfl
        | venue => exact nomatch hv
        | party => exact nomatch hv)

/-- info: 'Eih.Treaty.a_vendor_is_in_the_vendor_room' does not depend on any axioms -/
#guard_msgs in #print axioms a_vendor_is_in_the_vendor_room

theorem the_vendor_room_is_derived_from_the_roster (roster : List Member) :
    vendorRoomAudience roster = channelAudience roster vendorSide :=
  rfl

/-- info: 'Eih.Treaty.the_vendor_room_is_derived_from_the_roster' does not depend on any axioms -/
#guard_msgs in #print axioms the_vendor_room_is_derived_from_the_roster

theorem an_audience_is_members (roster : List Member) (p : Member → Bool) (u : Nat)
    (h : u ∈ channelAudience roster p) : ∃ m, m ∈ roster ∧ m.user = u := by
  obtain ⟨m, hm, he⟩ := mem_map_back (roster.filter p) h
  exact ⟨m, mem_of_mem_filter roster hm, he⟩

/-- info: 'Eih.Treaty.an_audience_is_members' does not depend on any axioms -/
#guard_msgs in #print axioms an_audience_is_members

theorem the_owner_may_close (m : Member) (t : Task) (h : Nat.beq m.user t.owner = true) : mayClose m t = true :=
  by (intros; (try dsimp only [Role, mayClose, Task, Member] at *); intros; (rw [h]; rfl))

/-- info: 'Eih.Treaty.the_owner_may_close' does not depend on any axioms -/
#guard_msgs in #print axioms the_owner_may_close

theorem the_couple_may_close (m : Member) (t : Task) (h : m.role = .couple) : mayClose m t = true :=
  by (intros; (try dsimp only [Role, mayClose, Task, Member] at *); intros; (rw [h]; (apply Room.or_swallows <;> fail)))

/-- info: 'Eih.Treaty.the_couple_may_close' does not depend on any axioms -/
#guard_msgs in #print axioms the_couple_may_close

theorem a_vendor_may_not_close_anothers (m : Member) (t : Task) (h1 : Nat.beq m.user t.owner = false)
    (h2 : m.role = .vendor) : mayClose m t = false := by
  show (Nat.beq m.user t.owner || (Role.beq m.role .couple || Role.beq m.role .planner)) = false
  rw [h1, h2]
  exact rfl

/-- info: 'Eih.Treaty.a_vendor_may_not_close_anothers' does not depend on any axioms -/
#guard_msgs in #print axioms a_vendor_may_not_close_anothers

theorem anyone_may_open_a_task (m : Member) : mayOpen m = true :=
  rfl

/-- info: 'Eih.Treaty.anyone_may_open_a_task' does not depend on any axioms -/
#guard_msgs in #print axioms anyone_may_open_a_task

theorem the_day_of_sheet_is_everyones_to_edit : dayOfIsEveryones = true :=
  rfl

/-- info: 'Eih.Treaty.the_day_of_sheet_is_everyones_to_edit' does not depend on any axioms -/
#guard_msgs in #print axioms the_day_of_sheet_is_everyones_to_edit

theorem every_edit_is_kept (w : List DayOfEdit) : behavior dayOfLog w = w :=
  by (intros; (apply Face.the_ledger_parks_the_word <;> fail))

/-- info: 'Eih.Treaty.every_edit_is_kept' does not depend on any axioms -/
#guard_msgs in #print axioms every_edit_is_kept

theorem the_last_edit_undoes (e : Nat) : ∀ w : List Nat, undo (w ++ [e]) = w
  | [] => rfl
  | [_] => rfl
  | x :: y :: w => congrArg (x :: ·) (the_last_edit_undoes e (y :: w))

/-- info: 'Eih.Treaty.the_last_edit_undoes' does not depend on any axioms -/
#guard_msgs in #print axioms the_last_edit_undoes

theorem the_venue_reads_counts_not_names (t : Table) (occ occ' : List Nat) (h : occ.length = occ'.length) :
    venueTable { t with occupants := occ } = venueTable { t with occupants := occ' } := by
  show (t.shape, occ.length) = (t.shape, occ'.length)
  rw [h]

/-- info: 'Eih.Treaty.the_venue_reads_counts_not_names' does not depend on any axioms -/
#guard_msgs in #print axioms the_venue_reads_counts_not_names

theorem a_season_reads_each_room_as_the_vendor (rs : List Room) (v : Nat) :
    seasonView rs v = rs.map (fun r => (vendorFace v).obs r .mine) :=
  rfl

/-- info: 'Eih.Treaty.a_season_reads_each_room_as_the_vendor' does not depend on any axioms -/
#guard_msgs in #print axioms a_season_reads_each_room_as_the_vendor

theorem the_seasons_sum_is_over_my_own_invoices (rs : List Room) (v : Nat) :
    seasonOwed rs v = (joinMap (fun r => (vendorFace v).obs r .mine) rs).sum :=
  rfl

/-- info: 'Eih.Treaty.the_seasons_sum_is_over_my_own_invoices' does not depend on any axioms -/
#guard_msgs in #print axioms the_seasons_sum_is_over_my_own_invoices

theorem a_confirmation_touches_only_its_channel (r : Room) (m : Nat) :
    differOnly roomFace (confirmIn r 0 m) r .confirmed := fun q hq => by
  cases q with
  | vendorRoom =>
      show joinMap (fun q => q.confirmed) ((r.requests.map (fun q => cond (Nat.beq q.channel 0) (confirm q m) q)).filter (fun q => Nat.beq q.channel 1))
        = joinMap (fun q => q.confirmed) (r.requests.filter (fun q => Nat.beq q.channel 1))
      rw [a_confirmation_elsewhere_leaves_a_channel 0 1 m rfl r.requests]
  | confirmed => exact absurd rfl hq
  | guests => rfl
  | sheet => rfl
  | ledger => rfl
  | timeline => rfl
  | bach => rfl

/-- info: 'Eih.Treaty.a_confirmation_touches_only_its_channel' does not depend on any axioms -/
#guard_msgs in #print axioms a_confirmation_touches_only_its_channel

theorem a_vendor_room_confirmation_touches_only_the_vendor_room (r : Room) (m : Nat) :
    differOnly roomFace (confirmIn r 1 m) r .vendorRoom := fun q hq => by
  cases q with
  | confirmed =>
      show joinMap (fun q => q.confirmed) ((r.requests.map (fun q => cond (Nat.beq q.channel 1) (confirm q m) q)).filter (fun q => Nat.beq q.channel 0))
        = joinMap (fun q => q.confirmed) (r.requests.filter (fun q => Nat.beq q.channel 0))
      rw [a_confirmation_elsewhere_leaves_a_channel 1 0 m rfl r.requests]
  | vendorRoom => exact absurd rfl hq
  | guests => rfl
  | sheet => rfl
  | ledger => rfl
  | timeline => rfl
  | bach => rfl

/-- info: 'Eih.Treaty.a_vendor_room_confirmation_touches_only_the_vendor_room' does not depend on any axioms -/
#guard_msgs in #print axioms a_vendor_room_confirmation_touches_only_the_vendor_room

theorem a_quiet_seat_does_not_hear_it (s : List Ask) (p : Ask) (h : enrolled Ask.beq s p = false) :
    ¬ hears roomFace s p :=
  by
    (intros;
      (apply Room.the_unenrolled_are_no_member <;>
          first
          | (apply an_ask_reads_itself <;> fail)
          | assumption))

/-- info: 'Eih.Treaty.a_quiet_seat_does_not_hear_it' does not depend on any axioms -/
#guard_msgs in #print axioms a_quiet_seat_does_not_hear_it

theorem the_bach_wall (r : Room) (b : List Nat) (hb : b ≠ r.bach) :
    reads roomFace coupleSeat (withBach r b) = reads roomFace coupleSeat r
      ∧ reads roomFace bestManSeat (withBach r b) ≠ reads roomFace bestManSeat r :=
  by (intros; (repeat' constructor); all_goals (intros; (apply the_bach_parts_the_best_man <;> assumption)))

/-- info: 'Eih.Treaty.the_bach_wall' does not depend on any axioms -/
#guard_msgs in #print axioms the_bach_wall

theorem no_couple_side_seat_hears_the_vendor_room : ¬ hears roomFace (earshot roomFace coupleSideSeats) .vendorRoom :=
  by (intros; (apply a_quiet_seat_does_not_hear_it <;> rfl))

/-- info: 'Eih.Treaty.no_couple_side_seat_hears_the_vendor_room' does not depend on any axioms -/
#guard_msgs in #print axioms no_couple_side_seat_hears_the_vendor_room

theorem the_vendor_room_holds_its_own_receipt (r : Room) (m : Nat) :
    reads roomFace coupleSeat (confirmIn r 1 m) = reads roomFace coupleSeat r
      ∧ reads roomFace lindaSeat (confirmIn r 1 m) = reads roomFace lindaSeat r
      ∧ reads roomFace bestManSeat (confirmIn r 1 m) = reads roomFace bestManSeat r :=
  by
    (intros; (repeat' constructor);
      all_goals
        (intros;
          (apply Witness.a_wall_hides_the_probe <;>
              first
              | (apply a_vendor_room_confirmation_touches_only_the_vendor_room <;> fail)
              | (apply a_quiet_seat_does_not_hear_it <;> rfl))))

/-- info: 'Eih.Treaty.the_vendor_room_holds_its_own_receipt' does not depend on any axioms -/
#guard_msgs in #print axioms the_vendor_room_holds_its_own_receipt

theorem the_couple_side_witnesses_no_vendor_room_license (r : Room) (m : Nat) :
    witnessed roomFace coupleSideSeats (confirmIn r 1 m) r := fun s hs =>
  a_wall_hides_the_probe roomFace (a_vendor_room_confirmation_touches_only_the_vendor_room r m) s
    (fun hp => no_couple_side_seat_hears_the_vendor_room (mem_joinMap_intro hs hp))

/-- info: 'Eih.Treaty.the_couple_side_witnesses_no_vendor_room_license' does not depend on any axioms -/
#guard_msgs in #print axioms the_couple_side_witnesses_no_vendor_room_license

theorem everyone_is_here (r : Room) (h : allClear r)
    {p : Party} (hp : p ∈ r.guests) (hr : p.rsvp = true) {m : Nat} (hm : m ∈ p.meals)
    (x : Nat) {gl gl' : List Party} (hperm : gl.Perm gl') :
    m ∈ r.delivered
      ∧ (∀ q, q ∈ r.requests → settled q = true)
      ∧ (sheet r.guests).length = heads r.guests
      ∧ heads gl = heads gl'
      ∧ witnessed roomFace coupleSideSeats (confirmIn r 1 x) r
      ∧ reads roomFace coupleSeat (confirmIn r 1 x) = reads roomFace coupleSeat r :=
  by
    (intros; (repeat' constructor);
      all_goals
        (intros;
          first
          | (apply everyone_clear_means_rose_ate <;> assumption)
          | (apply everyone_clear_means_every_request_settled <;> assumption)
          | (apply Roster.the_sheet_counts_the_heads <;> fail)
          | (apply Roster.reseating_keeps_the_heads <;> assumption)
          | (apply the_couple_side_witnesses_no_vendor_room_license <;> fail)
          | (apply ((the_vendor_room_holds_its_own_receipt _ _)).1 <;> fail)))

/-- info: 'Eih.Treaty.everyone_is_here' does not depend on any axioms -/
#guard_msgs in #print axioms everyone_is_here

end Eih.Treaty

the map of relations — every law a node, an arrow for each citation the elaborator reads (bin/counter chart; without --laws the carriers join the map)

graph LR
  subgraph Eih_Treaty["Eih.Treaty"]
    a_confirmation_elsewhere_leaves_a_channel["a_confirmation_elsewhere_leaves_a_channel"]
    a_confirmation_parts_the_audience["a_confirmation_parts_the_audience"]
    a_confirmation_touches_only_its_channel["a_confirmation_touches_only_its_channel"]
    a_covered_wedding_is_still_the_couples["a_covered_wedding_is_still_the_couples"]
    a_file_is_never_wider_than_its_channel["a_file_is_never_wider_than_its_channel"]
    a_line_touches_only_the_ledger["a_line_touches_only_the_ledger"]
    a_quiet_seat_does_not_hear_it["a_quiet_seat_does_not_hear_it"]
    a_season_reads_each_room_as_the_vendor["a_season_reads_each_room_as_the_vendor"]
    a_vendor_is_in_the_vendor_room["a_vendor_is_in_the_vendor_room"]
    a_vendor_may_not_close_anothers["a_vendor_may_not_close_anothers"]
    a_vendor_never_sees_anothers_invoice["a_vendor_never_sees_anothers_invoice"]
    a_vendor_room_confirmation_touches_only_the_vendor_room["a_vendor_room_confirmation_touches_only_the_vendor_room"]
    a_vendor_room_file_is_absent_from_the_couples_files["a_vendor_room_file_is_absent_from_the_couples_files"]
    a_vendor_sees_only_their_own["a_vendor_sees_only_their_own"]
    a_vendor_sees_the_floor_and_edits_nothing_there["a_vendor_sees_the_floor_and_edits_nothing_there"]
    an_ask_reads_itself["an_ask_reads_itself"]
    an_audience_is_members["an_audience_is_members"]
    an_edit_is_within_the_lane["an_edit_is_within_the_lane"]
    anyone_may_open_a_task["anyone_may_open_a_task"]
    edit_is_within_sight["edit_is_within_sight"]
    every_edit_is_kept["every_edit_is_kept"]
    everyone_clear_means_every_request_settled["everyone_clear_means_every_request_settled"]
    everyone_clear_means_rose_ate["everyone_clear_means_rose_ate"]
    everyone_is_here["everyone_is_here"]
    join_and_pay_are_unrelated["join_and_pay_are_unrelated"]
    lanes_shrink_never_lock["lanes_shrink_never_lock"]
    linda_never_sees_the_ledger["linda_never_sees_the_ledger"]
    no_couple_side_seat_hears_the_vendor_room["no_couple_side_seat_hears_the_vendor_room"]
    outside_the_audience_hears_no_receipt["outside_the_audience_hears_no_receipt"]
    the_audience_hears_the_receipt_by_name["the_audience_hears_the_receipt_by_name"]
    the_bach_parts_the_best_man["the_bach_parts_the_best_man"]
    the_bach_touches_only_the_bach["the_bach_touches_only_the_bach"]
    the_bach_wall["the_bach_wall"]
    the_caterer_never_sees_the_guests["the_caterer_never_sees_the_guests"]
    the_caterer_never_sees_the_ledger["the_caterer_never_sees_the_ledger"]
    the_caterer_reads_the_delivery["the_caterer_reads_the_delivery"]
    the_couple_is_never_in_the_vendor_room["the_couple_is_never_in_the_vendor_room"]
    the_couple_may_close["the_couple_may_close"]
    the_couple_side_witnesses_no_vendor_room_license["the_couple_side_witnesses_no_vendor_room_license"]
    the_day_lane_keeps_the_day_of_sheet["the_day_lane_keeps_the_day_of_sheet"]
    the_day_lane_sees_no_task_list["the_day_lane_sees_no_task_list"]
    the_day_of_sheet_is_everyones_to_edit["the_day_of_sheet_is_everyones_to_edit"]
    the_delivery_is_the_sheet["the_delivery_is_the_sheet"]
    the_delivery_moves_no_guest["the_delivery_moves_no_guest"]
    the_guests_touch_only_the_guests["the_guests_touch_only_the_guests"]
    the_last_edit_undoes["the_last_edit_undoes"]
    the_maker_sees_shape_not_content["the_maker_sees_shape_not_content"]
    the_owner_may_close["the_owner_may_close"]
    the_party_never_pays["the_party_never_pays"]
    the_payer_is_the_owner_or_the_host["the_payer_is_the_owner_or_the_host"]
    the_room_covers_itself["the_room_covers_itself"]
    the_room_witnesses_the_license["the_room_witnesses_the_license"]
    the_same_page_counts_only_within_earshot["the_same_page_counts_only_within_earshot"]
    the_same_page_hears_its_own_earshot["the_same_page_hears_its_own_earshot"]
    the_seasons_sum_is_over_my_own_invoices["the_seasons_sum_is_over_my_own_invoices"]
    the_sender_is_never_asked["the_sender_is_never_asked"]
    the_vendor_room_holds_its_own_receipt["the_vendor_room_holds_its_own_receipt"]
    the_vendor_room_is_derived_from_the_roster["the_vendor_room_is_derived_from_the_roster"]
    the_venue_edits_the_floor_and_never_sees_the_list["the_venue_edits_the_floor_and_never_sees_the_list"]
    the_venue_reads_counts_not_names["the_venue_reads_counts_not_names"]
    the_wedding_party_is_never_in_the_vendor_room["the_wedding_party_is_never_in_the_vendor_room"]
  end
  subgraph Witness["Witness"]
    Witness_a_wall_hides_the_probe["a_wall_hides_the_probe"]
    Witness_speak_now["speak_now"]
    Witness_the_seat_that_hears_it_reads_it["the_seat_that_hears_it_reads_it"]
  end
  subgraph Roster["Roster"]
    Roster_a_yes_reaches_the_sheet["a_yes_reaches_the_sheet"]
    Roster_reseating_keeps_the_heads["reseating_keeps_the_heads"]
    Roster_the_sheet_counts_the_heads["the_sheet_counts_the_heads"]
  end
  a_confirmation_parts_the_audience --> Witness_the_seat_that_hears_it_reads_it
  no_couple_side_seat_hears_the_vendor_room --> a_quiet_seat_does_not_hear_it
  the_bach_wall --> the_bach_parts_the_best_man
  the_room_witnesses_the_license --> Witness_speak_now
  everyone_clear_means_rose_ate --> Roster_a_yes_reaches_the_sheet
  the_bach_parts_the_best_man --> Witness_the_seat_that_hears_it_reads_it
  a_quiet_seat_does_not_hear_it --> an_ask_reads_itself
  a_confirmation_touches_only_its_channel --> a_confirmation_elsewhere_leaves_a_channel
  a_vendor_room_confirmation_touches_only_the_vendor_room --> a_confirmation_elsewhere_leaves_a_channel
  everyone_is_here --> the_couple_side_witnesses_no_vendor_room_license
  everyone_is_here --> everyone_clear_means_every_request_settled
  everyone_is_here --> the_vendor_room_holds_its_own_receipt
  everyone_is_here --> everyone_clear_means_rose_ate
  everyone_is_here --> Roster_the_sheet_counts_the_heads
  everyone_is_here --> Roster_reseating_keeps_the_heads
  the_couple_side_witnesses_no_vendor_room_license --> no_couple_side_seat_hears_the_vendor_room
  the_couple_side_witnesses_no_vendor_room_license --> Witness_a_wall_hides_the_probe
  the_couple_side_witnesses_no_vendor_room_license --> a_vendor_room_confirmation_touches_only_the_vendor_room
  the_vendor_room_holds_its_own_receipt --> a_quiet_seat_does_not_hear_it
  the_vendor_room_holds_its_own_receipt --> Witness_a_wall_hides_the_probe
  the_vendor_room_holds_its_own_receipt --> a_vendor_room_confirmation_touches_only_the_vendor_room

the data-model shadow — every structure a table, every seat a view over the columns its probes read, every wall theorem the policy it licenses (bin/counter schema)

-- the data-model shadow of grown/assays/eih.lean, read from the kernel (bin/counter schema)
-- every foreign key is a field; every policy is a theorem; nothing here that the treaty does not need

CREATE TYPE page AS ENUM ('floorPlan', 'guestList', 'samePage', 'invoices', 'budget', 'guests', 'site', 'team', 'dayOf', 'tasks');
CREATE TYPE ask AS ENUM ('guests', 'sheet', 'ledger', 'timeline', 'bach', 'confirmed', 'vendorRoom');
CREATE TYPE vendor_ask AS ENUM ('timeline', 'mine');
CREATE TYPE role AS ENUM ('couple', 'planner', 'vendor', 'venue', 'party');
CREATE TYPE thing AS ENUM ('wedding', 'season');

CREATE TABLE member (
  id serial PRIMARY KEY,
  user_ integer NOT NULL,
  role role NOT NULL,
  kind integer NOT NULL,
  day_lane boolean NOT NULL,
  arrival integer NOT NULL,
  phone integer NOT NULL
);

CREATE TABLE request (
  id serial PRIMARY KEY,
  channel integer NOT NULL,
  audience integer[] NOT NULL,
  sender integer NOT NULL,
  confirmed integer[] NOT NULL
);

CREATE TABLE party (
  id serial PRIMARY KEY,
  name integer NOT NULL,
  rsvp boolean NOT NULL,
  meals integer[] NOT NULL
);

CREATE TABLE day_of_edit (
  id serial PRIMARY KEY,
  who integer NOT NULL,
  row integer NOT NULL,
  before integer NOT NULL,
  after integer NOT NULL
);

CREATE TABLE channel (
  id serial PRIMARY KEY,
  audience integer[] NOT NULL
);

CREATE TABLE task (
  id serial PRIMARY KEY,
  owner integer NOT NULL,
  assignee integer NOT NULL,
  done boolean NOT NULL
);

CREATE TABLE file (
  id serial PRIMARY KEY,
  channel integer NOT NULL REFERENCES channel(id)
);

CREATE TABLE bill (
  id serial PRIMARY KEY,
  thing thing NOT NULL,
  payer role NOT NULL
);

CREATE TABLE table_ (
  id serial PRIMARY KEY,
  shape integer NOT NULL,
  occupants integer[] NOT NULL
);

CREATE TABLE room (
  id serial PRIMARY KEY,
  delivered integer[] NOT NULL,
  timeline integer[] NOT NULL,
  bach integer[] NOT NULL
);
CREATE TABLE room_guests (
  room_id integer NOT NULL REFERENCES room(id),
  position integer NOT NULL,
  party_id integer NOT NULL REFERENCES party(id)
);
CREATE TABLE room_ledger (
  room_id integer NOT NULL REFERENCES room(id),
  position integer NOT NULL,
  c0 integer NOT NULL,
  c1 integer NOT NULL,
  c2 integer NOT NULL
);
CREATE TABLE room_requests (
  room_id integer NOT NULL REFERENCES room(id),
  position integer NOT NULL,
  request_id integer NOT NULL REFERENCES request(id)
);

-- makerFace: a face over room — each probe a column
CREATE FUNCTION room_as_maker_face(room_id integer) RETURNS TABLE(unit integer) LANGUAGE sql STABLE AS $$
  SELECT cardinality((SELECT array_agg(party_id ORDER BY position) FROM room_guests c WHERE c.room_id = room.id)) FROM room WHERE id = $1 $$;

-- roomFace: a face over room — each probe a column
CREATE FUNCTION room_as_room_face(room_id integer) RETURNS TABLE(guests integer[], sheet integer[], ledger integer[], timeline integer[], bach integer[], confirmed integer[], vendor_room integer[]) LANGUAGE sql STABLE AS $$
  SELECT ARRAY(SELECT (SELECT name FROM party WHERE id = x) FROM unnest((SELECT array_agg(party_id ORDER BY position) FROM room_guests c WHERE c.room_id = room.id)) WITH ORDINALITY AS u(x, o) ORDER BY o), room.delivered, ARRAY(SELECT (x).c2 FROM unnest((SELECT array_agg(c ORDER BY position) FROM room_ledger c WHERE c.room_id = room.id)) AS x ORDER BY (x).position), room.timeline, room.bach, ARRAY(SELECT m FROM unnest(ARRAY(SELECT x FROM unnest((SELECT array_agg(request_id ORDER BY position) FROM room_requests c WHERE c.room_id = room.id)) WITH ORDINALITY AS u(x, o) WHERE ((SELECT channel FROM request WHERE id = x) = 0) ORDER BY o)) WITH ORDINALITY AS u(x, o), unnest((SELECT confirmed FROM request WHERE id = x)) WITH ORDINALITY AS v(m, i) ORDER BY o, i), ARRAY(SELECT m FROM unnest(ARRAY(SELECT x FROM unnest((SELECT array_agg(request_id ORDER BY position) FROM room_requests c WHERE c.room_id = room.id)) WITH ORDINALITY AS u(x, o) WHERE ((SELECT channel FROM request WHERE id = x) = 1) ORDER BY o)) WITH ORDINALITY AS u(x, o), unnest((SELECT confirmed FROM request WHERE id = x)) WITH ORDINALITY AS v(m, i) ORDER BY o, i) FROM room WHERE id = $1 $$;

-- vendorFace: a face over room, parameterized (1) — each probe a column
CREATE FUNCTION room_as_vendor_face(room_id integer, p1 integer) RETURNS TABLE(timeline integer[], mine integer[]) LANGUAGE sql STABLE AS $$
  SELECT room.timeline, ARRAY(SELECT (x).c2 FROM unnest(ARRAY(SELECT x FROM unnest((SELECT array_agg(c ORDER BY position) FROM room_ledger c WHERE c.room_id = room.id)) AS x WHERE ((x).c0 = $2) ORDER BY (x).position)) AS x ORDER BY (x).position) FROM room WHERE id = $1 $$;

-- joinsFree: a rule over role, derived, never stored
CREATE FUNCTION joins_free(role) RETURNS boolean LANGUAGE sql IMMUTABLE AS $$
  SELECT CASE $1 WHEN 'couple' THEN true WHEN 'planner' THEN true WHEN 'vendor' THEN true WHEN 'venue' THEN true WHEN 'party' THEN true END $$;

-- edited: a rule over role, derived, never stored
CREATE FUNCTION edited(role) RETURNS page[] LANGUAGE sql IMMUTABLE AS $$
  SELECT CASE $1 WHEN 'couple' THEN ARRAY['floorPlan', 'guestList', 'samePage', 'invoices', 'budget', 'guests', 'site', 'team', 'dayOf', 'tasks']::page[] WHEN 'planner' THEN ARRAY['floorPlan', 'guestList', 'invoices', 'team', 'dayOf', 'tasks']::page[] WHEN 'vendor' THEN ARRAY['invoices', 'dayOf', 'tasks']::page[] WHEN 'venue' THEN ARRAY['floorPlan', 'invoices', 'dayOf', 'tasks']::page[] WHEN 'party' THEN ARRAY['floorPlan', 'guestList', 'dayOf', 'tasks']::page[] END $$;

-- seen: a rule over role, derived, never stored
CREATE FUNCTION seen(role) RETURNS page[] LANGUAGE sql IMMUTABLE AS $$
  SELECT CASE $1 WHEN 'couple' THEN ARRAY['floorPlan', 'guestList', 'samePage', 'invoices', 'budget', 'guests', 'site', 'team', 'dayOf', 'tasks']::page[] WHEN 'planner' THEN ARRAY['floorPlan', 'guestList', 'samePage', 'invoices', 'team', 'dayOf', 'tasks']::page[] WHEN 'vendor' THEN ARRAY['floorPlan', 'samePage', 'invoices', 'team', 'dayOf', 'tasks']::page[] WHEN 'venue' THEN ARRAY['floorPlan', 'samePage', 'invoices', 'team', 'dayOf', 'tasks']::page[] WHEN 'party' THEN ARRAY['floorPlan', 'guestList', 'samePage', 'team', 'dayOf', 'tasks']::page[] END $$;

-- pays: a rule over role, derived, never stored
CREATE FUNCTION pays(role) RETURNS boolean LANGUAGE sql IMMUTABLE AS $$
  SELECT CASE $1 WHEN 'couple' THEN true WHEN 'planner' THEN true WHEN 'vendor' THEN true WHEN 'venue' THEN true WHEN 'party' THEN false END $$;

-- owner: a rule over thing, derived, never stored
CREATE FUNCTION owner(thing) RETURNS role LANGUAGE sql IMMUTABLE AS $$
  SELECT (CASE $1 WHEN 'wedding' THEN 'couple' WHEN 'season' THEN 'vendor' END)::role $$;

-- vendorRoomRequestOf: derived, not yet drawn (data over List Eih.Treaty.Member)

-- heardBy: derived, never stored
-- described by outside_the_audience_hears_no_receipt, the_audience_hears_the_receipt_by_name
CREATE FUNCTION heard_by(request_id integer, arg2 integer) RETURNS integer[] LANGUAGE sql STABLE AS $$
  SELECT (CASE WHEN (arg2 = ANY(SELECT unnest(request.audience))) THEN request.confirmed ELSE ARRAY[]::integer[] END) FROM request WHERE id = $1 $$;

-- channelAudience: derived, not yet drawn (data over List Eih.Treaty.Member)

-- inChannel: derived, never stored
CREATE FUNCTION in_channel(request_ids integer[], arg2 integer) RETURNS integer[] LANGUAGE sql STABLE AS $$
  SELECT ARRAY(SELECT m FROM unnest(ARRAY(SELECT x FROM unnest($1) WITH ORDINALITY AS u(x, o) WHERE ((SELECT channel FROM request WHERE id = x) = arg2) ORDER BY o)) WITH ORDINALITY AS u(x, o), unnest((SELECT confirmed FROM request WHERE id = x)) WITH ORDINALITY AS v(m, i) ORDER BY o, i) $$;

-- asked: derived, never stored
-- described by the_sender_is_never_asked
CREATE FUNCTION asked(request_id integer) RETURNS integer[] LANGUAGE sql STABLE AS $$
  SELECT ARRAY(SELECT x FROM unnest(request.audience) WITH ORDINALITY AS u(x, o) WHERE (NOT (x = request.sender)) ORDER BY o) FROM request WHERE id = $1 $$;

-- readRoom: derived, not yet drawn (data over Eih.Treaty.Room)

-- seasonView: derived, not yet drawn (a list of lists — the shadow holds no jagged array)

-- venue_chart: derived, not yet drawn (calls venue_table, beyond the fragment)

-- venueTable: derived, not yet drawn (data over Eih.Treaty.Table)

-- sheet: derived, never stored
-- described by everyone_is_here, the_caterer_reads_the_delivery, the_delivery_is_the_sheet
CREATE FUNCTION sheet(party_ids integer[]) RETURNS integer[] LANGUAGE sql STABLE AS $$
  SELECT (SELECT array_agg(m ORDER BY g.position) FROM unnest($1) WITH ORDINALITY AS g(elem_id, position) JOIN party p ON p.id = g.elem_id, unnest(p.meals) m WHERE p.rsvp) $$;

-- visible: a check, derived, never stored
-- described by a_file_is_never_wider_than_its_channel, a_vendor_room_file_is_absent_from_the_couples_files
CREATE FUNCTION visible(file_id integer, arg2 integer) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT (arg2 = ANY(SELECT unnest((SELECT audience FROM channel WHERE id = file.channel)))) FROM file WHERE id = $1 $$;

-- canSee: a check, derived, never stored
-- described by a_vendor_room_file_is_absent_from_the_couples_files
CREATE FUNCTION can_see(file_id integer, arg2 integer) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT (arg2 = ANY(SELECT unnest((SELECT audience FROM channel WHERE id = file.channel)))) FROM file WHERE id = $1 $$;

-- mayClose: a check, derived, never stored
-- described by a_vendor_may_not_close_anothers, the_couple_may_close, the_owner_may_close
CREATE FUNCTION may_close(member_id integer, arg2 integer) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT ((member.user_ = (SELECT owner FROM task WHERE id = arg2)) OR ((member.role = 'couple') OR (member.role = 'planner'))) FROM member WHERE id = $1 $$;

-- vendorSide: a check, derived, never stored
-- described by the_vendor_room_is_derived_from_the_roster
CREATE FUNCTION vendor_side(member_id integer) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT ((member.role = 'vendor') OR ((member.role = 'venue') OR (member.role = 'planner'))) FROM member WHERE id = $1 $$;

-- mayOpen: a check, derived, never stored
-- described by anyone_may_open_a_task
CREATE FUNCTION may_open(member_id integer) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT true FROM member WHERE id = $1 $$;

-- withBach: a clerk — never a second copy of the row, an update to it
-- described by the_bach_parts_the_best_man, the_bach_touches_only_the_bach, the_bach_wall
CREATE FUNCTION with_bach(room_id integer, arg2 integer[]) RETURNS void LANGUAGE sql AS $$
  UPDATE room SET bach = arg2 WHERE id = $1 $$;

-- ask: a clerk over a has-many field (requests) — not yet drawn

-- withLine: a clerk over the has-many ledger — a prepend: shift the child rows, insert at zero
-- described by a_line_touches_only_the_ledger, a_vendor_never_sees_anothers_invoice, linda_never_sees_the_ledger, the_caterer_never_sees_the_ledger
CREATE FUNCTION with_line(room_id integer, arg2 integer[]) RETURNS void LANGUAGE sql AS $$
  UPDATE room_ledger SET position = position + 1 WHERE room_id = $1;
  INSERT INTO room_ledger (room_id, position, c0, c1, c2) VALUES ($1, 0, $2[1], $2[2], $2[3]) $$;

-- confirm: a clerk — never a second copy of the row, an update to it
-- described by a_confirmation_elsewhere_leaves_a_channel, outside_the_audience_hears_no_receipt
CREATE FUNCTION confirm(request_id integer, arg2 integer) RETURNS void LANGUAGE sql AS $$
  UPDATE request SET confirmed = array_prepend(arg2, request.confirmed) WHERE id = $1 $$;

-- close: a clerk — never a second copy of the row, an update to it
CREATE FUNCTION close(task_id integer) RETURNS void LANGUAGE sql AS $$
  UPDATE task SET done = true WHERE id = $1 $$;

-- withGuests: a clerk over the has-many guests — a replacement: delete, then insert in order
-- described by the_caterer_never_sees_the_guests, the_guests_touch_only_the_guests, the_maker_sees_shape_not_content
CREATE FUNCTION with_guests(room_id integer, arg2 integer[]) RETURNS void LANGUAGE sql AS $$
  DELETE FROM room_guests WHERE room_id = $1;
  INSERT INTO room_guests (room_id, position, party_id) SELECT $1, ordinality - 1, id FROM unnest($2) WITH ORDINALITY AS u(id, ordinality) $$;

-- assign: a clerk — never a second copy of the row, an update to it
CREATE FUNCTION assign(task_id integer, arg2 integer) RETURNS void LANGUAGE sql AS $$
  UPDATE task SET assignee = arg2 WHERE id = $1 $$;

-- edits: a rule over role, derived, never stored
CREATE FUNCTION edits(role, page) RETURNS boolean LANGUAGE sql IMMUTABLE AS $$
  SELECT ($2 = ANY(SELECT unnest(edited($1)))) $$;

-- sees: a rule over role, derived, never stored
CREATE FUNCTION sees(role, page) RETURNS boolean LANGUAGE sql IMMUTABLE AS $$
  SELECT ($2 = ANY(SELECT unnest(seen($1)))) $$;

-- seasonOwed: derived, never stored
-- described by the_seasons_sum_is_over_my_own_invoices
CREATE FUNCTION season_owed(room_ids integer[], arg2 integer) RETURNS integer LANGUAGE sql STABLE AS $$
  SELECT (SELECT coalesce(sum(x), 0) FROM unnest(ARRAY(SELECT m FROM unnest($1) WITH ORDINALITY AS u(x, o), unnest((SELECT mine FROM room_as_vendor_face(x, arg2))) WITH ORDINALITY AS v(m, i) ORDER BY o, i)) AS x) $$;

-- vendorRoomMembers: derived, never stored
-- described by a_vendor_is_in_the_vendor_room, the_couple_is_never_in_the_vendor_room, the_wedding_party_is_never_in_the_vendor_room
CREATE FUNCTION vendor_room_members(member_ids integer[]) RETURNS integer[] LANGUAGE sql STABLE AS $$
  SELECT ARRAY(SELECT x FROM unnest($1) WITH ORDINALITY AS u(x, o) WHERE vendor_side(x) ORDER BY o) $$;

-- tally: derived, never stored
-- described by the_same_page_hears_its_own_earshot
CREATE FUNCTION tally(request_id integer) RETURNS integer LANGUAGE sql STABLE AS $$
  SELECT cardinality(ARRAY(SELECT x FROM unnest(request.confirmed) WITH ORDINALITY AS u(x, o) WHERE (x = ANY(SELECT unnest(asked(request.id)))) ORDER BY o)) FROM request WHERE id = $1 $$;

-- heads: derived, never stored
-- described by (drawn by the_sheet_counts_the_heads), everyone_is_here
CREATE FUNCTION heads(party_ids integer[]) RETURNS integer LANGUAGE sql STABLE AS $$
  SELECT cardinality(sheet($1)) $$;

-- lawful: a check, derived, never stored
-- described by the_payer_is_the_owner_or_the_host
CREATE FUNCTION lawful(bill_id integer) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT ((bill.payer = owner(bill.thing)) OR ((bill.payer = 'vendor') AND (owner(bill.thing) = 'couple'))) FROM bill WHERE id = $1 $$;

-- settled: a check, derived, never stored
-- described by everyone_clear_means_every_request_settled, everyone_is_here
CREATE FUNCTION settled(request_id integer) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT (asked(request.id) <@ request.confirmed) FROM request WHERE id = $1 $$;

-- deliver: a clerk — never a second copy of the row, an update to it
-- described by the_caterer_reads_the_delivery, the_delivery_is_the_sheet, the_delivery_moves_no_guest
CREATE FUNCTION deliver(room_id integer) RETURNS void LANGUAGE sql AS $$
  UPDATE room SET delivered = sheet((SELECT array_agg(party_id ORDER BY position) FROM room_guests c WHERE c.room_id = room.id)) WHERE id = $1 $$;

-- confirmIn: a clerk over the has-many requests — the element's clerk confirm run on each child the condition selects
-- described by a_confirmation_parts_the_audience, a_confirmation_touches_only_its_channel, a_vendor_room_confirmation_touches_only_the_vendor_room, everyone_is_here, the_couple_side_witnesses_no_vendor_room_license, the_vendor_room_holds_its_own_receipt
CREATE FUNCTION confirm_in(room_id integer, arg2 integer, arg3 integer) RETURNS void LANGUAGE sql AS $$
  SELECT confirm(c.request_id, arg3) FROM room_requests c WHERE c.room_id = $1 AND ((SELECT channel FROM request WHERE id = c.request_id) = arg2) $$;

-- samePage: derived, never stored
-- described by the_same_page_counts_only_within_earshot, the_same_page_hears_its_own_earshot
CREATE FUNCTION same_page(request_ids integer[], arg2 integer) RETURNS integer LANGUAGE sql STABLE AS $$
  SELECT (SELECT coalesce(sum(x), 0) FROM unnest(ARRAY(SELECT tally(x) FROM unnest(ARRAY(SELECT x FROM unnest($1) WITH ORDINALITY AS u(x, o) WHERE (arg2 = ANY(SELECT unnest((SELECT audience FROM request WHERE id = x)))) ORDER BY o)) WITH ORDINALITY AS u(x, o) ORDER BY o)) AS x) $$;

-- unanswered: derived, never stored
CREATE FUNCTION unanswered(request_ids integer[]) RETURNS integer[] LANGUAGE sql STABLE AS $$
  SELECT ARRAY(SELECT x FROM unnest($1) WITH ORDINALITY AS u(x, o) WHERE (NOT settled(x)) ORDER BY o) $$;

-- vendorRoomAudience: derived, never stored
-- described by the_vendor_room_is_derived_from_the_roster
CREATE FUNCTION vendor_room_audience(member_ids integer[]) RETURNS integer[] LANGUAGE sql STABLE AS $$
  SELECT ARRAY(SELECT (SELECT user_ FROM member WHERE id = x) FROM unnest(vendor_room_members($1)) WITH ORDINALITY AS u(x, o) ORDER BY o) $$;

-- memberSees: a check, derived, never stored
-- described by an_edit_is_within_the_lane, lanes_shrink_never_lock, the_day_lane_keeps_the_day_of_sheet, the_day_lane_sees_no_task_list
CREATE FUNCTION member_sees(member_id integer, arg2 page) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT (sees(member.role, arg2) AND (NOT (member.day_lane AND (arg2 = 'tasks')))) FROM member WHERE id = $1 $$;

-- allClear: a check, derived, never stored
-- described by everyone_clear_means_every_request_settled, everyone_clear_means_rose_ate, everyone_is_here
CREATE FUNCTION all_clear(room_id integer) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT ((room.delivered = sheet((SELECT array_agg(party_id ORDER BY position) FROM room_guests c WHERE c.room_id = room.id))) AND (unanswered((SELECT array_agg(request_id ORDER BY position) FROM room_requests c WHERE c.room_id = room.id)) = ARRAY[]::integer[])) FROM room WHERE id = $1 $$;

-- memberEdits: a check, derived, never stored
-- described by an_edit_is_within_the_lane
CREATE FUNCTION member_edits(member_id integer, arg2 page) RETURNS boolean LANGUAGE sql STABLE AS $$
  SELECT (edits(member.role, arg2) AND member_sees(member.id, arg2)) FROM member WHERE id = $1 $$;

-- catererSeat: hears timeline, sheet, confirmed, vendorRoom
-- licensed by the_caterer_never_sees_the_guests, the_caterer_never_sees_the_ledger
CREATE VIEW room_as_caterer_seat AS SELECT room.id, f.timeline, f.sheet, f.confirmed, f.vendor_room FROM room, LATERAL room_as_room_face(room.id) f;

-- roomSeat: hears guests, sheet, ledger, timeline, bach, confirmed, vendorRoom
-- licensed by the_room_covers_itself, the_room_witnesses_the_license
CREATE VIEW room_as_room_seat AS SELECT room.id, f.guests, f.sheet, f.ledger, f.timeline, f.bach, f.confirmed, f.vendor_room FROM room, LATERAL room_as_room_face(room.id) f;

-- lindaSeat: hears guests, timeline, confirmed
-- licensed by everyone_is_here, linda_never_sees_the_ledger, the_vendor_room_holds_its_own_receipt
CREATE VIEW room_as_linda_seat AS SELECT room.id, f.guests, f.timeline, f.confirmed FROM room, LATERAL room_as_room_face(room.id) f;

-- coupleSeat: hears guests, sheet, ledger, timeline, confirmed
-- licensed by a_confirmation_parts_the_audience, everyone_is_here, the_bach_wall, the_vendor_room_holds_its_own_receipt
CREATE VIEW room_as_couple_seat AS SELECT room.id, f.guests, f.sheet, f.ledger, f.timeline, f.confirmed FROM room, LATERAL room_as_room_face(room.id) f;

-- pages: hears floorPlan, guestList, samePage, invoices, budget, guests, site, team, dayOf, tasks
CREATE VIEW member_as_pages AS SELECT id, role AS floor_plan, role AS guest_list, role AS same_page, role AS invoices, role AS budget, role AS guests, role AS site, role AS team, role AS day_of, role AS tasks FROM member;

-- bestManSeat: hears timeline, bach, confirmed
-- licensed by everyone_is_here, the_bach_parts_the_best_man, the_bach_wall, the_vendor_room_holds_its_own_receipt
CREATE VIEW room_as_best_man_seat AS SELECT room.id, f.timeline, f.bach, f.confirmed FROM room, LATERAL room_as_room_face(room.id) f;