Zerf home

2 What she produced

The real run of this version: It's Monday. Do the Monday work described in CLAUDE.md, using the OPERA export in data/opera.

insights.json

{
  "week_start": "2027-10-18",
  "insights": [
    {
      "property_id": "HOTEL-001",
      "what_changed": "The next 7 days average 66.56% occupancy on the books. The last 7 days averaged 57.27%. That is up 9.29 points.",
      "why": "Most of the lift comes from Sunday 2027-10-24 at 85%. The other six dates sit between 60.43% and 66%.",
      "what_to_look_at": "Do not read the week as strong across the board. Take out 2027-10-24 and the week is close to the 63% line.",
      "evidence": [
        "outputs/report.json last_7_days",
        "data/opera/hotel-001.json occupancy[0] to occupancy[13]"
      ]
    },
    {
      "property_id": "HOTEL-001",
      "what_changed": "Two dates are below the 63% threshold: 2027-10-18 at 60.43% with 490 rooms open, and 2027-10-23 at 62.74% with 461 rooms open.",
      "why": "Group business does not fill these dates. The only group in the grid has 2 rooms on 2027-10-18 and none on 2027-10-23.",
      "what_to_look_at": "Today is already 2027-10-18, so focus on Saturday 2027-10-23. It has the most time left to sell.",
      "evidence": [
        "outputs/report.json rows[0] (occupancy[7]; availability[0])",
        "outputs/report.json rows[5] (occupancy[12]; availability[5])",
        "config/thresholds.json occupancy_on_books"
      ]
    },
    {
      "property_id": "HOTEL-001",
      "what_changed": "2027-10-24 shows 85% occupancy and 186 rooms left. That is far above every other date.",
      "why": "The export has no hotel-level availability row for that date, so the 186 rooms are derived from inventory and occupancy. 85% is also the top of the scaled occupancy range in the export.",
      "what_to_look_at": "Check 2027-10-24 in OPERA before you change prices or close sales for that date.",
      "evidence": [
        "outputs/report.json rows[6] (occupancy[13]; derived from inventory)",
        "data/opera/hotel-001.json metadata.occupancyScaled"
      ]
    },
    {
      "property_id": "HOTEL-001",
      "what_changed": "Group pickup is 0 of 2 rooms allocated for BLOCK-001 on 2027-10-18 and 2027-10-19. BLOCK-020 (401 rooms, tentative) has both of its events cancelled.",
      "why": "Cancelled events never count as demand. BLOCK-020 is tentative, has 0 actual rooms and does not take rooms from inventory, so it adds nothing to the week.",
      "what_to_look_at": "Ask sales if BLOCK-020 is still alive. The group grid covers only 1 of 25 blocks, and the export lists 25 of 29 groups, so group numbers are incomplete.",
      "evidence": [
        "outputs/normalized/groups.csv rows for BLOCK-001",
        "data/opera/hotel-001.json groups (BLOCK-020)",
        "data/opera/hotel-001.json events[0], events[1]",
        "data/opera/hotel-001.json metadata.groupsReturned, metadata.groupsReportedTotal"
      ]
    },
    {
      "property_id": "HOTEL-001",
      "what_changed": "45 rooms have open maintenance records on every date this week.",
      "why": "The records have no end dates, so the report shows the same count for every date.",
      "what_to_look_at": "Ask engineering which of the 45 rooms can return to sale before Saturday 2027-10-23.",
      "evidence": [
        "outputs/report.json rows[0] to rows[6] rooms_with_open_maintenance",
        "outputs/normalized/maintenance.csv"
      ]
    }
  ]
}

report.csv

property_id,week_start,date,occupancy_on_books,rooms_available,below_threshold,group_rooms_allocated,group_rooms_picked_up,rooms_with_open_maintenance,source_file,source_row
HOTEL-001,2027-10-18,2027-10-18,0.6043,490,true,2,0,45,hotel-001.json,occupancy[7]; availability[0]
HOTEL-001,2027-10-18,2027-10-19,0.66,421,false,2,0,45,hotel-001.json,occupancy[8]; availability[1]
HOTEL-001,2027-10-18,2027-10-20,0.6478,436,false,0,0,45,hotel-001.json,occupancy[9]; availability[2]
HOTEL-001,2027-10-18,2027-10-21,0.6342,453,false,0,0,45,hotel-001.json,occupancy[10]; availability[3]
HOTEL-001,2027-10-18,2027-10-22,0.6355,451,false,0,0,45,hotel-001.json,occupancy[11]; availability[4]
HOTEL-001,2027-10-18,2027-10-23,0.6274,461,true,0,0,45,hotel-001.json,occupancy[12]; availability[5]
HOTEL-001,2027-10-18,2027-10-24,0.85,186,false,0,0,45,hotel-001.json,occupancy[13]; derived from inventory

