feat(skills): add maintainer loop skills for automated PR triage and salvage#1585
Draft
feat(skills): add maintainer loop skills for automated PR triage and salvage#1585
Conversation
…salvage A suite of 8 agent skills and 4 TypeScript scripts that automate the NemoClaw maintainer workflow: triage open PRs, check merge gates, salvage near-ready contributions, detect hotspots, and close test gaps. Skills: - nemoclaw-maintainer-loop: orchestrator for /loop integration - nemoclaw-maintainer-triage: deterministic queue builder (calls gh-pr-merge-now) - nemoclaw-maintainer-merge-gate: 4-gate approval checker - nemoclaw-maintainer-salvage-pr: near-ready PR rescue with fork push support - nemoclaw-maintainer-security-sweep: security-focused review routing - nemoclaw-maintainer-test-gaps: targeted test coverage for risky code - nemoclaw-maintainer-hotspots: churn/conflict pressure detection - nemoclaw-maintainer-sequence-work: large issue decomposition Scripts (node --experimental-strip-types): - triage.ts: calls gh-pr-merge-now, enriches with risky-area detection, scores - check-gates.ts: CI, conflicts, CodeRabbit, risky-code-tested gates - hotspots.ts: 30-day git churn + open PR file overlap analysis - state.ts: local state file CRUD (init, exclude, history, set-queue) Signed-off-by: Carlos Villela <cvillela@nvidia.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Replace 9 separate maintainer skills with 3 phase-based skills matching the daily ship cycle: morning (triage + label), day (execute + loop), evening (handoff + tag). Inner workflows become reference docs under the day skill with progressive disclosure. Key changes: - Extract shared.ts to deduplicate RISKY_PATTERNS, run(), scoring weights - Fail-closed gate checker (was defaulting to pass on API error) - Named scoring constants with documented rationale - Add PR-REVIEW-PRIORITIES.md codifying the review priority order - Add version-label-based daily cadence (label items with target tag, bump stragglers at EOD, cut patch tag for overnight QA) - stderr logging in shell helpers instead of silent swallowing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…w issues New scripts for deterministic operations that were previously inline: - version-target.ts: compute next patch version + find stragglers - version-progress.ts: shipped vs open for a version label - bump-stragglers.ts: move open items from one version label to next - handoff-summary.ts: commits since last tag + risky areas + QA focus Review fixes: - Remove duplicated scoring table from morning (reference PR-REVIEW-PRIORITIES.md) - Security sweep uses triage-identified items instead of re-running find-review-pr - Evening uses state.ts script command for state updates - Morning uses version-target.ts for straggler discovery (no ambiguous placeholder) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both version-progress.ts and triage.ts now include ageDays as a computed field in their JSON output, so triage tables never depend on Claude doing date arithmetic from raw ISO timestamps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
At a daily ship cadence most PRs are <24h old, making ageDays show 0 for everything. ageHours gives useful resolution. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove external gh-pr-merge-now dependency from triage script. The script now fetches open PRs directly via gh CLI, classifies them as merge-ready / near-miss / blocked, and scores them using the same weighted model. Key changes: - Fetch basic PR data first (lightweight), then enrich top candidates with statusCheckRollup individually to avoid GraphQL timeouts - Add single retry with 3s delay for transient GitHub API failures - Add labels array to QueueItem output for version-label awareness - Classification logic: merge-now requires approved + green CI + clean merge state; near-miss allows up to 2 fixable blockers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GitHub's GraphQL API returns 502 when requesting too many PRs with rich fields (statusCheckRollup, mergeStateStatus, reviewDecision). Limit to 50 most recent PRs which is sufficient for daily triage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three bugs in the triage classifier: - BLOCKED merge state was treated as a conflict (it means "missing required reviews", not a conflict — DIRTY is the actual conflict) - StatusContext checks (CodeRabbit) use state/context fields, not conclusion/status — handle both shapes from gh CLI - No bucket existed between "approved + merge-ready" and "needs salvage", so most OSS PRs fell to blocked Add review-ready bucket (green CI, not draft, no conflicts) scored at +35, between merge-now (+40) and near-miss (+30). Also simplify by fetching statusCheckRollup in the initial query (works at limit 50) instead of per-PR enrichment. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace single gh pr list (capped at 50 by GraphQL) with gh api --paginate using the REST endpoint. Fetches all open PRs as lightweight NDJSON, then enriches only the top candidates with CI/review data via per-PR GraphQL calls. Previous: 50 PRs visible, missed older security PRs Now: all 243 open PRs visible, oldest items no longer invisible to triage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The salvage workflow was biased toward "ask the contributor and wait" which blocks the daily ship cadence. Now defaults to maintainer does the work (rebase, fix conflicts, add tests, push). Only defer to contributor when intent is ambiguous from the diff. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GitHub invalidates approvals when new commits are pushed. Approving a PR with conflicts is wasted effort since the rebase push resets it. Merge gate now explicitly: do not approve DIRTY PRs. Correct sequence is salvage (rebase) → CI green → approve → report ready for merge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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
/loop 10m /nemoclaw-maintainer-loopcontinuous operationgh-pr-merge-nowas data engine)Test plan
/nemoclaw-maintainer-loopand verify triage outputnode --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-loop/scripts/triage.ts --approved-onlynode --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-loop/scripts/check-gates.ts <pr-number>prekvalidation (tested in pre-commit)🤖 Generated with Claude Code