Skip to content

fix(skills): align maintainer workflows with canonical policy#5953

Merged
cv merged 10 commits into
mainfrom
codex/align-maintainer-skills-policy
Jun 29, 2026
Merged

fix(skills): align maintainer workflows with canonical policy#5953
cv merged 10 commits into
mainfrom
codex/align-maintainer-skills-policy

Conversation

@cv

@cv cv commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Aligns NemoClaw maintainer skills with the canonical workflow policy so triage, review prioritization, post-release retargeting, stale verification, and PR approval use one consistent model. Removes duplicated or conflicting instructions and adds executable policy regressions.

Changes

  • Route triage and stale verification through native Issue Type, Project 199 fields, and canonical labels.
  • Automatically bump open version-labeled stragglers to the next patch after the tag and workflow-managed latest are verified.
  • Keep cross-issue sweeping separate from comparator scoring and use Project Priority for review ordering.
  • Require a PR-body DCO declaration and GitHub-verified commits in merge-gate and comparator checks.
  • Add behavioral and static regression tests for the aligned maintainer policies, including post-tag straggler bumping.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: internal maintainer skills only; user-facing product behavior and documentation are unchanged.
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: self-reviewed against the canonical maintainer policy references; static policy ratchets and executable gate tests cover the changed decisions.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Git hooks passed during commit and push, or npx prek run --from-ref main --to-ref HEAD passes
  • Targeted tests pass for changed behavior
  • Full npm test passes (broad runtime changes only)
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • New Features
    • Added contributor compliance as a mandatory Tier-0 gate (DCO in PR body plus all commits marked “Verified”).
    • Expanded Tier-0 gate model to include additional required checks (and updated degraded-mode eligibility/salvage behavior).
    • Incorporated Project Priority (Urgent/High) into maintainer triage and security PR selection/scoring.
  • Bug Fixes
    • Made required CI-check handling fail closed with clearer “missing” reporting.
  • Documentation
    • Updated maintainer playbooks to emphasize explicit carry-forward recording and clarified label/version semantics.
  • Tests
    • Added/expanded automated coverage for gate behavior and priority mapping; removed obsolete straggler-bumping tests.
  • Chores
    • Removed the straggler-bumping script in favor of carry-forward workflows.

@cv cv added chore Build, CI, dependency, or tooling maintenance area: skills Skills, agent behaviors, prompts, or skill packaging area: project-management Taxonomy, triage, workflow, roadmap, or project process labels Jun 29, 2026
@cv cv self-assigned this Jun 29, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR updates maintainer skill docs and scripts to add contributor compliance checks, replace label-bumping with carry-forward release semantics, switch priority handling to GitHub Project fields, and rewrite triage and verify-stale workflows around canonical policy loading and approved write sets.

Changes

Contributor compliance gates

Layer / File(s) Summary
Policy and gate documentation
.agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md, .agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md, .agents/skills/nemoclaw-maintainer-pr-comparator/SKILL.md, .agents/skills/nemoclaw-maintainer-pr-comparator/checks/tier-0-gates.md, .agents/skills/nemoclaw-maintainer-pr-comparator/repo-policy.md, .agents/skills/nemoclaw-maintainer-pr-comparator/tiebreakers.md, .agents/skills/nemoclaw-maintainer-pr-comparator/templates/verdict.md
Adds contributor compliance as a hard gate, updates gate counts and failure categories, and rewrites DCO/Verified-commit wording across the merge-gate and PR-comparator docs.
Gate collection and evaluation logic
.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts, .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh
Adds contributor compliance checks to both gate scripts, including PR body parsing, commit verification checks, fail-closed behavior, and JSON output updates.
Contributor compliance test coverage
test/skills/check-gates-compliance.test.ts
Adds mocked CLI tests for passing and failing DCO/Verified-commit cases and comparator CI failure handling.
Policy conformance tests
test/maintainer-skills-policy.test.ts
Adds filesystem-backed assertions covering the updated maintainer guidance across the workflow docs and scripts.

Carry-forward release semantics and Project Priority

Layer / File(s) Summary
Release and cadence wording
.agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md, .agents/skills/nemoclaw-maintainer-morning/SKILL.md, .agents/skills/nemoclaw-maintainer-evening/SKILL.md, .agents/skills/nemoclaw-maintainer-cross-issue-sweep/SKILL.md, .agents/skills/nemoclaw-maintainer-pr-comparator/SKILL.md, .agents/skills/nemoclaw-skills-guide/SKILL.md, .agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md
Replaces bump/housekeep instructions with carry-forward release semantics and updates version-label handling across the daily maintainer docs and skill catalog.
Project Priority scoring and discovery
.agents/skills/nemoclaw-maintainer-day/scripts/shared.ts, .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts, .agents/skills/nemoclaw-maintainer-find-review-pr/SKILL.md, .agents/skills/nemoclaw-maintainer-morning/SKILL.md
Moves PR prioritization from labels to Project Priority fields, updates scoring and queue output, and revises related skill documentation.

Canonical triage workflow rewrite

Layer / File(s) Summary
Triage workflow and reference removal
.agents/skills/nemoclaw-maintainer-triage/SKILL.md, .agents/skills/nemoclaw-maintainer-triage/references/triage-instructions.md
Rewrites triage to load canonical policy files, use native Issue Type and Project fields, enforce accepted write sets, and removes the standalone instructions reference.

Verify-stale approval flow

Layer / File(s) Summary
Verify-stale skill workflow
.agents/skills/nemoclaw-maintainer-verify-stale/SKILL.md
Updates the skill workflow to require approved Project/comment write sets and to avoid label-based verdict handling.
Environment and reproducer checks
.agents/skills/nemoclaw-maintainer-verify-stale/reference/environment-and-reproducer.md, .agents/skills/nemoclaw-maintainer-verify-stale/reference/brev-provisioning.md, .agents/skills/nemoclaw-maintainer-verify-stale/reference/reproduction-rubrics.md
Normalizes casing, changes GitHub project-scope handling, removes a label-existence precheck, and rewrites the local-first predicate and infra-failure preconditions.
Scoring, comments, and logging
.agents/skills/nemoclaw-maintainer-verify-stale/reference/candidate-selection.md, .agents/skills/nemoclaw-maintainer-verify-stale/reference/scoring-comments-and-logging.md, .agents/skills/nemoclaw-maintainer-verify-stale/reference/by-design.md
Reworks candidate selection, scoring, marker formats, dry-run/write-set handling, infra-failure mutation rules, and activity logging for the verify-stale flow.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#3327: Overlaps on nemoclaw-maintainer-verify-stale and release-tag skill documentation changes.
  • NVIDIA/NemoClaw#3327: Shares the same maintainer-policy workflow surface and related skill references.

Suggested labels

enhancement: skill

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: aligning maintainer workflow skills with the canonical policy.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/align-maintainer-skills-policy

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

@github-code-quality

github-code-quality Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the branch is 96%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File 94233c9 +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/li...bprocess-env.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.ts 97%
nemoclaw/src/bl...print/runner.ts 95%
nemoclaw/src/co...ration-state.ts 94%
nemoclaw/src/bl...ate-networks.ts 94%
nemoclaw/src/index.ts 94%

TypeScript / code-coverage/cli

The overall coverage in the branch is 68%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File 94233c9 +/-
src/lib/actions...all/run-plan.ts 80%
src/lib/state/o...oard-session.ts 79%
src/lib/actions...dbox/rebuild.ts 74%
src/lib/state/sandbox.ts 72%
src/lib/shields/index.ts 70%
src/lib/onboard/preflight.ts 69%
src/lib/actions...licy-channel.ts 59%
src/lib/onboard...er-gpu-patch.ts 59%
src/lib/policy/index.ts 52%
src/lib/onboard.ts 20%

Updated June 29, 2026 15:59 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: None
Optional E2E: None

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • None. No NemoClaw E2E jobs are recommended. The changes are limited to maintainer agent skills, GitHub/release workflow helper scripts, policy/runbook Markdown, and focused tests. They do not affect installer/onboarding, sandbox lifecycle, credentials, security boundaries, network policy, inference routing, deployment artifacts, or real assistant user flows covered by the existing E2E suite.

Optional E2E

  • None.

New E2E recommendations

  • None.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Recommendation

Required Vitest E2E scenarios: None
Optional Vitest E2E scenarios: None

Workflow run

Full Vitest E2E advisor summary

Vitest E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required Vitest E2E scenarios

  • None. Changes are limited to maintainer agent skills/scripts and non-scenario unit tests outside test/e2e-scenario; they do not affect the Vitest E2E scenario registry, workflow, live support, fixtures, or scenario behavior.

Optional Vitest E2E scenarios

  • None.

Relevant changed files

  • None.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: Add or justify PRA-T1 and any related test follow-ups.
Open items: 0 required · 0 warnings · 0 suggestions · 1 test follow-up
Since last review: 2 prior items resolved · 0 still apply · 0 new items found

Action checklist

  • PRA-T1 Add or justify test follow-up: Acceptance clause
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Acceptance clause — No linked issue acceptance clauses were available in the deterministic GitHub context. — add test evidence or identify existing coverage. The validation context reported linkedIssues: [], so there were no linked issue body or comment clauses to map.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Blocked

Merge posture: Do not merge until addressed
Primary next action: Fix PRA-8: DCO regex ^ anchor rejects valid indented Signed-off-by declarations; then add or justify PRA-T1.
Open items: 4 required · 16 warnings · 6 suggestions · 8 test follow-ups
Since last review: 3 prior items resolved · 14 still apply · 6 new items found

Action checklist

  • PRA-8 Fix: DCO regex ^ anchor rejects valid indented Signed-off-by declarations in .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:362
  • PRA-9 Fix: Shell DCO regex has same ^ anchor flaw as check-gates.ts in .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh:100
  • PRA-10 Fix: DCO regex allows malformed email addresses missing domain dot in .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:362
  • PRA-11 Fix: Zero security test coverage for DCO edge cases in new contributor compliance gate in test/skills/check-gates-compliance.test.ts:1
  • PRA-1 Resolve or justify: Source-of-truth review needed: shared.ts run() error swallowing
  • PRA-2 Resolve or justify: Source-of-truth review needed: triage.ts enrichPr() silent catch
  • PRA-3 Resolve or justify: Source-of-truth review needed: triage.ts hardcoded Project 199
  • PRA-4 Resolve or justify: Source-of-truth review needed: shared.ts RISKY_PATTERNS over-broad
  • PRA-5 Resolve or justify: Source-of-truth review needed: bump-stragglers.ts duplicate gh logic
  • PRA-6 Resolve or justify: Source-of-truth review needed: collect-gates.sh error conflation
  • PRA-7 Resolve or justify: Source-of-truth review needed: check-gates.ts no error_type in contributorCompliance
  • PRA-12 Resolve or justify: run() swallows all errors and returns empty string in .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:55
  • PRA-13 Resolve or justify: enrichPr() silent catch leaves PR unenriched without trace in .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:150
  • PRA-14 Resolve or justify: Hardcoded Project 199 in fetchProjectPriorities in .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:200
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Runtime validation
  • PRA-T5 Add or justify test follow-up: Runtime validation
  • PRA-T6 Add or justify test follow-up: Zero security test coverage for DCO edge cases in new contributor compliance gate
  • PRA-T7 Add or justify test follow-up: Acceptance clause
  • PRA-T8 Add or justify test follow-up: shared.ts run() error swallowing
  • PRA-21 In-scope improvement: Add 'enriched' boolean to QueueItem so consumers know CI data quality in .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:200
  • PRA-22 In-scope improvement: Adopt Result type across maintainer scripts for error handling in .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:55
  • PRA-23 In-scope improvement: Verify-stale still references label-based workflow in some places in .agents/skills/nemoclaw-maintainer-verify-stale/reference/scoring-comments-and-logging.md:1
  • PRA-24 In-scope improvement: pra-gate.ts validateAdvisorRun trusts run.name without verifying workflow identity in .agents/skills/nemoclaw-maintainer-day/scripts/pra-gate.ts:1
  • PRA-25 In-scope improvement: Verdict template shows 'PR #B is closer' in degraded mode but comparator logic ranks PR #A first in .agents/skills/nemoclaw-maintainer-pr-comparator/templates/verdict.md:1
  • PRA-26 In-scope improvement: Triage skill references deleted triage-instructions.md in some paths in .agents/skills/nemoclaw-maintainer-triage/SKILL.md:1

Findings index

ID Severity Category Location Required action
PRA-1 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-2 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-3 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-4 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-5 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-6 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-7 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-8 Required security .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:362 Remove ^ anchor or use (?:^|\s) to allow optional leading whitespace. Change to /(?:^|\s)Signed-off-by:\s+.+\s+<[^<>\s]+@[^<>\s]+>\s*$/imu or trimStart each line before matching.
PRA-9 Required security .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh:100 Align both regexes to accept optional leading whitespace. In shell: grep -Eq '(^|[[[:space:]]])Signed-off-by:[[:space:]]+...' or preprocess with sed 's/^[[[:space:]]]*//'.
PRA-10 Required security .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:362 Tighten email pattern to require at least one dot in domain: <[^<>\s]+@[^<>\s]+\.[^<>\s]+> or use a proper email regex.
PRA-11 Required tests test/skills/check-gates-compliance.test.ts:1 Add four test cases covering: (1) indented DCO under markdown heading, (2) email missing domain dot, (3) multiple commits with mixed verified/unverified status, (4) DCO with extra whitespace variations. Use the existing runGate/runComparatorGate fixtures.
PRA-12 Resolve/justify architecture .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:55 Return a Result type {ok: true, stdout: string} | {ok: false, error: Error} or throw on non-zero exit and let callers catch. At minimum, log error at error level not stderr write.
PRA-13 Resolve/justify architecture .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:150 Log enrichment failure at error level with PR number and error message. Consider returning Result type from enrichPr. Add 'enriched: boolean' field to QueueItem output.
PRA-14 Resolve/justify architecture .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:200 Read project_id and org from repo-policy.md (or new triage config) and interpolate into GraphQL query. Add project_id field to repo-policy.yaml and parse it in triage.ts.
PRA-15 Resolve/justify architecture .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:17 Narrow patterns to security-relevant paths: /policies?\//, /credentials?\//, or anchor to specific directories like /\.github\/workflows\/.*policy/, /nemoclaw.*credential/.
PRA-16 Resolve/justify architecture .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh:115 Add error_type field to output distinguishing 'api_error' from 'no_commits' from 'unverified_commits'. Log error to stderr for debugging. Update tiebreakers.md accordingly.
PRA-17 Resolve/justify architecture .agents/skills/nemoclaw-maintainer-day/scripts/bump-stragglers.ts:1 Refactor to use shared.ts run() and ghJson() for consistency. Note: this requires fixing run() error handling first (F5).
PRA-18 Resolve/justify architecture test/skills/check-gates-compliance.test.ts:25 Replace with TypeScript-based mock using Map of command->response, or use vitest's vi.mock with a fake gh module. Keep shell only for true integration tests.
PRA-19 Resolve/justify correctness .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:1 Split into modules: fetch-prs.ts, enrich-pr.ts, classify-pr.ts, score-pr.ts, project-priority.ts, hotspots.ts, main.ts. Each with focused unit tests.
PRA-20 Resolve/justify correctness .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:372 Add error_type field to GateResult for contributorCompliance (like collect-gates.sh now has commit_fetch_failed/commit_parse_failed). Consider structured error codes.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-8 Required — DCO regex ^ anchor rejects valid indented Signed-off-by declarations

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:362
  • Category: security
  • Problem: The DCO_DECLARATION regex uses ^ with multiline flag (imu), requiring 'Signed-off-by' at column 0. Contributors commonly indent under markdown headings (e.g., '## Summary\n\n Signed-off-by: User <user@example.com>'), causing false rejection at the new contributor compliance gate. This is a regression of PRA-7 from the previous review.
  • Impact: Valid contributor PRs with properly formatted but indented DCO declarations are blocked at the contributor compliance gate, forcing maintainers to either reject compliant contributors or manually override the gate.
  • Required action: Remove ^ anchor or use (?:^|\s) to allow optional leading whitespace. Change to /(?:^|\s)Signed-off-by:\s+.+\s+<[^<>\s]+@[^<>\s]+>\s*$/imu or trimStart each line before matching.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run: node -e "const re = /^Signed-off-by:\\s+.+\\s+<[^<>\\s]+@[^<>\\s]+>\\s*$/imu; console.log(re.test('Signed-off-by: A <a@b.com>'), re.test(' Signed-off-by: A <a@b.com>'))" -- both should be true
  • Missing regression test: Add test case in check-gates-compliance.test.ts: body with indented DCO '## Summary\n\n Signed-off-by: Example User <user@example.com>' should pass contributorCompliance gate
  • Done when: The required change is committed and verification passes: Run: node -e "const re = /^Signed-off-by:\\s+.+\\s+<[^<>\\s]+@[^<>\\s]+>\\s*$/imu; console.log(re.test('Signed-off-by: A <a@b.com>'), re.test(' Signed-off-by: A <a@b.com>'))" -- both should be true.
  • Evidence: Line 362: const DCO_DECLARATION = /^Signed-off-by:\s+.+\s+<[^<>\s]+@[^<>\s]+>\s*$/imu; test fixture at test/skills/check-gates-compliance.test.ts only tests non-indented declarations.

PRA-9 Required — Shell DCO regex has same ^ anchor flaw as check-gates.ts

  • Location: .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh:100
  • Category: security
  • Problem: Shell script uses grep -Eq '^Signed-off-by:[[:space:]]+...' with ^ anchor, creating drift between TypeScript (merge gate) and shell (PR comparator) implementation. This is a regression of PRA-8.
  • Impact: A PR could pass the merge gate but fail the comparator (or vice versa) depending on DCO indentation, causing inconsistent gate decisions.
  • Required action: Align both regexes to accept optional leading whitespace. In shell: grep -Eq '(^|[[[:space:]]])Signed-off-by:[[:space:]]+...' or preprocess with sed 's/^[[[:space:]]]*//'.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run: echo ' Signed-off-by: A <a@b.com>' | grep -Eq '^Signed-off-by:[[:space:]]+.+[[:space:]]+<[^<>[:space:]]+@[^<>[:space:]]+>[[:space:]]*$' && echo PASS || echo FAIL -- should PASS but currently FAILs
  • Missing regression test: Add test case in check-gates-compliance.test.ts comparator section: indented DCO should pass contributor_compliance gate
  • Done when: The required change is committed and verification passes: Run: echo ' Signed-off-by: A <a@b.com>' | grep -Eq '^Signed-off-by:[[:space:]]+.+[[:space:]]+<[^<>[:space:]]+@[^<>[:space:]]+>[[:space:]]*$' && echo PASS || echo FAIL -- should PASS but currently FAILs.
  • Evidence: collect-gates.sh line 100: if printf '%s' "$raw" | jq -r '.body // ""' | grep -Eq '^Signed-off-by:[[:space:]]+.+[[:space:]]+<[^<>[:space:]]+@[^<>[:space:]]+>[[:space:]]*$'; then

PRA-10 Required — DCO regex allows malformed email addresses missing domain dot

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:362
  • Category: security
  • Problem: The email pattern <[^<>\s]+@[^<>\s]+> accepts 'user@example' (no TLD) as valid. DCO requires a valid email address format. This is a regression of PRA-9.
  • Impact: Contributors could satisfy the DCO gate with syntactically invalid email addresses, undermining the identity verification purpose of DCO.
  • Required action: Tighten email pattern to require at least one dot in domain: <[^<>\s]+@[^<>\s]+\.[^<>\s]+> or use a proper email regex.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run: node -e "const re = /^Signed-off-by:\\s+.+\\s+<[^<>\\s]+@[^<>\\s]+>\\s*$/imu; console.log(re.test('Signed-off-by: A <a@b>'))" -- should be false but currently true
  • Missing regression test: Add test case: 'Signed-off-by: Example User <user@example>' should fail contributorCompliance gate
  • Done when: The required change is committed and verification passes: Run: node -e "const re = /^Signed-off-by:\\s+.+\\s+<[^<>\\s]+@[^<>\\s]+>\\s*$/imu; console.log(re.test('Signed-off-by: A <a@b>'))" -- should be false but currently true.
  • Evidence: Line 362: const DCO_DECLARATION = /^Signed-off-by:\s+.+\s+<[^<>\s]+@[^<>\s]+>\s*$/imu; email pattern lacks dot requirement

PRA-11 Required — Zero security test coverage for DCO edge cases in new contributor compliance gate

  • Location: test/skills/check-gates-compliance.test.ts:1
  • Category: tests
  • Problem: The new test file has 11 tests but none cover the three critical DCO edge cases: indented declarations, missing domain dot in email, or mixed verification status across multiple commits. This is PRA-10 from the previous review, now confirmed in the new test file.
  • Impact: The DCO regex flaws (F1-F3) have no automated regression protection. Future refactors could silently reintroduce or worsen these issues.
  • Required action: Add four test cases covering: (1) indented DCO under markdown heading, (2) email missing domain dot, (3) multiple commits with mixed verified/unverified status, (4) DCO with extra whitespace variations. Use the existing runGate/runComparatorGate fixtures.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: grep -n 'indented\|missing.*domain\|mixed.*commit' test/skills/check-gates-compliance.test.ts -- returns no matches
  • Missing regression test: Four specific test cases as described above
  • Done when: The required change is committed and verification passes: grep -n 'indented\|missing.*domain\|mixed.*commit' test/skills/check-gates-compliance.test.ts -- returns no matches.
  • Evidence: check-gates-compliance.test.ts has 16 tests but zero for indented DCO, missing domain dot, or mixed commit verification
