Add maintainer activity freshness to the submission gate#335
Conversation
📝 WalkthroughWalkthroughAdds a maintainer-activity quality gate: UTC datetime helpers and an age-evaluation function, GitHub issue fetching to extract maintainer timestamps, CLI option to configure max age, wiring into evaluation to emit pass/warn checks, updated docs, and comprehensive tests including live-mode mocks. ChangesMaintainer Activity Quality Gate
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRsSuggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
TateLyman
left a comment
There was a problem hiding this comment.
Reviewed the maintainer-activity freshness gate for Bounty #319.
What I checked:
- Read the diff in docs/agent-guide.md, scripts/submission_quality_gate.py, and tests/test_submission_quality_gate.py.
- Verified the new live-context path only enriches the referenced bounty with maintainer activity metadata and keeps the gate advisory: it emits WARN when activity cannot be verified or is stale, not FAIL.
- Checked the activity source: owner-authored bounty creation and OWNER/MEMBER/COLLABORATOR comments are the only sources counted, so contributor chatter does not make a stale round look active.
- Verified live smoke against #319 returns PASS with maintainer activity seen 0 days ago.
Validation run locally on head 88c200a:
- uv run --extra dev python -m pytest tests/test_submission_quality_gate.py tests/test_docs_public_urls.py -q -> 31 passed
- uv run --extra dev ruff check scripts/submission_quality_gate.py tests/test_submission_quality_gate.py -> passed
- uv run --extra dev ruff format --check scripts/submission_quality_gate.py tests/test_submission_quality_gate.py -> passed
- uv run --extra dev python -m mypy scripts/submission_quality_gate.py -> success
- uv run --extra dev python scripts/docs_smoke.py -> docs smoke ok
- git diff --check -> clean
No blockers found. One small edge to keep in mind later: the age check uses whole elapsed days, so a threshold boundary can be up to almost one day lenient; that is acceptable for an advisory freshness warning.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/submission_quality_gate.py`:
- Around line 88-90: The current check uses (now - last_activity).days which
floors partial days; change the freshness check to compare the raw timedelta:
compute delta = now - last_activity and use if delta >
timedelta(days=max_age_days) to decide staleness, then derive age_days
separately for display (e.g. age_days = max(0, int(delta.total_seconds() //
86400)) or similar) so human-readable counts are computed independently of the
threshold comparison; update the variables max_age_days, age_days, now,
last_activity, and the staleness if-condition accordingly.
- Around line 291-300: The maintainer-detection logic in
_load_issue_maintainer_activity is only checking
issue.get("author").get("login") against repo_owner but comments use
authorAssociation vs MAINTAINER_ASSOCIATIONS; update the gh CLI fields requested
to include "authorAssociation" (add to the --json list) and change the
issue-author check to mirror comment logic by reading
issue.get("authorAssociation") and treating it as a maintainer when it is in
MAINTAINER_ASSOCIATIONS (instead of comparing logins). Locate and update the
list of fields passed to gh issue view and the conditional that currently uses
issue_author/repo_owner in _load_issue_maintainer_activity to use
issue.get("authorAssociation") with MAINTAINER_ASSOCIATIONS.
- Around line 212-214: The maintainer activity check
(_maintainer_activity_check) is only appended to checks inside the payable-pass
branch, which drops the maintainer freshness signal when payability isn't a
pass; move the call and append logic so activity_check =
_maintainer_activity_check(bounty_ref, bounty, now) is executed regardless of
payability, and if activity_check is not None add it to checks (preserve the
existing None guard) so maintainer_activity is emitted even when payability is
unverified.
In `@tests/test_submission_quality_gate.py`:
- Around line 263-323: Extend the existing
test_submission_quality_gate_live_context_adds_maintainer_activity to include a
regression case where the issue author.login is not equal to the repo owner but
the author's association indicates a maintainer (e.g., "MEMBER" or "OWNER");
update the fake_run for the ["gh", "issue", "view"] branch to return a second
scenario (or add a new test) where "author": {"login": "someone_else"} and one
of the comments has "authorAssociation": "MEMBER"/"OWNER", then call
_load_live_context and evaluate_submission as before and assert that
bounties[0]["maintainer_activity_verified"] is True and
last_maintainer_activity_at matches the maintainer comment timestamp to ensure
maintainer-by-association is accepted.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: ba8203d3-dd54-4fdf-91db-052a4a56ee1c
📒 Files selected for processing (3)
docs/agent-guide.mdscripts/submission_quality_gate.pytests/test_submission_quality_gate.py
| "--json", | ||
| "author,comments,createdAt", | ||
| ] | ||
| ) | ||
| activity_times = [] | ||
| repo_owner = repo.split("/", 1)[0].lower() | ||
| issue_author = str((issue.get("author") or {}).get("login") or "").lower() | ||
| created_at = _parse_datetime(issue.get("createdAt")) | ||
| if issue_author == repo_owner and created_at is not None: | ||
| activity_times.append(created_at) |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Does gh issue view --jsonexpose the issue's top-levelauthorAssociation field, and what is the exact field name to request?
💡 Result:
Yes—gh issue view --json exposes the issue’s top-level author association via the authorAssociation field name. [1] To request it, use: gh issue view <number-or-url> --json authorAssociation [1] (According to the gh issue view docs, the available JSON fields for that command include author, assignees, and stateReason etc.; among those supported fields, the author association is requested as authorAssociation.) [1]
Citations:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import itertools,sys,os,platform,subprocess, textwrap, json, re, pathlib
path="scripts/submission_quality_gate.py"
with open(path,'r',encoding='utf-8') as f:
lines=f.readlines()
start=260
end=340
for i in range(start-1,end):
if 0<=i<len(lines):
ln=i+1
print(f"{ln}:{lines[i].rstrip()}")
PYRepository: ramimbo/mergework
Length of output: 3348
Fix maintainer activity detection to use authorAssociation for issue author too.
scripts/submission_quality_gate.py::_load_issue_maintainer_activity() currently counts the issue creator only when issue.get("author").login matches repo_owner, while comments already filter by comment.authorAssociation against MAINTAINER_ASSOCIATIONS. This misses maintainer-opened bounties from MEMBER/COLLABORATOR creators and will mark them unverified until a qualifying comment appears. gh issue view --json supports the top-level authorAssociation field (request via --json authorAssociation). Update the issue view JSON request and apply the same authorAssociation filtering logic to the issue author.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/submission_quality_gate.py` around lines 291 - 300, The
maintainer-detection logic in _load_issue_maintainer_activity is only checking
issue.get("author").get("login") against repo_owner but comments use
authorAssociation vs MAINTAINER_ASSOCIATIONS; update the gh CLI fields requested
to include "authorAssociation" (add to the --json list) and change the
issue-author check to mirror comment logic by reading
issue.get("authorAssociation") and treating it as a maintainer when it is in
MAINTAINER_ASSOCIATIONS (instead of comparing logins). Locate and update the
list of fields passed to gh issue view and the conditional that currently uses
issue_author/repo_owner in _load_issue_maintainer_activity to use
issue.get("authorAssociation") with MAINTAINER_ASSOCIATIONS.
There was a problem hiding this comment.
♻️ Duplicate comments (2)
tests/test_submission_quality_gate.py (1)
352-410: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winAdd a regression for maintainer issue authors without maintainer comments.
This test covers
MEMBERvia comment association, but not the issue-author association path. Add a case wheregh issue viewreturns top-level"authorAssociation": "MEMBER"(or"COLLABORATOR") with empty comments, and assert maintainer activity is verified fromcreatedAt.As per coding guidelines,
tests/**/*.py: Add or update tests for changed behavior.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_submission_quality_gate.py` around lines 352 - 410, Add a new regression test similar to test_submission_quality_gate_live_context_accepts_member_comments that exercises the "issue-author" maintainer-activity path: mock submission_quality_gate.subprocess.run so "gh issue view" returns a top-level "authorAssociation": "MEMBER" (or "COLLABORATOR") and an empty comments list, ensure submission_quality_gate._load_live_context is invoked with the same inputs and that the returned data sets last_maintainer_activity_at to the issue createdAt and maintainer_activity_verified to True, then call evaluate_submission and assert the maintainer_activity check passes (refer to test_submission_quality_gate_live_context_accepts_member_comments, submission_quality_gate._load_live_context, and evaluate_submission to mirror structure).scripts/submission_quality_gate.py (1)
293-295:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse
authorAssociationfor issue-author maintainer detection.On Line [294], the issue payload does not request top-level
authorAssociation, and on Lines [298]-[302] maintainer detection depends onauthor.login == repo_owner. This misses maintainer-opened issues fromMEMBER/COLLABORATORaccounts unless a qualifying comment exists.Proposed fix
issue = _run_gh_json( [ "gh", "issue", "view", str(issue_number), "--repo", repo, "--json", - "author,comments,createdAt", + "author,authorAssociation,comments,createdAt", ] ) activity_times = [] - repo_owner = repo.split("/", 1)[0].lower() - issue_author = str((issue.get("author") or {}).get("login") or "").lower() + issue_author_association = str(issue.get("authorAssociation") or "").upper() created_at = _parse_datetime(issue.get("createdAt")) - if issue_author == repo_owner and created_at is not None: + if issue_author_association in MAINTAINER_ASSOCIATIONS and created_at is not None: activity_times.append(created_at)Does `gh issue view --json` support top-level `authorAssociation`, and is `--json authorAssociation` the correct field request?Also applies to: 298-302
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/submission_quality_gate.py` around lines 293 - 295, The gh issue view JSON request is missing top-level authorAssociation; update the fields list (currently ["author,comments,createdAt"]) to include "authorAssociation" so the CLI returns that property, and then change the maintainer-detection logic in this module to check the issue object's authorAssociation (e.g., issue.authorAssociation or issue["authorAssociation"]) for values like "OWNER", "MEMBER", or "COLLABORATOR" instead of relying solely on author.login == repo_owner; ensure the new check is used wherever maintainer detection occurs (refer to the issue variable and repo_owner symbol in the file).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@scripts/submission_quality_gate.py`:
- Around line 293-295: The gh issue view JSON request is missing top-level
authorAssociation; update the fields list (currently
["author,comments,createdAt"]) to include "authorAssociation" so the CLI returns
that property, and then change the maintainer-detection logic in this module to
check the issue object's authorAssociation (e.g., issue.authorAssociation or
issue["authorAssociation"]) for values like "OWNER", "MEMBER", or "COLLABORATOR"
instead of relying solely on author.login == repo_owner; ensure the new check is
used wherever maintainer detection occurs (refer to the issue variable and
repo_owner symbol in the file).
In `@tests/test_submission_quality_gate.py`:
- Around line 352-410: Add a new regression test similar to
test_submission_quality_gate_live_context_accepts_member_comments that exercises
the "issue-author" maintainer-activity path: mock
submission_quality_gate.subprocess.run so "gh issue view" returns a top-level
"authorAssociation": "MEMBER" (or "COLLABORATOR") and an empty comments list,
ensure submission_quality_gate._load_live_context is invoked with the same
inputs and that the returned data sets last_maintainer_activity_at to the issue
createdAt and maintainer_activity_verified to True, then call
evaluate_submission and assert the maintainer_activity check passes (refer to
test_submission_quality_gate_live_context_accepts_member_comments,
submission_quality_gate._load_live_context, and evaluate_submission to mirror
structure).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4ee51524-71e1-406f-a840-d4be3bf64c37
📒 Files selected for processing (2)
scripts/submission_quality_gate.pytests/test_submission_quality_gate.py
|
Follow-up after review feedback, pushed in
Validation after the follow-up:
|
Refs #319
What changed
Why
Validation
uv run --extra dev python -m pytest tests/test_submission_quality_gate.py tests/test_docs_public_urls.py -quv run --extra dev ruff check scripts/submission_quality_gate.py tests/test_submission_quality_gate.pyuv run --extra dev ruff format --check scripts/submission_quality_gate.py tests/test_submission_quality_gate.pyuv run --extra dev python scripts/docs_smoke.pyuv run --extra dev python -m mypy scripts/submission_quality_gate.pypython scripts/submission_quality_gate.py --text-file <draft> --repo ramimbo/mergework --format text-> PASS, maintainer activity seen 0 days agoSafety
Summary by CodeRabbit
New Features
Documentation
Tests