feat: add groomer next-task mode#406
Conversation
There was a problem hiding this comment.
AI Automated Review
Full PR review.
Analysis engine: MiniMax-M2.7@https://litellm.jory.dev/v1 (anthropic) — routed smart (risk match: public_route_changes)
PR Review: feat: add groomer next-task mode
Summary
This PR adds a mode=groom query parameter to the /api/agents/[agentName]/next-task endpoint, enabling a separate grooming task queue for agents to triage unlabeled/missing-metadata issues. The implementation appears functionally correct against issue PR 398's acceptance criteria, but there is a security concern with route access controls.
Change-by-Change Findings
1. src/app/api/agents/[agentName]/next-task/route.ts
- Added groom mode branch that queries open issues, scores them by triage urgency, and returns one groom task
- Groom mode correctly filters: open issues only, enabled repos only
- Scoring prioritizes: unlabeled issues > missing status > missing priority > backlog lane
- Returns idle task when no grooming candidates exist
- Returns
createGroomTask()withagentName,lane, and issue reference
2. src/lib/agent-task.ts
- Added optional
lanefield toGroomTaskinterface andGroomTaskInput createGroomTasknow passes through the lane value
3. Test coverage
- 20+ new test cases covering groom mode behavior
- Tests verify eligibility rules, priority ordering, tie-breaking, context inclusion
- No auth-related tests observed in the diff
Required Check Results
✅ verify route access controls are in place
Finding: MISSING AUTHORIZATION
The new groom mode branch in /api/agents/[agentName]/next-task/route.ts does not implement any authentication check. The route:
- Does not call
authorizeRequest()or any auth helper - Does not validate
DISPATCH_AGENT_TOKENbearer token - Does not check for any session or credentials
This is consistent with the existing route behavior (the entire endpoint lacks auth), but it means the groom mode is publicly accessible to anyone who can reach the API. The route exposes:
- All open issue titles, URLs, and labels in the database
- Repository full names being tracked
- Issue triage state (which issues lack status/priority/agent/lane)
The agent queue APIs documented in AGENTS.md use DISPATCH_AGENT_TOKEN bearer auth, but this specific route does not enforce it.
✅ check for unintended public endpoints
The groom mode is an additional query parameter on an existing endpoint, not a new endpoint. No new public endpoints were introduced.
Standards Compliance
- AGENTS.md conventions: Label conventions (
status/*,priority/*,agent/*, lane) are correctly handled. Groom tasks follow the existingAgentTaskcontract pattern. ✅ - Code standards: Appropriate HTTP status codes, JSON responses, error handling via try/catch. ✅
- No agent-specific names: Uses generic "groomer" in tests, consistent with
agent/*label patterns. ✅
Linked Issue Fit
Issue PR 398 acceptance criteria:
- ✅ "groomer gets one grooming task at a time" — returns single groom task or idle
- ✅ "untriaged/no-status issues can appear here" — eligible if missing status label
- ✅ "backlog issues can be promoted when ready" — backlog lane issues are eligible
- ✅ "finished work can be closed out" —
stopAfterincludes "Close if completed" - ✅ "worker queues remain separate from groomer work" — mode=groom branch is distinct from normal implement/followup-pr flows
Evidence Provider Findings
None present.
Tool Harness Findings
The auth grep search returned no matches in the route file, confirming no DISPATCH_AGENT_TOKEN check exists in this route.
Unknowns / Needs Verification
- Intentional unauthenticated access: If this route is intentionally public for internal-only deployments, this is not a blocker—but it should be documented.
- Existing route auth gap: The entire
/api/agents/[agentName]/next-taskendpoint lacks auth checks, not just the new groom mode. This is a pre-existing condition, but the PR extends functionality on an unauthenticated route.
Recommendation
The functional implementation correctly addresses issue PR 398. However, the route access control gap should be addressed before merging. Options:
- Add
DISPATCH_AGENT_TOKENbearer auth validation to the route - Document that this endpoint is intentionally unauthenticated (requires operator acknowledgment)
- Add a middleware-level guard for
/api/agents/*routes
Without explicit auth on groom mode, any caller can enumerate your entire grooming queue and issue triage state.
Verdict derived from structured findings (verdict_policy=findings_severity_gated): 0 blocker finding(s) out of 1; model verdict was 'request_changes'.
| const excludeDecomposed = searchParams.get("exclude_decomposed"); | ||
| const includeClaimed = searchParams.get("includeClaimed") === "true"; | ||
| const includeRenovate = searchParams.get("includeRenovate") === "true"; | ||
| const mode = searchParams.get("mode"); |
There was a problem hiding this comment.
Automated finding from AI PR review.
Closes #398