The rule
To determine the CURRENT stage of any HS deal, ALWAYS query HS live. NEVER infer from:
- Email notifications (e.g. "Contract Sent for [Deal Name]")
- Calendar events
- Transcript content
- Memory file historical entries
- Stage-history timestamps in propertiesWithHistory
Those are evidence of past events. They may reflect a state that was REVERTED (false positive), or a state that was promoted but later rolled back (deal lost momentum), or simply stale.
How to verify
python
Via chrome_bridge or Gmail MCP-side fetch (authenticated HS tab):
import subprocess
BRIDGE = "/Users/josephbowens/Library/Application Support/SkyRun/chrome_bridge.py"
TAB = subprocess.run(["/usr/bin/python3", BRIDGE, "find", "hubspot.com"], capture_output=True, text=True).stdout.strip()
js = """
fetch('/api/crm/v3/objects/deals/{deal_id}?portalId=23273108&properties=dealstage,dealname,hs_lastmodifieddate', {{
headers: {{'X-HubSpot-CSRF-hubspotapi': (document.cookie.match(/csrf\\.app=([^;]+)/)||[])[1]}}
}}).then(r=>r.json()).then(j=>JSON.stringify(j))
"""
The dealstage value is the canonical truth. Cross-reference against reference_hs_pipeline_stages.md to translate stage IDs to SkyRun-renamed labels.
Why this rule exists
2026-04-29 19:58 UTC: deal_sync.py's old mapping flipped Hadank from appointmentscheduled โ presentationscheduled (the Contract column in SkyRun's renamed pipeline). HS auto-fired the contract-sent notification email.
2026-04-30 19:58 UTC: Notification email actually arrived in Joseph's inbox (delayed delivery).
2026-04-30 20:42 UTC: Joseph caught it, agent reverted the stage to qualifiedtobuy, deal_sync.py mapping was patched. Audit manifest closed the bug.
2026-05-01 12:36 UTC: nightly-consolidation re-fired, scanned the morning's emails, found the 4/30 contract-sent notification, and updated MEMORY.md + project_active_deal_hadank.md to reflect "๐ด CONTRACT SENT 4/30 19:58Z." This was the SAME false-positive surfacing for the SECOND time โ through a different code path. Joseph: "I didnt send a contract to him and this is the second time I've gotten this notification."
The first false-positive was the deal_sync.py bug (closed by yesterday's audit). The second was the consolidation agent treating an HS notification email as authoritative state evidence. Different mechanism, same hallucinated-stage outcome.
Mechanical rule for agents (especially nightly-consolidation, qb-quarterback, live-ea, stalled-deal-watchdog)
**Before writing any stage-inference into MEMORY.md, project_active_deal_*.md, or morning brief:**
1. Query the deal's CURRENT dealstage from HS live
2. If a notification email or transcript suggests a different stage, treat that as evidence-of-past-event-only โ NOT as current state
3. If the past-event suggests a stage transition that the current dealstage contradicts, FLAG IT as a potential false-positive AND surface to Joseph for verification rather than writing it as fact
4. The notification email's date (when delivered to inbox) is NOT the date of the stage transition โ HS often delays notification delivery by hours or days
Pattern to detect false-positives
When stage history (propertiesWithHistory) shows a flip-and-revert pattern within 24-48 hours:
- flip_to_X at T1 โ revert_to_Y at T2 where T2 - T1 < 48h
- This is almost always a false-positive correction, not a normal stage progression
Agents should treat the FINAL state in the history as the canonical state, and any intermediate flip as a known error to acknowledge but NOT propagate.
Cross-references
reference_hs_pipeline_stages.mdโ stage IDs vs labels (the "scrambled" mapping wherecontractsent=Won,closedwon=Lost, etc.)~/Library/Application Support/SkyRun/deal_sync.pyโ the script whose mapping bug caused the original false-positive (lines 65-79; fixed 2026-04-30)project_active_deal_hadank.mdโ the live test casefeedback_freshness_before_surface.mdโ sister rule about checking current state before surfacing items as overduefeedback_no_fabrication_personal.mdโ overarching no-fabrication discipline