Skip to main content
A developer’s portfolio page typically contains far more git links than just their own profile and repositories. Project pages link to upstream libraries, open-source work references maintainers, collaboration sections mention teammates, and blog posts embed links to third-party repos. When GitResolve scrapes a portfolio or parses a resume PDF, it collects all of these links together — and then must figure out which one of them is actually the candidate. The resolveOwnerAndCategorize function solves this problem by cross-referencing profile links against repo links and applying a four-case decision algorithm that produces both an ownerProfile and a confidence level explaining how certain the resolution is.

The knownOwnerProfile bypass

When the input is already a git_profile or repo_url, the owner is known before disambiguation runs. The resolver extracts the username directly from the URL, constructs a knownOwnerProfile, and passes it to resolveOwnerAndCategorize. This skips the four-case algorithm entirely.
If you already know the candidate’s GitHub username — for example, they applied through a form that collected it — pass it as knownOwnerProfile to guarantee confidence: 'high' regardless of what links the portfolio contains.

The four disambiguation cases

resolveOwnerAndCategorize inspects the full set of ExtractedGitLink objects found in a source and applies one of four resolution strategies depending on what is present.
1

Case 1 — Single unique profile username: high confidence

If exactly one distinct git profile username appears across all profile-type links (after deduplication by username, case-insensitive), that user is unambiguously the owner.Result: ownerProfile set to that profile link, confidence: 'high'.This is the most common case for a personal portfolio that links only to the candidate’s own GitHub profile in the header or footer.
2

Case 2 — Multiple distinct profile usernames: cross-reference with repos

When two or more distinct profile usernames are found, GitResolve cannot immediately determine which is the candidate. Instead it counts how many repo links belong to each username and uses that score to pick the owner.A warning is always added: 'Multiple profile links found: alice, bob, charlie'.The outcome depends on the repo scores:
3

Case 3 — No profile links, only repo links: infer from username frequency

Some resumes and older portfolios list repository links but no direct profile URLs. In this case, GitResolve groups all repo links by their username field and picks the username that appears most often.A synthetic profile link is constructed at https://{host}/{username} (e.g. https://github.com/janedoe) and set as ownerProfile.
4

Case 4 — No links at all: confidence none

If the input yielded zero ExtractedGitLink objects — the page could not be fetched, the PDF contained no recognisable git URLs, or all links were filtered as reserved paths — disambiguation cannot produce any result.Result: ownerProfile: null, confidence: 'none', warning: 'No git links found'.

Confidence level reference

Repo categorization

Once ownerUsername is established, every link in the input set is assigned to one of three buckets. Deduplication by URL (case-insensitive) is applied across all three buckets before the result is returned. Profile links and gist links are not placed in any bucket — they appear only in allLinks.
Username matching is always case-insensitive. A portfolio linking to github.com/JaneDoe and a repo owned by janedoe will be correctly matched to the same person.

Calling resolveOwnerAndCategorize directly

While the function is called internally by scrapePortfolio and parseResume, you can invoke it directly when you have a pre-built set of ExtractedGitLink objects.
The return type of resolveOwnerAndCategorize is the internal OwnerResolution interface, which is not exported from @clyrisai/gitresolve. TypeScript will infer the type structurally — you can access all fields on the return value without importing the type name.

Using the knownOwnerProfile parameter

Input Classification

How inputs are categorized before disambiguation runs

Result Structure

The full shape of ResolverResult and AggregatedResult