Review findings by urgency: 4 required fixes, 16 items to resolve/justify, 6 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-1 Resolve/justify — Source-of-truth review needed: shared.ts run() error swallowing

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that run() failure returns structured error not empty string
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: shared.ts run() catches all exceptions and returns ''

PRA-2 Resolve/justify — Source-of-truth review needed: triage.ts enrichPr() silent catch

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that failure logs error and QueueItem gets enriched: false
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: triage.ts line 150: catch { /* leave as-is */ }

PRA-3 Resolve/justify — Source-of-truth review needed: triage.ts hardcoded Project 199

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that fetchProjectPriorities reads config from repo-policy.md
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: triage.ts fetchProjectPriorities() has hardcoded 'organization(login: "NVIDIA") projectV2(number: 199)'

PRA-4 Resolve/justify — Source-of-truth review needed: shared.ts RISKY_PATTERNS over-broad

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that isRiskyFile('docs/policy-guide.md') returns false while isRiskyFile('nemoclaw/src/policy/engine.ts') returns true
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: shared.ts RISKY_PATTERNS includes /policy/i, /credential/i, /ssrf/i, /inference/i without path anchoring

PRA-5 Resolve/justify — Source-of-truth review needed: bump-stragglers.ts duplicate gh logic

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that bump-stragglers.ts uses shared.ts helpers with timeout
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: bump-stragglers.ts defines own gh/ghJsonArray/execFileSync wrappers

PRA-6 Resolve/justify — Source-of-truth review needed: collect-gates.sh error conflation

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that API error produces error_type='api_error' distinct from 'missing_dco'
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: collect-gates.sh commits_fetch_failed and commit_parse_failed both lead to same gate_contributor_compliance=false

PRA-7 Resolve/justify — Source-of-truth review needed: check-gates.ts no error_type in contributorCompliance

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that API error produces error_type='api_error' in contributorCompliance gate output
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: check-gates.ts checkContributorCompliance() returns generic error messages without error_type

PRA-12 Resolve/justify — run() swallows all errors and returns empty string

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:55
  • Category: architecture
  • Problem: The shared.run() helper catches all exceptions, logs to stderr, and returns empty string. Callers cannot distinguish between command failure, timeout, auth error, or empty output. This is PRA-1/PRA-11 from previous review, still unfixed.
  • Impact: Silent failures cascade: ghJson returns null on empty string, which callers treat as 'not found' vs 'API error'. This caused the fail-closed behavior in check-gates.ts but without diagnostic detail.
  • Recommended action: Return a Result type {ok: true, stdout: string} | {ok: false, error: Error} or throw on non-zero exit and let callers catch. At minimum, log error at error level not stderr write.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read shared.ts:55-70 -- run() returns '' on any exception; ghJson returns null on empty string; check-gates.ts treats null as fail-closed without error context
  • Missing regression test: Test that run() failure propagates error type to caller (e.g., ghJson returns structured error not null)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read shared.ts:55-70 -- run() returns '' on any exception; ghJson returns null on empty string; check-gates.ts treats null as fail-closed without error context.
  • Evidence: shared.ts run() function catches all errors and returns ''

PRA-13 Resolve/justify — enrichPr() silent catch leaves PR unenriched without trace

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:150
  • Category: architecture
  • Problem: The enrichPr function has a bare catch block that swallows all errors (line 150: 'catch { /* leave as-is */ }'). Failed enrichment leaves PR with empty reviewDecision/statusCheckRollup, classifying it as 'blocked' with no diagnostic. This is PRA-2/PRA-14 from previous review.
  • Impact: PRs that fail enrichment (network blip, API limit, GraphQL error) appear as 'blocked' in triage output with no indication of why. Maintainers cannot distinguish 'actually blocked' from 'enrichment failed'.
  • Recommended action: Log enrichment failure at error level with PR number and error message. Consider returning Result type from enrichPr. Add 'enriched: boolean' field to QueueItem output.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read triage.ts:140-155 -- try/catch with empty catch block; no error logging; PR retains defaults
  • Missing regression test: Test that enrichPr failure logs error and QueueItem gets enriched: false
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read triage.ts:140-155 -- try/catch with empty catch block; no error logging; PR retains defaults.
  • Evidence: triage.ts line 150: catch { /* leave as-is */ }

PRA-14 Resolve/justify — Hardcoded Project 199 in fetchProjectPriorities

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:200
  • Category: architecture
  • Problem: The GraphQL query hardcodes organization 'NVIDIA' and project number 199. This prevents reuse in other repos and makes the script brittle to project restructuring. This is PRA-3/PRA-12 from previous review.
  • Impact: Skill cannot be used in forks or other NVIDIA projects without code changes. Project number changes would silently break priority scoring.
  • Recommended action: Read project_id and org from repo-policy.md (or new triage config) and interpolate into GraphQL query. Add project_id field to repo-policy.yaml and parse it in triage.ts.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: grep -n 'organization.*NVIDIA.*projectV2.*199' .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts -- hardcoded in query string
  • Missing regression test: Test that fetchProjectPriorities reads config from repo-policy.md
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: grep -n 'organization.*NVIDIA.*projectV2.*199' .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts -- hardcoded in query string.
  • Evidence: triage.ts fetchProjectPriorities() has hardcoded 'organization(login: "NVIDIA") projectV2(number: 199)'

PRA-15 Resolve/justify — RISKY_PATTERNS over-broad -- matches 'policy'/'credential' anywhere in path

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:17
  • Category: architecture
  • Problem: Patterns /policy/i, /credential/i, /ssrf/i, /inference/i match any path containing these substrings (e.g., 'docs/policy-guide.md', 'scripts/credential-helper.sh'). This is PRA-4/PRA-16 from previous review.
  • Impact: False positives mark non-risky files as risky, triggering unnecessary test requirements and security sweeps. Dilutes the signal of genuinely risky changes.
  • Recommended action: Narrow patterns to security-relevant paths: /policies?\//, /credentials?\//, or anchor to specific directories like /\.github\/workflows\/.*policy/, /nemoclaw.*credential/.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read shared.ts:17-25 -- /policy/i matches 'my-policy-doc.md' anywhere in repo
  • Missing regression test: Test that isRiskyFile('docs/policy-guide.md') returns false while isRiskyFile('nemoclaw/src/policy/engine.ts') returns true
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read shared.ts:17-25 -- /policy/i matches 'my-policy-doc.md' anywhere in repo.
  • Evidence: shared.ts RISKY_PATTERNS includes /policy/i, /credential/i, /ssrf/i, /inference/i without path anchoring

PRA-16 Resolve/justify — collect-gates.sh doesn't distinguish API error from compliance failure

  • Location: .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh:115
  • Category: architecture
  • Problem: When gh api fails to fetch commits or returns malformed JSON, the script sets gate_contributor_compliance=false with the same 'ineligible:contributor_compliance' failure as a real DCO/verification failure. This is PRA-13 from previous review.
  • Impact: Maintainers cannot tell if a PR failed contributor compliance because of missing DCO/unverified commits vs. a transient GitHub API error. Leads to false rejections or wasted debugging.
  • Recommended action: Add error_type field to output distinguishing 'api_error' from 'no_commits' from 'unverified_commits'. Log error to stderr for debugging. Update tiebreakers.md accordingly.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read collect-gates.sh:75-105 -- commits_fetch_failed and commit_parse_failed both lead to same gate_contributor_compliance=false and same failure classification
  • Missing regression test: Test that API error produces error_type='api_error' while missing DCO produces error_type='missing_dco'
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read collect-gates.sh:75-105 -- commits_fetch_failed and commit_parse_failed both lead to same gate_contributor_compliance=false and same failure classification.
  • Evidence: collect-gates.sh lines 75-105: commits_fetch_failed and commit_parse_failed both set gate_contributor_compliance=false with same failure string

PRA-17 Resolve/justify — bump-stragglers.ts uses execFileSync directly instead of shared.ts helpers

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/bump-stragglers.ts:1
  • Category: architecture
  • Problem: The script reimplements gh JSON parsing and error handling instead of using shared.run()/ghJson(). It has no timeout, no maxBuffer limit, and duplicates logic. This is PRA-5/PRA-20/PRA-22 from previous review.
  • Impact: Inconsistent error handling, no timeout protection, maintenance burden. If shared.ts improves (e.g., Result type), bump-stragglers.ts won't benefit.
  • Recommended action: Refactor to use shared.ts run() and ghJson() for consistency. Note: this requires fixing run() error handling first (F5).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read bump-stragglers.ts -- imports only parseStringArg from shared.ts; defines own gh/ghJsonArray/execFileSync wrappers
  • Missing regression test: Test that bump-stragglers.ts respects timeout and maxBuffer from shared.ts
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read bump-stragglers.ts -- imports only parseStringArg from shared.ts; defines own gh/ghJsonArray/execFileSync wrappers.
  • Evidence: bump-stragglers.ts imports only parseStringArg from shared.ts; defines own gh/ghJsonArray functions using execFileSync directly

PRA-18 Resolve/justify — New test infrastructure replicates shell-based gh mock pattern

  • Location: test/skills/check-gates-compliance.test.ts:25
  • Category: architecture
  • Problem: All four new test files (bump-stragglers.test.ts, check-gates-compliance.test.ts, triage-runtime.test.ts, maintainer-skills-policy.test.ts) use shell-based gh mocks via temp bin directories. This replicates the pattern flagged in PRA-6/PRA-19 as a maintenance burden.
  • Impact: Shell mocks are fragile (string matching on args), hard to debug, and don't integrate with TypeScript type checking. Changes to gh CLI output format break tests silently.
  • Recommended action: Replace with TypeScript-based mock using Map of command->response, or use vitest's vi.mock with a fake gh module. Keep shell only for true integration tests.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: grep -r 'mkdtempSync.*bin.*gh' test/ -- all four test files create temp bin/gh mock scripts
  • Missing regression test: Migrate one test file to TypeScript mock as proof of concept
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: grep -r 'mkdtempSync.*bin.*gh' test/ -- all four test files create temp bin/gh mock scripts.
  • Evidence: All four new test files use mkdtempSync + bin/gh shell script mock pattern

PRA-19 Resolve/justify — triage.ts monolith growth -- consider splitting into modules

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:1
  • Category: correctness
  • Problem: triage.ts is now 610 lines handling fetching, enrichment, classification, scoring, Project priority, file analysis, hotspot detection, and output. This is PRA-23 from previous review, exacerbated by new Project priority logic.
  • Impact: Hard to test individual behaviors, hard to review changes, high cognitive load. Bug fixes risk regressions in unrelated logic.
  • Recommended action: Split into modules: fetch-prs.ts, enrich-pr.ts, classify-pr.ts, score-pr.ts, project-priority.ts, hotspots.ts, main.ts. Each with focused unit tests.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: wc -l .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts -- 610 lines, 12 imports, 8 top-level functions
  • Missing regression test: After split, each module should have independent unit tests
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: wc -l .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts -- 610 lines, 12 imports, 8 top-level functions.
  • Evidence: triage.ts is 610 lines with 8 top-level functions handling multiple responsibilities

