policy: unattended block + 4 Bucket-C gate routers (AB#3104, PR1 of 2) - #320
Closed
PolyphonyRequiem wants to merge 1 commit into
Closed
Conversation
…s (AB#3104)
Adds the policy.unattended block (acceptance_mode/review_wait_mode/cap_mode)
promised by AB#3104, then fronts four deterministic human gates with upstream
policy-router scripts that bypass the gate when the operator opted in.
Schema additions:
- PolicyConfig.Unattended (UnattendedPolicy { AcceptanceMode, ReviewWaitMode, CapMode })
- UnattendedAcceptanceMode (manual|auto)
- UnattendedReviewWaitMode (wait|skip)
- UnattendedCapMode (manual|auto_proceed|auto_fail)
- PolicyLoader.ApplyBuiltInDefaults defaults all three to safe (manual/wait/manual)
- ValidateUnattended rejects unknown enum values at parse time
- PolicyLoadResult.Unattended snapshot exposed via 'polyphony policy load'
Workflow wiring (4 of 22 Bucket-C gates — see AB#3104 for the catalogue):
- apex_completion_gate (apex-driver.yaml) — acceptance_mode=auto bypasses to close_mark_satisfied
- user_acceptance (implement-merge-group.yaml) — acceptance_mode=auto bypasses to pr_platform_router
- pending_review_gate (plan-level.yaml) — review_wait_mode=skip bypasses to pr_poll_platform_router
- stuck_review_gate (plan-level.yaml) — review_wait_mode=skip bypasses to stuck_review_reset
Each router mirrors the canonical pattern from root-fallback-gate.yaml (lines 88-101):
polyphony policy load -> route on output.unattended.<mode>.
policy-fasttrack.yaml gets unattended: { auto, skip, auto_proceed }; the canonical
policy.yaml ships with all-manual defaults plus a documentation block.
Tests: 5 new unit tests for the schema (defaults, full preserve, partial preserve,
all-bad-mode rejection, snake_case JSON serialization).
Remaining 18 Bucket-C gates filed for PR2 under AB#3104.
Refs: AB#3104, AB#3103
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bucket-C policy controllability — schema + first 4 gates (AB#3104, PR1 of 2)
What this PR ships
A new
policy.unattendedblock that lets an operator opt deterministic, non-policyhuman_gatenodes into auto-routes, plus the upstream router scripts that wire the first four gates from the AB#3103 audit.Schema (5 files)
src/Polyphony/Policy/PolicyConfig.csUnattendedPolicy { AcceptanceMode, ReviewWaitMode, CapMode }+ threestatic classconstants (UnattendedAcceptanceMode,UnattendedReviewWaitMode,UnattendedCapMode) mirroring theRootFallbackAutoDecide/RenegotiationAutoDecideprecedent. NewPolicyConfig.Unattendedproperty.src/Polyphony/Policy/PolicyLoader.csApplyBuiltInDefaultsdefaults all three modes to safe (manual/wait/manual). NewValidateUnattendedrejects unknown enum values at parse time with a clear message.src/Polyphony/Models/PolicyLoadResult.csPolicyUnattendedSnapshotrecord +PolicyLoadResult.Unattendedproperty — exposes the resolved snapshot viapolyphony policy load.src/Polyphony/PolyphonyJsonContext.csPolicyUnattendedSnapshotfor AOT serialization.src/Polyphony/Commands/PolicyCommands.csSnapshotUnattendedhelper + wires it intoLoad().YAML examples (2 files)
.polyphony-config/policy.yamlunattended:block with comments documenting each mode and which gates it controls..polyphony-config/policy-fasttrack.yamlunattended: { acceptance_mode: auto, review_wait_mode: skip, cap_mode: auto_proceed }so the canonical fast-track preset bypasses the wired gates. CAVEAT block updated to call out PR1 vs PR2 coverage.Workflow wiring (3 files, 4 gates)
Each gate gets an upstream
<gate>_policy_routerscript step that callspolyphony policy loadand routes either to the bypass target (the route the operator's "happy" option would have selected) or falls through to the human gate. Pattern mirrorsroot-fallback-gate.yamllines 88–101.apex-driver.yamlapex_completion_gateacceptance_mode=autoclose_mark_satisfiedimplement-merge-group.yamluser_acceptanceacceptance_mode=autopr_platform_routerplan-level.yamlpending_review_gatereview_wait_mode=skippr_poll_platform_routerplan-level.yamlstuck_review_gatereview_wait_mode=skipstuck_review_resetTests (1 file)
tests/Polyphony.Tests/Commands/PolicyCommandsTests.cs— five newUnattendedtests:Load_NoFile_AppliesUnattendedDefaults— defaults ofmanual/wait/manual.Load_FileWithUnattended_PreservesAllModes(Theory ×4) — round-trips every mode combination.Load_PartialUnattended_FillsMissingFromDefaults— partial override doesn't blow away unspecified modes.Load_BadUnattendedMode_ReturnsConfigError(Theory ×3) — bad mode surfaces field name + bad token in the error envelope.Load_Unattended_SnakeCaseFieldNames_PresentInRawJson— JSON serialization stays snake_case.All 55
PolicyCommandsTestspass.What this PR explicitly does NOT do
Wave 2 (AB#3104 follow-on PR) wires the remaining 18 Bucket-C gates from the audit:
revise_cap_gate,remediation_cap_gate,pr_fix_exhausted_gate,depth_exceeded_gate,closed_unmerged_gate,scope_violation_gate,stale_generation_gate,dependency_gate,conflict_resolution_gate, etc.ado_stuck_review_gate,ado_pr_pending_gate,ado_pr_changes_requested_gate.human_satisfaction_gate(apex-item-dispatch).PR2 also adds harness scenarios that prove the bypass paths actually flow end-to-end. The schema + the four wired gates here are the smallest viable slice that lets the operator unblock an unattended research dogfood run on the happy path.
Verification
dotnet build src/Polyphony.SchemaExporter/Polyphony.SchemaExporter.csproj— green.dotnet test --filter Unattended— 12 tests pass (5 new + 7 from policy: POLYPHONY_POLICY_PATH env override + policy-fasttrack example (AB#3103) #319 sharingPolicyFileFixture).dotnet test(full suite) — 3349 / 3357 pass; the four intermittents (ProcessRunnerTests.RunAsync_TimeoutAfterEmittedOutput,ManifestCommandsTests.RecordRebase_HappyPath_AppendsAndReportsCount,PlanCommandsRebaseStaleDescendantTests.ParentPrFresh_ProceedsToRebase,PrCommandsMergePlanAdoTests.OpenPr_CompletesAndRecordsLedger) pass when re-run individually, so they are pre-existing flakes unrelated to this change.conductor validate— green forapex-driver.yaml,implement-merge-group.yaml,plan-level.yaml.tests/lint-jinja-resolver.ps1— PASS, 0 errors, 31 (pre-existing) warnings.Closes / refs
POLYPHONY_POLICY_PATHenv override (depends on the PolicyLoader resolution path).