The tree was a debranded snapshot of upstream taken around 2026-02-20, and upstream has moved about five months since. This replaces it with upstream master, mechanically re-derived: bin/debrand does the rename, and the pipeline and squashed migrations are restored from the shipped tree. Not a merge. The previous import replaced the tree wholesale in a single commit, so there is no shared content history to merge against. Reproducing the rename on the new tree is what actually converges. What survives: .hanzo/workflows, the Dockerfiles and bin/docker* entrypoints, compose files, LLM.md, and insights/migrations. The squashed initial migration is load-bearing — the live database records it by name, so upstream's ~918 individual migrations cannot come back. Nine products are dropped as unreferenced. Twenty-one more that we do not run are kept anyway because the core app still imports them; unpicking those is a refactor and does not belong in a rebase. This base does not build yet, and the reasons are not in the rename: upstream now wants Python 3.13.13 against our 3.12.12 and Django 5.2 against our 4.2, and the dependency manifests still name upstream packages that we republish under our own names. Those are decisions, not renames.
2.8 KiB
Ticket queries
All queries run through the Insights MCP execute-sql tool in the internal project (US, project 2).
Always confirm table columns via system.information_schema.columns before querying a system.* table.
Open web analytics tickets from the conversations product
SELECT ticket_number, id, status, priority, channel_source,
substring(last_message_text, 1, 400) AS last_msg, created_at, message_count
FROM system.support_tickets
WHERE status IN ('new', 'open', 'pending')
AND created_at >= now() - INTERVAL 21 DAY
AND (last_message_text ILIKE '%web analytics%'
OR last_message_text ILIKE '%bounce%'
OR last_message_text ILIKE '%utm%'
OR last_message_text ILIKE '%pageview%'
OR email_subject ILIKE '%web analytics%')
ORDER BY created_at DESC
Caveats: last_message_text is only the latest message and may be truncated; message_count > 1 means there is history you have not seen.
The keyword filter misses tickets phrased differently — also read the #support-web-analytics Slack channel for the Zendesk-mirrored stream.
Full comment history via the Zendesk warehouse mirror
system.support_tickets has no messages table. The Zendesk mirror does, inside a JSON array column:
SELECT created_at, body FROM (
SELECT created_at,
JSONExtractString(
arrayJoin(JSONExtractArrayRaw(assumeNotNull(toString(child_events)))),
'body') AS body
FROM zendesk.ticket_events
WHERE ticket_id = {zendesk_ticket_id}
) WHERE body != ''
ORDER BY created_at ASC
Notes: assumeNotNull is required (arrayJoin cannot sit inside Nullable); apply LIMIT after the subquery or arrayJoin eats it; MCP display truncates long cells, so extract fields instead of dumping raw JSON.
Resolve a requester to an org/team (US and EU)
SELECT 'us' AS region, u.email, u.current_team_id
FROM postgres.insights_user u WHERE u.email = '{email}'
UNION ALL
SELECT 'eu', u.email, u.current_team_id
FROM eu_postgres_insights_user u WHERE u.email = '{email}'
Also useful: postgres.insights_organizationdomain (verified domains only — often empty for smaller orgs), postgres.insights_organization by name, all_insights_team.
EU customer data is not queryable from the US MCP project.
For per-team event data on either region, use the query-datastore-via-metabase skill.
Error tracking cross-reference
Frontend crashes reported by EU customers usually have US occurrences too (Insights staff and US users hit the same code).
Search the internal project's error tracking with the MCP tools; source on the issue row names the sourcemapped file, and verbosity: stack on events gives resolved frame names, so you can go from a minified customer stack to file:line without a local repro.