feat(scoring): simulate open-pr pressure scenarios - #348
Merged
JSONbored merged 2 commits intoJun 3, 2026
Conversation
Adds src/services/open-pr-pressure-scenarios.ts, a pure simulator that
models how opening another PR affects repo queue pressure and contributor
strategy. Compares three options — open new work, wait, or clean up
existing work first — using repo queue health and maintainer-lane signals.
Advisory only; no payout/reward/score claims and no GitHub actions.
simulateOpenPrPressure({ queueHealth, roleContext, contributorOpenPrCount })
returns a ranked OpenPrPressureSimulation:
- queuePressure: low/medium/high/critical, or "unknown" when queueHealth
is null (missing-signal repos).
- lane: "maintainer" when roleContext.maintainerLane, else "contributor",
ranked by separate heuristics.
- scenarios: each option carries rank, recommended flag, known facts
(observed queue counts/state), assumptions (projections), tradeoffs,
and blockers — facts and assumptions are kept in distinct fields.
- recommendedOption + summary.
Contributor ranking: own open PRs + heavy pressure -> cleanup_first;
own PRs + light pressure -> cleanup_first; no own PRs + heavy pressure
-> wait; otherwise open_new_work. cleanup_first carries a blocker when
the contributor has no open PRs to clean. Maintainer ranking: open_new_work
by default, cleanup_first (queue triage) under critical pressure; maintainers
are never penalized for their own concurrent PRs.
Scope is open-PR pressure only; linked-issue eligibility and duplicate/
stale blockers are handled by separate services (JSONbored#288/JSONbored#289). All public
text runs through sanitizePublicComment.
test/unit/open-pr-pressure-scenarios.test.ts (new, 16 tests):
- Fixtures for low-pressure, high-pressure, maintainer-lane, and
missing-signal repos, asserting recommended option, ranking order,
facts, assumptions, and blockers.
- Facts-vs-assumptions separation check.
- Public sanitizer tests: every scenario field across all fixtures passes
sanitizePublicComment; no payout/reward/score claims appear.
JSONbored
approved these changes
Jun 3, 2026
JSONbored
left a comment
Owner
There was a problem hiding this comment.
@web-dev0521 this is a focused addition and the shape looks right.
A few notes:
- Keeping the scenario math isolated makes this easy to validate before wiring it into higher-level planning surfaces.
- The tests cover the pressure cases directly instead of only checking a happy path.
- The PR description has the issue and validation evidence needed for review.
No code changes requested.
Validation expected:
- Keep the current CI suite green through merge.
oktofeesh1
added a commit
to oktofeesh1/loopover-oktofeesh1
that referenced
this pull request
Jun 19, 2026
…o summary (JSONbored#348) `simulateOpenPrPressure` (open-pr-pressure-scenarios.ts, JSONbored#348) and the `renderPublicScenarioSummary` `options`/headline rendering for it were both implemented and tested, but the only production caller — buildLocalBranchAnalysis — never built or passed `pressureSimulation`. As a result `scenarioSummary.options` was ALWAYS empty in analyze-branch / preflight / local-diff, and the strategy guidance (open new work / wait / clean up first) never reached contributors. Build the simulation at the call site (roleContext is already in scope; derive queueHealth via buildCollisionReport + buildQueueHealth, and the contributor's own open-PR count) and pass it through. Pure/read-only and public-safe — the renderer already sanitizes every line. Test: local-branch.test.ts now asserts scenarioSummary.options is populated (3 ranked options, exactly one recommended, non-empty label + nextStep). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
JSONbored
added a commit
that referenced
this pull request
Jun 20, 2026
…o summary (#348) (#923) `simulateOpenPrPressure` (open-pr-pressure-scenarios.ts, #348) and the `renderPublicScenarioSummary` `options`/headline rendering for it were both implemented and tested, but the only production caller — buildLocalBranchAnalysis — never built or passed `pressureSimulation`. As a result `scenarioSummary.options` was ALWAYS empty in analyze-branch / preflight / local-diff, and the strategy guidance (open new work / wait / clean up first) never reached contributors. Build the simulation at the call site (roleContext is already in scope; derive queueHealth via buildCollisionReport + buildQueueHealth, and the contributor's own open-PR count) and pass it through. Pure/read-only and public-safe — the renderer already sanitizes every line. Test: local-branch.test.ts now asserts scenarioSummary.options is populated (3 ranked options, exactly one recommended, non-empty label + nextStep). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: ghost <49853598+JSONbored@users.noreply.github.com>
Closed
12 tasks
5 tasks
This was referenced Jul 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/services/open-pr-pressure-scenarios.ts— a puresimulateOpenPrPressure()that compares open new work / wait / cleanup-first using repo queue health and maintainer-lane signalstest/unit/open-pr-pressure-scenarios.test.ts(16 tests): low-pressure, high-pressure, maintainer-lane, missing-signal fixtures + public sanitizer testsScope
CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typecheck— cleannpm run test:coveragelocally — 788 pass (1 skipped); pre-existing Windows failures confirmed onmainbefore this branch; coverage stays above 97%npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderateIf any required check was skipped, explain why:
Safety
payout/reward/scoreclaims appear.Notes
OpenPrPressureSimulationshape:lanecontributorormaintainer(fromRoleContext.maintainerLane)queuePressurelow/medium/high/critical, orunknownwhenqueueHealthis nullrecommendedOptionscenarios[]rank,recommended,facts,assumptions,tradeoffs,blockerssummaryContributor-lane ranking:
cleanup_firstcarries a blocker ("no open PR(s)… nothing to clean up") when the contributor has no open PRs.Maintainer-lane ranking:
open_new_workby default (maintainer work is repo-health work, not outside-contributor queue load), switching tocleanup_first(queue triage) under critical pressure. Maintainers are never penalized for their own concurrent PRs (no blocker emitted).Facts vs assumptions:
factsare observed queue signals (open PR/issue counts, stale PRs, the contributor's own open PR count);assumptionsare projections (e.g. "opening another PR would add to the current high pressure"). Missing-signal repos mark these as estimates and recommend a conservativewait.Test structure (16 tests): four repo fixtures (low/high/maintainer/missing-signal) asserting recommended option, full ranking order, facts, assumptions, and blockers; a facts-vs-assumptions separation check; and two sanitizer tests confirming every field passes
sanitizePublicCommentand no payout/reward/score language appears.