Skip to content

Open-PR threshold folds the planned PR's own token score into its concurrency allowance #454

Description

@galuis116

Repo: JSONbored/gittensory
File: src/scoring/preview.ts (computeScoreCore, lines 306–311)
Severity: low–medium (scoring gate; see Confidence caveats — this may be intentional)

Summary

The open-PR spam gate computes openPrThreshold by adding the planned PR's
own
totalTokenScore to the contributor's established-history token score.
That means previewing a single large PR inflates the contributor's own allowance
for concurrent open PRs, even with zero merged history.

Evidence

// src/scoring/preview.ts:306
const openPrThreshold = Math.min(
  constant(constants, "MAX_OPEN_PR_THRESHOLD", 30),
  constant(constants, "EXCESSIVE_PR_PENALTY_BASE_THRESHOLD", 2) +
    Math.floor((nonNegative(input.existingContributorTokenScore) + totalTokenScore) / constant(constants, "OPEN_PR_THRESHOLD_TOKEN_SCORE", 300)),
);
const openPrMultiplier = openPrCount <= openPrThreshold ? 1 : 0;

The preview input carries two distinct fields (src/api/routes.ts:392/396,
src/mcp/server.ts):

  • existingContributorTokenScore — the contributor's prior merged repo
    token-score history (the established-trust signal).
  • totalTokenScore — the planned PR's own token score.

The threshold-bonus argument is existingContributorTokenScore + totalTokenScore,
so the in-flight PR's tokens count toward the concurrency allowance.

Concrete input → output

existingContributorTokenScore: 0 (no merged history — what reward-risk.ts:197
hardcodes), planned totalTokenScore: 300, openPrCount: 3:

  • Threshold = min(30, 2 + floor((0 + 300) / 300)) = min(30, 3) = 3
    openPrMultiplier = 1 (3 ≤ 3), gate passes.
  • If the planned PR's tokens are excluded: threshold = 2 + floor(0/300) = 2
    → 3 > 2, openPrMultiplier = 0, gate fails.

A 1500-token planned PR yields threshold 7 instead of 2. So the size of the PR
being previewed raises how many concurrent open PRs the contributor may keep
scoreable.

Suggested change (if confirmed a bug)

Base the threshold bonus on established merged history only:

Math.floor(nonNegative(input.existingContributorTokenScore) / constant(constants, "OPEN_PR_THRESHOLD_TOKEN_SCORE", 300)),

Confidence caveats (why this is NOT filed as a confirmed bug)

This report is uncertain — do not treat it as confirmed:

  1. No in-repo canonical to verify against. The behavior was flagged as
    diverging from a canonical oss_scoring.py, but that reference does not
    exist in this repository
    , so the "correct" semantics can't be confirmed here.
  2. No in-repo contradiction. openPrThreshold is computed in exactly one
    place (preview.ts); the engine / reward-risk paths only consume the result,
    so nothing internal disagrees with it.
  3. A test comment models the threshold using totalTokenScore.
    test/unit/scoring.test.ts:510 writes 2 + floor(90/300) = 2, plugging in
    the input's totalTokenScore (90) rather than existingContributorTokenScore
    — suggesting the inclusion may be intentional. (That test value gives bonus 0
    under either reading, so it does not actually distinguish them.)
  4. A reasonable design interpretation exists: the preview projects "if this
    PR merged," so folding its tokens into the allowance could be deliberate.

Recommendation: confirm intended semantics with the maintainer (does the
open-PR threshold represent established merged-history trust, or a
planned-PR-as-merged projection?) before changing anything.

Metadata

Metadata

Assignees

No one assigned

    Labels

    slopAI slop and/or attempts to game additional points via manipulation or alt profiles.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions