> ## 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.

# Result Structure: ResolverResult and AggregatedResult

> Complete field-by-field reference for ResolverResult, AggregatedResult, and ExtractedGitLink — the three core output types returned by GitResolve.

Every resolved source produces a typed output object that captures both what was found and how confident GitResolve is about the result. When you call `scrapePortfolio` or `parseResume` directly, you receive a `ResolverResult` for that single source. When you run the CLI in batch mode across multiple inputs for the same candidate, each candidate's sources are merged into an `AggregatedResult`. Understanding the shape of these objects — including what goes into `warnings`, when `error` appears, and how `ownedRepos` differs from `externalRepos` — lets you build reliable downstream logic on top of GitResolve's output.

## TypeScript import

```typescript theme={null}
import type {
  ResolverResult,
  ExtractedGitLink,
  InputType,
  GitProvider,
  GitLinkType,
} from "@clyrisai/gitresolve";
```

<Note>
  `AggregatedResult` is defined in the source type system but is **not exported from the package index**. It is used internally by the CLI when merging multiple sources for a single candidate. You cannot import it directly from `@clyrisai/gitresolve` in your own code.
</Note>

***

## ResolverResult

`ResolverResult` is the return type of both `scrapePortfolio` and `parseResume`. It contains everything GitResolve found about one source input.

<ResponseField name="source" type="string" required>
  The original input string — the URL that was scraped, or the file path that was parsed. Preserved exactly as passed in.
</ResponseField>

<ResponseField name="sourceType" type="InputType" required>
  The `InputType` for this source. One of `'repo_url'`, `'git_profile'`, `'portfolio'`, `'resume_file'`, `'resume_url'`, `'linkedin'`, or `'unknown'`. For most sources this is the value returned by `classifyInput`; the CLI sets `'resume_url'` when it downloads a remote PDF before parsing. See [Input Classification](/concepts/input-classification) for the full decision logic.
</ResponseField>