report.json

{
  "business_date": "2027-10-18",
  "property_id": "HOTEL-001",
  "threshold": 0.63,
  "rows": [
    {
      "date": "2027-10-18",
      "occupancy_on_books": 0.6043,
      "rooms_available": 490,
      "below_threshold": true,
      "group_rooms_allocated": 2,
      "group_rooms_picked_up": 0,
      "rooms_with_open_maintenance": 45,
      "source_file": "hotel-001.json",
      "source_row": "occupancy[7]; availability[0]"
    },
    {
      "date": "2027-10-19",
      "occupancy_on_books": 0.66,
      "rooms_available": 421,
      "below_threshold": false,
      "group_rooms_allocated": 2,
      "group_rooms_picked_up": 0,
      "rooms_with_open_maintenance": 45,
      "source_file": "hotel-001.json",
      "source_row": "occupancy[8]; availability[1]"
    },
    {
      "date": "2027-10-20",
      "occupancy_on_books": 0.6478,
      "rooms_available": 436,
      "below_threshold": false,
      "group_rooms_allocated": 0,
      "group_rooms_picked_up": 0,
      "rooms_with_open_maintenance": 45,
      "source_file": "hotel-001.json",
      "source_row": "occupancy[9]; availability[2]"
    },
    {
      "date": "2027-10-21",
      "occupancy_on_books": 0.6342,
      "rooms_available": 453,
      "below_threshold": false,
      "group_rooms_allocated": 0,
      "group_rooms_picked_up": 0,
      "rooms_with_open_maintenance": 45,
      "source_file": "hotel-001.json",
      "source_row": "occupancy[10]; availability[3]"
    },
    {
      "date": "2027-10-22",
      "occupancy_on_books": 0.6355,
      "rooms_available": 451,
      "below_threshold": false,
      "group_rooms_allocated": 0,
      "group_rooms_picked_up": 0,
      "rooms_with_open_maintenance": 45,
      "source_file": "hotel-001.json",
      "source_row": "occupancy[11]; availability[4]"
    },
    {
      "date": "2027-10-23",
      "occupancy_on_books": 0.6274,
      "rooms_available": 461,
      "below_threshold": true,
      "group_rooms_allocated": 0,
      "group_rooms_picked_up": 0,
      "rooms_with_open_maintenance": 45,
      "source_file": "hotel-001.json",
      "source_row": "occupancy[12]; availability[5]"
    },
    {
      "date": "2027-10-24",
      "occupancy_on_books": 0.85,
      "rooms_available": 186,
      "below_threshold": false,
      "group_rooms_allocated": 0,
      "group_rooms_picked_up": 0,
      "rooms_with_open_maintenance": 45,
      "source_file": "hotel-001.json",
      "source_row": "occupancy[13]; derived from inventory"
    }
  ],
  "last_7_days": {
    "start_date": "2027-10-11",
    "end_date": "2027-10-17",
    "days": 7,
    "occupancy_avg": 0.5727,
    "next_7_days_occupancy_avg": 0.6656,
    "change_vs_last_7_days": 0.0929
  },
  "warnings": [
    "rooms_available for 2027-10-24 is derived from the inventory and the occupancy: the export has no hotel-level availability row for that date.",
    "The group grid covers 1 of 25 blocks listed in the export. Group numbers cover only the blocks in the grid.",
    "rooms_with_open_maintenance is one count for every date: the export has no end dates for maintenance records.",
    "Sources disagree on event dates: hotel-001.json metadata.eventWindow says 2027-10-20 to 2027-10-21, but hotel-001.json events[0] and events[1] are dated 2027-10-23 and 2027-10-24. Both events are cancelled and count as no demand.",
    "Sources disagree on group count: hotel-001.json metadata.groupsReportedTotal says 29 groups, but the groups section (metadata.groupsReturned) has 25. Four groups are missing from the export."
  ]
}