PRA-20 Resolve/justify — Contributor compliance error message doesn't distinguish API failure from empty commits

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:372
  • Category: correctness
  • Problem: When gh api fails or returns no commits, the gate fails with 'Could not verify PR commit signatures (API error -- fail-closed)' but the output details don't include error_type. This is PRA-18 from previous review.
  • Impact: Maintainers see generic 'fail-closed' message and cannot tell if it's a real compliance issue or transient API problem.
  • Recommended action: Add error_type field to GateResult for contributorCompliance (like collect-gates.sh now has commit_fetch_failed/commit_parse_failed). Consider structured error codes.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read check-gates.ts:340-380 -- error paths return generic messages without error_type field
  • Missing regression test: Test that API error produces error_type='api_error' in contributorCompliance gate output
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read check-gates.ts:340-380 -- error paths return generic messages without error_type field.
  • Evidence: check-gates.ts checkContributorCompliance() returns generic error messages without error_type

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

PRA-21 Improvement — Add 'enriched' boolean to QueueItem so consumers know CI data quality

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:200
  • Category: correctness
  • Problem: Un-enriched PRs classify as 'blocked' due to empty checks, but consumers cannot distinguish 'actually failing CI' from 'never checked'. This was PRA-15 from previous review.
  • Impact: Triage output consumers (maintainers, dashboards) may deprioritize PRs that are actually fine but un-enriched due to API limits.
  • Suggested action: Add 'enriched: boolean' field to QueueItem output. Set true when enrichPr succeeded, false otherwise.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Read triage.ts QueueItem interface -- no enriched field; classifyPr uses empty checks as 'failing'
  • Missing regression test: Test that QueueItem.enriched === true for enriched PRs, false for un-enriched
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: QueueItem interface lacks enriched field; classifyPr treats empty checks as failing

PRA-22 Improvement — Adopt Result type across maintainer scripts for error handling

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:55
  • Category: correctness
  • Problem: The run()/ghJson() pattern of returning empty string/null on error forces callers to use fail-closed logic without context. A Result type would enable proper error propagation. This is PRA-17 from previous review.
  • Impact: All maintainer scripts (check-gates, triage, bump-stragglers, hotspots) share the same error-swallowing pattern. Fixing it once would benefit all.
  • Suggested action: Define Result<T> = {ok: true, value: T} | {ok: false, error: Error} in shared.ts. Migrate run() and ghJson() to return Result. Update all callers.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: grep -r 'run(' .agents/skills/nemoclaw-maintainer-day/scripts/ -- 20+ call sites across 5 files
  • Missing regression test: Test that run() failure returns Result with error, not empty string
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: shared.ts run() and ghJson() return ''/null on error; 20+ call sites across check-gates.ts, triage.ts, hotspots.ts, etc.

PRA-23 Improvement — Verify-stale still references label-based workflow in some places

  • Location: .agents/skills/nemoclaw-maintainer-verify-stale/reference/scoring-comments-and-logging.md:1
  • Category: correctness
  • Problem: The skill.md says 'uses native Bug type, Project Status Won't Fix' but some reference files may still mention label operations. Need to verify all references are updated.
  • Impact: Inconsistent documentation could mislead maintainers using the skill.
  • Suggested action: Audit all verify-stale reference files for legacy label operations (gh issue edit --add-label, --label bug, etc.) and update to Project field operations.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: grep -r 'gh issue edit.*--add-label\|--label bug' .agents/skills/nemoclaw-maintainer-verify-stale/reference/
  • Missing regression test: Policy test that verifies no label-based operations in verify-stale references
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: verify-stale SKILL.md claims native Bug type but reference files may have legacy label ops

PRA-24 Improvement — pra-gate.ts validateAdvisorRun trusts run.name without verifying workflow identity

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/pra-gate.ts:1
  • Category: correctness
  • Problem: validateAdvisorRun checks run.name === 'PR Review / Advisor' but doesn't verify the workflow file path or ID. A different workflow with the same name could pass validation.
  • Impact: Low probability but possible spoof if another workflow is named identically. Defense in depth suggests verifying workflow path or ID.
  • Suggested action: Also check run.workflow_id or run.path against known PR Review Advisor workflow. Requires fetching workflow metadata.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Read pra-gate.ts:110-130 -- only checks name, event, head_sha, run_attempt, timestamp
  • Missing regression test: Test that validateAdvisorRun rejects workflow with same name but different path
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: pra-gate.ts validateAdvisorRun() only validates run.name, not workflow_id or path