<ResponseField name="ownerProfile" type="ExtractedGitLink | null" required>
  The resolved git profile for the candidate, or `null` if no owner could be determined. When `confidence` is `'none'`, this field is always `null`. See [ExtractedGitLink](#extractedgitlink) below for the shape of this object.
</ResponseField>

<ResponseField name="confidence" type="'high' | 'medium' | 'low' | 'none'" required>
  How certain GitResolve is about the `ownerProfile` attribution. See the [confidence levels table](#confidence-levels) for the full meaning of each level.
</ResponseField>

<ResponseField name="ownedRepos" type="ExtractedGitLink[]" required>
  Repository links where `link.username` matches the resolved owner (case-insensitive). These are repos the candidate owns. Deduplicated by URL.
</ResponseField>

<ResponseField name="contributions" type="ExtractedGitLink[]" required>
  Links with `type === 'pull_request'` or `type === 'issue'`. These represent explicit contribution activity found in the source. Deduplicated by URL.
</ResponseField>

<ResponseField name="externalRepos" type="ExtractedGitLink[]" required>
  Repository links owned by someone other than the resolved owner. These may be libraries depended on, employer repositories, or open-source projects the candidate referenced without owning. Deduplicated by URL.
</ResponseField>

<ResponseField name="allLinks" type="ExtractedGitLink[]" required>
  The complete, unfiltered set of every parsed git link found in the source — profiles, repos, gists, PRs, issues, and other link types combined. Use this for custom filtering or auditing the raw extraction output.
</ResponseField>

<ResponseField name="warnings" type="string[]" required>
  Non-fatal diagnostic messages logged during processing. This includes the browser provider used, disambiguation decisions and rationale, and edge-case flags. See [The warnings array](#the-warnings-array) for a full description.
</ResponseField>

<ResponseField name="error" type="string">
  Present only when a fatal error occurred during processing — for example, a network failure fetching the portfolio URL, or a file read error on a resume path. When `error` is set, the other fields (`ownedRepos`, `allLinks`, etc.) will be empty arrays and `confidence` will be `'none'`. See [The error field](#the-error-field) for details.
</ResponseField>

***

## ExtractedGitLink

`ExtractedGitLink` is the atomic unit of every link GitResolve extracts. It appears in `ownerProfile`, `ownedRepos`, `contributions`, `externalRepos`, and `allLinks`.

<ResponseField name="url" type="string" required>
  The canonical URL for this link. For repos, this is the normalized form `https://{host}/{owner}/{repo}`. For PRs and issues, the raw URL (including the PR/issue number path) is preserved. For synthetic profile links (created in Case 3 of disambiguation), this is `https://{host}/{username}`.
</ResponseField>

<ResponseField name="provider" type="GitProvider" required>
  The git hosting platform. One of `'github'`, `'gitlab'`, or `'bitbucket'`.
</ResponseField>

<ResponseField name="type" type="GitLinkType" required>
  The kind of resource this link points to. See the [GitLinkType values table](#gitlinktype-values) below.
</ResponseField>

<ResponseField name="username" type="string" required>
  The username or organization name extracted from the URL path. Used for all ownership matching. Matching is always performed case-insensitively.
</ResponseField>

<ResponseField name="repo" type="string">
  The repository name. Present when `type` is `'repo'`, `'pull_request'`, or `'issue'`. Absent for `'profile'` and `'gist'` links.
</ResponseField>

<ResponseField name="number" type="string">
  The PR or issue number as a string. Present only when `type` is `'pull_request'` or `'issue'`.
</ResponseField>

### GitLinkType values

| Value          | Description                                                       |
| -------------- | ----------------------------------------------------------------- |
| `profile`      | A user or organization profile page (e.g. `github.com/janedoe`)   |
| `repo`         | A repository root (e.g. `github.com/janedoe/my-project`)          |
| `gist`         | A GitHub Gist (e.g. `gist.github.com/janedoe/abc123`)             |
| `pull_request` | A pull request or merge request URL including a numeric ID        |
| `issue`        | An issue URL including a numeric ID                               |
| `other`        | A valid git host URL that did not match any of the above patterns |

***

## AggregatedResult

<Warning>
  `AggregatedResult` is **not exported from the `@clyrisai/gitresolve` package index** and cannot be imported directly. It is an internal type used by the CLI. The field reference below documents its shape for CLI output consumers and contributors only.
</Warning>

`AggregatedResult` is the output type for CLI batch runs where multiple source inputs (a portfolio URL, a resume PDF, a repo URL) are resolved together for a single candidate. GitResolve merges the individual `ResolverResult` objects, deduplicates links across sources, and picks the highest-confidence owner profile. Note that unlike `ResolverResult`, `AggregatedResult` has no `error` field — errors are captured on individual `ResolverResult` objects before aggregation.

<ResponseField name="candidateUsername" type="string | null" required>
  The final resolved username for this candidate, or `null` if no owner could be determined across any source. Derived from `ownerProfile.username`.
</ResponseField>

<ResponseField name="sources" type="string[]" required>
  All input strings that were resolved and merged into this aggregate. For example `["https://janedoe.dev", "./resumes/janedoe.pdf"]`.
</ResponseField>

<ResponseField name="sourceTypes" type="InputType[]" required>
  The `InputType` value for each entry in `sources`, in the same order.
</ResponseField>

<ResponseField name="ownerProfile" type="ExtractedGitLink | null" required>
  The best owner profile resolved across all sources. When one source yields `confidence: 'high'`, that profile wins. When all sources are lower confidence, the first resolved profile is used.
</ResponseField>

<ResponseField name="confidence" type="'high' | 'medium' | 'low' | 'none'" required>
  The highest confidence level achieved across all merged sources.
</ResponseField>

<ResponseField name="ownedRepos" type="ExtractedGitLink[]" required>
  Deduplicated union of `ownedRepos` from all sources, filtered to the resolved owner.
</ResponseField>

<ResponseField name="contributions" type="ExtractedGitLink[]" required>
  Deduplicated union of `contributions` from all sources.
</ResponseField>

<ResponseField name="externalRepos" type="ExtractedGitLink[]" required>
  Deduplicated union of `externalRepos` from all sources.
</ResponseField>

<ResponseField name="allLinks" type="ExtractedGitLink[]" required>
  Deduplicated union of `allLinks` from all sources.
</ResponseField>

<ResponseField name="warnings" type="string[]" required>
  Combined warnings from all merged `ResolverResult` objects.
</ResponseField>

***

## Confidence levels

| Level    | Meaning                                                                                                                                                                                                                                                                                                           |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `high`   | The owner was determined with certainty — either from a direct `git_profile`/`repo_url` input, a single unambiguous profile link, or a clear repo-count majority when multiple profiles were present.                                                                                                             |
| `medium` | The owner was inferred rather than directly identified. In Case 2 (multiple profiles), this means two profiles tied for the highest repo count. In Case 3 (no profiles), this means the owner was inferred from repo-username frequency — either all repos share one username, or one username clearly dominates. |
| `low`    | The owner is a best guess — profiles or repos were found but evidence was tied or contradictory. The first candidate was picked, but downstream code should treat this result with caution.                                                                                                                       |
| `none`   | No git links were found at all, or the source was a type that cannot be resolved (e.g. `linkedin`). `ownerProfile` is `null`.                                                                                                                                                                                     |

***

## The warnings array

The `warnings` array is always present (never `undefined`) and collects non-fatal diagnostic messages logged throughout processing. These messages are useful for debugging scraper output and understanding disambiguation decisions.

Common warnings you will encounter:

| Warning message pattern                                                     | When it appears                                                                                |
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `Used fetch provider (SPA rendering layer …)`                               | Portfolio was fetched with the fallback `fetch` provider; a headless browser was not available |
| `Used {name} provider for page content`                                     | Portfolio was fetched with a named browser provider (e.g. Puppeteer, Browserless)              |
| `Found {n} git URL(s) in text content`                                      | Resume text extraction found git URLs                                                          |
| `Text extraction failed: {message}`                                         | The `unpdf` text pass failed; annotation extraction may still succeed                          |
| `Annotation extraction failed: {message}`                                   | The `unpdf` annotation pass failed                                                             |
| `Owner strictly determined by profile URL input: {username}`                | `knownOwnerProfile` was provided; algorithm was bypassed                                       |
| `Multiple profile links found: {usernames}`                                 | Case 2 disambiguation was triggered                                                            |
| `Owner determined by repo cross-reference: {scores}`                        | Case 2 resolved to `high` confidence via repo count comparison                                 |
| `⚠ Tied repo ownership between profiles: {scores}. Picked {username}.`      | Case 2 ended in a tie; `medium` confidence                                                     |
| `None of the profile links match any repo owner — picking first profile`    | Case 2 found profiles but zero matching repos; `low` confidence                                |
| `Multiple profiles found but no repos to cross-reference — picking first`   | Case 2 with no repos at all; `low` confidence                                                  |
| `No profile link found — all repos belong to same user, inferred as owner`  | Case 3 single username; `medium` confidence                                                    |
| `No profile link found — inferred from repo majority: {counts}`             | Case 3 dominant username; `medium` confidence                                                  |
| `No profile link found — tied repo ownership: {counts}. Picked {username}.` | Case 3 tie; `low` confidence                                                                   |
| `No git links found`                                                        | Case 4; `confidence: 'none'`                                                                   |

***

## The error field

The `error` field on `ResolverResult` is only present when a fatal, unrecoverable exception occurred. It is absent (`undefined`) on successful runs — even runs that produced zero links.

Conditions that set `error`:

* **Network failure** — the portfolio URL timed out or returned a non-recoverable HTTP error
* **File system error** — the resume file path does not exist or cannot be read
* **Unexpected exception** — any other unhandled error thrown inside the scraper or parser

When `error` is set, `ownerProfile` is `null`, `confidence` is `'none'`, and all link arrays (`ownedRepos`, `allLinks`, etc.) are empty. The `warnings` array may still contain partial diagnostic output from before the error occurred.

<Note>
  Partial extraction failures — such as one PDF parsing pass failing while the other succeeds — are reported in `warnings`, not `error`. An `error` value means the entire source could not be processed.
</Note>

***

## JSON examples

### ResolverResult example

<Expandable title="Full ResolverResult JSON">
  ```json theme={null}
  {
    "source": "https://janedoe.dev",
    "sourceType": "portfolio",
    "ownerProfile": {
      "url": "https://github.com/janedoe",
      "provider": "github",
      "type": "profile",
      "username": "janedoe"
    },
    "confidence": "high",
    "ownedRepos": [
      {
        "url": "https://github.com/janedoe/api-server",
        "provider": "github",
        "type": "repo",
        "username": "janedoe",
        "repo": "api-server"
      },
      {
        "url": "https://github.com/janedoe/portfolio-site",
        "provider": "github",
        "type": "repo",
        "username": "janedoe",
        "repo": "portfolio-site"
      }
    ],
    "contributions": [
      {
        "url": "https://github.com/torvalds/linux/pull/99",
        "provider": "github",
        "type": "pull_request",
        "username": "torvalds",
        "repo": "linux",
        "number": "99"
      }
    ],
    "externalRepos": [
      {
        "url": "https://github.com/expressjs/express",
        "provider": "github",
        "type": "repo",
        "username": "expressjs",
        "repo": "express"
      }
    ],
    "allLinks": [
      {
        "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/janedoe/portfolio-site",
        "provider": "github",
        "type": "repo",
        "username": "janedoe",
        "repo": "portfolio-site"
      },
      {
        "url": "https://github.com/torvalds/linux/pull/99",
        "provider": "github",
        "type": "pull_request",
        "username": "torvalds",
        "repo": "linux",
        "number": "99"
      },
      {
        "url": "https://github.com/expressjs/express",
        "provider": "github",
        "type": "repo",
        "username": "expressjs",
        "repo": "express"
      }
    ],
    "warnings": [
      "Used puppeteer provider for page content",
      "Owner strictly determined by profile URL input: janedoe"
    ]
  }
  ```
</Expandable>

### AggregatedResult example

<Expandable title="Full AggregatedResult JSON">
  ```json theme={null}
  {
    "candidateUsername": "janedoe",
    "sources": [
      "https://janedoe.dev",
      "./resumes/jane_doe.pdf"
    ],
    "sourceTypes": [
      "portfolio",
      "resume_file"
    ],
    "ownerProfile": {
      "url": "https://github.com/janedoe",
      "provider": "github",
      "type": "profile",
      "username": "janedoe"
    },
    "confidence": "high",
    "ownedRepos": [
      {
        "url": "https://github.com/janedoe/api-server",
        "provider": "github",
        "type": "repo",
        "username": "janedoe",
        "repo": "api-server"
      },
      {
        "url": "https://github.com/janedoe/portfolio-site",
        "provider": "github",
        "type": "repo",
        "username": "janedoe",
        "repo": "portfolio-site"
      },
      {
        "url": "https://github.com/janedoe/data-pipeline",
        "provider": "github",
        "type": "repo",
        "username": "janedoe",
        "repo": "data-pipeline"
      }
    ],
    "contributions": [
      {
        "url": "https://github.com/torvalds/linux/pull/99",
        "provider": "github",
        "type": "pull_request",
        "username": "torvalds",
        "repo": "linux",
        "number": "99"
      }
    ],
    "externalRepos": [
      {
        "url": "https://github.com/expressjs/express",
        "provider": "github",
        "type": "repo",
        "username": "expressjs",
        "repo": "express"
      }
    ],
    "allLinks": [
      {
        "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/janedoe/portfolio-site",
        "provider": "github",
        "type": "repo",
        "username": "janedoe",
        "repo": "portfolio-site"
      },
      {
        "url": "https://github.com/janedoe/data-pipeline",
        "provider": "github",
        "type": "repo",
        "username": "janedoe",
        "repo": "data-pipeline"
      },
      {
        "url": "https://github.com/torvalds/linux/pull/99",
        "provider": "github",
        "type": "pull_request",
        "username": "torvalds",
        "repo": "linux",
        "number": "99"
      },
      {
        "url": "https://github.com/expressjs/express",
        "provider": "github",
        "type": "repo",
        "username": "expressjs",
        "repo": "express"
      }
    ],
    "warnings": [
      "Used puppeteer provider for page content",
      "Owner strictly determined by profile URL input: janedoe",
      "Found 2 git URL(s) in text content"
    ]
  }
  ```
</Expandable>

<CardGroup cols={2}>
  <Card title="Input Classification" icon="filter" href="/concepts/input-classification">
    How every input is categorized before processing begins
  </Card>

  <Card title="Disambiguation" icon="code-branch" href="/concepts/disambiguation">
    How GitResolve resolves ambiguous link sets to a single owner
  </Card>
</CardGroup>
