upskill-event-manager/Status.md
ben 7b895ad785
Some checks failed
HVAC Plugin CI/CD Pipeline / Security Analysis (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Code Quality & Standards (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Unit Tests (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Integration Tests (push) Has been cancelled
Security Monitoring & Compliance / Dependency Vulnerability Scan (push) Has been cancelled
Security Monitoring & Compliance / Secrets & Credential Scan (push) Has been cancelled
Security Monitoring & Compliance / WordPress Security Analysis (push) Has been cancelled
Security Monitoring & Compliance / Static Code Security Analysis (push) Has been cancelled
Security Monitoring & Compliance / Security Compliance Validation (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Deploy to Production (push) Has been cancelled
HVAC Plugin CI/CD Pipeline / Notification (push) Has been cancelled
Security Monitoring & Compliance / Security Summary Report (push) Has been cancelled
Security Monitoring & Compliance / Security Team Notification (push) Has been cancelled
docs: update Status.md with Zoho user sync production fixes
Documents the iterative debugging of user sync on production:
version constant mismatch, GET search criteria fix, error reporting
priority, phone/name validation, and spam account cleanup.
Final result: 64/64 active trainers syncing to Zoho CRM.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 12:58:24 -04:00

1156 lines
48 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HVAC Community Events - Project Status
**Last Updated:** February 6, 2026
**Current Session:** Zoho CRM Sync Production Fix
**Version:** 2.2.11 (Deployed to Production)
---
## 🎯 NEXT SESSION - CAPTCHA IMPLEMENTATION
### Status: 📋 **PLANNED**
**Objective:** Add CAPTCHA to all user-facing forms to prevent spam and bot submissions.
**Forms to Update:**
- Training login form
- Trainer registration form
- Contact forms (trainer, venue)
- Any other public-facing forms
---
## 🎯 CURRENT SESSION - ZOHO CRM SYNC PRODUCTION FIX (Feb 6, 2026)
### Status: ✅ **COMPLETE - 64/64 Trainers Syncing to Zoho CRM**
**Objective:** Fix Zoho CRM user sync that was silently failing on production - 0/65 users syncing despite "connection successful" status.
### Issues Found & Fixed (iterative production debugging)
1. **Version Constant Mismatch** (`includes/class-hvac-plugin.php`)
- `HVAC_PLUGIN_VERSION` stuck at `'2.0.0'` while `HVAC_VERSION` was `'2.2.10'`
- Admin JS used `HVAC_PLUGIN_VERSION` for cache busting, so browser served old JS without reset handler
- Fix: Bumped both constants to `'2.2.11'`
2. **GET Request Search Criteria Ignored** (`includes/zoho/class-zoho-sync.php`)
- `sync_users()` passed search criteria as `$data` parameter to `make_api_request()`
- But `make_api_request()` ignores `$data` for GET requests (line 345 only includes body for POST/PUT/PATCH)
- Every Zoho contact search returned unfiltered results, causing all syncs to fail
- Fix: Moved criteria into URL query string: `/Contacts/search?criteria=(Email:equals:...)`
3. **Error Reporting Priority** (`includes/zoho/class-zoho-sync.php`)
- `validate_api_response()` checked generic `error` key before Zoho-specific `data[0]` errors
- Users saw "API error with status code 400" instead of actionable field-level errors
- Fix: Reordered to check Zoho `data[0]` errors first, added field-level detail (api_name, expected_data_type, info)
4. **Phone Field Validation** (`includes/zoho/class-zoho-sync.php`)
- Zoho rejects invalid phone formats with HTTP 400
- Fix: Strip non-digit chars, require 10+ digits, only include Phone field when valid
5. **Last_Name Required Field** (`includes/zoho/class-zoho-sync.php`)
- Zoho Contacts module requires Last_Name but some WP users had empty last names
- Fix: Fallback chain: `last_name` meta → `display_name``user_login`
6. **Spam Account Cleanup** (production WP-CLI)
- User 14 (`rigobertohugo19`, `info103@noreply0.com`) was a spam/bot registration with no name
- Demoted from `hvac_trainer` to `subscriber`
### Production Sync Results (iterative)
| Attempt | Synced | Failed | Issue |
|---------|--------|--------|-------|
| 1st (pre-fix) | 0 | 65 | Search criteria not sent to Zoho API |
| 2nd (search fix) | 63 | 2 | Generic "status code 400" errors |
| 3rd (error detail) | 0 | 2 | User 57: invalid Phone, User 14: missing Last_Name |
| 4th (data validation) | 31 | 1 | User 57 phone still failing (7-digit threshold too low) |
| 5th (10-digit threshold) | 26 | 0 | **All 65 trainers synced** |
| Final (User 14 demoted) | **64/64** | **0** | All active trainers syncing |
### Files Modified
| File | Change |
|------|--------|
| `includes/class-hvac-plugin.php` | Synced `HVAC_PLUGIN_VERSION` to `'2.2.11'` (was stuck at `'2.0.0'`) |
| `includes/zoho/class-zoho-sync.php` | Search criteria in URL, error priority fix, phone sanitization, Last_Name fallback |
### Git Commits
- `03b9bce5` - fix(zoho): Fix silent sync failures with API response validation and hash reset
- `4c22b9db` - fix(zoho): Fix user sync search criteria and improve data validation
---
## 📋 PREVIOUS SESSION - ZOHO CRM SYNC ARCHITECTURE FIX (Feb 6, 2026)
### Status: ✅ **COMPLETE - Deployed to Production**
**Objective:** Fix Zoho CRM integration that appeared connected but was silently failing to sync data (events, attendees, ticket sales not appearing in Zoho CRM).
### Root Cause Analysis (4-model consensus: GPT-5, Gemini 3, Zen Code Review, Zen Debug)
The sync pipeline had a "silent failure" architecture:
1. **Connection test only uses GET** - bypasses staging write block, giving false confidence
2. **Staging mode returned fake `'status' => 'success'`** for blocked writes - appeared successful
3. **Sync methods unconditionally updated `_zoho_sync_hash`** after any "sync" - poisoned hashes
4. **Subsequent syncs compared hashes, found matches, skipped all records** - permanent data loss
5. **No API response validation** - even real Zoho errors were silently ignored
### Fixes Implemented
1. **API Response Validation** (`includes/zoho/class-zoho-sync.php`)
- Added `validate_api_response()` helper method
- Checks for WP_Error, staging mode blocks, HTTP errors, Zoho error codes
- Confirms success with ID extraction before treating a sync as successful
2. **Hash-Only-On-Success** (`includes/zoho/class-zoho-sync.php`)
- All 5 sync methods (events, users, attendees, rsvps, purchases) rewritten
- `_zoho_sync_hash` only updates when Zoho API confirms the write succeeded
- Failed syncs increment `$results['failed']` with error details
- Changed `catch (Exception)` to `catch (\Throwable)` for comprehensive error handling
3. **Staging Mode Detection Fix** (`includes/zoho/class-zoho-crm-auth.php`)
- Replaced fragile `strpos()` substring matching with `wp_parse_url()` hostname comparison
- Production (`upskillhvac.com` / `www.upskillhvac.com`) explicitly whitelisted
- All other hostnames default to staging mode
- `HVAC_ZOHO_PRODUCTION_MODE` / `HVAC_ZOHO_STAGING_MODE` constants can override
- Staging fake responses now return `'skipped_staging'` instead of misleading `'success'`
4. **Admin UI: Hash Reset & Staging Warning** (`includes/admin/class-zoho-admin.php`, `assets/js/zoho-admin.js`)
- Added `reset_sync_hashes()` AJAX handler - clears all `_zoho_sync_hash` from postmeta and usermeta
- Added "Force Full Re-sync (Reset Hashes)" button with confirmation dialog
- Connection test now surfaces staging warning when staging mode is active
5. **Staging Environment Fix** (staging `wp-config.php`)
- Removed `HVAC_ZOHO_PRODUCTION_MODE` constant from staging wp-config.php
- Staging now correctly blocks all Zoho write operations via hostname detection
- GET requests (reads) still pass through for testing
### Files Modified
| File | Change |
|------|--------|
| `includes/zoho/class-zoho-sync.php` | Added `validate_api_response()`, rewrote all 5 sync methods for validated hashing |
| `includes/zoho/class-zoho-crm-auth.php` | Rewrote `is_staging_mode()` with hostname parsing, changed fake response status |
| `includes/admin/class-zoho-admin.php` | Added `reset_sync_hashes()` handler, reset button HTML, staging warning in connection test |
| `assets/js/zoho-admin.js` | Added reset hashes button handler, staging warning display in connection test |
---
## 📋 PREVIOUS SESSION - NEAR ME BUTTON MOBILE FIX (Feb 6, 2026)
### Status: ✅ **COMPLETE - Deployed to Staging**
**Objective:** Fix mobile layout issue where the "Near Me" button caused the search bar to shrink when location was granted.
### Issues Found & Fixed
1.**CSS/HTML Button Structure Bug** (`assets/js/find-training-filters.js`)
- When the Near Me button state changed, the HTML was replaced without the `.hvac-btn-text` wrapper class
- On mobile, CSS hides `.hvac-btn-text`, but unwrapped text was visible causing layout issues
- Fixed in 5 locations: loading state, success state, error reset, clear filters, remove location filter
2.**No Feedback for Empty Results** (`assets/js/find-training-filters.js`)
- When "Near Me" filter returned no results within 100km, user saw empty map with no explanation
- Added notification: "No trainers, venues, or events found within 100km of your location. Try removing the 'Near Me' filter to see all results."
### Files Modified
| File | Change |
|------|--------|
| `assets/js/find-training-filters.js` | Fixed button HTML to preserve `.hvac-btn-text` wrapper; added empty results notification |
### Code Changes
**Button HTML Fix (5 locations):**
```javascript
// Before (broken on mobile):
$button.html('<span class="dashicons dashicons-yes-alt"></span> Near Me');
// After (correct):
$button.html('<span class="dashicons dashicons-yes-alt"></span><span class="hvac-btn-text">Near Me</span>');
```
**Empty Results Notification:**
```javascript
if (self.userLocation) {
const totalResults = HVACTrainingMap.trainers.length +
HVACTrainingMap.venues.length +
HVACTrainingMap.events.length;
if (totalResults === 0) {
self.showLocationError('No trainers, venues, or events found within 100km...');
}
}
```
### Mobile Testing Performed
- ✅ 375x812 (iPhone X) - Map and markers display correctly
- ✅ 320x568 (iPhone SE) - Map and markers display correctly
- ✅ Cluster markers expand on click
- ✅ Individual trainer markers clickable
- ✅ Info windows display correctly
- ✅ Profile modal opens and displays correctly
---
## 📋 PREVIOUS SESSION - CHAMPION DIFFERENTIATION ON FIND TRAINING (Feb 2, 2026)
### Status: ✅ **COMPLETE - Deployed to Production**
**Objective:** Differentiate measureQuick Certified Champions from Trainers on the Find Training map. Champions do not offer public training, so they should be displayed differently.
### Changes Made
1.**Backend Data** (`includes/find-training/class-hvac-training-map-data.php`)
- Added `is_champion` flag for trainers with "Certified measureQuick Champion" certification
- Champions return empty `city` field (only state shown)
2.**Champion Marker Icon** (`assets/js/find-training-map.js`)
- Added `getChampionIcon()` method with white outline (vs green for Trainers)
- Champions use distinct visual appearance on map
3.**Sidebar Cards** (`assets/js/find-training-map.js`)
- Champions show only state (e.g., "Ohio" not "Canton, Ohio")
- Champions have non-clickable cards (no modal popup)
- Added `hvac-champion-card` CSS class
4.**Info Windows** (`assets/js/find-training-map.js`)
- Champions show only state in location
- No "View Profile" button for Champions
- Fixed location formatting to handle empty city gracefully
5.**Sorting** (`assets/js/find-training-map.js`)
- Champions sorted to end of trainer list
- Secondary sort by name for stable ordering
- Applied to both `loadMapData` and `loadTrainerDirectory`
6.**CSS Styling** (`assets/css/find-training-map.css`)
- Champion cards have non-clickable appearance
- No hover effects (cursor: default, no transform/shadow)
### Files Modified
| File | Change |
|------|--------|
| `includes/find-training/class-hvac-training-map-data.php` | Added `is_champion` flag, empty city for champions |
| `assets/js/find-training-map.js` | Champion icon, card display, click prevention, sorting |
| `assets/css/find-training-map.css` | Champion card non-clickable styling |
### Verification (Staging)
- ✅ API returns `is_champion: true` for 18 champions
- ✅ Champions have empty city in API response
- ✅ Champions sorted to end of list
- ✅ Champion cards show only state
- ✅ Clicking champion card does NOT open modal
- ✅ Clicking trainer card DOES open modal (regression test)
### Code Review Findings (Gemini 3)
- **Fixed:** Location formatting bug - empty city could show ", California"
- **Fixed:** Unstable sort order - added secondary sort by name
---
## 📋 PREVIOUS SESSION - TABBED INTERFACE FOR FIND TRAINING (Feb 1, 2026)
### Status: ✅ **COMPLETE - Deployed to Production**
**Objective:** Refactor the Find Training page sidebar from a single trainer list to a tabbed interface with Trainers, Venues, and Events tabs.
### Changes Made
1.**Tab Navigation System** (`templates/page-find-training.php`)
- Replaced "42 trainers" header with three tabs: Trainers | Venues | Events
- Each tab displays dynamic count in parentheses
- ARIA accessibility attributes (role="tablist", role="tab", aria-selected)
- Keyboard navigation (arrow keys, Home, End)
2.**Visibility Toggles Relocated**
- Moved from map overlay to sidebar header
- Colored dots (teal/orange/purple) match marker colors
- Only control map marker visibility, not tab content
3.**Venue Cards** (`assets/js/find-training-map.js`)
- Name with building icon
- City, State location
- "X upcoming events" count
4.**Event Cards** (`assets/js/find-training-map.js`)
- Date badge showing month/day
- Event title
- Venue name
- Cost display
- "Past" badge for past events
5.**Info Modal** (`templates/page-find-training.php`)
- "What is Upskill HVAC?" section
- "How to Use" instructions
- Map Legend (trainer/venue/event markers)
6.**Context-Aware Search** (`assets/js/find-training-filters.js`)
- Placeholder changes based on active tab
- Client-side filtering for instant results (150ms debounce)
- Falls back to server-side when filters active
7.**CSS Styling** (`assets/css/find-training-map.css`)
- Tab navigation container and button styles
- Venue card and event card layouts
- Info button and modal styling
- Responsive adjustments for tablet/mobile
### Files Modified
| File | Change |
|------|--------|
| `templates/page-find-training.php` | Tab navigation, panels, info modal |
| `assets/js/find-training-map.js` | Tab switching, card creators, grid renderers |
| `assets/js/find-training-filters.js` | Context-aware search, client-side filtering |
| `assets/css/find-training-map.css` | ~300 lines new CSS for tabs, cards, modal |
| `includes/class-hvac-plugin.php` | Version bump 2.2.5 → 2.2.6 (CDN cache bust) |
### Issue Resolved: CDN Cache
**Problem:** After deployment, browser loaded old JavaScript without new `initTabs` method.
**Root Cause:** CDN cached old assets. Deploy script clears WP/OPcache but not CDN edge cache.
**Fix:** Bumped `HVAC_VERSION` from 2.2.5 to 2.2.6, changing script URL query string to force cache refresh.
### Verified on Staging
- ✅ 42 trainers tab count
- ✅ 9 venues tab count
- ✅ 8 events tab count
- ✅ Tab switching works with proper ARIA attributes
- ✅ Venue cards display correctly
- ✅ Event cards with date badges display correctly
- ✅ Info modal opens and displays content
- ✅ Visibility toggles control map markers
---
## 📋 PREVIOUS SESSION - MEASUREQUICK APPROVED TRAINING LABS (Feb 1, 2026)
### Status: ✅ **COMPLETE - Deployed to Staging, Venues Displaying Correctly**
**Objective:** Transform /find-training to showcase only measureQuick Approved Training Labs with venue categories, equipment/amenities tags, and contact forms.
1.**Venue Taxonomies Created** (`includes/class-hvac-venue-categories.php` NEW)
- `venue_type` - For lab classification (e.g., "measureQuick Approved Training Lab")
- `venue_equipment` - Furnace, Heat Pump, AC, Mini-Split, Boiler, etc.
- `venue_amenities` - Coffee, Water, Projector, WiFi, Parking, etc.
- All taxonomies registered on `tribe_venue` post type
2.**9 Approved Training Labs Configured** (via WP-CLI script)
- Fast Track Learning Lab (ID: 6631) - Joe Medosch
- Progressive Training Lab (ID: 6284) - Samantha Brazie
- NAVAC Technical Training Center (ID: 6476) - Andrew Greaves
- Stevens Equipment Supply - Phoenix (ID: 6448) - Robert Cone
- San Jacinto College South Campus (ID: 6521) - Terry McWilliams
- Johnstone Supply - Live Fire Training Lab (ID: 4864) - Dave Petz
- Stevens Equipment Supply - Johnstown (ID: 1648) - Phil Sweren
- TruTech Tools Training Center (NEW) - Val Buckles
- Auer Steel & Heating Supply (NEW) - Mike Breen
3.**Map Data Filtered by Taxonomy**
- `get_venue_markers()` now includes `tax_query` for `mq-approved-lab` term
- Only approved training labs appear as venue markers
- Equipment, amenities, and POC data included in venue info
4.**Venue Modal Enhanced**
- Equipment badges (teal outline chips)
- Amenities badges (gray outline chips)
- Contact form with name, email, phone, company, message
- POC receives email notification on submission
5.**6 POC Trainer Accounts Created**
- Samantha Brazie, Andrew Greaves, Terry McWilliams
- Phil Sweren, Robert Cone, Dave Petz
- All with `hvac_trainer` role and approved status
### Files Created
| File | Description |
|------|-------------|
| `includes/class-hvac-venue-categories.php` | Venue taxonomy registration (singleton) |
| `scripts/setup-approved-labs.php` | WP-CLI script to configure all labs |
| `scripts/check-venue-coordinates.php` | Diagnostic script to verify venue coordinates |
| `scripts/geocode-approved-labs.php` | Geocode venues missing coordinates |
### Files Modified
| File | Change |
|------|--------|
| `includes/class-hvac-plugin.php` | Load venue categories class |
| `includes/find-training/class-hvac-training-map-data.php` | Add tax_query filter, include equipment/amenities |
| `includes/class-hvac-ajax-handlers.php` | Add venue contact form AJAX handler |
| `templates/page-find-training.php` | Add equipment/amenities badges, contact form |
| `assets/js/find-training-map.js` | Render badges, bind contact form handler |
| `assets/css/find-training-map.css` | Equipment/amenities badge styles |
### Issue Resolved: Venues Now Displaying on Map ✅
**Root Cause:** `venue_type` taxonomy wasn't being registered when `get_venue_markers()` ran.
`HVAC_Venue_Categories::instance()` was instantiated at 'init' priority 5, but then tried to add hooks to 'init' priority 5 for taxonomy registration. Since WordPress was already processing priority 5 handlers, the hook never fired.
**Fix Applied:**
1. **`includes/class-hvac-venue-categories.php`** - Added `did_action('init')` check in constructor
- If 'init' has already fired, call `register_taxonomies()` and `create_default_terms()` directly
- Otherwise, use the standard hook approach
2. **`includes/find-training/class-hvac-training-map-data.php`** - Fixed HTML entity encoding
- Venue names now use `html_entity_decode()` to properly display `&` and `` characters
- Event titles also fixed
**Result:**
- ✅ All 9 approved training labs now display as orange venue markers on the map
- ✅ Venue names display correctly (e.g., "Auer Steel & Heating Supply" not "Auer Steel &#038;...")
- ✅ Marker clustering works with mixed trainer/venue markers
---
## 📋 PREVIOUS SESSION - FIND TRAINING PAGE ENHANCEMENTS (Feb 1, 2026)
### Status: ✅ **COMPLETE - Deployed to Production**
**Objective:** Improve Find Training page UX with viewport sync and marker hover interactions.
### Changes Made
1.**Viewport Sync** - Sidebar now shows only trainers visible in current map area
- Added `visibleTrainers` array to track filtered trainers
- Added `syncSidebarWithViewport()` method filtering by map bounds
- Map `idle` event triggers sync on pan/zoom
- Count shows "X of Y trainers" when zoomed in
2.**Marker Hover Interaction** - Info window appears on hover
- Added `mouseover` event listener to trainer/venue markers
- Set `optimized: false` on markers for reliable hover events
- Hover shows info window preview with "View Profile" button
- Click on "View Profile" opens full modal with contact form
3.**Legacy URL Redirects**
- `/find-a-trainer/``/find-training/` (301 redirect)
- `/find-trainer/``/find-training/` (301 redirect)
- Removed old page from Page Manager
### Files Modified
| File | Change |
|------|--------|
| `assets/js/find-training-map.js` | Added viewport sync, hover events, optimized:false |
| `assets/js/find-training-filters.js` | Updated filter handler for visibleTrainers |
| `includes/class-hvac-route-manager.php` | Added legacy URL redirects |
| `includes/class-hvac-page-manager.php` | Removed find-a-trainer page definition |
| `includes/class-hvac-plugin.php` | Version bumped to 2.2.4 |
### Verified Behavior
- ✅ Hover over marker → Info window appears immediately
- ✅ Click "View Profile" → Full modal with trainer details + contact form
- ✅ Pan/zoom map → Sidebar updates to show visible trainers only
- ✅ Legacy URLs redirect to new page
---
## 📋 PREVIOUS SESSION - FIND TRAINING PAGE IMPLEMENTATION (Jan 31 - Feb 1, 2026)
### Status: ✅ **COMPLETE - Deployed to Production**
**Objective:** Replace the buggy MapGeo-based `/find-a-trainer` page with a new `/find-training` page built from scratch using Google Maps JavaScript API.
### Why This Change
The existing IGM/amCharts implementation had a fundamental bug that corrupted marker coordinates (longitude gets overwritten with latitude). After multiple fix attempts, building fresh with Google Maps API provides:
- Full control over marker data
- No third-party plugin dependencies
- Better long-term maintainability
- Ability to show both trainers AND venues
### Files Created (8 new files)
| File | Description |
|------|-------------|
| `includes/find-training/class-hvac-find-training-page.php` | Main page handler (singleton), AJAX endpoints, asset enqueuing |
| `includes/find-training/class-hvac-training-map-data.php` | Data provider for trainer/venue markers with caching |
| `includes/find-training/class-hvac-venue-geocoding.php` | Auto-geocoding for TEC venues via Google API |
| `templates/page-find-training.php` | Page template with map, filters, modals |
| `assets/js/find-training-map.js` | Google Maps initialization, markers, clustering |
| `assets/js/find-training-filters.js` | Filter handling, geolocation, AJAX |
| `assets/css/find-training-map.css` | Complete responsive styling |
| `assets/images/marker-trainer.svg` | Teal person icon for trainers |
| `assets/images/marker-venue.svg` | Orange building icon for venues |
### Files Modified (3 files)
| File | Change |
|------|--------|
| `includes/class-hvac-page-manager.php` | Added find-training page definition |
| `includes/class-hvac-plugin.php` | Load new find-training classes |
| `includes/class-hvac-ajax-handlers.php` | Added contact form AJAX handler |
### Multi-Model Code Review Findings & Fixes
Ran comprehensive code review using GPT-5, Gemini 3, and Zen MCP tools. Found and fixed 6 issues:
| # | Severity | Issue | Fix |
|---|----------|-------|-----|
| 1 | **CRITICAL** | Missing `hvac_submit_contact_form` AJAX handler | Added full handler with rate limiting, validation, email |
| 2 | **HIGH** | XSS risk in InfoWindow onclick handlers | Replaced with DOM creation + addEventListener |
| 3 | **MEDIUM** | Uncached filter dropdown SQL queries | Added wp_cache with 1-hour TTL |
| 4 | **MEDIUM** | AJAX race condition on rapid filters | Added request abort handling |
| 5 | **LOW** | Hardcoded `/trainer/registration/` URL | Changed to `site_url()` |
| 6 | **LOW** | `alert()` for geolocation errors | Added inline dismissible notification |
### Features Implemented
- ✅ Google Maps with custom trainer/venue markers
- ✅ MarkerClusterer for dense areas
- ✅ Filter by State, Certification, Training Format
- ✅ Search by name/location
- ✅ "Near Me" geolocation button
- ✅ Trainer/Venue toggle switches
- ✅ Trainer profile modal with contact form
- ✅ Venue info modal with upcoming events
- ✅ Trainer directory grid below map
- ✅ 301 redirect from `/find-a-trainer` to `/find-training`
- ✅ Auto-geocoding for new venues
- ✅ Rate-limited batch geocoding for existing venues
### Deployment Status
- ✅ Deployed to staging
- ✅ Map loads with markers and clustering
- ✅ Filters working (state, certification, format)
- ✅ Contact form functional
- ✅ Deployed to production
---
## 📋 PREVIOUS SESSION - E2E TESTING & BUG FIXES (Feb 1, 2026)
### Status: ✅ **COMPLETE - Deployed to Staging, Ready for Production**
**Objective:** Deploy security fixes to staging, run E2E tests, fix discovered bugs, and validate all functionality.
### Deployment & Testing Summary
1.**Deployed to Staging** - All 12 security fixes from previous session
2.**E2E Tests Passed** - Master trainer pages, security endpoints verified
3.**Discovered & Fixed 2 Critical Bugs** - Trainers table, event pages
4.**Created E2E Testing Skill** - `.claude/commands/e2e-visual-test.md`
5.**Added Staging Email Filter** - Prevents accidental user spam
### Bugs Found & Fixed
| Bug | Severity | Root Cause | Fix |
|-----|----------|------------|-----|
| **Trainers table empty** | HIGH | `ajax_filter_trainers()` used complex SQL that returned empty; `count_trainers_by_status()` only queried `hvac_trainer` role | Rewrote to use `get_trainers_table_data()` (same as working dashboard); fixed role query to include both roles |
| **Event pages blank** | HIGH | Template path mismatch: code referenced `page-trainer-event-manage.php` but file is `page-manage-event.php` | Fixed path in `class-hvac-event-manager.php:138` |
### Files Modified (4 files)
1. **`includes/class-hvac-master-trainers-overview.php`**
- Rewrote `ajax_filter_trainers()` to use reliable `get_trainers_table_data()`
- Fixed `count_trainers_by_status()` to include `hvac_master_trainer` role
- Now shows 53 trainers, 5 active (was showing 0)
2. **`includes/class-hvac-event-manager.php`**
- Fixed template path: `page-trainer-event-manage.php``page-manage-event.php`
- Event creation form now fully functional
3. **`hvac-community-events.php`**
- Added staging email filter (only `ben@tealmaker.com` receives emails)
- Protects real users from test emails during development
4. **`.claude/commands/e2e-visual-test.md`** (new)
- Created E2E visual testing skill for Playwright MCP browser tools
- Documents login procedure, test sequence, credentials
### E2E Test Results
| Feature | Status | Notes |
|---------|--------|-------|
| Master Trainer Login | ✅ PASS | Custom `/training-login/` works |
| Master Dashboard | ✅ PASS | Stats, tables, AJAX functional |
| Trainers Table | ✅ PASS | 53 trainers displayed correctly |
| Announcements | ✅ PASS | Modal opens, form accessible |
| Event Creation | ✅ PASS | Full form with all TEC fields |
| Certificate Reports | ✅ PASS | Empty state (needs events) |
| Security Endpoints | ✅ PASS | 4/4 properly return 401/400 |
### Staging Email Protection
Emails on staging are now filtered:
- **Allowed:** `ben@tealmaker.com`, `ben@measurequick.com`
- **Blocked:** All other recipients (logged for debugging)
- **Subject Prefix:** `[STAGING]` added to allowed emails
### Next Steps
1. ⏳ Deploy to production: `./scripts/deploy.sh production`
2. ⏳ Verify production functionality
3. ⏳ Monitor for any issues
---
## 📋 PREVIOUS SESSION - MULTI-MODEL SECURITY CODE REVIEW (Jan 31, 2026)
### Status: ✅ **COMPLETE - Deployed to Staging**
**Objective:** Comprehensive security and business logic code review using 4 AI models (GPT-5, Gemini 3, Kimi K2.5, Zen MCP) across 11 critical files (~9,000 lines).
### Critical Issues Found & Fixed (12 total)
| ID | Severity | Issue | File |
|----|----------|-------|------|
| C1 | **CRITICAL** | Passwords stored in transients | `class-hvac-registration.php` |
| U1 | **CRITICAL** | O(3600) token verification loop (DoS) | `class-hvac-ajax-security.php` |
| U2 | **HIGH** | `remove_all_actions()` breaks WP isolation | `class-hvac-plugin.php` |
| C2 | **HIGH** | Encryption key in same database as data | `class-hvac-secure-storage.php` |
| M3 | **HIGH** | Revoked certificates still downloadable | `class-certificate-manager.php` |
| U3 | **HIGH** | Security headers not applied to AJAX | `class-hvac-ajax-security.php` |
| C3 | **MEDIUM** | IP spoofing undermines rate limiting | `class-hvac-security.php` |
| M1 | **MEDIUM** | Weak CSP with `unsafe-eval` | `class-hvac-ajax-security.php` |
| C5 | **MEDIUM** | Duplicate component initialization | `class-hvac-plugin.php` |
| U9 | **MEDIUM** | File-scope side-effect initialization | `class-hvac-trainer-profile-manager.php` |
| U11 | **LOW** | Timezone inconsistency in cert numbers | `class-certificate-manager.php` |
| U4 | **HIGH** | zoho-config.php not in .gitignore | `.gitignore` |
### Deliverables
-**Full Report:** `MULTI-MODEL-CODE-REVIEW-REPORT.md`
-**12 Security Fixes:** All implemented and deployed to staging
---
## 📋 PREVIOUS SESSION - MASTER TRAINER PROFILE EDIT ENHANCEMENT (Jan 9, 2026)
### Status: ✅ **COMPLETE - Deployed to Production**
**Objective:** Fix broken button styling and add all trainer profile fields to the master trainer profile edit page.
**Issues Fixed:**
1. **Button Styling Broken** - "Back to Dashboard" and "Cancel" buttons appeared faded/invisible due to CSS conflicts with theme
2. **Missing Profile Fields** - Only showing basic name fields, needed all trainer profile fields
3. **No Password Reset** - Master trainers couldn't trigger password resets for trainers they manage
### Changes Made
1.**Fixed Button Styling** (`templates/page-master-trainer-profile-edit-simple.php`)
- Added scoped CSS with new class names (`hvac-btn-primary`, `hvac-btn-secondary`, `hvac-btn-outline`)
- Avoids theme CSS conflicts by using page-specific selectors
- Proper colors, hover states, and responsive behavior
2.**Added All Profile Fields** (6 complete sections)
- **Profile Settings:** Visibility (Public/Private)
- **Certification Information:** Status, Type, Date Certified
- **Personal Information:** Name, Email, LinkedIn URL, Bio
- **Professional Information:** Accreditation, Training Audience/Formats/Locations/Resources (checkboxes)
- **Business Information:** Business Type, Revenue Target, Application Details
- **Location Information:** City, State, Country, Coordinates with re-geocode button
3.**Added Password Reset Button**
- New "Send Password Reset Email" button in Personal Information section
- Uses WordPress built-in `retrieve_password()` function
- Shows status feedback (Sending... / Sent! / Error)
- Requires master trainer or admin permissions
- All actions logged for audit trail
4.**Added AJAX Handler** (`includes/class-hvac-ajax-handlers.php`)
- New `hvac_send_password_reset` endpoint
- Nonce verification, permission checks, input validation
- Secure implementation using WordPress core functions
### Files Modified
- `templates/page-master-trainer-profile-edit-simple.php` - Complete rewrite with all fields
- `includes/class-hvac-ajax-handlers.php` - Added password reset handler
### URLs
- **Production:** `https://upskillhvac.com/master-trainer/edit-trainer-profile/?user_id=75`
- **Staging:** `https://upskill-staging.measurequick.com/master-trainer/edit-trainer-profile/?user_id=75`
---
## 📋 PREVIOUS SESSION - TEC COMMUNITY EVENTS DEPENDENCY ANALYSIS (Jan 5, 2026)
### Status: ✅ **COMPLETE - Documented as Technical Debt**
**Objective:** Analyze whether "The Events Calendar: Community" (TEC CE) plugin is still being used after recent refactoring.
**Findings:**
- The plugin **still actively relies on TEC CE** for event creation/editing
- Core shortcode `[tribe_community_events]` is used in 7 template/class files
- TEC CE hooks are used for field processing and form customization
- `HVAC_Event_Manager` has custom CRUD capabilities but production paths use TEC CE
**Removal Scope:**
- **Estimated effort:** 9-14 days of development
- **Key work:** Custom forms, date pickers, validation, template updates, testing
- **Risk:** Recurring events complexity, Event Tickets integration
**Decision:** Deferred as technical debt. Current implementation is functional and stable.
### Deliverables
1.**Analysis Report:** `docs/reports/TEC-COMMUNITY-EVENTS-DEPENDENCY-ANALYSIS.md`
2.**CLAUDE.md Updated:** Added Technical Debt section
3.**Status.md Updated:** This entry
---
## 📋 PREVIOUS SESSION - SCHEDULED SYNC PERSISTENCE FIX (Dec 20, 2025)
### Status: ✅ **COMPLETE - Deployed to Production**
**Problem:** Scheduled sync showed "Not Scheduled" after page refresh, even though settings were saved correctly.
**Root Cause:**
- `HVAC_Zoho_Scheduled_Sync` was only loaded in admin context
- On non-admin requests (including WP-Cron), custom cron schedules weren't registered
- WordPress was clearing cron events because it didn't recognize the schedules
### Fixes Applied
1.**Load Scheduled Sync on ALL Requests** (`class-hvac-plugin.php`)
- Moved `HVAC_Zoho_Scheduled_Sync::instance()` initialization to main plugin loader
- Now loads alongside other schedulers (like Communication Scheduler)
- Ensures cron schedules and action hooks are always registered
2.**Add `add_option` Hook** (`class-zoho-scheduled-sync.php`)
- Added `add_option_hvac_zoho_auto_sync` hook for first-time setting creation
- WordPress fires `add_option_` (not `update_option_`) on first save
3.**Explicit Scheduling in Save** (`class-zoho-admin.php`)
- `save_settings()` now explicitly calls `schedule_sync()` or `unschedule_sync()`
- Ensures scheduling works even when option value hasn't changed
- `update_option_` hook only fires when value actually changes
### Files Modified
- `includes/class-hvac-plugin.php` - Load scheduled sync globally
- `includes/zoho/class-zoho-scheduled-sync.php` - Add first-time option hook
- `includes/admin/class-zoho-admin.php` - Explicit scheduling call
---
## 📋 PREVIOUS SESSION - PUBLIC MAP & DIRECTORY FIX (Dec 21, 2025)
### Status: 🔄 **IN PROGRESS - Deployed to Staging (Strategy H)**
**Problem:** Map markers missing. Data analysis reveals markers have identical Latitude and Longitude values (corruption).
**Root Cause:**
- IGM Plugin's client-side processing corrupts `longitude` by overwriting it with `latitude` immediately before rendering.
- Previous PHP Injection strategies (D-G) caused 500 errors due to `WP_Query` timing/context issues in the footer.
**Solution (Strategy H):**
1.**Javascript Interceptor:** Injected a robust interceptor script in `class-hvac-mapgeo-integration.php`.
2.**Mechanism:** Uses `Object.defineProperty` on `window.iMapsData` to catch the data assignment *before* the map plugin sees it.
3.**Repair Logic:** Detects corrupted markers (Lat == Lng) and instantly restores correct values from safe `lat`/`lng` backup keys provided by PHP.
4.**Cleanup:** Removed dangerous PHP query injections that were causing server errors.
**Current Status:**
- Fix deployed to Staging.
- Pending verification of visible markers and "Healed" console logs.
**Next Steps:**
1. Verify map renders correctly on Staging.
2. Deploy to Production.
---
## 📋 PREVIOUS SESSION - SCHEDULED ZOHO SYNC (Dec 19, 2025)
### Status: ✅ **COMPLETE - WP-Cron Scheduled Sync Implemented**
**Summary:**
- **Scheduled Sync:** WP-Cron job syncs new/modified records on configurable interval
- **Incremental Sync:** Only syncs records modified since last sync run
- **Admin UI:** Enable/disable toggle, interval selector (5min-daily), status display
- **Manual Trigger:** "Run Sync Now" button for testing
### Changes Made
1.**New File: `class-zoho-scheduled-sync.php`**
- WP-Cron management with custom intervals
- `run_scheduled_sync()` processes all data types
- Tracks last sync time for incremental filtering
- Stores results for status display
2.**Updated `class-zoho-sync.php`**
- All 5 sync methods now accept `$since_timestamp` parameter
- When provided, filters queries by `post_modified >= since_date`
3.**Updated `class-zoho-admin.php`**
- Added `save_settings()` AJAX handler
- Added `run_scheduled_sync_now()` AJAX handler
- Enhanced admin UI with new intervals and status display
4.**Updated `zoho-admin.js`**
- Settings form reloads page on save
- "Run Sync Now" button with result display
### Interval Options
| Value | Frequency |
|-------|-----------|
| `every_5_minutes` | Every 5 minutes (default) |
| `every_15_minutes` | Every 15 minutes |
| `every_30_minutes` | Every 30 minutes |
| `hourly` | Hourly |
| `every_6_hours` | Every 6 hours |
| `daily` | Daily |
### Admin Page Location
- `/wp-admin/admin.php?page=hvac-zoho-sync`
- Look for "Scheduled Sync Settings" section
---
## 📋 PREVIOUS SESSION - BATCH SYNC ENHANCEMENT (Dec 18, 2025)
### Status: ✅ **COMPLETE - All Sync Tasks Now Auto-Iterate with Progress Bar**
**Summary:**
- **All 5 Sync Types:** Now support batch pagination with auto-continue
- **Progress Bar:** Visual feedback showing `X of Y processed (N%)`
- **No Manual Repeating:** Frontend auto-loops until `has_more: false`
- **Orphan Cleanup:** Deleted 14 test attendees referencing deleted events
### Changes Made
1.**Backend Pagination:**
- All sync methods (`sync_events`, `sync_users`, `sync_attendees`, `sync_rsvps`, `sync_purchases`) now accept `$offset` and `$limit` parameters
- Each returns `has_more`, `next_offset`, and `total` for pagination
- Admin endpoint updated to pass offset to sync methods
2.**Frontend Progress UI:**
- New `syncWithProgress()` function replaces single AJAX calls
- Auto-continues batches until complete
- Progress bar shows percentage and count
- Accumulated results across all batches
### Files Modified
- `includes/zoho/class-zoho-sync.php` - Pagination for all 5 sync methods
- `includes/admin/class-zoho-admin.php` - Offset parameter handling
- `assets/js/zoho-admin.js` - Progress bar + auto-continue logic
---
## 📋 PREVIOUS SESSION - ZOHO CRM ATTENDEE SYNC (Dec 17-18, 2025)
### Status: ✅ **COMPLETE - All Attendees Syncing Successfully**
**Summary:**
- **Events Sync:** ✅ WORKING. 39 events synced with enhanced field mapping.
- **Attendees Sync:** ✅ WORKING. 50/50 synced, 0 errors, all contacts updated with custom fields.
### Issues Resolved
1.**Campaign Member Linking:**
- Fixed API endpoint: `PUT /Contacts/{id}/Campaigns` (was `/Campaigns/{id}/Contacts/{id}`)
- Fixed `log_debug()` visibility (private → public)
2.**Attendee Field Mapping:**
- measureQuick Email → `Email` (primary, used for lookup)
- Attendee Email → `Secondary_Email`
- Attendee Cell Phone → `Mobile`
- Company Role → `Primary_Role`
- Fixed meta key: `_tec_tickets_commerce_attendee_fields` with hyphenated field names
3.**Email Fallback Logic:**
- If attendee email empty, use measureQuick email (and vice versa)
- Only fails if BOTH emails are empty
4.**DUPLICATE_DATA Handling:**
- When Zoho returns "duplicate exists", extract existing contact ID from error
- Use that ID to update instead of failing
5.**Existing Contact Updates:**
- Existing contacts now updated via PUT with new field data on each sync
---
### Zoho CRM Integration - Staging Environment (Working)
**Status:** ✅ OAuth Working, Sync Methods Implemented, Dry-Run Tested
**Completed:**
1.**OAuth Authentication Verified**
- Refresh token exists and is valid
- API connection successful (53 modules accessible)
- Read operations working (Contacts, Campaigns, Users)
2.**Read-Only API Tests Passed**
- Organization Info: Manifold Cloud Services (America/Detroit)
- Contacts: 5+ records readable (Tanner Moore, Pete Knochelmann, etc.)
- Campaigns: 5+ records readable (Nov 28, Oct 23, etc.)
- CRM Users: Ben Reed (CEO), JR Lawhorne (Manager), etc.
3.**Sync Class Bug Fixes**
- Fixed user roles: `trainer`/`trainee` → `hvac_trainer`/`hvac_master_trainer`
- Fixed event filter: Removed restrictive `_hvac_event_type` meta query
- Fixed event display: Changed `eventDisplay` from `list` to `custom` to include past events
- Fixed WooCommerce dependency: Added graceful error handling
4.**Event Tickets Integration (NEW)**
- Replaced WooCommerce sync with Event Tickets (Tickets Commerce) support
- Added `sync_attendees()` method → Zoho Contacts + Campaign Members
- Added `sync_rsvps()` method → Zoho Leads + Campaign Members
- Updated meta keys for Tickets Commerce (`_tec_tickets_commerce_*`)
- Updated meta keys for RSVPs (`_tribe_rsvp_*`)
5.**Admin Interface Updated**
- Added "Sync Attendees" button (Contacts + Campaign Members)
- Added "Sync RSVPs" button (Leads + Campaign Members)
- Renamed "Sync Purchases" to "Sync Orders" (Tickets Commerce)
**Dry-Run Results (Staging - No Data Sent to Zoho):**
| Sync Type | Records Found | Status |
|-----------|---------------|--------|
| Events → Campaigns | 20 | ✅ Ready |
| Trainers → Contacts | 53 | ✅ Ready |
| Attendees → Contacts + Campaign Members | 79 | ✅ Ready |
| RSVPs → Leads + Campaign Members | 4 | ✅ Ready |
| Orders → Invoices | 52 | ✅ Ready |
**Zoho CRM Mapping Strategy:**
- **Events** → **Campaigns** (direct mapping)
- **Trainers** (hvac_trainer, hvac_master_trainer) → **Contacts** (with Contact_Type field)
- **Ticket Attendees** → **Contacts** + **Campaign Members** (links Contact ↔ Campaign)
- **RSVPs** → **Leads** + **Campaign Members** (links Lead ↔ Campaign)
- **Ticket Orders** → **Invoices** (financial records)
**Staging Protection Active:**
- All write operations (POST/PUT/DELETE) are blocked on staging
- Only production (`upskillhvac.com`) can write to Zoho CRM
- Dry-run shows what would sync without actually sending data
**Admin Page Location:**
- `/wp-admin/admin.php?page=hvac-zoho-sync`
**Files Modified:**
- `includes/zoho/class-zoho-sync.php` - Complete rewrite for Event Tickets
- `includes/admin/class-zoho-admin.php` - Added new sync buttons
---
## 📅 PREVIOUS SESSION - GEMINI TRANSITION & VALIDATION (Dec 16, 2025)
### Gemini Development Environment Setup
**Objective:** Transition from Claude Code-specific tooling to Gemini/Antigravity agent development workflow.
**Completed:**
1.**Created `GEMINI.md`** - New development guidelines
- Critical safety constraints for Cloudways Shared VPS
- Workflows for testing (`/test`) and deployment
- Coding standards (Singleton pattern, security, PHP 8+ modernization)
- Agent personas (Tester, Security Auditor, Deployment Engineer)
2.**Environment Configuration**
- Updated `.gitignore` to allow `.agent/`, `.mcp.json`, `GEMINI.md`
- Created `/home/ben/dev/upskill-event-manager/.agent/workflows/test.md`
- Fixed file access blocked by gitignore
3.**PHP 8+ Compatibility Verification**
- **Issue:** `true|\WP_Error` syntax causing PHP fatal errors on staging (PHP 8.0)
- **Fix:** Changed to `bool|\WP_Error` in `includes/class-hvac-security-helpers.php:231`
- **Status:** Deployed to staging, verified working
4.**Comprehensive Test Suite**
- **File:** `test-comprehensive-validation.js` (Playwright E2E tests)
- **Fixed:** Login form selectors (`#user_login`, `#user_pass`, `#wp-submit`)
- **Modes:** Headless (default) or headed (`DISPLAY=:1 HEADLESS=false`)
- **Results:**
- Master Trainer pages: ✅ ALL PASSING (4/4)
- Security endpoints: ✅ ALL SECURE (4/4)
- Trainer pages: ⚠️ Require authentication (expected)
**Test Results Summary:**
```
✅ Master Dashboard - Functional with navigation
✅ Announcements - Fully functional & responsive
✅ Pending Approvals - Fully functional & responsive
✅ Trainers - Fully functional & responsive
🔒 Security: All AJAX endpoints properly secured (401/400 responses)
- hvac_get_trainer_stats
- hvac_manage_announcement
- hvac_approve_trainer
- hvac_approve_trainer_v2
```
**Test Credentials Updated:**
- `test_master` / `Test123!` (hvac_master_trainer)
- `test_trainer` / `Test123!` (hvac_trainer)
- `test_admin` / `Test123!` (administrator)
5.**Master Trainer Navigation Dropdown Fix** (Dec 16, 2025)
- **Issue:** Green/teal colored boxes appearing in navigation toolbar instead of dropdown arrows
- **Root Cause:** Empty `<span class="menu-toggle">` elements with CSS background styling
- **Fix:** Replaced with `<span class="dropdown-arrow">▼</span>` in `includes/class-hvac-master-menu-system.php:327`
- **Impact:** All master trainer pages (`/master-trainer/*`)
- **Status:** ✅ Deployed to staging, verified working
- **Verification:** Screenshots confirm dropdown arrows display correctly, green boxes removed
---
## 📁 RECENT DEPLOYMENTS
### v2.1.7 - Critical Nonce Fix (Nov 3, 2025)
**Issue:** Announcement submission completely broken - nonce mismatch
**Fix:** Changed nonce action from `hvac_announcements_admin_nonce``hvac_announcements_nonce`
**Files:** `includes/class-hvac-announcements-admin.php` (line 96)
**Status:** ✅ Deployed to staging, fully functional
### v2.1.6 - Technical Debt Cleanup
**Fixes:**
1. Version synchronization (2.0.0 → 2.1.6 in plugin header)
2. FOUC prevention (modal `display: none` by default)
3. Conditional logging (`error_log()` → `HVAC_Logger::log()`)
### v2.1.5 - Z-Index Stacking Fix
**Issue:** WordPress media modal appearing behind announcement modal
**Fix:** Reduced announcement modal z-index from 999999 → 100000
**Result:** Media modals (z-index 160000) now properly stack on top
---
## 🧪 TESTING INFRASTRUCTURE
### Comprehensive Test Suite
**File:** `test-comprehensive-validation.js`
**Framework:** Playwright (Node.js)
**Run Tests:**
```bash
# Headless (default)
node test-comprehensive-validation.js
# Headed mode (visible browser)
DISPLAY=:1 HEADLESS=false node test-comprehensive-validation.js
```
**Test Coverage:**
- ✅ Trainer pages (4 pages)
- ✅ Master trainer pages (4 pages)
- ✅ Security/AJAX endpoints (4 endpoints)
- ✅ Layout & responsive design
- ✅ Authentication flows
---
## 🚀 DEPLOYMENT
### Staging Environment
**URL:** https://upskill-staging.measurequick.com
**Version:** 2.1.7 + PHP 8+ fixes
**Server:** Cloudways Shared VPS (PHP 8.0)
**Status:** ✅ Fully functional
**Deploy to Staging:**
```bash
./scripts/deploy.sh staging
```
**Verify Deployment:**
```bash
./scripts/verify-plugin-fixes.sh
```
### Production Environment
**URL:** https://upskillhvac.com
**Version:** 2.2.11 (latest)
**Server:** Cloudways Shared VPS
---
## 🔧 KEY DEVELOPMENT GUIDELINES
### GEMINI.md Rules (NEW)
1. **Safety First:**
- NEVER delete files outside project directory
- NEVER execute `rm -rf` without confirmation
- NEVER modify system configs (`/etc/*`, `/var/*`)
- NEVER deploy to production without explicit request
2. **Infrastructure Constraints:**
- Cloudways Shared VPS (limited resources)
- Do NOT force PHP version changes
- Do NOT install system-level packages
- Be mindful of CPU/RAM usage
3. **Testing Mandatory:**
```bash
node test-comprehensive-validation.js
```
4. **Security Standards:**
- Always sanitize input
- Always escape output
- Verify nonces on forms & AJAX
- Check roles/capabilities
### WordPress Architecture
- **Singleton Pattern:** All core classes use `::instance()`
- **Template Security:** All templates start with security check
- **PHP 8+ Modernization:** In progress (avoid PHP 8.2+ features)
---
## 📚 DOCUMENTATION
### Primary Files
- **`GEMINI.md`** - Gemini agent development guidelines (NEW)
- **`CLAUDE.md`** - Claude Code agent guidelines (legacy)
- **`docs/ARCHITECTURE.md`** - Plugin architecture details
- **`docs/CLAUDE-CODE-DEVELOPMENT-BEST-PRACTICES.md`** - Development patterns
### Workflows
- **`.agent/workflows/test.md`** - Running comprehensive tests (`/test`)
---
## 📋 NEXT ACTIONS
### Immediate
1.**Production Deployment** - Deploy v2.1.7 + PHP 8+ fixes (pending user approval)
2.**PHP 8+ Modernization** - Continue Phase 2 modernization
3. 🔜 **Enhancements** - New features for next session
### Pre-Production Checklist
- ✅ PHP 8+ compatibility verified
- ✅ Security endpoints validated
- ✅ Master trainer pages functional
- ✅ Comprehensive tests passing
- ✅ No fatal errors on staging
**Deploy Command:**
```bash
./scripts/deploy.sh production
```
---
## ⚠️ KNOWN ISSUES
### Minor (Non-Blocking)
1. **Playwright Headless Login** - Works in headed mode with correct selectors
2. **jQuery Loading Timing** - Brief "jQuery is not defined" error (non-blocking)
3. **Dashboard Responsive** - Minor responsive layout issue (cosmetic)
---
## 📊 SUMMARY
**Current State:****PRODUCTION READY**
**Key Achievements:**
- Gemini development environment established
- PHP 8+ compatibility verified and deployed
- Comprehensive test suite functional (headed mode)
- All security endpoints properly secured
- Master trainer features fully operational
- Test accounts updated and working
**Quality Metrics:**
- Test Coverage: 8 pages + 4 security endpoints
- Success Rate: 100% master trainer pages
- Security: 100% endpoints secured
- PHP Compatibility: ✅ No fatal errors
**Agent Transition:**
- From: Claude Code + MCP tools
- To: Gemini/Antigravity + direct tooling
- Status: ✅ Complete and validated
---
*For detailed historical context, see git history and previous Status.md versions*