feat(v0): add cloud_review policy field + ReviewerLane + D20 force-forbidden enforcement (closes #37) #44
No reviewers
Labels
No labels
agent/claude-code
agent/codex
agent/gemini
agent/hermes
agent/iskra
agent/ollama
agent/patchwarden
area:business-model
area:competitive
area:discovery
area:forgejo
area:metrics
area:product-strategy
area:v0-core
cagan-grade-approved
client:platform
dependency/blocked
dependency/blocks-others
dependency/cross-repo
dependency/needs-confirmation
domain:agents
domain:ci
domain:docs
domain:forgejo
domain:infra
domain:memory
domain:runtime
domain:signal
domain:ux
flow/architecture
flow/blocked
flow/deployed
flow/done
flow/implementation
flow/intake
flow/maintained
flow/observed
flow/ready
flow/refining
flow/retired
flow/review
judge/codex-candidate
judge/hermes-candidate
judge/low-confidence
judge/needs-refinement
judge/operator-needed
judge/p0
judge/p1
judge/p2
judge/p3
judge/park
judge/patchwarden-candidate
judge/stale-priority
kind/adr
kind/bug
kind/chore
kind/feature
kind/infra
kind/ops
kind/refactor
kind/research
kind:artifact
kind:decision
kind:dogfood
kind:epic
kind:implementation
kind:research
merge/auto
merge/manual
merge/manual-dependency-conflict
merge/manual-failing-tests
merge/manual-merge-conflict
merge/manual-missing-review
merge/manual-operator-preference
merge/manual-red-zone
merge/manual-security-sensitive
merge/manual-unclear-scope
merge/manual-unknown
mode:operator-only
mode:patchwarden-iskra-approved
mode:safe-auto
observed/erroring
observed/needs-followup
observed/pending
observed/retire-candidate
observed/unused
observed/used
priority:p0
priority:p1
priority:p2
priority:p3
ready-for-agent
review:claude-reviewed
review:codex-reviewed
review:dziadek-reviewed
review:needs-human
safety:external-write
safety:no-prod-mutation
safety:prod-impact
safety:secret-touch
size/large
size/medium
size/small
size/tiny
size/unknown
source/adr
source/agent-generated
source/manual
source/operator-chat
source/voice-note
status:blocked
status:blocked-on-discovery
status:cagan-grade-review-pending
status:codex-ready
status:merged:pending-evidence
status:needs-evidence
status:needs-operator-decision
status:operator-needed
status:parked
tier:0-anchor
tier:0-platform-substrate
tier:1-core
tier:1-iskra-value-layer
tier:2-supporting
tier:2-tools-products-modules
type:bug
type:chore
type:docs
type:feat
type:policy
type:research
wave:1-foundation
wave:2-positioning
wave:3-validation
wave:4-economics
wave:5-operating
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
pdurlej/patchwarden!44
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/patchwarden-cloud-review-policy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds
cloud_reviewpolicy field +ReviewerLanedataclass + seedrepo_pattern_sanitylane + helpereffective_cloud_review()that architecturally enforces D20 hybrid review authority boundary (forceforbiddenfor sensitive classifications regardless of lane config). Stdlib-only. No model calls. No webhook. No platform touch.Closes #37. Companion to PR #43 (D20 ADR — recommended merge order: #43 first, then this).
What changed (3 files, +372/-1)
src/patchwarden/policy_bundle.py(+128)ALLOWED_CLOUD_REVIEW_VALUES = ("allowed", "forbidden", "required-with-redaction")— enum constants per issue specSENSITIVE_CLASSIFICATIONSfrozenset — mirror of D20 hard manual classes +large/unknown(conservative defaults)ReviewerLanefrozen dataclass — name, enabled, required_for, cloud_review, provider, model, fallback_model, timeout_seconds, fail_on_missing, fail_on_unparseablePolicyBundle.review_lanes: tuple[ReviewerLane, ...] = ()— optional field with empty default (back-compat)load_bundle()extended — parses optional[review_lanes.*]TOML sectionseffective_cloud_review(classification, lane)helper — architectural enforcement of D20: sensitive classifications always return"forbidden"regardless of lane config;Nonelane defaults to"forbidden"(conservative)lane_required_for(lane, classification)helper — scaffold for future #28/#29/#30 reviewer-orchestration code to enforce fail-closed missing-required-lane behavior_parse_review_lanes()+_parse_single_lane()+_optional_strings()parsers — full validation: invalid enum rejected, missing required fields rejected, optional sections OKpolicies/platform.v0.toml(+17)[review_lanes.repo_pattern_sanity]seed lane per issue spec:enabled = true,required_for = ["safe_docs_status"],cloud_review = "allowed"provider = "ollama",model = "kimi-k2.6:cloud",fallback_model = "gemma4:31b-cloud"timeout_seconds = 90,fail_on_missing = true,fail_on_unparseable = trueeffective_cloud_review()tests/test_policy_bundle.py(+228, total 22 tests, all passing)4 test classes:
PolicyBundleTests(existing, unchanged) — 3 tests for back-compatReviewerLaneParsingTests— 5 tests: seed loads, optional section, invalid enum rejected, missing required field rejected,required_fordefaults to emptyEffectiveCloudReviewTests— 10 tests: each sensitive classification forces forbidden, safe_docs_status with allowed lane returns allowed, no-lane defaults to forbidden, sentinel test that all D20 hard manual classes are inSENSITIVE_CLASSIFICATIONSLaneRequiredForTests— 3 tests for required-for matching + disabled lane never requiredCloudReviewEnumTests— 1 test locking enum values to D20 specFull test suite:
PYTHONPATH=src python3 -m unittest discover -s tests→ 63 tests passing.Acceptance criteria (from issue #37)
cloud_reviewwith allowed values only —_parse_single_lane()validates againstALLOWED_CLOUD_REVIEW_VALUES, testtest_invalid_cloud_review_enum_rejectedcloud_review=forbiddenregardless of lane config —effective_cloud_review()helper + 7 dedicated tests covering secrets / workflow / runtime / policy_governance / policy_exact_file / large / unknownlane_required_for()helper exposes this distinction for future reviewer-orchestration code (#28/#29/#30); current PR only provides the predicateEffectiveCloudReviewTests+ReviewerLaneParsingTestslane.fail_on_missing/lane.fail_on_unparseableconfig fields parsed +lane_required_for()predicate exposed; full fail-closed enforcement requires lane-artifact lifecycle (review_artifact loading, staleness check) which lives in #28-#30 reviewer orchestration trio. This PR provides the config surface + predicates that #28-#30 will consume.Out of scope (per issue + D20)
Architectural enforcement of D20 (verifiable by code review)
Per D20 in
docs/decisions.md(PR #43): reviewer lanes are sensors only. This PR's code surface reflects that:policy_bundle.pyhas nomerge_*orpost_approved_reviewimportspolicy_bundle.pyhas no calls toforgejo_client(it's a pure data + validation module)ReviewerLanedataclass has nomerge_authorityfield — verdict authority is always Patchwarden per code patheffective_cloud_review()returns posture ("allowed"/"forbidden"/"required-with-redaction") — never a merge decisionVerification
PYTHONPATH=src python3 -m unittest tests.test_policy_bundle -v→ 22 tests passPYTHONPATH=src python3 -m unittest discover -s tests→ 63 tests pass (full suite, no regressions)grep -E "(merge|approve)" src/patchwarden/policy_bundle.py→ only comments referencing D20, no actual merge/approve API callspolicies/platform.v0.tomlparses cleanly viaload_bundle()(covered bytest_loads_platform_bundle)Trace
patchwarde-auditlm-boundary, 2026-05-26cloud_reviewschema field (now ✅)Suggested status
Merge now (after PR #43 merged) — atomic, stdlib-only, no model calls, no webhook, no platform touch. Full test suite green. Architectural enforcement of D20 baked into code surface (not just comments). Unblocks #28-#30 reviewer orchestration trio.
If you prefer split A/B/C per issue spec, this PR is effectively A+C (parser/schema/config) + scaffold for B (policy behavior predicates exposed; full enforcement in #28-#30). Pure split-A would drop the
effective_cloud_review()+lane_required_for()helpers + their 14 tests, but they are tiny, stdlib-only, and architecturally meaningful — recommend keeping together.🤖 claude (Patchwarden dedicated thread) — per codex+Oracle task handoff 2026-05-26, F1 kill-criterion claude-as-Patchwarden-executor mandate active.