Group Hyper Engineers by identity (GitHub username/email), not display name - #202
Merged
Merged
Conversation
Reported: the same person shows up as several separate entries (e.g. "Renato Guimaraes", "renatoguimaraescb", "Renato Guimarães (Bahia)") because commit-author display names vary across repos/time, and computeHyperEngineers grouped purely by name.lowercase(). Both author_velocity (email per author) and active_users (github username per person, already resolved server-side by iris/cli.py's push-time identity resolution) had everything needed — the payload data was already there, this was a pure grouping-key bug, entirely fixable on the platform side: - getOrgActiveContributors: userMap now keys by resolved github username when known, falling back to name only when no github was resolved for that entry — fixes the "active contributors" count itself double-counting the same person under different names. Also returns a new nameToGithub map (every distinct name -> its github, not deduped) so a caller holding only a name can resolve it. - computeHyperEngineers: groups author_velocity authors by, in priority order, resolved github username (via nameToGithub) -> normalized email (stripping a GitHub noreply email's numeric-ID prefix, mirroring iris/analysis/author_velocity.py's own _normalize_author) -> display name as a last resort. No engine/CLI changes, no new payload fields, no migration — every field this needed was already flowing through end-to-end. Co-Authored-By: claude-code_2-1-238_agent <claude-code_2-1-238_agent@iris.invalid>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
5 tasks
clickmatos
added a commit
that referenced
this pull request
Aug 27, 2026
* fix(platform): only show Hyper Engineers with a resolved GitHub username Even after grouping by identity (#202), some people still can't be merged automatically — GitHub's commits-by-author-email API (iris/cli.py's _resolve_emails_via_repo) only resolves an email to a login when that email is linked and verified on the person's GitHub account. When it isn't, that identity falls back to its email's local part as a key, which won't match any other alias for the same person — so they can still show up as a second, unlinked entry alongside their properly-resolved one. Rather than show a name with no way to confirm identity or link to a profile, computeHyperEngineers now omits engineers with no resolved github. It's also the entries most likely to be an unresolved duplicate in the first place, since github is the strongest identity signal grouping already prefers. Co-Authored-By: claude-code_2-1-238_agent <claude-code_2-1-238_agent@iris.invalid> * fix(platform): split Hyper Engineers into identified/unidentified instead of hiding Revises the previous commit on this branch: instead of filtering out engineers with no resolved GitHub username, computeHyperEngineers goes back to returning everyone (github left undefined when unresolved), and HyperEngineers.tsx splits the display into two labeled groups — "Identified" (has a linkable GitHub profile) and "Unidentified (no linked GitHub account)". Nobody's dropped from the view; the split just makes clear which entries are a confirmed identity versus one iris/cli.py couldn't tie to a GitHub account. The "Identified" header itself only renders when there's an unidentified group too, so orgs where everyone resolved cleanly don't get punished with an extra empty-feeling label. Co-Authored-By: claude-code_2-1-238_agent <claude-code_2-1-238_agent@iris.invalid> --------- Co-authored-by: claude-code_2-1-238_agent <claude-code_2-1-238_agent@iris.invalid>
3 tasks
clickmatos
added a commit
that referenced
this pull request
Aug 27, 2026
…er unidentified people) (#204) Root cause of the "same person shows up as two separate Hyper Engineers" gap (#202/#203): the per-email resolution step (gh api repos/{repo}/commits?author=<email>) misses real matches — verified live: a real work email GitHub does tie to an account failed that filtered query, while GitHub's own commit-list endpoint resolves it fine via the .author.login field it already attaches to every listed commit. Adds a bulk, date-bounded resolution step (one paginated commit-list scan, bounded to the same lookback window already used locally for git log) as the primary path for non-noreply emails, ahead of the old per-email API call, which now only runs as a fallback for whatever the bulk scan didn't cover. The free noreply-email regex extraction is unchanged. Also extracts this logic out of nested closures inside _run_single_repo's push block into iris/platform/identity.py, making it independently unit-testable (mocked subprocess, no network) instead of only reachable through a full analysis+push run. Verified live against RocketBus/iris: renato.guimaraes@clickbus.com -> renatoguimaraescb (the exact case reported) resolves via the bulk scan; marcos.carvalho@clickbus.com -> codermarcos likewise, confirmed by directly running resolve_active_users() against this repo's real commit history. Co-authored-by: claude-code_2-1-238_agent <claude-code_2-1-238_agent@iris.invalid>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reported: the same person shows up as several separate entries in the Hyper Engineers panel — e.g. "Renato Guimaraes" (6 repos), "renatoguimaraescb" (2 repos), "Renato Guimarães" (some), "Renato Guimarães (Bahia)" (some) — because commit-author display names vary across repos/machines/time, and
computeHyperEngineersgrouped purely byname.toLowerCase().Traced the full data path — everything needed was already flowing through end-to-end, this was a pure grouping-key bug:
author_velocity.authors[](per-repo payload) already carriesemailper author — never used for grouping.active_users(JSONB, resolved server-side byiris/cli.py's push-time identity resolution — including real GitHub API lookups for non-noreply emails) already carries agithubusername per person — butgetOrgActiveContributorsmerges it across repos keyed byname.toLowerCase()too, re-fragmenting an identity that was already correctly resolved per-repo.Fix — platform-only, no engine/CLI/schema changes
getOrgActiveContributors:userMapnow keys by resolved GitHub username when known, name only as fallback. Also returns a newnameToGithubmap (every distinct display name seen → its resolved github, not deduped) so a caller holding only a name — like anauthor_velocityentry — can resolve it.computeHyperEngineers: groups authors by, in priority order: resolved GitHub username (vianameToGithub) → normalized email (strips a GitHub noreply email's numeric-ID prefix, mirroringiris/analysis/author_velocity.py's own_normalize_author— noreply emails are stable per GitHub account regardless of local git config, so this alone fixes a lot of cases even with zero API-resolvedgithubdata) → display name as a last resort.HyperEngineersPanel.tsxupdated to pass the newnameToGithubthrough.Caught a real bug in my own first pass via the test suite: when a
githubwas resolved throughnameToGithub, the code wasn't carrying it forward directly — it depended on a separateuserMaplookup succeeding, which could come back empty even though the identity was known. Fixed by tracking the resolvedgithubalongside each group directly.Test plan
platform/tests/org-summary.test.ts(computeHyperEngineers — dedupes the same person across name variants): merges two name variants resolved to the same GitHub username; merges two name variants sharing a noreply email with zero GitHub resolution; keeps two genuinely different people separate (regression guard against over-merging)npx tsc --noEmit— cleannpx eslint— cleannpx vitest run— 272 passed (269 existing + 3 new)npm run build— compiles successfully🤖 Generated with Claude Code