Skip to content

feat(scoring): per-repo time-decay hyperparameters + go live (#703) - #733

Merged
JSONbored merged 1 commit into
mainfrom
feat/time-decay-per-repo
Jun 14, 2026
Merged

feat(scoring): per-repo time-decay hyperparameters + go live (#703)#733
JSONbored merged 1 commit into
mainfrom
feat/time-decay-per-repo

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

What

Completes #703: time-decay now resolves each repo's own curve and goes live (SCORING_TIME_DECAY_ENABLED=true).

  • The curve comes from the code — defaults are parsed live from upstream's constants.py into the scoring snapshot (the TIME_DECAY_* constants are now modeled).
  • …but changes per repo — each repo's scoring.time_decay overrides overlay the defaults per-field, mirroring upstream's resolve_time_decay. GITTENSOR_REGISTRY_URL is master_repositories.json, so these are the same overrides upstream reads → gittensory's projection matches upstream's actual scoring.

How

  • registry/normalize.ts: parse the nested scoring.time_decay block per repo (grace_period_hours, sigmoid_midpoint_days, sigmoid_steepness, min_multiplier) → RegistryRepoConfig.timeDecay; absent/invalid fields stay null (→ fall back to the default at resolve time).
  • scoring/preview.ts: resolveTimeDecay(constants, overrides) overlays per-field (override ?? default); calculateTimeDecay(prAgeHours, constants, overrides?) applies the resolved per-repo curve; computeScoreCore passes repo.registryConfig.timeDecay.
  • wrangler.jsonc: SCORING_TIME_DECAY_ENABLED=true — the go-live switch (deploys on merge via Workers Builds).

Real example

JSONbored/gittensory already sets scoring.time_decay: { grace_period_hours: 24, sigmoid_midpoint_days: 10, min_multiplier: 0.05 } upstream — so on this repo an 18h-old PR is still fresh (24h grace), where a default-config repo (12h grace) would have started decaying. sigmoid_steepness (unset) falls back to the upstream default 0.4.

Safety

A fresh PR is unaffected (decay 1.0), and no caller passes prAgeHours today — so going live changes nothing until a projection explicitly asks for an aged-PR score. Per-repo curves then apply automatically.

Tests

scoring.time_decay parsing (partial / empty-object / absent / array), resolveTimeDecay per-field overlay, calculateTimeDecay with overrides (grace + midpoint), and the preview applying each repo's resolved curve. 97% coverage held; typecheck + UI lint + OpenAPI clean.

Time-decay now resolves each repo's curve from its registry config and goes live
(SCORING_TIME_DECAY_ENABLED=true). The defaults come straight from upstream's
constants.py (parsed into the live snapshot now that the TIME_DECAY_* constants
are modeled); each repo's scoring.time_decay overrides overlay them per-field —
mirroring upstream's resolve_time_decay.

- registry/normalize.ts: parse the nested scoring.time_decay block per repo
  (grace_period_hours, sigmoid_midpoint_days, sigmoid_steepness, min_multiplier)
  into RegistryRepoConfig.timeDecay; absent/invalid fields stay null.
- scoring/preview.ts: resolveTimeDecay overlays overrides on the snapshot defaults
  (per-field ?? default); calculateTimeDecay(prAgeHours, constants, overrides?) uses
  the resolved per-repo curve; computeScoreCore passes repo.registryConfig.timeDecay
  so each live repo's settings apply.
- wrangler.jsonc: SCORING_TIME_DECAY_ENABLED=true — the go-live switch (deploys on merge).

GITTENSOR_REGISTRY_URL is master_repositories.json, so these overrides are the SAME
source upstream reads (e.g. JSONbored/gittensory already sets grace_period_hours: 24)
— gittensory's projection matches upstream's scoring. A fresh PR is unaffected (decay
1.0); only aged-PR projections decay, so going live changes nothing until a caller
supplies prAgeHours.

Tests: scoring.time_decay parsing (partial/empty/absent), resolveTimeDecay overlay,
calculateTimeDecay with overrides, and the preview applying each repo's resolved
curve. 97% coverage held; OpenAPI clean.
@ghost

ghost commented Jun 14, 2026

Copy link
Copy Markdown

Note

Gittensory Gate skipped

PR closed before full evaluation. No late first comment was created.

Signal Result Evidence Action
Gate result ⚠️ Skipped #733 is no longer open. No action.

💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

@ghost ghost added the gittensory:reviewed label Jun 14, 2026
@ghost

ghost commented Jun 14, 2026

Copy link
Copy Markdown

gittensory · advisory review

Reviewed 6 changed file(s) — two independent AI reviewers.

Suggested action:Safe to merge — both reviewers found no blocking issues.

Reviewer A · gpt-oss-120b — recommends ✅ merge
This PR introduces per‑repository time‑decay hyper‑parameters, adds parsing of those overrides from the registry, updates the scoring preview to apply them, and includes comprehensive unit tests and an env‑var switch. The changes are well‑scoped and type‑safe.

Suggestions

  • Confirm that the config variable used in computeScoreCore is the repository config that now includes timeDecay; if its name differs, adjust the reference.
  • Add a unit test verifying that the SCORING_TIME_DECAY_ENABLED environment flag correctly disables the decay logic in previews.
  • Run the full test suite to ensure no other modules are affected by the new optional timeDecay field in RegistryRepoConfig.

Worth double-checking

  • If config is undefined in some code paths, config?.timeDecay will be undefined, which is intended, but ensure no runtime errors arise.
  • Overrides with non‑numeric values should correctly fall back to defaults; verify edge cases with NaN or Infinity.

Reviewer B · nemotron-3-120b-a12b — recommends ✅ merge
The PR implements per-repo time-decay hyperparameters for scoring, allowing repository-specific overrides of grace period, sigmoid midpoint, steepness, and minimum multiplier. It updates scoring logic, registry normalization, types, and adds comprehensive tests. The feature is gated by SCORING_TIME_DECAY_ENABLED (set to true) and appears correct, well-tested, and consistent with the project's deterministic scoring goals.

Suggestions

  • Add a comment in resolveTimeDecay clarifying that null overrides are treated as 'no overrides' (already covered by pickOverride logic).
  • Consider adding a test for extreme override values (e.g., negative gracePeriodHours) to ensure they fall back to defaults.
  • In wrangler.jsonc, the comment mentions 'Owner-reviewed; this is the go-live switch'—ensure this matches the project's governance process for feature flags.

Worth double-checking

  • Verify that the time decay multiplier calculation remains deterministic and safe for all possible override combinations (e.g., zero or negative values).
  • Ensure the feature flag SCORING_TIME_DECAY_ENABLED is respected in all code paths (it is gated in computeScoreCore via input.applyTimeDecay, which likely derives from this flag).
  • Check that the registry normalization handles malformed time_decyn objects gracefully (already covered by tests).

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@ghost ghost added the gittensory-review label Jun 14, 2026
@JSONbored
JSONbored merged commit c00d3cb into main Jun 14, 2026
10 checks passed
@JSONbored
JSONbored deleted the feat/time-decay-per-repo branch June 14, 2026 17:34
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jun 14, 2026
@github-actions github-actions Bot mentioned this pull request Jun 14, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant