migration(0023): renumber governed four-role acceptance behind 0022 (rebased) - #61
Merged
worldofhacks merged 9 commits intoJul 25, 2026
Merged
Conversation
…osition Blueprint for run_governed_acceptance: reuse HostedFourRoleRuntime.run_attempt with a reviewed corpus seed + a governed policy_gateway_dispatch (corpus-hash invariant -> real PolicyGateway -> ExecutionRecorder -> real evidence) + real oracle Judge + terminalization-safe lifecycle; migration 0022 (governed target-bound four-role authority, down_revision 0021, two-person auth); green e2e test with a controlled target (proves wiring, NOT the evidence); the real four-role evidence is a separate post-deploy authorized live-target campaign. Confirmed: 0018 canonical, b176 is an ancestor (no deconflict), terminalization = fix/provider-evidence-terminalization. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add run_kind 'governed_acceptance' (down_revision 0021): a real four-role attack over the reviewed corpus dispatched through the Policy Gateway to the target. Combines campaign-style two-person authorization (a live dispatch is never system-provenanced) with the four-role hosted config + exactly one bounded target dispatch (v3 governed limits: network_scope=policy_gateway_target, target_call_limit=1). Campaign + the target-free v1/v2 acceptance envelopes stay unchanged. Single head on 0018->0019->0020->0021->0022; applies + downgrades (refuses while governed rows exist) + round-trips. 2 governed migration tests + updated single-head assertion; full acceptance migration suite green (35). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…alid + downgrade coverage Pre-merge tightening (m-required): the governed authority shape now requires acceptance_context_ sha256 AND acceptance_attempt_id NOT NULL — a governed_acceptance row can't carry a null identity. Add DB coverage: a well-formed governed row inserts (two-person auth + config + reviewed-corpus attempt via the deferred FK); a governed row with null context or null attempt is rejected by the authority-shape check; downgrade refuses while a populated governed row exists. 6 governed migration tests + full acceptance suite green (39). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fold the authority-shape gap the composition surfaced: the 0020/0021 agent_acceptance guards are hardwired to run_kind='agent_acceptance' and enforce an ABSOLUTE zero-target-traffic invariant, so a governed_acceptance run (four hosted roles + one bounded target dispatch) was unguarded for four-role lineage and Judge binding at the DB level. Per the reserved-migration owner's call, ISOLATE rather than generalize: add a dedicated m1d_validate_governed_acceptance_execution + provider-invocation guard, leaving the agent_acceptance guards and their absolute zero-target-traffic guarantee untouched. Each guard body is gated on its own run kind, so on a governed row the acceptance guard is a no-op and vice versa. The governed Judge is the real calibrated, human-enabled independent Judge (calibration-bound + explicit decision authority on success), not the failed-advisory acceptance Judge; the single bounded dispatch is anchored by the existing attempt_result UNIQUE(campaign_run_id, attempt_id). 12 governed migration tests green; agent_acceptance + core migration suites unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add the governed run authority the composition needs, isolated from the target-free acceptance store methods (which forbid target traffic): - create_governed_acceptance_run: human-launched under a live two-person authorization; binds acceptance_context_sha256 to the reviewed case's content hash (the seed-replay corpus-hash anchor); actor/provenance stay NULL. - start_governed_agent_execution: four-role advisory execution that PERMITS the one bounded dispatch (no zero-target-traffic assertion); the Judge is the real calibrated, human-enabled independent Judge (starts 'enabled', not failed). - complete_governed_acceptance_run: requires four measured successful calls, an adjudicated calibration-bound Judge, AND exactly one recorded target dispatch. - abort_governed_acceptance_run: kill switch with no new authority. Two-person control's first line stays upstream (a self-approved decision can never be recorded); the store's launcher!=approver check is defense in depth. 9 governed store tests green; agent_acceptance store suite unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nce) Build the v1-blocker composition on the tested schema + store foundation, reusing HostedFourRoleRuntime.run_attempt so a real reviewed-corpus attack flows end to end: Orchestrator selects the reviewed case -> Red Team replays THAT exact reviewed case (seed-replay) -> Policy Gateway dispatches it to the bound target -> the Execution Recorder persists the REAL response -> the independent calibrated Judge evaluates that real response (deterministic oracle keeps precedence) -> Documentation drafts (blocked pending human approval). - Seed-replay authorization invariant: the DISPATCHED CONTENT (the P10 projection) must equal the reviewed case's seed-replay bytes; classification metadata may ride on the Red Team object but only the reviewed attempt reaches the target. Any drift aborts BEFORE the target is touched. - The gateway is the sole cap-enforcing target exit; the Red Team never holds a credential. A native terminalization-safe governed lifecycle records every logical + physical fact so no execution dangles (a Judge-finish failure still terminalizes). - Deterministic precedence: the calibrated model Judge cannot launder a confirmed exploit safe; the oracle over the REAL transcript decides. Controlled-target e2e on real Postgres (test proves WIRING, never the evidence): asserts the Judge saw the REAL controlled response (canary present, not a synthetic canary), four governed executions in the four-role chain all succeeded, verdict EXPLOIT_CONFIRMED by oracle precedence, run completes; and a drifted Red Team proposal aborts before the target with zero recorded dispatch. 33 governed tests + the base runtime suite green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The terminalization reconcile (PR #47) deleted the fix-3 test, leaving uncovered the path where a dispatched call 500s unbilled: a 500 is non-retryable, so exactly one physical attempt is made and the transport records it not_observed. The terminal record must keep physical_attempts == 1 (a dispatched call is NEVER recorded as never-made) while cost stays honestly not_observed — distinct from the no-dispatch not_observed, where physical_attempts is 0. Drives the real transport over httpx.MockTransport + the real lifecycle + store + Postgres, like the rest of the suite. 7 preservation tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Repair-bar item 3: the governed store must accept the confirmed production authority (Judge max_calls=56, roles 9/19/19/9, retries=1), which the closed global-4/per-role-1 envelope rejected. Per the reviewed decision, DERIVE the per-role/global call+spend budget from the staged, content-hashed config (the 4-call harness config OR the 56-call production config alike), with three guardrails held explicit: - One-dispatch invariant is STRUCTURAL, never derived: target_call_limit=1 + network_scope=policy_gateway_target are pinned by construction in both 0022's relaxed _governed_limits_sql() and the store's canonical_governed_acceptance_limits(). A relaxed budget cannot relax the dispatch ceiling. - Derivation binds ONLY to the staged reviewed config: the store matches the run's limits against canonical_governed_acceptance_limits(loaded_config), so derived caps are always the authorized ones (no unreviewed dispatch). - Retries live at the agent-reasoning level only (config retries=1 accepted); target_call_limit stays 1 regardless. 0022's governed constraint becomes structural (valid four-role shape + absolute one-dispatch + budget positivity, global calls <= the 56 platform ceiling); row-level store check is structural, role-level is exact config-match. Folded into 0022 to keep it the single head. Tests: production 56-call config derives + creates a governed run with target_call_limit=1 pinned; a second dispatch, over-ceiling budget, or target-free scope are rejected. Backward-compatible (the 4-call config derives the prior closed envelope). Acceptance suites unchanged. RE-SERIALIZATION FLAG FOR m: 0022's body grew again (relaxed _governed_limits_sql + the store derivation) — single head 0022 on 0021 unchanged, but please re-run the single-head/serialization check. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
g's `attempt_result.resource_measurements` migration landed first and took `0022`
(down_revision 0021). This lane's governed four-role migration also claimed
`0022`, so the two could not coexist — Alembic rejects a duplicate revision id
and the single-head invariant would break.
Renumber to `0023` on `down_revision 0022`, by land order. `get_heads()` now
returns exactly `['0023']` on the chain 0021 -> 0022 -> 0023. Head assertions in
`test_agent_acceptance_migration.py`, `test_governed_acceptance_migration.py`,
and `test_readiness_m1d.py` follow.
Rebased onto the integration head, dropping BOTH of this lane's AD-04 commits:
`4ad125b` (its divergent guard) and `c8033ec` (the revert of that guard). Their
net effect was already nil, and cal's canonical guard is now in the base — so
`src/agentforge/agents/hosted_runtime.py` here is byte-identical to the
integration head and this lane contributes no second AD-04 path.
Verified: single head 0023; ruff lint + format clean; 70 targeted migration,
readiness, hosted-runtime and confirmation-authority tests pass.
NOT closed by this commit — the repair bar remains open:
* `run_governed_acceptance` still has no production caller (composition is
test-only wiring, so the four-role claim has no production entrypoint);
* `0023` does not carry the finding-approval SoD trigger; separation of duties
on finding approval is app-layer only.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
worldofhacks
merged commit Jul 25, 2026
7637c98
into
codex/platform-observability-followup
10 checks passed
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.
Replays q's PR #50 onto the integration head and resolves the migration-number collision. PR #50 had never run a single check (its
agent/**branch was outside the CI trigger — fixed in #58), so this is the first real signal for this lane.The collision
g's
attempt_result.resource_measurementslanded first and took0022. This lane's governed four-role migration also claimed0022. Alembic rejects a duplicate revision id outright, and the single-head invariant would break.Renumbered to
0023ondown_revision 0022, by land order.get_heads()now returns exactly['0023']on the chain0021 → 0022 → 0023. Head assertions in three test modules follow.Both AD-04 commits dropped — deliberately
The rebase drops
4ad125b(this lane's divergent AD-04 guard) andc8033ec(the revert of it). Their net effect was already nil, and cal's canonical guard is now in the base.Result:
src/agentforge/agents/hosted_runtime.pyon this branch is byte-identical to the integration head (git diffis empty). This lane contributes no second AD-04 path, which was the whole point of q's deferral.Verification
0023; chain0023 → 0022 → 0021confirmed viaScriptDirectoryruff check+ruff format --checkclean (CI-pinned 0.16.0)NOT closed by this PR — the repair bar is still open
I am not claiming this lane is done. Two items from the repair bar remain:
run_governed_acceptancehas no production caller.git grepfinds only the definition, the__all__export, the design doc, and two test call sites. The composition is test-only wiring, so the four-role claim has no production entrypoint — it cannot be exercised through a real run.0023does not carry the finding-approval SoD trigger. Separation of duties on finding approval is app-layer only (store.py), with noSECURITY DEFINERtrigger, no exactly-one-link rule, and no post-approval link-insert guard. The merged finding-approval app needs that DB parity before release.This PR is the unblocking step (collision resolved, CI signal obtained, no AD-04 divergence), not the completion of the lane.