---
name: HS deal stage — current API state is sole source of truth
description: When determining a deal's CURRENT stage, query HS live (`/api/crm/v3/objects/deals/{id}?properties=dealstage`). DO NOT infer stage from email notifications, calendar events, or transcript content — those are HISTORICAL evidence and may reflect reverted/false-positive states. Hardwired 2026-05-01 after the Hadank double-false-positive.
type: feedback
last_updated: 2026-05-01
originSessionId: 6250c599-625a-4c16-9ba6-368c0a7715ed
---

## 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 where `contractsent`=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 case
- `feedback_freshness_before_surface.md` — sister rule about checking current state before surfacing items as overdue
- `feedback_no_fabrication_personal.md` — overarching no-fabrication discipline
