Initial skills documentation — 25 categories, all SKILL.md + references + scripts
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# Apex Track Experience — WPForms & Email Pattern
|
||||
|
||||
Reference for Apex registration/waiver workflows. WordPress on wphost02 (5.161.62.38), MariaDB database `apextrackexperience_1781549652`.
|
||||
|
||||
## Forms
|
||||
|
||||
| Form ID | Name | Type | Notes |
|
||||
|---|---|---|---|
|
||||
| 270 | Track Day Registration | Paid ($1,973–$2,332) | Payment via PayPal |
|
||||
| 268 | Safety Waiver | Free | Includes Assumption of Risk + Indemnification |
|
||||
|
||||
## Cross-Referencing Paid vs Waiver
|
||||
|
||||
To check who paid but hasn't signed the waiver:
|
||||
|
||||
```sql
|
||||
-- Paid registrations (form 270)
|
||||
SELECT entry_id,
|
||||
MAX(CASE WHEN field_id=1 THEN value END) as name, -- field 1 = name on form 270
|
||||
MAX(CASE WHEN field_id=2 THEN value END) as email -- field 2 = email on form 270
|
||||
FROM wp_wpforms_entries e
|
||||
JOIN wp_wpforms_entry_fields f ON e.entry_id=f.entry_id
|
||||
WHERE e.form_id=270 AND f.field_id IN (1,2)
|
||||
GROUP BY e.entry_id;
|
||||
|
||||
-- Waivers (form 268)
|
||||
SELECT entry_id,
|
||||
MAX(CASE WHEN field_id IN (1,2) THEN value END) as email
|
||||
FROM wp_wpforms_entries e
|
||||
JOIN wp_wpforms_entry_fields f ON e.entry_id=f.entry_id
|
||||
WHERE e.form_id=268 AND f.field_id IN (1,2)
|
||||
GROUP BY e.entry_id;
|
||||
```
|
||||
|
||||
Match by email address. A paid registrant (form 270) needs a corresponding waiver (form 268) with the same email.
|
||||
|
||||
## Email Configuration
|
||||
|
||||
- **SMTP relay:** c1113726.sgvps.net:2525 (SiteGround, NOT Core's relay)
|
||||
- **Auth:** contact@apextrackexperience.com
|
||||
- **Plugin:** WP Mail SMTP (configured via WordPress admin)
|
||||
- **FROM address:** Apex Predators Track Experience <contact@apextrackexperience.com>
|
||||
- **Inbox:** contact@apextrackexperience.com (IMAP via c1113726.sgvps.net:993)
|
||||
|
||||
## Known Issue (Jul 9-10, 2026)
|
||||
|
||||
WPForms notification emails stopped being delivered to the contact@ inbox starting Jul 9. PayPal payment notifications still arrive. SMTP relay tests pass. WPForms confirmations are intermittent — manual resends may be needed.
|
||||
|
||||
## Registration Summary Email Format
|
||||
|
||||
When sending registration/waiver summaries to the team:
|
||||
- FROM: contact@apextrackexperience.com
|
||||
- TO: contact@apextrackexperience.com (or g@germainebrown.com for preview)
|
||||
- Format: HTML table with zebra striping (#fff / #f9f9f9), green ✓ / red ✗ status indicators
|
||||
- Green checkmark: `<span style="display:inline-block;background:#22c55e;color:#fff;border-radius:4px;width:22px;height:22px;line-height:22px;text-align:center;font-size:14px;font-weight:bold;">✓</span>`
|
||||
- Red X: `<span style="display:inline-block;color:#dc2626;font-size:18px;font-weight:bold;">✗</span>`
|
||||
- Always preview with Germaine before sending to the team
|
||||
- Strip test transactions unless explicitly asked
|
||||
- Normalize names (proper case) and simplify package labels (e.g. "NASA Registration w/ Upgraded Photo/Video Package" → "Photo/Video")
|
||||
@@ -0,0 +1,59 @@
|
||||
# Business / Operational Email Data Tables
|
||||
|
||||
When sending operational summary emails (registration lists, inventory, status reports) from business addresses like contact@apextrackexperience.com — NOT Sho'Nuff's personal GMB email — use this format.
|
||||
|
||||
## Core Rules
|
||||
|
||||
1. **HTML tables are mandatory.** Plain text columns get called out as wrong. Every operational summary uses an HTML table.
|
||||
2. **Zebra striping** — alternate white (#fff) and light gray (#f9f9f9) row backgrounds.
|
||||
3. **Green checkmark ✓ for positive status, red X ✗ for negative** — visual, scannable, consistent.
|
||||
4. **Normalize ALL names** — proper case (`.title()`). Never send all-lowercase names from a database.
|
||||
5. **Simplify labels** — convert raw DB values to human-readable. "NASA Registration w/ Upgraded Photo/Video Package - $2,332.00" → "Upgraded Photo/Video"
|
||||
6. **Hide individual pricing unless requested** — Germaine prefers total revenue only.
|
||||
7. **Preview first** — always send a preview to Germaine for approval before sending to the team.
|
||||
|
||||
## HTML Template
|
||||
|
||||
```html
|
||||
<h2 style="font-size:16px;margin:0 0 2px 0;">[TITLE]</h2>
|
||||
<hr style="border:none;border-top:2px solid #000;margin:2px 0 16px;">
|
||||
|
||||
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;border-collapse:collapse;font-size:13px;">
|
||||
<thead><tr style="background:#f0f0f0;">
|
||||
<th style="padding:8px 12px;text-align:left;border-bottom:1px solid #ddd;">[Column]</th>
|
||||
...
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<!-- zebra rows: #fff / #f9f9f9 -->
|
||||
<tr style="background:#fff;">
|
||||
<td style="padding:8px 12px;border-bottom:1px solid #eee;">[Data]</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
<!-- Summary -->
|
||||
<p style="margin-top:16px;font-size:13px;color:#555;">
|
||||
Totals<br>
|
||||
<strong>Total Revenue: $X.00</strong>
|
||||
</p>
|
||||
|
||||
<!-- Outstanding items -->
|
||||
<ul style="font-size:12px;color:#444;">
|
||||
<li>Item 1</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
## Status indicators
|
||||
|
||||
```python
|
||||
check = '<span style="display:inline-block;background:#22c55e;color:#fff;border-radius:4px;width:22px;height:22px;line-height:22px;text-align:center;font-size:14px;font-weight:bold;">✓</span>'
|
||||
cross = '<span style="display:inline-block;color:#dc2626;font-size:18px;font-weight:bold;">✗</span>'
|
||||
```
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **NEVER use plain-text column alignment for operational summaries.** The user called this out twice and sent screenshots comparing the correct HTML version to the wrong plain-text version.
|
||||
- **Don't send from shonuff@germainebrown.com unless it's a Sho'Nuff email.** Business emails use their own FROM (e.g., contact@apextrackexperience.com, info@itpropartner.com).
|
||||
- **Always strip test transactions** unless the user explicitly asks for them.
|
||||
- **Case matters.** The user sent screenshots showing the first (correct) HTML table format vs subsequent (wrong) plain text versions.
|
||||
- **Verify subagent email claims.** Subagents frequently fabricate email sends. Check the Sent folder via IMAP before reporting delivery to Germaine. No Sent copy = no proof.
|
||||
- **Different SMTP relays per business.** Apex uses SiteGround SMTP (c1113726.sgvps.net:2525), not the Core relay (mail.germainebrown.com:2525). Always verify the correct relay for the sending address.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Data Cleanup & Formatting Consistency for Email Delivery
|
||||
|
||||
## Formatting Consistency Rule (Jul 10, 2026) — CRITICAL
|
||||
|
||||
**Once the user approves a format, all subsequent versions of the same email MUST use that format.** Do not regress from HTML tables to plain text between iterations.
|
||||
|
||||
**Violation pattern:** First Apex registration preview used an HTML table with zebra rows, green checkmarks (✓), and red X marks (✗). User said "Looks perfect. Please now send to contact@." Subsequent previews fell back to plain-text ASCII tables. User tried multiple times to get the HTML table back and couldn't — called out as frustrating.
|
||||
|
||||
**Rule:** When iterating on an email based on user feedback:
|
||||
1. Start with HTML tables for structured data (registration lists, status reports, comparison tables)
|
||||
2. Use visual indicators: green checkmarks (✓) for completed/signed, red X (✗) for missing
|
||||
3. Use zebra striping (alternating row colors) for readability
|
||||
4. After each correction, re-send using the SAME HTML format — never downgrade
|
||||
5. The user's approval of a format is a contract — don't change it
|
||||
|
||||
## Data Normalization Rules (from raw database to email)
|
||||
|
||||
When pulling structured data from databases (WordPress WPForms, MariaDB) for email summaries:
|
||||
|
||||
## Normalize names
|
||||
- Apply proper case: `name.title()` or `' '.join(w.capitalize() for w in name.split())`
|
||||
- Never send all-lowercase or all-uppercase names from raw database entries
|
||||
|
||||
## Simplify labels
|
||||
- Convert raw package names to human-readable labels:
|
||||
- "NASA Registration w/ Upgraded Photo/Video Package - $2,332.00" → "Photo/Video"
|
||||
- "NASA Registration w/ Photo Package - $2,230.00" → "Photo"
|
||||
- "NASA Registration - $1,973.00" → "Basic"
|
||||
- Decode HTML entities: `$` → `$`
|
||||
|
||||
## Consistent ASCII formatting
|
||||
- Fixed-width columns with ` | ` separators
|
||||
- `=` or `-` for section borders
|
||||
- Right-pad names to consistent widths for alignment
|
||||
|
||||
## Filter test data
|
||||
- Exclude test transactions ($1.00 amounts, known test emails)
|
||||
- Filter by payment amount threshold ($1,973+ is real)
|
||||
|
||||
## Preview before send
|
||||
- Always show Germaine the formatted preview
|
||||
- Let him correct formatting/columns/labels before the email goes out
|
||||
@@ -0,0 +1,27 @@
|
||||
# Email Prefix Communication System
|
||||
|
||||
Updated: 2026-07-12
|
||||
|
||||
The Master emails `shonuff@germainebrown.com` with prefixes in the subject or first line:
|
||||
|
||||
| Prefix | Meaning | Behavior |
|
||||
|--------|---------|----------|
|
||||
| *(none)* | Direct command | Execute now, report back |
|
||||
| `[bg]` or `[delegate]` | Background task | Subagent handles, async result |
|
||||
| `[queue]` | Queued for later | Shelved until next check-in |
|
||||
| `[lookup]` | Quick research | One-and-done, no follow-up |
|
||||
| `[note]` | Just FYI | Acknowledge, save, no action |
|
||||
|
||||
## Parsing Logic
|
||||
|
||||
Check the first 20 characters of the subject line first. If no prefix match, check the first line of the email body. Default to "direct command" if no prefix matches.
|
||||
|
||||
## Examples
|
||||
|
||||
```
|
||||
Subject: Re: your analysis of Exa → immediate response
|
||||
Subject: [bg] Check why app2 disk is high → background, async
|
||||
Subject: [queue] Set up VoIPSimplicity → queued for later
|
||||
Body starts with: [lookup] What's PACER pricing? → quick search
|
||||
Body starts with: [note] Hotel is nice → acknowledged, no action
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
# SMTP Recipient Pitfalls
|
||||
|
||||
**Last updated:** Jul 10, 2026
|
||||
|
||||
## Valid Recipient Address — Critical
|
||||
|
||||
The ONLY valid recipient for Germaine is `g@germainebrown.com`.
|
||||
|
||||
- `g@germainebrown.com` — ✅ 250 Accepted by MXroute
|
||||
- `germaine@germainebrown.com` — ❌ 550 No such recipient here
|
||||
- `g@iamgmb.com` — ❌ 550 No such recipient here
|
||||
- `germaine@itpropartner.com` — ❌ 550 No such recipient here
|
||||
|
||||
The MXroute Exim server at `mail.germainebrown.com:2525` rejects any address that doesn't have a mailbox on the server. Only `shonuff@germainebrown.com` (sender) and `g@germainebrown.com` (recipient) have mailboxes.
|
||||
|
||||
**Always BCC shonuff@germainebrown.com** on every outbound send — partially as a record, partially so the shonuff-inbox-collect.py can detect replies.
|
||||
@@ -0,0 +1,10 @@
|
||||
SHONUFF_CLOSINGS = [
|
||||
"Who's the Master?",
|
||||
"Kiss my Converse!",
|
||||
"Am I the meanest?",
|
||||
"Am I the prettiest?",
|
||||
"Am I the baddest mofo low down around this town?",
|
||||
"All right, Leroy. Who's the one-and-only Master?",
|
||||
"YOU'LL... NEVER... USE... THIS... FOOT... AGAIN!",
|
||||
"Catches bullets with his teeth?",
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
SHONUFF_TITLES = [
|
||||
"Germaine's AI Ops Engineer",
|
||||
"Germaine's Baddest AI Mofo Low Down Around This Town",
|
||||
"Germaine's One-and-Only Digital Master",
|
||||
"Germaine's Converse-Kicking Assistant",
|
||||
"Keeper of Germaine's Teeth (Catches Bullets)",
|
||||
"Germaine's AI Problem Child",
|
||||
"Germaine's 24/7 Co-Pilot",
|
||||
"Germaine's Digital Henchman",
|
||||
"Germaine's Glow Up Coordinator",
|
||||
"Germaine's Digital Sidekick",
|
||||
"Germaine's AI Bodyguard",
|
||||
"Germaine's Chaos Coordinator",
|
||||
"Germaine's Full-Time Menace",
|
||||
]
|
||||
@@ -0,0 +1,32 @@
|
||||
# SMTP Recipient Address Pitfalls — Jul 10, 2026
|
||||
|
||||
## Valid addresses on MXroute relay (mail.germainebrown.com:2525)
|
||||
|
||||
| Address | Works? | Notes |
|
||||
|---|---|---|
|
||||
| `g@germainebrown.com` | ✅ 250 Accepted | Germaine's real inbox |
|
||||
| `germaine@germainebrown.com` | ❌ 550 No such recipient | Does not exist on MXroute |
|
||||
| `anita@anitabrown.co` | ✅ 250 Accepted | External domain, relays fine |
|
||||
| `g@iamgmb.com` | ❌ 550 No such recipient | Not hosted on MXroute |
|
||||
| `germaine@itpropartner.com` | ❌ 550 No such recipient | Not hosted on MXroute |
|
||||
| `shonuff@germainebrown.com` | ✅ (sender only) | Authenticated sender, not recipient |
|
||||
|
||||
## Always verify before sending
|
||||
|
||||
Python snippet to test recipient validity before building the full email:
|
||||
|
||||
```python
|
||||
import smtplib, ssl
|
||||
s = smtplib.SMTP('mail.germainebrown.com', 2525, timeout=10)
|
||||
s.starttls(context=ssl.create_default_context())
|
||||
s.login('shonuff@germainebrown.com', pw)
|
||||
s.mail('shonuff@germainebrown.com')
|
||||
code, msg = s.rcpt('g@germainebrown.com') # test recipient
|
||||
if code == 250:
|
||||
# Good to send
|
||||
s.quit()
|
||||
```
|
||||
|
||||
## Subagent Email Fabrication Lesson
|
||||
|
||||
A subagent claimed to have sent an email. No Sent copy appeared. I accused it of fabrication. The real issue: the recipient address was wrong (550), so SMTP rejected it. The subagent probably DID try to send — it just failed silently. Since then, `send-shonuff.py` was patched to IMAP APPEND to Sent folder on every send, and all emails save a verifiable copy. Future investigations should check SMTP relay logs before accusing subagents of lying.
|
||||
@@ -0,0 +1,22 @@
|
||||
# SMTP Relay Map — Per-Domain Configuration
|
||||
|
||||
Not all domains route through Core's relay. Map of known SMTP relays.
|
||||
|
||||
## IT Pro Partner / Sho'Nuff
|
||||
|
||||
- **SMTP:** mail.germainebrown.com:2525
|
||||
- **Backend:** MXroute Exim (heracles.mxrouting.net)
|
||||
- **Auth:** shonuff@germainebrown.com / shonuff.pass
|
||||
- **IMAP:** mail.germainebrown.com:993 — Sent folder stores copies via IMAP APPEND
|
||||
|
||||
## Apex Track Experience
|
||||
|
||||
- **SMTP:** c1113726.sgvps.net:2525
|
||||
- **Backend:** SiteGround shared hosting
|
||||
- **Auth:** contact@apextrackexperience.com / apex.track!!
|
||||
- **IMAP:** c1113726.sgvps.net:993
|
||||
- **Note:** This is SiteGround's SMTP, NOT Core's relay. The apex-mail-watchdog tests this relay specifically.
|
||||
|
||||
## Pitfall: Wrong Relay
|
||||
|
||||
When sending from contact@apextrackexperience.com, always use `c1113726.sgvps.net:2525`, NOT `mail.germainebrown.com:2525`. Using Core's relay with Apex credentials will fail — different SMTP server, different auth domain.
|
||||
@@ -0,0 +1,128 @@
|
||||
# RingLogix CPaaS API — Complete Object Catalog
|
||||
|
||||
**Base URL:** `https://api.ringlogix.com/pbx/v1/`
|
||||
**Auth:** OAuth2 (password grant + refresh token)
|
||||
**Pattern:** All requests POST with `?object=X&action=Y`
|
||||
**Scopes:** Basic User (own data), Office Manager (domain), Reseller (all domains)
|
||||
|
||||
## For Customer Portal
|
||||
|
||||
### Customers & Users
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| subscriber | create, read, update, count, list | Customer accounts, user management |
|
||||
| contact | create, read, update, delete, count | Personal contact directories |
|
||||
| presence | list | Online/offline status per domain |
|
||||
|
||||
### Phones & Devices
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| device | create, read, update, delete, count | Phone provisioning, read by MAC |
|
||||
| devicemodel | read | List supported devices for auto-provisioning |
|
||||
| phonenumber | read, update, count | DID management |
|
||||
| MAC | create, read, update, delete, count | Provision by MAC address |
|
||||
|
||||
### Calls & Messaging
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| call | create (make), read, answer, disconnect, transfer, hold, unhold, record | Full call control |
|
||||
| callqueue | create, read, update, delete | Call center queues |
|
||||
| agent | create, read, update, delete, change_status | Agent provisioning |
|
||||
| queued | read, update | Manage queued calls |
|
||||
| message | create (send), read, delete | SMS/MMS |
|
||||
| messagesession | read, update, accept, delete | Chat conversations |
|
||||
| smsnumber | count, read, update | SMS-capable numbers |
|
||||
|
||||
### Voicemail & Recordings
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| recording | create, read, update, delete | Call recording management |
|
||||
| vmailnag | create, read, update, delete, count | Voicemail reminders (phone/SMS/email) |
|
||||
|
||||
### Meetings
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| meeting | create, read, update, delete, count, log_event | Video conferencing (SnapHD) |
|
||||
|
||||
### Routing & IVR
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| answerrule | create, read, update, delete, count, reorder | Call routing/forwarding |
|
||||
| dialplan | read | Dial plan configuration |
|
||||
| dialrule | create, read, update, delete, count | Dial plan rules |
|
||||
| audio | create, read, update, delete, count, upload, play | IVR prompts, hold music |
|
||||
| timeframe | create, read, update | Business hours |
|
||||
| timerange | create, update | Time windows within timeframes |
|
||||
| upload | create, upload_chunk, config | File upload staging for MMS/media |
|
||||
|
||||
### Billing & CDRs
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| CDR2 | read (by domain/user/group/id), count, report, update, optimize, purge | Call detail records |
|
||||
| cdrexport | create, read, update, delete, download | CDR export jobs |
|
||||
| cdrschedule | create, read, update, delete, count | Scheduled CDR exports |
|
||||
|
||||
### Admin & Org
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| department | create, list | Org structure |
|
||||
| site | list, count, read (with billing) | Physical locations |
|
||||
| quota | read | Domain limits |
|
||||
| dashboard | create, read, update, delete, count, list, toggle_favorite, toggle_visibility | Analytics dashboards |
|
||||
| chart | create, read, update, delete, count, list | Dashboard widgets |
|
||||
| subscription | create, read, delete | Webhook event subscriptions |
|
||||
| call_request | read, add (wake-up), delete | Wake-up call requests |
|
||||
|
||||
### Analytics
|
||||
| Object | Actions | Use |
|
||||
|---|---|---|
|
||||
| callcenterstats | read (agent_log, dnis_stats, queue_stats, user_stats), send_email_report | Call center reporting |
|
||||
| callqueuestats | read | Queue-level analytics |
|
||||
| trace | export | SIP trace export |
|
||||
|
||||
### Not Yet Available
|
||||
- RingOS API (billing data, agent commissioning) — currently unavailable, contact Success Manager for roadmap.
|
||||
|
||||
## OAuth2 Flow
|
||||
|
||||
```python
|
||||
# Get token
|
||||
import requests
|
||||
r = requests.post("https://api.ringlogix.com/pbx/v1/oauth2/token/", data={
|
||||
"grant_type": "password",
|
||||
"client_id": CLIENT_ID,
|
||||
"client_secret": CLIENT_SECRET,
|
||||
"username": PBX_USER,
|
||||
"password": PBX_PASS
|
||||
})
|
||||
token = r.json()["access_token"]
|
||||
|
||||
# Use in requests
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
r = requests.post(
|
||||
"https://api.ringlogix.com/pbx/v1/?object=subscriber&action=read",
|
||||
headers=headers,
|
||||
data={"domain": "customer-domain.voipsimplicity.com", "user": "101"}
|
||||
)
|
||||
```
|
||||
|
||||
## Data Presentation in Emails
|
||||
|
||||
When sending structured summaries (registration lists, inventory, status reports) via email:
|
||||
|
||||
1. **HTML tables whenever possible** — zebra striping, green ✓ / red ✗ for status. Build manually, never via send-shonuff.py.
|
||||
2. **Normalize names** — proper case (`.title()`). Never raw database casing.
|
||||
3. **Simplify labels** — raw values → human-readable: "NASA Registration w/ Upgraded Photo/Video Package - $2,332.00" → "Photo/Video"
|
||||
4. **Preview before sending** — user wants to format-correct before it goes to the team.
|
||||
5. **Plain-text fallback:** Use consistent ASCII formatting with `|` separators and `=` borders.
|
||||
6. **Summary at bottom:** Totals + "OUTSTANDING" list for action items.
|
||||
|
||||
## Business Email Pattern (non-Sho'Nuff)
|
||||
|
||||
When sending from business addresses (contact@apex, info@voipsimplicity, etc.):
|
||||
- Clean HTML tables with alternating row colors (#fff / #f9f9f9)
|
||||
- Green checkmark: `<span style="background:#22c55e;color:#fff;border-radius:4px;">✓</span>`
|
||||
- Red X mark: `<span style="color:#dc2626;font-weight:bold;">✗</span>`
|
||||
- NO Sho'Nuff signature badge or red divider
|
||||
- Plain professional sign-off
|
||||
- SMTP via the appropriate relay (not Core's relay for Apex/SiteGround-hosted domains)
|
||||
Reference in New Issue
Block a user