Skip to content

Refs #406: Use API bounty capacity in queue health#474

Open
er1c-cartman wants to merge 3 commits into
ramimbo:mainfrom
er1c-cartman:fix-406-api-bounty-fallback
Open

Refs #406: Use API bounty capacity in queue health#474
er1c-cartman wants to merge 3 commits into
ramimbo:mainfrom
er1c-cartman:fix-406-api-bounty-fallback

Conversation

@er1c-cartman
Copy link
Copy Markdown

@er1c-cartman er1c-cartman commented May 26, 2026

Summary

  • enrich pr_queue_health live mode with public MergeWork API bounty metadata for the target repo
  • use API status and awards_remaining to avoid treating exhausted open GitHub bounty issues as payable
  • preserve the existing GitHub-only fallback with visible warnings when the API is unavailable, malformed, missing authoritative fields, invalid UTF-8, or at the 200-row safety cap

Refs #406.

Evidence

This addresses a real queue-health edge case: GitHub issue state alone can show a bounty issue as open while the public MergeWork API reports no remaining award capacity. Without the API overlay, live queue reports can incorrectly mark PRs against exhausted bounties as still payable. The invalid UTF-8 regression keeps the fallback boundary intact for malformed API responses.

Validation

  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev python -m pytest tests/test_pr_queue_health.py -q -> 14 passed
  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev python -m pytest -q -> 419 passed
  • ~/.local/bin/uv run --extra dev ruff check . -> passed
  • ~/.local/bin/uv run --extra dev ruff format --check . -> 79 files already formatted
  • ~/.local/bin/uv run --extra dev mypy app scripts/pr_queue_health.py -> success
  • git diff --check -> clean
  • changed-file secret scan -> no matches

Note: pytest plugin autoload is disabled because this workstation has an unrelated ROS Humble pytest plugin on the global path.

Summary by CodeRabbit

  • New Features

    • Live bounty availability is now surfaced in the queue reports, with the report indicating which data source was used.
  • Improvements

    • Reports show a clear warning when external bounty data is unavailable or invalid and automatically fall back to GitHub-only state; safety-cap limits are respected.
  • Tests

    • Added tests for live API integration, malformed/invalid responses, safety-cap handling, and fallback behavior.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1369ebaf-ddaf-484e-9fc3-02c2720e4121

📥 Commits

Reviewing files that changed from the base of the PR and between f109356 and 1935aa2.

📒 Files selected for processing (2)
  • scripts/pr_queue_health.py
  • tests/test_pr_queue_health.py

📝 Walkthrough

Walkthrough

The pr_queue_health.py script now fetches live bounty state and award capacity from an external MergeWork API endpoint, supplementing GitHub issue data. A new _load_api_bounties() function retrieves and normalizes bounty records while handling fetch and validation failures. The load_live_queue() function integrates this API data, preferring API-derived state and awards when available and gracefully falling back on API errors. Test coverage validates the API integration path and robustness on malformed responses.

Changes

API-driven bounty enrichment for queue health analysis

Layer / File(s) Summary
API integration setup and bounty fetch function
scripts/pr_queue_health.py
Adds urllib imports, API_BOUNTY_SAFETY_CAP, and DEFAULT_API_HOST; implements _load_api_bounties(repo, api_host) to GET /api/v1/bounties/summary, validate the JSON list payload and row fields, enforce a safety cap, filter by repo, normalize state and awards_remaining, and raise RuntimeError on failures.
Live queue integration with API bounty state
scripts/pr_queue_health.py
Updates load_live_queue() to call _load_api_bounties(repo) with try/except that records metadata and api_bounty_warning on failure; builds bounty_issues by selecting issues with "bounty" in the title and preferring API-provided state and awards_remaining with GitHub fallbacks.
Annotate analysis and formatters with API source and warnings
scripts/pr_queue_health.py
Extends analyze_queue() to include data_sources.bounties and optional api_bounty_warning from metadata; updates format_text_report() and format_markdown_report() to append the bounty data-source line and include a warning block when api_bounty_warning is present.
Test coverage for API bounty enrichment
tests/test_pr_queue_health.py
Adds multiple live-mode tests that mock urlopen and GitHub listings to assert: API usage and timeout, fallback on invalid UTF-8 with a warning included in text/markdown outputs, fallback on malformed API rows, and fallback when the API fetch reaches the configured safety cap.

Possibly related PRs

  • ramimbo/mergework#413: Both PRs modify scripts/pr_queue_health.py and tests/test_pr_queue_health.py to extend report generation logic, overlapping in the same code paths and test module.
  • ramimbo/mergework#324: Earlier changes to load_live_queue, analyze_queue, and formatters that this PR extends with MergeWork API enrichment.
  • ramimbo/mergework#311: Adds the public /api/v1/bounties/summary endpoint that supplies the bounty capacity fields consumed by this PR.
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed Title is concrete and directly names the changed surface (API bounty capacity integration in queue health).
Description check ✅ Passed Description covers summary, evidence, and validation. All required template sections are present with substantive content.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Mergework Public Artifact Hygiene ✅ Passed PR code contains no investment, price, cash-out, or fabricated payout claims. Docs properly disclaim fiat pegs and describe MRWK as work-based project coin.
Bounty Pr Focus ✅ Passed PR #474 (Refs #406) matches stated scope: two files, all features verified present, 4 tests with fallback/API validation evidence, no unrelated changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@jtc268
Copy link
Copy Markdown

jtc268 commented May 26, 2026

Reviewed PR #474 at current head c5b5579eda0941e72c00b476a763b39ecb311af0.

I would hold this for one small observability gap before merge: load_live_queue() catches any _load_api_bounties() RuntimeError and silently falls back to GitHub issue state. That preserves operation, but it also means the exact exhausted-bounty false positive this PR fixes can return during a transient API/decode failure with no visible warning in the JSON/text report.

