Skip to content

feat(skills): add maintainer loop skills for automated PR triage and salvage#1585

Draft
cv wants to merge 12 commits intomainfrom
cv/maintainer-skills
Draft

feat(skills): add maintainer loop skills for automated PR triage and salvage#1585
cv wants to merge 12 commits intomainfrom
cv/maintainer-skills

Conversation

@cv
Copy link
Copy Markdown
Contributor

@cv cv commented Apr 7, 2026

Summary

Test plan

  • Invoke /nemoclaw-maintainer-loop and verify triage output
  • Run node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-loop/scripts/triage.ts --approved-only
  • Run node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-loop/scripts/check-gates.ts <pr-number>
  • Verify skills YAML passes prek validation (tested in pre-commit)

🤖 Generated with Claude Code

…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>
@cv cv marked this pull request as draft April 7, 2026 20:46
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 7, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7fab10b8-824f-470f-85e9-0790c401be5b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cv/maintainer-skills

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

cv and others added 11 commits April 8, 2026 00:50
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>
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.

1 participant