Sam asked for the next protective step after the SAIL-AWAY PTO cutover: a report-only worker that checks approved future PTO records for blank Outlook IDs, IDs still pointing to SAIL Boat, and unreadable SAIL-AWAY event links. The scope was staging only. Scheduling, repair writes, alerts, and go-live remain separate.
Created a local read-only worker at /Users/samaguiar/Documents/Projects/admin/outlook-audits/sail-away-calendar-migration-20260603/sail_away_pto_drift_monitor.py. It queries live LITIFY_ORG for approved future Time_Off_Request__c rows, resolves the SAIL Boat calendar live through Microsoft Graph, reads each Salesforce event ID against SAIL-AWAY first, then checks the legacy SAIL Boat paths only when SAIL-AWAY cannot read the ID.
Created unit tests at /Users/samaguiar/Documents/Projects/admin/outlook-audits/sail-away-calendar-migration-20260603/test_sail_away_pto_drift_monitor.py and a runbook at /Users/samaguiar/Documents/Projects/admin/outlook-audits/sail-away-calendar-migration-20260603/SAIL-AWAY-PTO-drift-monitor-runbook-2026-06-15.md.
The worker emits machine-readable JSON reports named sail-away-pto-drift-monitor-report-<UTC timestamp>.json. The verified report from the final code path is /Users/samaguiar/Documents/Projects/admin/outlook-audits/sail-away-calendar-migration-20260603/sail-away-pto-drift-monitor-report-20260615T114241Z.json.
Live Salesforce read: sf org list --json showed LITIFY_ORG connected as sam@kylawoffice.com. The worker then ran live SOQL against Time_Off_Request__c for approved future PTO rows.
Live Graph read: the worker used the existing Graph diagnostic auth path and read SAIL-AWAY plus Nathaniel Hatfield's SAIL Boat calendar. It did not create, patch, delete, schedule, or notify.
Verification commands passed: python3 -m unittest admin/outlook-audits/sail-away-calendar-migration-20260603/test_sail_away_pto_drift_monitor.py, python3 -m py_compile ..., and a live report-only worker run.
The verified live report checked 38 approved future PTO rows. Summary: 34 rows were readable on SAIL-AWAY, 4 rows were readable on legacy SAIL Boat, 0 rows had blank Outlook_Event_ID__c, and 0 rows were fully unreadable.
The 4 drift rows are the June 14 catch-up records: a4RUV000004NOFR2A4 Payton Klatt, a4RUV000004RDlF2AW Charles Willis, a4RUV000004OqmL2AS Jenni Hubbard, and a4RUV000004RDmr2AG Charles Willis. Each current Salesforce event ID returned SAIL-AWAY 404 and SAIL Boat 200.
/Users/samaguiar/Documents/Projects/admin/outlook-audits/sail-away-calendar-migration-20260603/sail_away_pto_drift_monitor.py/Users/samaguiar/Documents/Projects/admin/outlook-audits/sail-away-calendar-migration-20260603/test_sail_away_pto_drift_monitor.py/Users/samaguiar/Documents/Projects/admin/outlook-audits/sail-away-calendar-migration-20260603/SAIL-AWAY-PTO-drift-monitor-runbook-2026-06-15.md/Users/samaguiar/Documents/Projects/admin/outlook-audits/sail-away-calendar-migration-20260603/sail-away-pto-drift-monitor-report-20260615T114241Z.json/Users/samaguiar/Documents/Projects/Repos/sail-litify/Litify_AI_Integration_Project/docs/litify-environment-diary.md/Users/samaguiar/Documents/Projects/Repos/sail-litify/Litify_AI_Integration_Project/OPS_LEDGER.md