Skip to content

Group Hyper Engineers by identity (GitHub username/email), not display name - #202

Merged
clickmatos merged 1 commit into
mainfrom
hyper-engineers-identity-grouping
Aug 27, 2026
Merged

Group Hyper Engineers by identity (GitHub username/email), not display name#202
clickmatos merged 1 commit into
mainfrom
hyper-engineers-identity-grouping

Conversation

@clickmatos

Copy link
Copy Markdown
Contributor

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 computeHyperEngineers grouped purely by name.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 carries email per author — never used for grouping.
  • active_users (JSONB, resolved server-side by iris/cli.py's push-time identity resolution — including real GitHub API lookups for non-noreply emails) already carries a github username per person — but getOrgActiveContributors merges it across repos keyed by name.toLowerCase() too, re-fragmenting an identity that was already correctly resolved per-repo.

Fix — platform-only, no engine/CLI/schema changes

  • getOrgActiveContributors: userMap now keys by resolved GitHub username when known, name only as fallback. Also returns a new nameToGithub map (every distinct display name seen → its resolved github, not deduped) so a caller holding only a name — like an author_velocity entry — can resolve it.
  • computeHyperEngineers: groups authors by, in priority order: resolved GitHub username (via nameToGithub) → normalized email (strips a GitHub noreply email's numeric-ID prefix, mirroring iris/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-resolved github data) → display name as a last resort.
  • HyperEngineersPanel.tsx updated to pass the new nameToGithub through.

Caught a real bug in my own first pass via the test suite: when a github was resolved through nameToGithub, the code wasn't carrying it forward directly — it depended on a separate userMap lookup succeeding, which could come back empty even though the identity was known. Fixed by tracking the resolved github alongside each group directly.

Test plan

  • New tests in 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 — clean
  • npx eslint — clean
  • npx vitest run — 272 passed (269 existing + 3 new)
  • npm run build — compiles successfully
  • Not verified against real data in a live browser — same standing limitation as prior platform PRs this session (no live Supabase session here).

🤖 Generated with Claude Code

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>
@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clickbus-iris Ready Ready Preview Aug 26, 2026 9:53pm

Request Review

@clickmatos
clickmatos merged commit 9ba9add into main Aug 27, 2026
5 checks passed
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>
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant