# How Bonus Points and Deductions Are Handled in Resume Scoring: A Technical Guide to the Hiring-Agent Repository

> Learn how bonus points and deductions affect resume scoring in the hiring agent repository. Understand score calculations and the 20-point bonus ceiling.

- Repository: [HackerRank/hiring-agent](https://github.com/interviewstreet/hiring-agent)
- Tags: deep-dive
- Published: 2026-06-28

---

**Bonus points are added to and deductions are subtracted from the aggregated category scores, with the final total capped at the maximum possible score plus a 20-point bonus ceiling.**

The `interviewstreet/hiring-agent` repository provides a structured resume evaluation system that scores candidates across four core categories before applying adjustments. Understanding how **bonus points and deductions in resume scoring** are mathematically processed and stored is crucial for customizing evaluation pipelines or auditing results. This guide examines the specific Pydantic models, calculation logic in the scoring module, and CSV export mechanisms that manage these adjustments.

## Pydantic Models for Adjustments

### Defining Bonus Points and Deductions in models.py

In [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py) (lines 31–42), the system defines **`BonusPoints`** and **`Deductions`** as Pydantic models that encapsulate these adjustments. The `BonusPoints` model restricts the `total` field to a range of 0–20 points, while `Deductions` stores a non-negative total (the negative sign is applied during calculation). Both models include descriptive fields—`breakdown` for bonuses and `reasons` for deductions—that provide human-readable context for the numeric adjustments.

## Score Calculation Logic in score.py

### Aggregating and Adjusting the Final Score

The core arithmetic occurs in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) (lines 57–68). After summing the four core category scores (Open Source, Self Projects, Production, Technical Skills), the function adds `evaluation.bonus_points.total` and subtracts `evaluation.deductions.total`. The computed sum is then bounded by `max_possible_score`, defined as the sum of category maximums plus the 20-point bonus ceiling.

### Reporting Bonuses and Deductions

The `print_evaluation_results` function (lines 71–84) handles display logic. It prints a "BONUS POINTS" block showing the total and breakdown when bonuses exist, and a "DEDUCTIONS" block when the deduction total exceeds zero. This mirrors the internal calculation and provides transparency in the evaluation output.

## Data Export in transform.py

When persisting evaluation data, `transform_evaluation_response` in [`transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/transform.py) (lines 15–22) maps adjustment data to four specific CSV columns: `bonus_points` and `bonus_breakdown` for bonuses, and `deductions` and `deduction_reasons` for deductions. This structure enables detailed analytics on how adjustments influence final candidate rankings.

## Implementation Examples

### Creating an Evaluation with Bonus Points and Deductions

```python
from models import (
    CategoryScore,
    Scores,
    BonusPoints,
    Deductions,
    EvaluationData,
)

# Core category scores

scores = Scores(
    open_source=CategoryScore(score=30, max=35, evidence="..."),
    self_projects=CategoryScore(score=25, max=30, evidence="..."),
    production=CategoryScore(score=20, max=25, evidence="..."),
    technical_skills=CategoryScore(score=8, max=10, evidence="..."),
)

# Bonus points earned (e.g., for a hackathon win)

bonus = BonusPoints(total=12.5, breakdown="Hackathon winner (+12.5)")

# Deductions (e.g., missing contact info)

deductions = Deductions(total=3, reasons="Missing phone number")

# Full evaluation object

evaluation = EvaluationData(
    scores=scores,
    bonus_points=bonus,
    deductions=deductions,
    key_strengths=["Strong open‑source contributions"],
    areas_for_improvement=["Add a professional summary"],
)

# Print the formatted results (including bonus & deductions)

from score import print_evaluation_results
print_evaluation_results(evaluation, candidate_name="Alice Example")

```

Running this script produces formatted output including the bonus and deduction details:

```

⭐ BONUS POINTS: 12.5
   Hackathon winner (+12.5)

⚠️  DEDUCTIONS: -3
   Missing phone number

```

### Exporting to CSV Format

```python
from transform import transform_evaluation_response

row = transform_evaluation_response(
    file_name="alice_resume.pdf",
    resume_data=None,          # (omitted for brevity)

    github_data=None,
    evaluation=evaluation,
)

print(row["bonus_points"], row["deductions"])

# → 12.5 3

```

The resulting dictionary contains `bonus_points`, `bonus_breakdown`, `deductions`, and `deduction_reasons` ready for CSV serialization.

## Summary

- **Bonus points** are capped at 20 points and defined in the `BonusPoints` model in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py) (lines 31–42).
- **Deductions** are stored as non-negative values in the `Deductions` model, with subtraction applied during final score calculation in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py).
- The final score is computed by adding bonuses and subtracting deductions from the core category scores, then capping at `max_possible_score` (category maximums plus 20).
- Both adjustments are exported via [`transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/transform.py) into dedicated CSV columns for downstream analysis.

## Frequently Asked Questions

### What is the maximum number of bonus points allowed?

The `BonusPoints` model in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/models.py) enforces a hard limit of 20 points on the `total` field. This constraint is also respected in the final score calculation in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py), where the `max_possible_score` equals the sum of category maximums plus 20.

### How does the system prevent negative total scores?

While deductions are stored as non-negative values in the `Deductions` model, the subtraction occurs during final aggregation in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py). The system caps the final result to realistic boundaries, though the underlying arithmetic processes the raw values before capping.

### Where is the final score calculation performed?

The definitive calculation occurs in [`score.py`](https://github.com/interviewstreet/hiring-agent/blob/main/score.py) within the evaluation results processing logic (lines 57–68). This function aggregates the four core category scores, applies the bonus addition and deduction subtraction, and enforces the maximum score boundary.

### How are bonus points and deductions exported for analysis?

The `transform_evaluation_response` function in [`transform.py`](https://github.com/interviewstreet/hiring-agent/blob/main/transform.py) (lines 15–22) maps these values to four distinct CSV columns: `bonus_points` and `bonus_breakdown` for bonuses, and `deductions` and `deduction_reasons` for deductions. This enables detailed post-processing and reporting workflows.