Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/clyrisai/gitresolve/llms.txt

Use this file to discover all available pages before exploring further.

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.
// When you pass a known owner, the algorithm is bypassed
resolveOwnerAndCategorize(links, "portfolio", knownOwnerProfile);
// → confidence: 'high', ownerProfile set directly from knownOwnerProfile
// → warning added: 'Owner strictly determined by profile URL input: <username>'
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.
// Portfolio HTML contains only one profile link: github.com/janedoe
// → ownerProfile.username = 'janedoe', confidence = 'high'
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:
ScenarioConfidenceBehaviour
One profile has strictly more matching repos than all othershighThat profile is the owner. A warning lists the repo scores per username.
Two or more profiles are tied for the highest repo count (and count > 0)mediumFirst tied profile is chosen. Warning flags the tie.
No repo links match any profile usernamelowFirst profile in the list is chosen. Warning notes the mismatch.
Multiple profiles found but zero repo links existlowFirst profile is chosen. Warning notes no repos available for cross-reference.
// Profile links: github.com/janedoe, github.com/alice-mentor
// Repo links: 4 repos owned by janedoe, 1 owned by alice-mentor
// → ownerProfile.username = 'janedoe', confidence = 'high'
// → warning: 'Owner determined by repo cross-reference: janedoe(4 repos), alice-mentor(1 repos)'
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.
ScenarioConfidence
All repos belong to a single usernamemedium
One username owns more repos than all others combinedmedium
Two or more usernames are tied for the most reposlow
// No profile links found
// Repo links: janedoe/api(×3), janedoe/frontend(×1), third-party/lib(×1)
// → synthetic ownerProfile.url = 'https://github.com/janedoe'
// → confidence = 'medium'
// → warning: 'No profile link found — inferred from repo majority: janedoe(4), third-party(1)'
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

LevelMeaningTypical source
highOwner identity is certainDirect git_profile/repo_url input, or one clear profile found, or one profile dominates repos
mediumOwner identity is a strong inference but not guaranteedMultiple profiles tied for top repo count (Case 2), or owner inferred from repo-username frequency with no explicit profile link (Case 3)
lowOwner identity is a best guessMultiple tied profiles or repos; no supporting evidence for a clear winner
noneOwner identity could not be determinedNo git links found at all, or LinkedIn-only source

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.
BucketPopulation rule
ownedReposlink.type === 'repo' and link.username matches ownerUsername (case-insensitive)
contributionslink.type === 'pull_request' or link.type === 'issue'
externalReposlink.type === 'repo' and link.username does not match ownerUsername
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.
import { resolveOwnerAndCategorize } from "@clyrisai/gitresolve";
import type { ExtractedGitLink } from "@clyrisai/gitresolve";

const links: ExtractedGitLink[] = [
  {
    url: "https://github.com/janedoe",
    provider: "github",
    type: "profile",
    username: "janedoe",
  },
  {
    url: "https://github.com/janedoe/api-server",
    provider: "github",
    type: "repo",
    username: "janedoe",
    repo: "api-server",
  },
  {
    url: "https://github.com/alice/some-library",
    provider: "github",
    type: "repo",
    username: "alice",
    repo: "some-library",
  },
  {
    url: "https://github.com/torvalds/linux/pull/99",
    provider: "github",
    type: "pull_request",
    username: "torvalds",
    repo: "linux",
    number: "99",
  },
];

const resolution = resolveOwnerAndCategorize(links);

console.log(resolution.ownerProfile?.username); // 'janedoe'
console.log(resolution.confidence);             // 'high'
console.log(resolution.ownedRepos.length);      // 1  (janedoe/api-server)
console.log(resolution.externalRepos.length);   // 1  (alice/some-library)
console.log(resolution.contributions.length);   // 1  (torvalds/linux#99)

Using the knownOwnerProfile parameter

const knownOwner: ExtractedGitLink = {
  url: "https://github.com/janedoe",
  provider: "github",
  type: "profile",
  username: "janedoe",
};

// All links categorized against janedoe; algorithm skipped
const resolution = resolveOwnerAndCategorize(links, "portfolio", knownOwner);
// → confidence: 'high', ownerProfile: knownOwner

Input Classification

How inputs are categorized before disambiguation runs

Result Structure

The full shape of ResolverResult and AggregatedResult

Build docs developers (and LLMs) love