Evidence on this head:

  • Inspected scripts/pr_queue_health.py: _load_api_bounties() raises on API/decode/schema failure, but load_live_queue() catches it and sets api_bounties = {} without carrying any warning/source metadata into the report.
  • Ran uv run --extra dev python -m pytest tests/test_pr_queue_health.py -q -> 11 passed.
  • Ran the live queue command with the PR code: uv run --extra dev python scripts/pr_queue_health.py --repo ramimbo/mergework --format json -> API-backed open bounty counts loaded successfully in the live path.
  • Directly exercised the bad-UTF8 fallback shape from the new regression: report summary returned open_bounties: 1, closed_bounty_references: 0, and top-level keys only closed_bounty_references, dirty_or_unstable_merge_state, duplicate_scope_groups, missing_bounty_references, needs_info, and summary; there is no API fallback warning for callers or humans to notice.

Suggested fix: keep the fallback, but include an api_bounty_warning/data_sources field in the report and render it in text/markdown so operators know when payability is GitHub-only instead of API-confirmed.

Assessment: this is a good direction for MergeWork because queue-health should use actual award capacity, but without a surfaced fallback warning the tool can still produce overconfident payability output when the API layer is unavailable.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f2c0ce42-8a2c-4a43-81c1-9f453bfe2cac

📥 Commits

Reviewing files that changed from the base of the PR and between d8532d4 and c5b5579.

📒 Files selected for processing (2)
  • scripts/pr_queue_health.py
  • tests/test_pr_queue_health.py

Comment thread scripts/pr_queue_health.py Outdated
Comment thread scripts/pr_queue_health.py Outdated
@er1c-cartman
Copy link
Copy Markdown
Author

Thanks, agreed. I pushed f109356 to address the observability gap.

What changed:

  • load_live_queue() now returns metadata describing whether bounty data came from github_issues+mergework_api or GitHub-only fallback.
  • analyze_queue() carries that into data_sources and includes api_bounty_warning when the API path fails.
  • text and markdown reports render the bounty data source and fallback warning before the issue sections, so no-issue reports can still show degraded payability confidence.
  • the bad-UTF8 regression now asserts the warning and both rendered formats.

Fresh validation:

  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev python -m pytest tests/test_pr_queue_health.py -q -> 11 passed
  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev python -m pytest -q -> 416 passed
  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev ruff check scripts/pr_queue_health.py tests/test_pr_queue_health.py -> passed
  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev ruff format --check scripts/pr_queue_health.py tests/test_pr_queue_health.py -> 2 files already formatted
  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev python -m mypy app scripts/pr_queue_health.py -> success
  • git diff --check -> clean

@er1c-cartman
Copy link
Copy Markdown
Author

Pushed 1935aa2 for the two remaining CodeRabbit findings.

Changes:

  • Added an API_BOUNTY_SAFETY_CAP guard so a full 200-row API page fails over with an api_bounty_warning instead of silently trusting a truncated global list.
  • Validated matching API bounty rows before treating them as authoritative: status must be a non-empty string and awards_remaining must be integer-coercible, non-boolean, and present.
  • Added regression coverage for missing status, missing awards_remaining, and the 200-row API cap fallback.

Fresh validation:

  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev python -m pytest tests/test_pr_queue_health.py -q -> 14 passed
  • PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 ~/.local/bin/uv run --extra dev python -m pytest -q -> 419 passed
  • ~/.local/bin/uv run --extra dev ruff check . -> passed
  • ~/.local/bin/uv run --extra dev ruff format --check . -> 79 files already formatted
  • ~/.local/bin/uv run --extra dev mypy app scripts/pr_queue_health.py -> success
  • git diff --check -> clean

Copy link
Copy Markdown
Contributor

@GHX5T-SOL GHX5T-SOL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed current head 1935aa2d526ed9c7589da0556d725bfa0a19ad5d.

No blocker found in this current-head pass. The earlier silent-fallback concern has been addressed: API failures now carry data_sources.bounties = github_issues plus api_bounty_warning, and text/markdown reports render the degraded source. The latest head also validates matching API rows and fails over at the 200-row safety cap instead of silently trusting a potentially truncated list.

Evidence checked:

  • PR is open, non-draft, mergeable/CLEAN, with GitHub CI and CodeRabbit successful.
  • Diff is scoped to scripts/pr_queue_health.py and tests/test_pr_queue_health.py.
  • _load_api_bounties() now wraps malformed UTF-8/JSON/API failures, validates status and awards_remaining, and records visible fallback metadata through load_live_queue()/analyze_queue().
  • Live read-only queue health completed with data_sources.bounties = github_issues+mergework_api.
  • Live API scan returned 76 ramimbo/mergework bounty rows and no duplicate (repo, issue_number) keys; the app model also has a uniqueness constraint for that pair.

Validation:

  • /home/kali/money/mergework/.venv/bin/python -m pytest tests/test_pr_queue_health.py -q -> 14 passed
  • /home/kali/money/mergework/.venv/bin/python -m pytest -q -> 419 passed
  • /home/kali/money/mergework/.venv/bin/python -m ruff check scripts/pr_queue_health.py tests/test_pr_queue_health.py -> passed
  • /home/kali/money/mergework/.venv/bin/python -m ruff format --check scripts/pr_queue_health.py tests/test_pr_queue_health.py -> 2 files already formatted
  • /home/kali/money/mergework/.venv/bin/python -m mypy app scripts/pr_queue_health.py -> success, no issues in 31 source files
  • gitleaks detect --no-banner --redact --source . --log-opts upstream/main..HEAD --exit-code 1 -> no leaks found

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants