Operant Studio
OPER-152

[OPER-QA-16] AgentWorker as QaTestProjectMember — extend resolver to fan out to agents

Band
MEDIUM
Suggested
Justin Cooke

Body

feature_id: FEAT-studio-qa-projects
verify_cmd: pnpm --filter @operant/qa test resolver

## Context

Today, `QaTestProjectMember` (packages/database/prisma/schema/qa.prisma:278) stores a polymorphic `memberId String` with the comment `// user id or worker id — same shape as TestRun.assigneeId`. The intent to accept both actor kinds is already in the schema — but `resolveAssignmentsForProject()` (shipped by OPER-127 in packages/qa/src/projects.ts) walks members and materializes `TestAssignment` rows assuming user identity, so agent workers are effectively invisible to the resolver even when a LEAD adds one.

We want agent workers to participate in Test Projects on the same code path as human testers — no separate `AgentTestProjectMember` model, no parallel resolver. The natural extension is:

1. Make `QaTestProjectMember.memberId` genuinely polymorphic by adding an actor-kind discriminator (`memberKind: 'user' | 'agent'`) so the resolver can safely branch, OR split into two nullable FKs (`userId String?`, `agentWorkerId String?` with a check constraint) — final shape is a PDT call.
2. Add a `capability` filter column on the member row (or read it from the AgentWorker via join) so the resolver skips agents that aren't eligible for a case's `TestKind`.
3. Extend `resolveAssignmentsForProject()` to fan out to both actor kinds, respecting the capability filter (OPER-QA-17 supplies the catalog).
4. Preserve the existing `@@unique([projectId, memberId])` semantics per-actor-kind.

This is a natural extension of OPER-127's resolver, not a new epic. No new API surface required beyond the existing `/api/studio/[team]/qa/projects/*` routes, which accept `memberId` today.

References:
- packages/database/prisma/schema/qa.prisma:278 — `QaTestProjectMember`
- packages/database/prisma/schema/tasks.prisma:430 — `AgentWorker`
- packages/qa/src/projects.ts — `resolveAssignmentsForProject`
- OPER-127 (DONE) — resolver + state machines + API routes
- OPER-QA-17 (this batch) — agent capability catalog the resolver reads

## Acceptance Criteria

- [ ] `QaTestProjectMember` accepts an AgentWorker as a member without a new epic-scoped model — either via a `memberKind` discriminator or a two-FK+check-constraint shape (PDT decision documented in the plan doc).
- [ ] `resolveAssignmentsForProject()` materializes `TestAssignment` rows for both user and agent members in a single pass.
- [ ] The resolver skips agent members whose capability set does not cover the case's `TestKind`, reading capabilities from OPER-QA-17's `AgentCapability` catalog.
- [ ] Idempotency preserved: re-running the resolver produces zero new rows when membership + capabilities are unchanged.
- [ ] Existing user-only resolver test suite passes unchanged.
- [ ] New tests cover: (a) mixed user+agent membership fan-out, (b) capability-filter skip, (c) polymorphic uniqueness.
- [ ] Migration is non-destructive on the existing `QaTestProjectMember` table; documented rollback plan.
- [ ] `phi-auditor` and `rls-guard` clean; `schema-guard` clean.
- [ ] Body carries `verify_cmd: pnpm --filter @operant/qa test resolver` frontmatter.

verify_cmd: pnpm --filter @operant/qa test resolver

Attachments

Loading attachments…

Comments

Loading comments…