# Investigating Git Repository Aliasing Issues in the Hiring Agent

> Resolve Git repository aliasing issues in the Hiring Agent. Discover common causes like regex patterns, API pagination, cache collisions, and LLM prompt ambiguity.

- Repository: [HackerRank/hiring-agent](https://github.com/interviewstreet/hiring-agent)
- Tags: how-to-guide
- Published: 2026-07-13

---

**The Hiring Agent repository does not implement custom Git-aliasing logic; instead, aliasing issues typically stem from username extraction regex patterns, API pagination handling, cache collisions, or LLM prompt ambiguity in the [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) module.**

When investigating Git repository aliasing issues in the **interviewstreet/hiring-agent** codebase, understanding the GitHub integration architecture is essential. The project interacts with GitHub purely through the public REST API, with all Git-related functionality centralized in a single module. This analysis explores the specific code paths in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py), [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py), and related files where repository identification errors commonly originate.


## How GitHub Integration Works in the Hiring Agent

The workflow follows a clear pipeline: [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) → [`pdf.py`](https://github.com/interviewstreet/hiring-agent/blob/main/pdf.py) → [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) → [`evaluator.py`](https://github.com/interviewstreet/hiring-agent/blob/main/evaluator.py). The [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) module handles four critical tasks: extracting the GitHub username from resume JSON data, fetching public profile information via `GET /users/:username`, retrieving repository lists through `GET /users/:username/repos`, and classifying repositories using an LLM prompt.

When `DEVELOPMENT_MODE=True` is set in [`config.py`](https://github.com/interviewstreet/hiring-agent/blob/main/config.py), raw API responses are cached under `cache/githubcache_<basename>.json` to prevent redundant network calls. The repository selection logic relies on the Jinja template located at `prompts/templates/github_project_selection.jinja`, which instructs the language model to select exactly seven unique projects.


## Common Sources of Repository Aliasing

### Incorrect Username Extraction

The `extract_github_username` function in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) uses a regular expression to parse GitHub URLs from the resume's "profiles" section. The current implementation matches `r"github\.com[:/](?P<user>[^/]+)"`, which extracts the path component immediately following the domain. However, this pattern captures organization aliases or redirect URLs as literal usernames, causing the system to query the wrong GitHub account.

### API Pagination Handling

Repository fetching occurs in the `fetch_all_repos` helper function, which iterates through paginated results using `per_page=100` parameters. If pagination stops prematurely—due to rate limiting or incomplete HTTP 429 handling—the resulting dataset may be incomplete. Missing repositories can lead the LLM to substitute alternative projects or duplicate entries from partial data.

### Caching Collisions

The development cache in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) generates filenames using only the PDF basename: `githubcache_<basename>.json`. Reprocessing the same PDF with different GitHub profiles returns stale cached data, effectively creating an alias where one user's repositories appear under another's processing context.

### LLM Prompt Ambiguity

The `github_project_selection.jinja` template asks the model to "select exactly 7 unique projects" without explicitly requiring canonical `owner/repo` identifiers. This ambiguity allows the LLM to return shortened names, alternative references, or aliases rather than the precise repository identifiers required for accurate evaluation.


## Diagnosing Aliasing Problems

Enable detailed logging and inspect raw API responses to identify where repository identification diverges. Set `DEVELOPMENT_MODE = True` in [`config.py`](https://github.com/interviewstreet/hiring-agent/blob/main/config.py) to preserve the raw GitHub API JSON at `cache/githubcache_<basename>.json`, then verify that the `full_name` fields contain expected `owner/repo` pairs.

Run the GitHub enrichment module in isolation to bypass the full pipeline:

```python
import json
from github import enrich_resume_with_github

# Load pre-extracted resume JSON

resume = json.load(open('cache/resumecache_example.json'))
enriched = enrich_resume_with_github(resume)

# Verify project identifiers

for proj in enriched['github_projects']:
    print(f"Repository: {proj['full_name']}")

```

If the output contains duplicate owner names or unexpected repositories, the issue lies in the extraction or pagination logic rather than the LLM evaluation phase.


## Fixes for Git Repository Aliasing

Implement robust username extraction by extending the regex to handle organization aliases and common URL suffixes like `.git`. Modify the cache key generation in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) to include the GitHub username: `githubcache_<basename>_<username>.json`, preventing cross-profile contamination.

Add rate-limit detection to the `fetch_all_repos` function in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py) to handle HTTP 429 responses with exponential backoff, ensuring complete pagination. Refine the `github_project_selection.jinja` template to explicitly request canonical `owner/repo` strings without additional text or formatting.

Override cache configuration programmatically:

```python

# In config.py

DEVELOPMENT_MODE = True
CACHE_KEY_TEMPLATE = "githubcache_{pdf_base}_{github_user}.json"

```


## Summary

- **The Hiring Agent** interacts with GitHub through the REST API centralized in [`github.py`](https://github.com/interviewstreet/hiring-agent/blob/main/github.py), not through custom Git aliasing.
- **Aliasing issues** typically originate from regex-based username extraction, incomplete API pagination, cache key collisions, or ambiguous LLM prompts.
- **Diagnosis** requires enabling `DEVELOPMENT_MODE` and inspecting cached responses at `cache/githubcache_<basename>.json`.
- **Resolution** involves strengthening the `extract_github_username` regex, implementing username-scoped cache keys, adding rate-limit retry logic, and refining the `github_project_selection.jinja` template instructions.


## Frequently Asked Questions

### Why does the Hiring Agent resolve repositories to the wrong GitHub user?

The `extract_github_username` function uses a regex pattern that captures any string following `github.com/`, including organization aliases or vanity URLs. If a resume contains a redirect link or organization membership URL instead of the personal profile, the system queries the wrong API endpoint and retrieves that entity's repositories instead.

### How does DEVELOPMENT_MODE help investigate repository aliasing?

Setting `DEVELOPMENT_MODE=True` in [`config.py`](https://github.com/interviewstreet/hiring-agent/blob/main/config.py) preserves raw GitHub API responses in `cache/githubcache_<basename>.json` files. This allows developers to inspect the exact `full_name` values returned by the API before LLM processing, identifying whether aliasing occurs during data fetching or during the subsequent selection and classification phase.

### What causes duplicate repository entries in the evaluation?

Duplicate entries typically result from incomplete pagination handling in the `fetch_all_repos` function combined with aggressive caching. If the API request fails silently or returns partial data, and the system retries without invalidating the cache, multiple processing runs may concatenate overlapping dataset fragments, creating apparent duplicates in the final project list.

### Where is the LLM instructed to select specific repositories?

The repository selection prompt resides in `prompts/templates/github_project_selection.jinja`. This template instructs the model to choose exactly seven projects, but without explicit constraints on identifier format, the LLM may return shorthand names or aliases rather than the canonical `owner/repo` strings required for accurate GitHub API correlation.