GV125 separates candidate composition from semantic authorization. A stacked child pull request is still required to carry a fresh assessment against its immediate comparison base and may not lose unsatisfied learning requirements, but open learning debt does not by itself make the child candidate untestable. The hard GV119/GV122 debt-closure decision applies at the authorization boundary.
Authorization is tightened at the same time: a human pull-request
merge carries an explicit target classification, and only a merge into
authorizedTarget can construct an
AuthorizedRevision. A merge into another candidate branch
remains human-reviewed candidate composition, not semantic
authority.
{-# OPTIONS --safe #-}
module Govenv.Assurance.GV125 where
open import Agda.Builtin.Bool using (true; false)
open import Agda.Builtin.Equality using (_≡_; refl)
open import Agda.Builtin.List using ([]; _∷_)
open import Govenv.Assurance.GV125.Counterexample.StackedPullRequestHardGate
open import Govenv.Authorization
open import Govenv.Kernel.Assurance using (StaticEvidence; staticEvidence)
open import Govenv.Kernel.Learning
open import Govenv.Learning using
(carriedDebt; containsRequirement; stackedCandidateRequirement)
data Impossible : Set where
reviewerPrincipal : Principal
reviewerPrincipal =
observedPrincipal "human-reviewer" human
reviewer : HumanPrincipal
reviewer =
humanPrincipal reviewerPrincipal refl
candidateMerge : HumanPullRequestMerge
candidateMerge =
humanPullRequestMerge
62
reviewer
(identifiedRevision "stacked-child")
candidateTarget
authorizedMerge : HumanPullRequestMerge
authorizedMerge =
humanPullRequestMerge
64
reviewer
(identifiedRevision "authorized-head")
authorizedTarget
authorized : AuthorizedRevision
authorized =
authorizedRevision authorizedMerge refl
candidateTargetCannotAuthorize :
HumanPullRequestMerge.target candidateMerge ≡ authorizedTarget →
Impossible
candidateTargetCannotAuthorize ()
record Proposition : Set where
constructor satisfied
field
observedOldGateBlocksStack :
candidateLearningAllowed
feature expands true false true openDebt noBypass ≡ false
stackCompositionAllowsPreservedDebt :
candidateCompositionAllowed
feature expands true false true noBypass ≡ true
stackCompositionRejectsLostDebt :
candidateCompositionAllowed
feature expands true false false noBypass ≡ false
compositionBoundaryDoesNotRequireAuthorizationClosure :
candidateBoundaryAllowed
candidateComposition true false ≡ true
authorizationBoundaryRequiresHardGate :
candidateBoundaryAllowed
authorizationBoundary true false ≡ false
authorizedBoundaryAcceptsClosedCandidate :
candidateBoundaryAllowed
authorizationBoundary true true ≡ true
candidateMergeHasNoAuthorizationTarget :
HumanPullRequestMerge.target candidateMerge ≡ authorizedTarget →
Impossible
authorizedMergeTargetsAuthority :
HumanPullRequestMerge.target
(AuthorizedRevision.authorization authorized) ≡
authorizedTarget
newLearningRequirementRemainsDebt :
containsRequirement stackedCandidateRequirement carriedDebt ≡ true
proof : Proposition
proof =
satisfied
refl
refl
refl
refl
refl
refl
candidateTargetCannotAuthorize
refl
refl
evidence : StaticEvidence 125
evidence = staticEvidence Proposition proof