PRA-25 Improvement — Verdict template shows 'PR #B is closer' in degraded mode but comparator logic ranks PR #A first

  • Location: .agents/skills/nemoclaw-maintainer-pr-comparator/templates/verdict.md:1
  • Category: correctness
  • Problem: The template example shows 'Verdict: Neither mergeable yet -- PR #B is closer' but the tiebreaker logic says 'Earlier PR (final deterministic fallback) -- first-mover gets the tie'. These conflict.
  • Impact: Documentation drift could confuse maintainers reading the template vs. actual skill behavior.
  • Suggested action: Align template example with actual tiebreaker logic (PR #A should be closer if it has lower number), or update tiebreaker logic to match intended behavior.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Read tiebreakers.md tiebreaker 5: 'Earlier PR (final deterministic fallback). Use only when nothing above distinguishes -- first-mover gets the tie.' vs verdict.md example showing PR #B
  • Missing regression test: N/A -- documentation consistency
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: verdict.md example shows PR #B as closer; tiebreakers.md tiebreaker 5 says first-mover (lower PR number) wins

PRA-26 Improvement — Triage skill references deleted triage-instructions.md in some paths

  • Location: .agents/skills/nemoclaw-maintainer-triage/SKILL.md:1
  • Category: correctness
  • Problem: The skill.md correctly points to ../nemoclaw-maintainer-policies/references/triage-instructions.md but the old file was deleted. Need to ensure all references are updated.
  • Impact: Minor -- the new canonical location exists and is referenced correctly in the skill.
  • Suggested action: Verify no stale references to .agents/skills/nemoclaw-maintainer-triage/references/triage-instructions.md remain in any file.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: grep -r 'triage-instructions.md' .agents/skills/ --include='*.md' | grep -v 'nemoclaw-maintainer-policies'
  • Missing regression test: Policy test that all triage references point to canonical policy package
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Old file .agents/skills/nemoclaw-maintainer-triage/references/triage-instructions.md was deleted; new canonical location is ../nemoclaw-maintainer-policies/references/triage-instructions.md
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — check-gates-compliance: indented DCO under markdown heading passes contributorCompliance gate. Changed code includes GitHub API integration points (check-gates.ts, triage.ts, collect-gates.sh, bump-stragglers.ts, pra-gate.ts) that need behavioral runtime validation. Unit tests with shell mocks don't validate real API behavior, error handling, or DCO regex edge cases.
  • PRA-T2 Runtime validation — check-gates-compliance: DCO with email missing domain dot fails contributorCompliance gate. Changed code includes GitHub API integration points (check-gates.ts, triage.ts, collect-gates.sh, bump-stragglers.ts, pra-gate.ts) that need behavioral runtime validation. Unit tests with shell mocks don't validate real API behavior, error handling, or DCO regex edge cases.
  • PRA-T3 Runtime validation — check-gates-compliance: multiple commits with mixed verified/unverified fails gate with correct unverifiedCommits list. Changed code includes GitHub API integration points (check-gates.ts, triage.ts, collect-gates.sh, bump-stragglers.ts, pra-gate.ts) that need behavioral runtime validation. Unit tests with shell mocks don't validate real API behavior, error handling, or DCO regex edge cases.
  • PRA-T4 Runtime validation — check-gates-compliance: comparator gate: indented DCO passes contributor_compliance. Changed code includes GitHub API integration points (check-gates.ts, triage.ts, collect-gates.sh, bump-stragglers.ts, pra-gate.ts) that need behavioral runtime validation. Unit tests with shell mocks don't validate real API behavior, error handling, or DCO regex edge cases.
  • PRA-T5 Runtime validation — triage-runtime: enrichPr failure logs error and QueueItem gets enriched: false. Changed code includes GitHub API integration points (check-gates.ts, triage.ts, collect-gates.sh, bump-stragglers.ts, pra-gate.ts) that need behavioral runtime validation. Unit tests with shell mocks don't validate real API behavior, error handling, or DCO regex edge cases.
  • PRA-T6 Zero security test coverage for DCO edge cases in new contributor compliance gate — Add four test cases covering: (1) indented DCO under markdown heading, (2) email missing domain dot, (3) multiple commits with mixed verified/unverified status, (4) DCO with extra whitespace variations. Use the existing runGate/runComparatorGate fixtures.
  • PRA-T7 Acceptance clause — Add behavioral and static regression tests for aligned maintainer policies, including post-tag straggler bumping — add test evidence or identify existing coverage. 4 new test files with 37 tests cover happy paths; bump-stragglers.test.ts covers post-tag bump; but zero tests for DCO edge cases (indented, missing domain dot, mixed commits) -- critical gap for security gate
  • PRA-T8 shared.ts run() error swallowing — Test that run() failure returns structured error not empty string. shared.ts run() catches all exceptions and returns ''
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: shared.ts run() error swallowing

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that run() failure returns structured error not empty string
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: shared.ts run() catches all exceptions and returns ''

PRA-2 Resolve/justify — Source-of-truth review needed: triage.ts enrichPr() silent catch

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that failure logs error and QueueItem gets enriched: false
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: triage.ts line 150: catch { /* leave as-is */ }

PRA-3 Resolve/justify — Source-of-truth review needed: triage.ts hardcoded Project 199

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that fetchProjectPriorities reads config from repo-policy.md
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: triage.ts fetchProjectPriorities() has hardcoded 'organization(login: "NVIDIA") projectV2(number: 199)'

PRA-4 Resolve/justify — Source-of-truth review needed: shared.ts RISKY_PATTERNS over-broad

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that isRiskyFile('docs/policy-guide.md') returns false while isRiskyFile('nemoclaw/src/policy/engine.ts') returns true
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: shared.ts RISKY_PATTERNS includes /policy/i, /credential/i, /ssrf/i, /inference/i without path anchoring

PRA-5 Resolve/justify — Source-of-truth review needed: bump-stragglers.ts duplicate gh logic

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that bump-stragglers.ts uses shared.ts helpers with timeout
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: bump-stragglers.ts defines own gh/ghJsonArray/execFileSync wrappers

PRA-6 Resolve/justify — Source-of-truth review needed: collect-gates.sh error conflation

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that API error produces error_type='api_error' distinct from 'missing_dco'
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: collect-gates.sh commits_fetch_failed and commit_parse_failed both lead to same gate_contributor_compliance=false

PRA-7 Resolve/justify — Source-of-truth review needed: check-gates.ts no error_type in contributorCompliance

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test that API error produces error_type='api_error' in contributorCompliance gate output
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: check-gates.ts checkContributorCompliance() returns generic error messages without error_type

PRA-8 Required — DCO regex ^ anchor rejects valid indented Signed-off-by declarations

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:362
  • Category: security
  • Problem: The DCO_DECLARATION regex uses ^ with multiline flag (imu), requiring 'Signed-off-by' at column 0. Contributors commonly indent under markdown headings (e.g., '## Summary\n\n Signed-off-by: User <user@example.com>'), causing false rejection at the new contributor compliance gate. This is a regression of PRA-7 from the previous review.
  • Impact: Valid contributor PRs with properly formatted but indented DCO declarations are blocked at the contributor compliance gate, forcing maintainers to either reject compliant contributors or manually override the gate.
  • Required action: Remove ^ anchor or use (?:^|\s) to allow optional leading whitespace. Change to /(?:^|\s)Signed-off-by:\s+.+\s+<[^<>\s]+@[^<>\s]+>\s*$/imu or trimStart each line before matching.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run: node -e "const re = /^Signed-off-by:\\s+.+\\s+<[^<>\\s]+@[^<>\\s]+>\\s*$/imu; console.log(re.test('Signed-off-by: A <a@b.com>'), re.test(' Signed-off-by: A <a@b.com>'))" -- both should be true
  • Missing regression test: Add test case in check-gates-compliance.test.ts: body with indented DCO '## Summary\n\n Signed-off-by: Example User <user@example.com>' should pass contributorCompliance gate
  • Done when: The required change is committed and verification passes: Run: node -e "const re = /^Signed-off-by:\\s+.+\\s+<[^<>\\s]+@[^<>\\s]+>\\s*$/imu; console.log(re.test('Signed-off-by: A <a@b.com>'), re.test(' Signed-off-by: A <a@b.com>'))" -- both should be true.
  • Evidence: Line 362: const DCO_DECLARATION = /^Signed-off-by:\s+.+\s+<[^<>\s]+@[^<>\s]+>\s*$/imu; test fixture at test/skills/check-gates-compliance.test.ts only tests non-indented declarations.

PRA-9 Required — Shell DCO regex has same ^ anchor flaw as check-gates.ts

  • Location: .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh:100
  • Category: security
  • Problem: Shell script uses grep -Eq '^Signed-off-by:[[:space:]]+...' with ^ anchor, creating drift between TypeScript (merge gate) and shell (PR comparator) implementation. This is a regression of PRA-8.
  • Impact: A PR could pass the merge gate but fail the comparator (or vice versa) depending on DCO indentation, causing inconsistent gate decisions.
  • Required action: Align both regexes to accept optional leading whitespace. In shell: grep -Eq '(^|[[[:space:]]])Signed-off-by:[[:space:]]+...' or preprocess with sed 's/^[[[:space:]]]*//'.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run: echo ' Signed-off-by: A <a@b.com>' | grep -Eq '^Signed-off-by:[[:space:]]+.+[[:space:]]+<[^<>[:space:]]+@[^<>[:space:]]+>[[:space:]]*$' && echo PASS || echo FAIL -- should PASS but currently FAILs
  • Missing regression test: Add test case in check-gates-compliance.test.ts comparator section: indented DCO should pass contributor_compliance gate
  • Done when: The required change is committed and verification passes: Run: echo ' Signed-off-by: A <a@b.com>' | grep -Eq '^Signed-off-by:[[:space:]]+.+[[:space:]]+<[^<>[:space:]]+@[^<>[:space:]]+>[[:space:]]*$' && echo PASS || echo FAIL -- should PASS but currently FAILs.
  • Evidence: collect-gates.sh line 100: if printf '%s' "$raw" | jq -r '.body // ""' | grep -Eq '^Signed-off-by:[[:space:]]+.+[[:space:]]+<[^<>[:space:]]+@[^<>[:space:]]+>[[:space:]]*$'; then

PRA-10 Required — DCO regex allows malformed email addresses missing domain dot

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:362
  • Category: security
  • Problem: The email pattern <[^<>\s]+@[^<>\s]+> accepts 'user@example' (no TLD) as valid. DCO requires a valid email address format. This is a regression of PRA-9.
  • Impact: Contributors could satisfy the DCO gate with syntactically invalid email addresses, undermining the identity verification purpose of DCO.
  • Required action: Tighten email pattern to require at least one dot in domain: <[^<>\s]+@[^<>\s]+\.[^<>\s]+> or use a proper email regex.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run: node -e "const re = /^Signed-off-by:\\s+.+\\s+<[^<>\\s]+@[^<>\\s]+>\\s*$/imu; console.log(re.test('Signed-off-by: A <a@b>'))" -- should be false but currently true
  • Missing regression test: Add test case: 'Signed-off-by: Example User <user@example>' should fail contributorCompliance gate
  • Done when: The required change is committed and verification passes: Run: node -e "const re = /^Signed-off-by:\\s+.+\\s+<[^<>\\s]+@[^<>\\s]+>\\s*$/imu; console.log(re.test('Signed-off-by: A <a@b>'))" -- should be false but currently true.
  • Evidence: Line 362: const DCO_DECLARATION = /^Signed-off-by:\s+.+\s+<[^<>\s]+@[^<>\s]+>\s*$/imu; email pattern lacks dot requirement

PRA-11 Required — Zero security test coverage for DCO edge cases in new contributor compliance gate

  • Location: test/skills/check-gates-compliance.test.ts:1
  • Category: tests
  • Problem: The new test file has 11 tests but none cover the three critical DCO edge cases: indented declarations, missing domain dot in email, or mixed verification status across multiple commits. This is PRA-10 from the previous review, now confirmed in the new test file.
  • Impact: The DCO regex flaws (F1-F3) have no automated regression protection. Future refactors could silently reintroduce or worsen these issues.
  • Required action: Add four test cases covering: (1) indented DCO under markdown heading, (2) email missing domain dot, (3) multiple commits with mixed verified/unverified status, (4) DCO with extra whitespace variations. Use the existing runGate/runComparatorGate fixtures.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: grep -n 'indented\|missing.*domain\|mixed.*commit' test/skills/check-gates-compliance.test.ts -- returns no matches
  • Missing regression test: Four specific test cases as described above
  • Done when: The required change is committed and verification passes: grep -n 'indented\|missing.*domain\|mixed.*commit' test/skills/check-gates-compliance.test.ts -- returns no matches.
  • Evidence: check-gates-compliance.test.ts has 16 tests but zero for indented DCO, missing domain dot, or mixed commit verification

PRA-12 Resolve/justify — run() swallows all errors and returns empty string

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:55
  • Category: architecture
  • Problem: The shared.run() helper catches all exceptions, logs to stderr, and returns empty string. Callers cannot distinguish between command failure, timeout, auth error, or empty output. This is PRA-1/PRA-11 from previous review, still unfixed.
  • Impact: Silent failures cascade: ghJson returns null on empty string, which callers treat as 'not found' vs 'API error'. This caused the fail-closed behavior in check-gates.ts but without diagnostic detail.
  • Recommended action: Return a Result type {ok: true, stdout: string} | {ok: false, error: Error} or throw on non-zero exit and let callers catch. At minimum, log error at error level not stderr write.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read shared.ts:55-70 -- run() returns '' on any exception; ghJson returns null on empty string; check-gates.ts treats null as fail-closed without error context
  • Missing regression test: Test that run() failure propagates error type to caller (e.g., ghJson returns structured error not null)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read shared.ts:55-70 -- run() returns '' on any exception; ghJson returns null on empty string; check-gates.ts treats null as fail-closed without error context.
  • Evidence: shared.ts run() function catches all errors and returns ''

PRA-13 Resolve/justify — enrichPr() silent catch leaves PR unenriched without trace

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:150
  • Category: architecture
  • Problem: The enrichPr function has a bare catch block that swallows all errors (line 150: 'catch { /* leave as-is */ }'). Failed enrichment leaves PR with empty reviewDecision/statusCheckRollup, classifying it as 'blocked' with no diagnostic. This is PRA-2/PRA-14 from previous review.
  • Impact: PRs that fail enrichment (network blip, API limit, GraphQL error) appear as 'blocked' in triage output with no indication of why. Maintainers cannot distinguish 'actually blocked' from 'enrichment failed'.
  • Recommended action: Log enrichment failure at error level with PR number and error message. Consider returning Result type from enrichPr. Add 'enriched: boolean' field to QueueItem output.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read triage.ts:140-155 -- try/catch with empty catch block; no error logging; PR retains defaults
  • Missing regression test: Test that enrichPr failure logs error and QueueItem gets enriched: false
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read triage.ts:140-155 -- try/catch with empty catch block; no error logging; PR retains defaults.
  • Evidence: triage.ts line 150: catch { /* leave as-is */ }

PRA-14 Resolve/justify — Hardcoded Project 199 in fetchProjectPriorities

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:200
  • Category: architecture
  • Problem: The GraphQL query hardcodes organization 'NVIDIA' and project number 199. This prevents reuse in other repos and makes the script brittle to project restructuring. This is PRA-3/PRA-12 from previous review.
  • Impact: Skill cannot be used in forks or other NVIDIA projects without code changes. Project number changes would silently break priority scoring.
  • Recommended action: Read project_id and org from repo-policy.md (or new triage config) and interpolate into GraphQL query. Add project_id field to repo-policy.yaml and parse it in triage.ts.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: grep -n 'organization.*NVIDIA.*projectV2.*199' .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts -- hardcoded in query string
  • Missing regression test: Test that fetchProjectPriorities reads config from repo-policy.md
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: grep -n 'organization.*NVIDIA.*projectV2.*199' .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts -- hardcoded in query string.
  • Evidence: triage.ts fetchProjectPriorities() has hardcoded 'organization(login: "NVIDIA") projectV2(number: 199)'

PRA-15 Resolve/justify — RISKY_PATTERNS over-broad -- matches 'policy'/'credential' anywhere in path

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts:17
  • Category: architecture
  • Problem: Patterns /policy/i, /credential/i, /ssrf/i, /inference/i match any path containing these substrings (e.g., 'docs/policy-guide.md', 'scripts/credential-helper.sh'). This is PRA-4/PRA-16 from previous review.
  • Impact: False positives mark non-risky files as risky, triggering unnecessary test requirements and security sweeps. Dilutes the signal of genuinely risky changes.
  • Recommended action: Narrow patterns to security-relevant paths: /policies?\//, /credentials?\//, or anchor to specific directories like /\.github\/workflows\/.*policy/, /nemoclaw.*credential/.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read shared.ts:17-25 -- /policy/i matches 'my-policy-doc.md' anywhere in repo
  • Missing regression test: Test that isRiskyFile('docs/policy-guide.md') returns false while isRiskyFile('nemoclaw/src/policy/engine.ts') returns true
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read shared.ts:17-25 -- /policy/i matches 'my-policy-doc.md' anywhere in repo.
  • Evidence: shared.ts RISKY_PATTERNS includes /policy/i, /credential/i, /ssrf/i, /inference/i without path anchoring

PRA-16 Resolve/justify — collect-gates.sh doesn't distinguish API error from compliance failure

  • Location: .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh:115
  • Category: architecture
  • Problem: When gh api fails to fetch commits or returns malformed JSON, the script sets gate_contributor_compliance=false with the same 'ineligible:contributor_compliance' failure as a real DCO/verification failure. This is PRA-13 from previous review.
  • Impact: Maintainers cannot tell if a PR failed contributor compliance because of missing DCO/unverified commits vs. a transient GitHub API error. Leads to false rejections or wasted debugging.
  • Recommended action: Add error_type field to output distinguishing 'api_error' from 'no_commits' from 'unverified_commits'. Log error to stderr for debugging. Update tiebreakers.md accordingly.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read collect-gates.sh:75-105 -- commits_fetch_failed and commit_parse_failed both lead to same gate_contributor_compliance=false and same failure classification
  • Missing regression test: Test that API error produces error_type='api_error' while missing DCO produces error_type='missing_dco'
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read collect-gates.sh:75-105 -- commits_fetch_failed and commit_parse_failed both lead to same gate_contributor_compliance=false and same failure classification.
  • Evidence: collect-gates.sh lines 75-105: commits_fetch_failed and commit_parse_failed both set gate_contributor_compliance=false with same failure string

PRA-17 Resolve/justify — bump-stragglers.ts uses execFileSync directly instead of shared.ts helpers

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/bump-stragglers.ts:1
  • Category: architecture
  • Problem: The script reimplements gh JSON parsing and error handling instead of using shared.run()/ghJson(). It has no timeout, no maxBuffer limit, and duplicates logic. This is PRA-5/PRA-20/PRA-22 from previous review.
  • Impact: Inconsistent error handling, no timeout protection, maintenance burden. If shared.ts improves (e.g., Result type), bump-stragglers.ts won't benefit.
  • Recommended action: Refactor to use shared.ts run() and ghJson() for consistency. Note: this requires fixing run() error handling first (F5).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read bump-stragglers.ts -- imports only parseStringArg from shared.ts; defines own gh/ghJsonArray/execFileSync wrappers
  • Missing regression test: Test that bump-stragglers.ts respects timeout and maxBuffer from shared.ts
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read bump-stragglers.ts -- imports only parseStringArg from shared.ts; defines own gh/ghJsonArray/execFileSync wrappers.
  • Evidence: bump-stragglers.ts imports only parseStringArg from shared.ts; defines own gh/ghJsonArray functions using execFileSync directly

PRA-18 Resolve/justify — New test infrastructure replicates shell-based gh mock pattern

  • Location: test/skills/check-gates-compliance.test.ts:25
  • Category: architecture
  • Problem: All four new test files (bump-stragglers.test.ts, check-gates-compliance.test.ts, triage-runtime.test.ts, maintainer-skills-policy.test.ts) use shell-based gh mocks via temp bin directories. This replicates the pattern flagged in PRA-6/PRA-19 as a maintenance burden.
  • Impact: Shell mocks are fragile (string matching on args), hard to debug, and don't integrate with TypeScript type checking. Changes to gh CLI output format break tests silently.
  • Recommended action: Replace with TypeScript-based mock using Map of command->response, or use vitest's vi.mock with a fake gh module. Keep shell only for true integration tests.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: grep -r 'mkdtempSync.*bin.*gh' test/ -- all four test files create temp bin/gh mock scripts
  • Missing regression test: Migrate one test file to TypeScript mock as proof of concept
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: grep -r 'mkdtempSync.*bin.*gh' test/ -- all four test files create temp bin/gh mock scripts.
  • Evidence: All four new test files use mkdtempSync + bin/gh shell script mock pattern

PRA-19 Resolve/justify — triage.ts monolith growth -- consider splitting into modules

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:1
  • Category: correctness
  • Problem: triage.ts is now 610 lines handling fetching, enrichment, classification, scoring, Project priority, file analysis, hotspot detection, and output. This is PRA-23 from previous review, exacerbated by new Project priority logic.
  • Impact: Hard to test individual behaviors, hard to review changes, high cognitive load. Bug fixes risk regressions in unrelated logic.
  • Recommended action: Split into modules: fetch-prs.ts, enrich-pr.ts, classify-pr.ts, score-pr.ts, project-priority.ts, hotspots.ts, main.ts. Each with focused unit tests.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: wc -l .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts -- 610 lines, 12 imports, 8 top-level functions
  • Missing regression test: After split, each module should have independent unit tests
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: wc -l .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts -- 610 lines, 12 imports, 8 top-level functions.
  • Evidence: triage.ts is 610 lines with 8 top-level functions handling multiple responsibilities

PRA-20 Resolve/justify — Contributor compliance error message doesn't distinguish API failure from empty commits

  • Location: .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:372
  • Category: correctness
  • Problem: When gh api fails or returns no commits, the gate fails with 'Could not verify PR commit signatures (API error -- fail-closed)' but the output details don't include error_type. This is PRA-18 from previous review.
  • Impact: Maintainers see generic 'fail-closed' message and cannot tell if it's a real compliance issue or transient API problem.
  • Recommended action: Add error_type field to GateResult for contributorCompliance (like collect-gates.sh now has commit_fetch_failed/commit_parse_failed). Consider structured error codes.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read check-gates.ts:340-380 -- error paths return generic messages without error_type field
  • Missing regression test: Test that API error produces error_type='api_error' in contributorCompliance gate output
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read check-gates.ts:340-380 -- error paths return generic messages without error_type field.
  • Evidence: check-gates.ts checkContributorCompliance() returns generic error messages without error_type

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 20

🧹 Nitpick comments (1)
test/maintainer-skills-policy.test.ts (1)

56-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Expand this carry-forward assertion to the other migrated docs.

This test only guards evening and cut-release-tag, but the same policy move also touched nemoclaw-maintainer-morning and .agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md. A regression in either of those files would still pass this suite. As per path instructions, **/*.test.{ts,js,mts,mjs,cts,cjs}: “Review tests for behavioral confidence rather than implementation lock-in.”

🤖 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 `@test/maintainer-skills-policy.test.ts` around lines 56 - 69, The
carry-forward policy coverage in the test is too narrow because it only asserts
the migrated behavior for `evening` and `cut-release-tag`. Expand the `preserves
open release labels as carry-forward work` test to also check
`nemoclaw-maintainer-morning` and
`.agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md` for the same
policy text and absence of `bump-stragglers`, using the existing `read` helper
and `fs.existsSync` assertions so regressions in those migrated docs are caught.

Source: Path instructions

🤖 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 @.agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md:
- Around line 124-127: Step 5 currently asks for a “shipped/closed items”
summary even though the workflow only gathers open issues/PRs, so update the
skill spec to make the output match the collected data. In SKILL.md, revise the
Step 5 summary under the release workflow so it either adds an explicit
closed-item retrieval step before summarizing, or removes the shipped/closed
bullet and keeps only carry-forward open issues/PRs. Keep the wording aligned
with the existing release summary section and the hand-authored nemoClaw
maintainer skill conventions.

In @.agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md:
- Around line 9-14: The Markdown source is missing the required repository SPDX
header, so add the standard SPDX license block at the top of this file before
any content. Update this docs file in the same style used by other compliant .md
sources, and verify the header appears as the first content in the file.

In @.agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md:
- Around line 7-13: The Markdown source file is missing the required SPDX header
at the top, so update the document to start with the repo’s mandatory SPDX
license block using Markdown-friendly comment syntax. Place it before the
existing policy text in PR-REVIEW-PRIORITIES.md and keep the rest of the content
unchanged.

In @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:
- Around line 362-372: The contributor-compliance DCO check in
checkContributorCompliance uses a case-insensitive DCO_DECLARATION matcher,
which conflicts with the case-sensitive comparator logic in collect-gates.sh.
Update the DCO_DECLARATION regex in check-gates.ts to match the same casing
rules as the shell comparator so both gate paths use one consistent
signed-off-by requirement. Keep the fix localized to DCO_DECLARATION and the
checkContributorCompliance flow.

In @.agents/skills/nemoclaw-maintainer-day/scripts/triage.ts:
- Around line 493-496: The enrichment flow in triage.ts applies projectPriority
only after the classified PR list has already been capped, so urgent items
outside the initial prefix can be missed. Update the triage pipeline around
fetchProjectPriorities, classified, and the enrichment-cap logic so
projectPriority is loaded and used before selecting which PRs receive CI/review
enrichment. Make sure the ordering or filtering step considers projectPriority
early enough that Urgent/High PRs are not excluded from the queue just because
they appear after the initial slice.
- Around line 317-359: The priority lookup in fetchProjectPriorities is reading
a non-existent top-level priority from gh project item-list output, so the
scoring path never gets a project boost. Update fetchProjectPriorities to
retrieve the project priority from a source that actually exposes it, such as a
GraphQL query or another API response, and keep the Map<number, string>
population keyed by PR number in triage.ts so the downstream priority-based
scoring can work.

In @.agents/skills/nemoclaw-maintainer-find-review-pr/SKILL.md:
- Around line 106-110: Update the review recommendation ordering so Project
Priority is the primary criterion in the final one-line suggestion, not PR age.
In the relevant guidance section of SKILL.md, adjust the recommendation logic to
prefer Urgent over High before considering older waiting time, while still using
passing checks as the next tie-breaker. Keep the final recommendation line
aligned with the priority-first behavior described by the skill.

In @.agents/skills/nemoclaw-maintainer-pr-comparator/checks/tier-0-gates.md:
- Around line 3-12: The Markdown file is missing the required SPDX license
header at the top. Update the document header by adding the repository-standard
SPDX comment in Markdown/HTML comment form as the first content in this file,
keeping the rest of the gate checklist unchanged; use the existing file type
convention for markdown files and ensure the header is present before any
headings or text.
- Line 66: Update the tier-0 gates contract to include the new Ineligible bucket
alongside trivial and substantive, and make sure contributor-compliance failures
are classified as Ineligible rather than substantive. Adjust the wording in the
tier-0 gates spec to match the policy used in tiebreakers.md so maintainers do
not treat missing PR-body DCO or unverified commits as salvageable failures.

In @.agents/skills/nemoclaw-maintainer-pr-comparator/repo-policy.md:
- Around line 27-28: The repo-policy.md file is missing the required SPDX
license header at the top, so add the repository-standard Markdown/HTML SPDX
comment before any content. Make sure the header uses the correct comment syntax
for a Markdown file and appears as the first line, while leaving the existing
policy text intact.

In @.agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh:
- Around line 55-77: The DCO detection in collect-gates.sh is still
case-sensitive, which can disagree with the comparator’s case-insensitive check.
Update the Signed-off-by matching logic in the contributor-compliance section to
treat the declaration case-insensitively, consistent with the check in
check-gates.ts, so the same PR casing yields the same result in both places.

In @.agents/skills/nemoclaw-maintainer-pr-comparator/templates/verdict.md:
- Around line 78-86: The example in verdict.md is using an ineligible PR as the
closer, which conflicts with the current policy. Update the "closer" example to
use an eligible PR (referencing the PR `#A` / PR `#B` example block) or rewrite the
example so it shows a rejection-only verdict when all candidates are ineligible.
Make sure the sample language no longer suggests salvaging PR `#A` after marking
it Ineligible, and instead aligns with the verdict flow used by the surrounding
template.
- Around line 78-86: The Markdown template is missing the repository-required
SPDX license header at the top of the file. Add the standard SPDX comment using
Markdown/HTML comment syntax before any content so the file complies with the
shared license-header rule for markdown sources. Keep the existing verdict
content unchanged and ensure the header is the first thing in the file.

In @.agents/skills/nemoclaw-maintainer-pr-comparator/tiebreakers.md:
- Around line 34-35: Add the repository-required SPDX license header comment at
the very top of the tiebreakers.md file using the Markdown/HTML comment form.
Keep the existing content unchanged and ensure the file begins with the standard
SPDX header so it complies with the markdown source-file licensing rule.
- Around line 34-35: Update the tiebreaker logic to rank on the new Ineligible
class so degraded mode never lets an ineligible PR win. In the
comparator/ranking section of tiebreakers.md, add Ineligible ahead of
substantive/trivial failures and make sure PR-body DCO missing or
non-GitHub-Verified commits are treated as immediate rejection rather than a
salvageable tie-break condition. Refer to the new Ineligible classification
consistently wherever the ranking order is documented.

In @.agents/skills/nemoclaw-maintainer-triage/SKILL.md:
- Around line 16-23: The triage skill still references the removed
triage-instructions.md in the ordered reading list, leaving a dead dependency
and unclear schema source. Update the SKILL.md guidance to stop requiring that
file and instead point the payload contract to the remaining canonical policy
docs, using the existing workflow-policy.md, label-taxonomy.json, and
examples.md references to locate the correct source of truth.

In
@.agents/skills/nemoclaw-maintainer-verify-stale/reference/candidate-selection.md:
- Around line 26-50: The selection step is missing fields it relies on, so
update the single-issue fetch and the paginated GraphQL query in
candidate-selection.md to load native issueType plus the live Project 199
Priority and Status fields, and increase the comments retrieval so the durable
marker scan does not silently miss older activity. Use the existing
candidate-selection flow and its issueType.name == "Bug" filter, and make sure
the Project 199 checks read from live project data instead of labels or inferred
state.

In
@.agents/skills/nemoclaw-maintainer-verify-stale/reference/scoring-comments-and-logging.md:
- Around line 93-96: The still-reproduces guidance is inconsistent about
transcript content, so update the template in scoring-comments-and-logging.md to
follow one rule only. Align the instructions used by the generation path (likely
the still-reproduces comment builder around the referenced marker/template) so
the final comment stays within the 30–80 word limit and does not mention both
transcripts if the template says to omit them; keep the marker and TTL wording
intact.
- Around line 297-319: The accepted write set handling in the verification flow
should fail fast on self-assignment errors as well, not just Project
lookup/update failures. Update the canonical apply path so the self-assignment
step is treated as part of the same atomic unit before posting the comment, and
abort the remaining writes if assignment fails; keep the exact accepted comment
as the final write only after Project and assignment both succeed. Use the
existing verification/write orchestration around the dry run, pre-post
state-check, and activity log to preserve the “exact accepted write set”
behavior.

In `@test/skills/check-gates-compliance.test.ts`:
- Around line 183-213: Add a comparator contributor-compliance test that covers
the missing-DCO path in check-gates-compliance.test.ts. Extend the existing
maintainer PR comparator block to verify that runComparatorGate returns
contributor_compliance false when the PR body lacks the Signed-off-by
declaration, while the commit itself remains verified. Assert the output details
include dco_declaration_present: false, a non-empty failure reason for the DCO
branch, and that failures contains substantive:contributor_compliance.

---

Nitpick comments:
In `@test/maintainer-skills-policy.test.ts`:
- Around line 56-69: The carry-forward policy coverage in the test is too narrow
because it only asserts the migrated behavior for `evening` and
`cut-release-tag`. Expand the `preserves open release labels as carry-forward
work` test to also check `nemoclaw-maintainer-morning` and
`.agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md` for the same
policy text and absence of `bump-stragglers`, using the existing `read` helper
and `fs.existsSync` assertions so regressions in those migrated docs are caught.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 77949c8f-18ad-4110-a5a7-60c105e334de

📥 Commits

Reviewing files that changed from the base of the PR and between c6113be and f600283.

📒 Files selected for processing (30)
  • .agents/skills/nemoclaw-maintainer-cross-issue-sweep/SKILL.md
  • .agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md
  • .agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md
  • .agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md
  • .agents/skills/nemoclaw-maintainer-day/scripts/bump-stragglers.ts
  • .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
  • .agents/skills/nemoclaw-maintainer-day/scripts/shared.ts
  • .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts
  • .agents/skills/nemoclaw-maintainer-evening/SKILL.md
  • .agents/skills/nemoclaw-maintainer-find-review-pr/SKILL.md
  • .agents/skills/nemoclaw-maintainer-morning/SKILL.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/SKILL.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/checks/tier-0-gates.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/repo-policy.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh
  • .agents/skills/nemoclaw-maintainer-pr-comparator/templates/verdict.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/tiebreakers.md
  • .agents/skills/nemoclaw-maintainer-triage/SKILL.md
  • .agents/skills/nemoclaw-maintainer-triage/references/triage-instructions.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/SKILL.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/brev-provisioning.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/by-design.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/candidate-selection.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/environment-and-reproducer.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/reproduction-rubrics.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/scoring-comments-and-logging.md
  • .agents/skills/nemoclaw-skills-guide/SKILL.md
  • test/bump-stragglers.test.ts
  • test/maintainer-skills-policy.test.ts
  • test/skills/check-gates-compliance.test.ts
💤 Files with no reviewable changes (3)
  • test/bump-stragglers.test.ts
  • .agents/skills/nemoclaw-maintainer-day/scripts/bump-stragglers.ts
  • .agents/skills/nemoclaw-maintainer-triage/references/triage-instructions.md

Comment thread .agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md Outdated
Comment thread .agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md
Comment thread .agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md
Comment thread .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts Outdated
Comment thread .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts
Comment thread .agents/skills/nemoclaw-maintainer-triage/SKILL.md
Comment thread .agents/skills/nemoclaw-maintainer-verify-stale/reference/candidate-selection.md Outdated
Comment thread test/skills/check-gates-compliance.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/skills/check-gates-compliance.test.ts (1)

136-136: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the repo’s POSIX PATH separator convention.

This test suite intentionally uses : for mocked-bin PATH setup on Linux runners; keep this consistent here.

Based on learnings, this repo’s tests should construct process.env.PATH with the POSIX separator : rather than path.delimiter.

Proposed fix
-        env: { ...process.env, PATH: `${bin}${path.delimiter}${process.env.PATH ?? ""}` },
+        env: { ...process.env, PATH: `${bin}:${process.env.PATH ?? ""}` },
🤖 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 `@test/skills/check-gates-compliance.test.ts` at line 136, The PATH setup in
the check-gates compliance test is using the platform-dependent path.delimiter,
but this repo’s test convention for mocked bins should stay POSIX-style. Update
the env construction in check-gates-compliance.test.ts to build process.env.PATH
with ":" instead of path.delimiter, keeping the mocked-bin setup consistent with
the existing Linux-oriented test behavior.

Source: Learnings

🤖 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.

Nitpick comments:
In `@test/skills/check-gates-compliance.test.ts`:
- Line 136: The PATH setup in the check-gates compliance test is using the
platform-dependent path.delimiter, but this repo’s test convention for mocked
bins should stay POSIX-style. Update the env construction in
check-gates-compliance.test.ts to build process.env.PATH with ":" instead of
path.delimiter, keeping the mocked-bin setup consistent with the existing
Linux-oriented test behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ea679916-20ab-4855-84e6-d44b2e3187e7

📥 Commits

Reviewing files that changed from the base of the PR and between f600283 and 14d379c.

📒 Files selected for processing (2)
  • .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh
  • test/skills/check-gates-compliance.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 @.agents/skills/nemoclaw-maintainer-pr-comparator/templates/verdict.md:
- Around line 79-90: The remediation for PR `#A` is too broad: it combines the
PR-body DCO gap with the GitHub Verified commit history gap into one
history-rewrite requirement. In the verdict template, update the guidance so the
DCO declaration is fixed by editing the PR body only, while the Verified-commits
requirement still points to replacing the branch with compliant history. Keep
the PR `#A` / PR `#B` decision flow and the suggested action wording aligned with
these distinct remedies.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7e037b67-d6df-4179-a05e-deed6db527f3

📥 Commits

Reviewing files that changed from the base of the PR and between 328c0a7 and 0c71d31.

📒 Files selected for processing (15)
  • .agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md
  • .agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md
  • .agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md
  • .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
  • .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts
  • .agents/skills/nemoclaw-maintainer-find-review-pr/SKILL.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/checks/tier-0-gates.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/repo-policy.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh
  • .agents/skills/nemoclaw-maintainer-pr-comparator/templates/verdict.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/tiebreakers.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/candidate-selection.md
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/scoring-comments-and-logging.md
  • test/maintainer-skills-policy.test.ts
  • test/skills/check-gates-compliance.test.ts
💤 Files with no reviewable changes (1)
  • .agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md
✅ Files skipped from review due to trivial changes (1)
  • .agents/skills/nemoclaw-maintainer-pr-comparator/repo-policy.md
🚧 Files skipped from review as they are similar to previous changes (10)
  • .agents/skills/nemoclaw-maintainer-pr-comparator/tiebreakers.md
  • .agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md
  • .agents/skills/nemoclaw-maintainer-pr-comparator/checks/tier-0-gates.md
  • .agents/skills/nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md
  • test/maintainer-skills-policy.test.ts
  • test/skills/check-gates-compliance.test.ts
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/candidate-selection.md
  • .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
  • .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh
  • .agents/skills/nemoclaw-maintainer-verify-stale/reference/scoring-comments-and-logging.md

@cv

cv commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

Automated-review follow-up for head 9a898c8cbc212ce26d0d5fb4eac01ccd24a921ae:

  • Addressed the GPT advisor findings: --approved-only now filters after per-PR enrichment; a fake-gh runtime suite covers approved-only behavior, live Project 199 Urgent/High mapping, unrelated/non-PR items, legacy priority-label non-scoring, and malformed Project output; comparator input is numeric-validated and every error/success object is serialized with jq -n.
  • The Project Priority source boundary is the live NVIDIA Project V2 Telegram bridge fails with "openshell: not found" because ~/.local/bin isn't on PATH for child processes #199 named by the canonical maintainer policy. The runtime parser resolves the live Priority field name and does not hardcode mutable field or option IDs. Malformed data is surfaced on stderr and covered by a regression test. This is the source implementation, not a localized workaround, so there is no workaround-removal condition.
  • The comparator's trusted-output boundary is now the script itself: non-numeric input produces a valid structured error before any GitHub call, and GitHub-derived strings/arrays/booleans are passed to jq with typed arguments. Regression tests cover malformed input and unusual string contents.
  • Nemotron PRA-1 through PRA-4 about indented/fenced/stricter-email DCO syntax are intentionally not applied. Both maintainer gates match the required CI source of truth in .github/workflows/dco-check.yaml, which requires an exact line-start Signed-off-by: declaration and uses the repository's existing address shape. Accepting syntax that CI rejects would make the gate disagree with the merge requirement; the parity regression test protects that contract.
  • Nemotron PRA-5 is also intentionally not applied: Project 199 is the canonical project explicitly identified by nemoclaw-maintainer-policies/references/label-taxonomy.json; introducing a second config surface would create another source of drift.
  • Nemotron PRA-14 and PRA-15 are false positives: the stale-verification reference says status: wont-fix is not a canonical label, and candidate-selection.md has no reference to the removed skill-local triage instructions.

Validation: 24 focused tests pass, CLI typecheck passes, Biome/shfmt/ShellCheck pass, normal commit hooks pass, and the pushed commit is GitHub Verified.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/skills/triage-runtime.test.ts (1)

154-159: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid pinning this test to exact score totals.

The 55/50/40 assertions lock the test to current scoring weights instead of the behavior under review. Assert priority mapping and relative ordering instead, so future score rebalancing does not break a still-correct test. As per path instructions, "Review tests for behavioral confidence rather than implementation lock-in" and "Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call assertions."

🤖 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 `@test/skills/triage-runtime.test.ts` around lines 154 - 159, The test in
triage-runtime.test.ts is over-specifying implementation details by asserting
exact score totals for queue items. Update the expectations around the
output.queue assertions to verify the priority mapping and relative ordering of
the items using the existing triage runtime behavior, while removing dependency
on the exact 55/50/40 values. Keep the assertions centered on observable
outcomes through the public boundary in the triage-runtime flow rather than
scoring weights.

Source: Path instructions

🤖 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 `@test/skills/triage-runtime.test.ts`:
- Around line 90-114: The inline fake gh dispatcher in the triage runtime test
is using forbidden if statements, so rewrite that helper script to dispatch
without any if-based branching. Update the fs.writeFileSync fixture content in
the test by replacing the current conditional chain with an allowed structure
such as switch-based dispatch or an extracted helper fixture, while preserving
the existing behaviors for api, pr view, pull request file listing, and the
fallback error path.

---

Nitpick comments:
In `@test/skills/triage-runtime.test.ts`:
- Around line 154-159: The test in triage-runtime.test.ts is over-specifying
implementation details by asserting exact score totals for queue items. Update
the expectations around the output.queue assertions to verify the priority
mapping and relative ordering of the items using the existing triage runtime
behavior, while removing dependency on the exact 55/50/40 values. Keep the
assertions centered on observable outcomes through the public boundary in the
triage-runtime flow rather than scoring weights.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f037de5a-9802-4c05-8461-d3d001cdfbd2

📥 Commits

Reviewing files that changed from the base of the PR and between 0c71d31 and 48edf83.

📒 Files selected for processing (4)
  • .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts
  • .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh
  • test/skills/check-gates-compliance.test.ts
  • test/skills/triage-runtime.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/skills/check-gates-compliance.test.ts
  • .agents/skills/nemoclaw-maintainer-pr-comparator/scripts/collect-gates.sh
  • .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts

Comment thread test/skills/triage-runtime.test.ts
@cv

cv commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

Disposition for the remaining non-blocking Nemotron warnings on head 9a898c8cb:

  • shared.ts run(), the broad risky-path patterns, and the un-enriched/default-blocked queue behavior predate this PR. run() already logs failures to stderr; triage explicitly documents that un-enriched items fail closed. Changing the shared return type, risky-path taxonomy, or queue output schema would be a separate cross-workflow design change.
  • Comparator commit-fetch failure and an empty commit response both intentionally fail the contributor gate closed. A more detailed diagnostic field would not change the eligibility decision and is not required for this policy-alignment fix.
  • The contributor-compliance message, test-file naming, and fake-gh organization suggestions are non-behavioral refactors. The behavioral boundaries added here have runtime coverage and pass the repository guardrails.
  • The stale-verification status: wont-fix text is explicitly a warning that it is not a canonical label; it does not prescribe applying that label.

These items are therefore documented as pre-existing, false-positive, or design-expanding follow-ups rather than current-PR correctness gaps. The five required DCO/Project findings are separately dispositioned in the earlier source-of-truth comment.

@cv

cv commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

Automated-review follow-up for head 9fb2f93560fdb8c9026089a51a5055c8191ab102:

  • The prior source-of-truth dispositions still apply to PRA-5 through PRA-15 and PRA-17/PRA-18. In particular, DCO parsing intentionally matches .github/workflows/dco-check.yaml; accepting indented syntax or imposing a new dotted-domain rule would disagree with the required CI gate. Project V2 Telegram bridge fails with "openshell: not found" because ~/.local/bin isn't on PATH for child processes #199 is the canonical project named by maintainer policy, while the live parser resolves mutable field/option IDs.
  • PRA-16 is not applicable to this update: bump-stragglers.ts now matches origin/main byte-for-byte. Its direct execFileSync use is intentional for deterministic post-release housekeeping because command and JSON failures must abort visibly. Replacing it with the current shared run() helper would weaken that contract: run() catches failures and returns an empty string.
  • The restored bump workflow is covered by seven focused tests, including the successful label creation/PR+issue retargeting path, invalid input, malformed GitHub output, and GitHub command failure. The policy regression suite also verifies the post-tag ordering and automatic next-patch bump.
  • The remaining shared.ts/triage/comparator warnings are pre-existing cross-workflow design topics already dispositioned above; they are not introduced by the restored release behavior.

Current validation: 14 focused release/policy tests pass, CLI typecheck passes, normal commit and push hooks pass, DCO and CodeRabbit checks pass, and the pushed commit is GitHub Verified.

@cv

cv commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

Final automated-review disposition for head 94233c95432cd8f6cff1edf3f1eea23ce576541f:

  • The GPT-5.5 advisor now recommends merge_as_is with 0 required findings, 0 warnings, and 0 suggestions. Its two commit-parsing findings are fixed: both gates fail closed on malformed output, and the TypeScript gate now validates external record types strictly. Regression tests cover malformed comparator NDJSON and type-skewed merge-gate verification data.
  • Nemotron PRA-8 through PRA-11 remain intentionally unapplied because both local gates match the required .github/workflows/dco-check.yaml contract: an exact line-start Signed-off-by: declaration and the existing repository address shape. Accepting indented declarations or imposing a new dotted-domain rule would make local gates disagree with required CI. Parity and failure-path tests protect this behavior.
  • PRA-1 through PRA-7 and PRA-12 through PRA-22 are previously dispositioned source-boundary or cross-workflow refactors. The restored bump-stragglers.ts matches origin/main byte-for-byte and intentionally aborts on command/JSON failures; replacing it with the current error-swallowing shared helper would weaken release housekeeping.
  • PRA-23 and PRA-26 are false positives verified by repository search and policy tests: the verify-stale references contain no label mutation commands, and all triage-instructions references resolve to the canonical policy package.
  • PRA-25 misreads a degraded-mode template placeholder as a numeric tie; actual results substitute the selected closer PR after applying the documented tiebreakers.
  • PRA-24 is optional defense-in-depth, not a current bypass. The gate already requires a github-actions[bot] comment, matching comment ID, embedded run ID, exact head SHA, pull-request event, run attempt, and timestamp bounded by the fetched run.

Local validation: 31 focused tests pass, CLI typecheck passes, all commit/push hooks pass, and every pushed commit is GitHub Verified.

@cv cv merged commit 6859d0a into main Jun 29, 2026
42 checks passed
@cv cv deleted the codex/align-maintainer-skills-policy branch June 29, 2026 16:02
@github-actions github-actions Bot added the v0.0.70 Release target label Jul 5, 2026
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
…#5953)

<!-- markdownlint-disable MD041 -->
## Summary
Aligns NemoClaw maintainer skills with the canonical workflow policy so
triage, review prioritization, post-release retargeting, stale
verification, and PR approval use one consistent model. Removes
duplicated or conflicting instructions and adds executable policy
regressions.

## Changes

- Route triage and stale verification through native Issue Type, Project
199 fields, and canonical labels.
- Automatically bump open version-labeled stragglers to the next patch
after the tag and workflow-managed latest are verified.
- Keep cross-issue sweeping separate from comparator scoring and use
Project Priority for review ordering.
- Require a PR-body DCO declaration and GitHub-verified commits in
merge-gate and comparator checks.
- Add behavioral and static regression tests for the aligned maintainer
policies, including post-tag straggler bumping.

## Type of Change

- [x] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Quality Gates
<!-- Check all that apply. For any "covered by existing tests", "not
applicable", or waiver entry, add a brief justification on the same line
or in the Changes section. -->
- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: internal maintainer skills
only; user-facing product behavior and documentation are unchanged.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: self-reviewed against
the canonical maintainer policy references; static policy ratchets and
executable gate tests cover the changed decisions.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification
<!-- Check each item you ran and confirmed. Leave unchecked items you
skipped. Doc-only changes do not require npm test unless you ran it. -->
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Git hooks passed during commit and push, or `npx prek run
--from-ref main --to-ref HEAD` passes
- [x] Targeted tests pass for changed behavior
- [ ] Full `npm test` passes (broad runtime changes only)
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
<!-- DCO sign-off is required in this PR description, and every commit
must appear as Verified in GitHub. Run: git config user.name && git
config user.email -->
Signed-off-by: Carlos Villela <cvillela@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added contributor compliance as a mandatory Tier-0 gate (DCO in PR
body plus all commits marked “Verified”).
* Expanded Tier-0 gate model to include additional required checks (and
updated degraded-mode eligibility/salvage behavior).
* Incorporated Project Priority (Urgent/High) into maintainer triage and
security PR selection/scoring.
* **Bug Fixes**
* Made required CI-check handling fail closed with clearer “missing”
reporting.
* **Documentation**
* Updated maintainer playbooks to emphasize explicit carry-forward
recording and clarified label/version semantics.
* **Tests**
* Added/expanded automated coverage for gate behavior and priority
mapping; removed obsolete straggler-bumping tests.
* **Chores**
* Removed the straggler-bumping script in favor of carry-forward
workflows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: project-management Taxonomy, triage, workflow, roadmap, or project process area: skills Skills, agent behaviors, prompts, or skill packaging chore Build, CI, dependency, or tooling maintenance v0.0.70 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants