feat(roles): add the read-only pr_reviewer role end-to-end

A global, read-only PR reviewer agent (pr-reviewer-1) that reviews inbound
external/fork PRs and posts one change-request. Wired end-to-end:

- identity: Role.PR_REVIEWER + agent + ROLE_LEVEL (QA-peer) + REVIEWER_ROLES
- lifecycle: CLAIM_RULES + ROLE_TEAM_RULES + a dedicated claim_pr_review /
  post_pr_review verb pair (distinct from QA's) + the pr_review_done action and
  its in_progress->completed transition; give_me_work / i_am_idle gain the role
- role_config: a read-only RoleConfig (allows_write=False)
- journaling: ALL_CELLS read tier so it can read internal intent like QA
- tracing: post_pr_review requires a learning entry; claim_pr_review is waived
- seeds presentation + factory prompt layer + builtin tools + the agentrole
  enum migration (037) + regenerated verb/lifecycle artifacts

Read-only at /app like QA/auditor; default-off — nothing dispatches review work
until external_pr_enabled. Foundation + role-config + enum suites green; ruff +
mypy clean; orchestrator boots.
This commit is contained in:
Renn F
2026-06-16 10:37:06 +02:00
parent beb2287316
commit 5902c0fe38
18 changed files with 294 additions and 4 deletions
+2
View File
@@ -20,6 +20,7 @@ def test_role_enum_has_every_role_inc_system() -> None:
"product_owner",
"head_marketing",
"auditor",
"pr_reviewer",
"prompter",
"secretary",
"ceo",
@@ -84,6 +85,7 @@ def test_agents_catalog_has_all_seed_slugs() -> None:
"auditor",
"intake-1",
"secretary-1",
"pr-reviewer-1",
}
actual = set(identity.AGENTS.keys())
assert actual == expected_slugs, f"agent catalog drift: {actual ^ expected_slugs}"
+1
View File
@@ -32,6 +32,7 @@ def test_role_enum_has_every_pre_gateway_role() -> None:
"product_owner",
"head_marketing",
"auditor",
"pr_reviewer", # reviews inbound external/fork PRs (read-only)
"prompter", # post-gateway intake role (human-only, drafts tasks)
"secretary", # CEO's chief-of-staff (human-only, gated CEO authority)
"ceo",