feat(persona): add role-based review personas (#51)
CI / test (pull_request) Successful in 15s
CI / review (/openai/v1, gpt-4.1, gpt41, openai, GPT_REVIEW_TOKEN) (pull_request) Failing after 17s
CI / review (/anthropic/v1, claude-sonnet-4-6, sonnet, anthropic, SONNET_REVIEW_TOKEN) (pull_request) Failing after 17s
CI / review (/openai/v1, gpt-4.1-mini, gpt41-mini, openai, GPT_REVIEW_TOKEN) (pull_request) Failing after 16s
CI / review (/openai/v1, gpt-5-mini, gpt5-mini, openai, GPT_REVIEW_TOKEN) (pull_request) Failing after 14s
CI / review (/openai/v1, gpt-5, security, openai, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m28s
CI / review (/openai/v1, gpt-5, gpt, openai, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m41s
CI / test (pull_request) Successful in 15s
CI / review (/openai/v1, gpt-4.1, gpt41, openai, GPT_REVIEW_TOKEN) (pull_request) Failing after 17s
CI / review (/anthropic/v1, claude-sonnet-4-6, sonnet, anthropic, SONNET_REVIEW_TOKEN) (pull_request) Failing after 17s
CI / review (/openai/v1, gpt-4.1-mini, gpt41-mini, openai, GPT_REVIEW_TOKEN) (pull_request) Failing after 16s
CI / review (/openai/v1, gpt-5-mini, gpt5-mini, openai, GPT_REVIEW_TOKEN) (pull_request) Failing after 14s
CI / review (/openai/v1, gpt-5, security, openai, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m28s
CI / review (/openai/v1, gpt-5, gpt, openai, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m41s
Implement role-based review personas that provide specialized review focus: - Security: vulnerabilities, auth, secrets, injection attacks - Architect: design patterns, code organization, API contracts - Docs: documentation quality, API clarity, error messages Changes: - Add persona loading from JSON files and embedded built-ins - Add --persona and --persona-file CLI flags (mutually exclusive) - Add BuildPersonaSystemPrompt for persona-specific prompts - Add FormatMarkdownWithDisplay for persona display names - Update action.yml with persona and persona-file inputs - Add comprehensive tests for all new functionality - Document personas in README with examples The persona system replaces the generic 'You are an expert code reviewer' prompt with domain-specific identity, focus areas, ignore list, and severity calibration. This reduces redundancy between multiple reviewers and catches domain-specific issues that generic reviewers miss. Closes #51
This commit is contained in:
@@ -159,3 +159,58 @@ func TestFormatMarkdown_RoleTitle(t *testing.T) {
|
||||
t.Error("should not contain role title header when reviewer name is empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatMarkdownWithDisplay(t *testing.T) {
|
||||
result := &ReviewResult{
|
||||
Verdict: "APPROVE",
|
||||
Summary: "Test summary",
|
||||
Findings: nil,
|
||||
Recommendation: "Test recommendation",
|
||||
}
|
||||
|
||||
t.Run("with display name", func(t *testing.T) {
|
||||
body := FormatMarkdownWithDisplay(result, "Security Specialist", "security")
|
||||
|
||||
// Header should use display name
|
||||
if !strings.Contains(body, "# Security Specialist Review") {
|
||||
t.Error("header should use display name")
|
||||
}
|
||||
|
||||
// Sentinel should use sentinel name
|
||||
if !strings.Contains(body, "<!-- review-bot:security -->") {
|
||||
t.Error("sentinel should use sentinel name")
|
||||
}
|
||||
|
||||
// Footer "Review by" should use display name
|
||||
if !strings.Contains(body, "*Review by Security Specialist*") {
|
||||
t.Error("footer should use display name")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("without display name", func(t *testing.T) {
|
||||
body := FormatMarkdownWithDisplay(result, "", "reviewer")
|
||||
|
||||
// Should fall back to sentinel name for header
|
||||
if !strings.Contains(body, "# Reviewer Review") {
|
||||
t.Error("header should fall back to sentinel name")
|
||||
}
|
||||
|
||||
if !strings.Contains(body, "<!-- review-bot:reviewer -->") {
|
||||
t.Error("sentinel should use sentinel name")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("empty both names", func(t *testing.T) {
|
||||
body := FormatMarkdownWithDisplay(result, "", "")
|
||||
|
||||
// Should not have header
|
||||
if strings.Contains(body, "# ") && strings.Contains(body, " Review") {
|
||||
t.Error("should not have header when both names empty")
|
||||
}
|
||||
|
||||
// Should not have sentinel
|
||||
if strings.Contains(body, "<!-- review-bot:") {
|
||||
t.Error("should not have sentinel when sentinel name empty")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user