refactor(decide): split type definitions into types.go; clarify detecting helper
Address PR review (aa-1): - Move the decider input/output type definitions (LifecycleDecision, ProbeInput, ProcessLiveness, OpenPRInput, DetectingInput) out of the execution file into a dedicated types.go, leaving decide.go for behaviour. - Expand the detecting() helper doc to spell out that it adapts a probe verdict into the shared CreateDetectingDecision anti-flap path so each probe branch doesn't re-implement the quarantine counter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9920c6daaa
commit
4d8a20676a
|
|
@ -23,65 +23,6 @@ const (
|
|||
DetectingMaxDuration = 5 * time.Minute
|
||||
)
|
||||
|
||||
// LifecycleDecision is the output of every decider: the derived display status
|
||||
// plus the canonical sub-state values to persist, the human-readable evidence,
|
||||
// and the (possibly updated) detecting memory.
|
||||
type LifecycleDecision struct {
|
||||
Status domain.SessionStatus
|
||||
Evidence string
|
||||
Detecting *domain.DetectingState
|
||||
SessionState domain.SessionState
|
||||
SessionReason domain.SessionReason
|
||||
PRState domain.PRState
|
||||
PRReason domain.PRReason
|
||||
}
|
||||
|
||||
// ProbeInput reconciles runtime + process liveness. A *failed* probe (timeout
|
||||
// or error) is distinct from a "dead" verdict and must route to detecting,
|
||||
// never to a death conclusion. KillRequested short-circuits to terminal.
|
||||
type ProbeInput struct {
|
||||
Runtime domain.RuntimeState
|
||||
RuntimeFailed bool
|
||||
Process ProcessLiveness
|
||||
ProcessFailed bool
|
||||
RecentActivity bool
|
||||
KillRequested bool
|
||||
Prior *domain.DetectingState
|
||||
Now time.Time
|
||||
}
|
||||
|
||||
// ProcessLiveness mirrors isProcessRunning's three-valued answer.
|
||||
type ProcessLiveness string
|
||||
|
||||
const (
|
||||
ProcessAlive ProcessLiveness = "alive"
|
||||
ProcessDead ProcessLiveness = "dead"
|
||||
ProcessIndeterminate ProcessLiveness = "indeterminate"
|
||||
)
|
||||
|
||||
// OpenPRInput drives the PR pipeline ladder for an open PR.
|
||||
type OpenPRInput struct {
|
||||
CIFailing bool
|
||||
ChangesRequested bool
|
||||
Approved bool
|
||||
Mergeable bool
|
||||
ReviewPending bool
|
||||
IdleBeyond bool // idle past the stuck threshold
|
||||
Number int
|
||||
URL string
|
||||
}
|
||||
|
||||
// DetectingInput feeds the quarantine counter. Evidence is hashed with
|
||||
// timestamps stripped, so "same ambiguous signal" keeps the counter climbing
|
||||
// while any real change resets it.
|
||||
type DetectingInput struct {
|
||||
Evidence string
|
||||
ProposedState domain.SessionState
|
||||
ProposedReason domain.SessionReason
|
||||
Prior *domain.DetectingState
|
||||
Now time.Time
|
||||
}
|
||||
|
||||
// ResolveProbeDecision reconciles runtime/process liveness into a decision.
|
||||
//
|
||||
// The ordering encodes the load-bearing invariants:
|
||||
|
|
@ -285,9 +226,11 @@ var timestampPatterns = []*regexp.Regexp{
|
|||
regexp.MustCompile(`\b\d{10,13}\b`),
|
||||
}
|
||||
|
||||
// detecting builds a quarantine decision from a probe verdict, threading the
|
||||
// prior counter through CreateDetectingDecision so probe ambiguity is subject
|
||||
// to the same anti-flap escalation as any other detecting cause.
|
||||
// detecting adapts a probe verdict into the shared anti-flap path. It packages
|
||||
// the proposed reason + evidence (plus the prior counter from the same probe
|
||||
// input) into a DetectingInput and defers to CreateDetectingDecision, so every
|
||||
// probe-driven ambiguity is counted and escalated by the identical quarantine
|
||||
// logic instead of each probe branch re-implementing the counter.
|
||||
func detecting(in ProbeInput, reason domain.SessionReason, evidence string) LifecycleDecision {
|
||||
return CreateDetectingDecision(DetectingInput{
|
||||
Evidence: evidence,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
package decide
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/aoagents/agent-orchestrator/backend/internal/domain"
|
||||
)
|
||||
|
||||
// LifecycleDecision is the output of every decider: the derived display status
|
||||
// plus the canonical sub-state values to persist, the human-readable evidence,
|
||||
// and the (possibly updated) detecting memory.
|
||||
type LifecycleDecision struct {
|
||||
Status domain.SessionStatus
|
||||
Evidence string
|
||||
Detecting *domain.DetectingState
|
||||
SessionState domain.SessionState
|
||||
SessionReason domain.SessionReason
|
||||
PRState domain.PRState
|
||||
PRReason domain.PRReason
|
||||
}
|
||||
|
||||
// ProbeInput reconciles runtime + process liveness. A *failed* probe (timeout
|
||||
// or error) is distinct from a "dead" verdict and must route to detecting,
|
||||
// never to a death conclusion. KillRequested short-circuits to terminal.
|
||||
type ProbeInput struct {
|
||||
Runtime domain.RuntimeState
|
||||
RuntimeFailed bool
|
||||
Process ProcessLiveness
|
||||
ProcessFailed bool
|
||||
RecentActivity bool
|
||||
KillRequested bool
|
||||
Prior *domain.DetectingState
|
||||
Now time.Time
|
||||
}
|
||||
|
||||
// ProcessLiveness mirrors isProcessRunning's three-valued answer.
|
||||
type ProcessLiveness string
|
||||
|
||||
const (
|
||||
ProcessAlive ProcessLiveness = "alive"
|
||||
ProcessDead ProcessLiveness = "dead"
|
||||
ProcessIndeterminate ProcessLiveness = "indeterminate"
|
||||
)
|
||||
|
||||
// OpenPRInput drives the PR pipeline ladder for an open PR.
|
||||
type OpenPRInput struct {
|
||||
CIFailing bool
|
||||
ChangesRequested bool
|
||||
Approved bool
|
||||
Mergeable bool
|
||||
ReviewPending bool
|
||||
IdleBeyond bool // idle past the stuck threshold
|
||||
Number int
|
||||
URL string
|
||||
}
|
||||
|
||||
// DetectingInput feeds the quarantine counter. Evidence is hashed with
|
||||
// timestamps stripped, so "same ambiguous signal" keeps the counter climbing
|
||||
// while any real change resets it.
|
||||
type DetectingInput struct {
|
||||
Evidence string
|
||||
ProposedState domain.SessionState
|
||||
ProposedReason domain.SessionReason
|
||||
Prior *domain.DetectingState
|
||||
Now time.Time
|
||||
}
|
||||
Loading…
Reference in New Issue