How Bonus Points and Deductions Are Calculated in Resume Evaluations

Bonus points and deductions are applied to the base category scores after initial evaluation, with bonuses adding up to 20 points and deductions subtracting from the total, followed by a hard cap at 120 points.

The interviewstreet/hiring-agent repository automates résumé screening using an AI-driven scoring system. After evaluating four core competency categories, the system applies bonus points and deductions to adjust the final score based on exceptional merits or identified shortcomings. Understanding this calculation logic helps engineers audit evaluation fairness and debug scoring discrepancies.

Bonus Points Implementation

Data Model Definition

The BonusPoints class in models.py (lines 31-34) defines the schema for extra credit:

class BonusPoints(BaseModel):
    total: int  # Range: 0-20

    breakdown: str  # Explanation of bonus criteria met

This model enforces a maximum of 20 bonus points and requires a human-readable breakdown string that explains which exceptional criteria the candidate met.

Addition Logic in score.py

When the AI evaluator returns a bonus_points field, score.py adds the total to the running aggregate. The implementation at lines 58-60 checks for attribute presence before arithmetic:

if hasattr(evaluation, "bonus_points") and evaluation.bonus_points:
    total_score += evaluation.bonus_points.total

The breakdown string is displayed to reviewers alongside the calculation for full transparency (lines 25-30).

Deductions Calculation

Deduction Schema

The Deductions model in models.py (lines 36-41) captures penalties using a positive integer total and详细 reasons string:

class Deductions(BaseModel):
    total: int  # Positive number to subtract

    reasons: str  # Detailed explanation of penalties

Unlike bonus points, deductions have no explicit upper bound in the model definition, allowing the evaluator to assign penalties proportional to the severity of identified shortcomings.

Subtraction Logic

In score.py (lines 61-64), the system subtracts the deduction total from the accumulated score:

if hasattr(evaluation, "deductions") and evaluation.deductions:
    total_score -= evaluation.deductions.total

Score Capping and Boundary Enforcement

After applying bonuses and deductions, score.py enforces a hard ceiling to prevent score overflow. The logic at lines 65-69 caps the final score at the category maximum plus 20 bonus points:

max_possible = sum(cat["max"] for cat in evaluation.scores.model_dump().values()) + 20
total_score = min(total_score, max_possible)  # Caps at 120 (100 + 20)

This ensures the theoretical maximum remains 120 points: 100 from base categories plus 20 bonus capacity. Deductions can lower the score significantly, though in practice scores remain positive because base category minimums typically offset penalties.

Complete Evaluation Workflow

The following Python snippet demonstrates the full calculation pipeline implemented in score.py:


# Calculate base score from four categories (capped at individual maxima)

total_score = sum(
    min(cat["score"], cat["max"]) for cat in evaluation.scores.model_dump().values()
)

# Apply bonus points if present (max 20)

if getattr(evaluation, "bonus_points", None):
    total_score += evaluation.bonus_points.total

# Apply deductions if present

if getattr(evaluation, "deductions", None):
    total_score -= evaluation.deductions.total

# Enforce hard ceiling (100 base + 20 bonus max)

max_possible = sum(cat["max"] for cat in evaluation.scores.model_dump().values()) + 20
final_score = min(total_score, max_possible)

Data Persistence and Auditing

The transform.py module persists these modifiers for downstream analysis. Lines 715-721 write both bonus_points.total and deductions.total to CSV exports, enabling audit trails and statistical review of evaluator behavior across candidate pools.

Summary

  • Bonus points are defined in models.py with a 0-20 point range and explanatory breakdown, added to the base score in score.py (lines 58-60).
  • Deductions subtract from the total based on the Deductions model's total field (lines 61-64), with reasons tracked for transparency.
  • Score capping occurs after modifiers are applied, limiting the maximum to 120 points (100 base + 20 bonus) as implemented in lines 65-69.
  • Auditability is maintained through CSV export in transform.py (lines 715-721) and detailed breakdown strings stored in the evaluation objects.

Frequently Asked Questions

What is the maximum number of bonus points that can be added?

The BonusPoints model enforces a maximum of 20 points, as defined in models.py. When combined with the 100-point base category maximum, the theoretical ceiling is 120 points before final capping.

Can deductions reduce a score below zero?

The source code in score.py does not explicitly enforce a floor at zero, though the final score typically remains positive because base category scores start above zero and deductions are usually smaller than the accumulated base score.

Where are bonus and deduction values stored for reporting?

The transform.py module writes both values to CSV exports at lines 715-721, persisting bonus_points.total and deductions.total alongside the final score for offline analysis and auditing.

How does the system handle evaluations without bonuses or deductions?

The score.py logic uses hasattr and truthiness checks (if evaluation.bonus_points:) to conditionally apply modifiers. If these fields are absent or null, the calculation proceeds with only the base category scores, skipping the addition or subtraction steps entirely.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →