Files
Assistant/modules/work/domain/delegation.go
m b3491520bd
CI / test (push) Successful in 20s
CI / test (pull_request) Successful in 20s
DEV-000069 general agent delegation codex bridge foundation
2026-08-17 20:07:14 +03:00

327 lines
13 KiB
Go

package domain
import (
"errors"
"strings"
"time"
"git.cin.su/m/Assistant/contracts/capability"
"git.cin.su/m/Assistant/contracts/work"
"git.cin.su/m/Assistant/platform/ids"
)
var ErrInvalidDelegation = errors.New("invalid delegation")
var ErrInvalidAgentRun = errors.New("invalid agent run")
var ErrInvalidAgentCheckpoint = errors.New("invalid agent checkpoint")
var ErrInvalidAgentResult = errors.New("invalid agent result")
var ErrInvalidDelegationVerification = errors.New("invalid delegation verification")
type DelegationRequest struct {
Goal work.Goal
Plan work.WorkPlan
Candidate work.PlanCandidate
Requirement work.CapabilityRequirement
Implementation capability.CapabilityImplementation
ConversationID work.ConversationRef
OriginalIntentText string
ContextSummary string
ContextRefs []string
VerificationSummary string
DerivedInstruction string
StartedAt time.Time
}
type DelegationBundle struct {
Delegation work.Delegation
Run work.AgentRun
}
func StartDelegation(input DelegationRequest) (DelegationBundle, error) {
if input.Goal.ID == "" || input.Plan.ID == "" || input.Candidate.ID == "" || input.Requirement.ID == "" ||
input.Implementation.ID == "" || input.Implementation.Kind != capability.ImplementationAgent ||
input.Requirement.CapabilityKind == "" || input.StartedAt.IsZero() || strings.TrimSpace(input.OriginalIntentText) == "" {
return DelegationBundle{}, ErrInvalidDelegation
}
delegationID, err := ids.New()
if err != nil {
return DelegationBundle{}, err
}
runID, err := ids.New()
if err != nil {
return DelegationBundle{}, err
}
millis := input.StartedAt.UnixMilli()
delegation := work.Delegation{
ID: work.DelegationID(delegationID),
GoalID: input.Goal.ID,
PlanID: input.Plan.ID,
PlanCandidateID: input.Candidate.ID,
CapabilityRequirementID: input.Requirement.ID,
CapabilityKind: input.Requirement.CapabilityKind,
SelectedImplementationID: input.Implementation.ID,
SelectedImplementationRev: input.Implementation.Revision,
SelectedImplementationKind: input.Implementation.Kind,
Protocol: protocolForImplementation(input.Implementation),
SourceIntentID: input.Goal.SourceIntentID,
SourceUtteranceID: input.Goal.SourceUtteranceID,
ConversationID: input.ConversationID,
ProjectID: input.Goal.ProjectID,
ProjectDisplayName: input.Goal.ProjectDisplayName,
DesiredOutcome: input.Goal.DesiredOutcome,
ConstraintSummary: nonEmpty(input.Goal.Constraints, "no additional constraints"),
VerificationSummary: nonEmpty(input.VerificationSummary, "verify outcome through tests, repository state, and explicit evidence"),
ContextSummary: buildContextSummary(input),
ContextRefs: append([]string{}, input.ContextRefs...),
State: work.DelegationRunning,
LatestRunID: work.AgentRunID(runID),
CreatedAtUnixMillis: millis,
UpdatedAtUnixMillis: millis,
}
run := work.AgentRun{
ID: work.AgentRunID(runID),
DelegationID: delegation.ID,
ImplementationID: input.Implementation.ID,
ImplementationRevision: input.Implementation.Revision,
Protocol: delegation.Protocol,
State: work.AgentRunStarted,
DerivedInstructionSummary: summarizeInstruction(input.DerivedInstruction),
StartedAtUnixMillis: millis,
UpdatedAtUnixMillis: millis,
}
if err := ValidateDelegation(delegation); err != nil {
return DelegationBundle{}, err
}
if err := ValidateAgentRun(run); err != nil {
return DelegationBundle{}, err
}
return DelegationBundle{Delegation: delegation, Run: run}, nil
}
func ValidateDelegation(value work.Delegation) error {
if value.ID == "" || value.GoalID == "" || value.PlanID == "" || value.PlanCandidateID == "" ||
value.CapabilityRequirementID == "" || value.CapabilityKind == "" || value.SelectedImplementationID == "" ||
value.SelectedImplementationRev < 1 || value.SelectedImplementationKind != capability.ImplementationAgent ||
value.Protocol == "" || value.SourceIntentID == "" || value.SourceUtteranceID == "" ||
strings.TrimSpace(value.DesiredOutcome) == "" || value.State == "" || value.CreatedAtUnixMillis < 1 ||
value.UpdatedAtUnixMillis < value.CreatedAtUnixMillis {
return ErrInvalidDelegation
}
return nil
}
func ValidateAgentRun(value work.AgentRun) error {
if value.ID == "" || value.DelegationID == "" || value.ImplementationID == "" || value.ImplementationRevision < 1 ||
value.Protocol == "" || value.State == "" || value.StartedAtUnixMillis < 1 || value.UpdatedAtUnixMillis < value.StartedAtUnixMillis {
return ErrInvalidAgentRun
}
return nil
}
func CheckpointRun(run work.AgentRun, blocker work.AgentBlockerClass, completed, remaining, tests, branch, commit, next string, refs []work.EvidenceRef, now time.Time) (work.AgentRun, work.AgentCheckpoint, error) {
if err := ValidateAgentRun(run); err != nil || now.IsZero() {
return work.AgentRun{}, work.AgentCheckpoint{}, ErrInvalidAgentRun
}
checkpointID, err := ids.New()
if err != nil {
return work.AgentRun{}, work.AgentCheckpoint{}, err
}
state := work.AgentRunCheckpointed
switch blocker {
case work.AgentBlockerExecutionWindow:
state = work.AgentRunExecutionWindowExhausted
case work.AgentBlockerHumanDecisionRequired, work.AgentBlockerMissingExternalCredential, work.AgentBlockerArchitectureDecision, work.AgentBlockerSecurityConflict:
state = work.AgentRunBlocked
case work.AgentBlockerTechnicalFailure:
state = work.AgentRunFailed
case work.AgentBlockerNone:
state = work.AgentRunCheckpointed
default:
return work.AgentRun{}, work.AgentCheckpoint{}, ErrInvalidAgentCheckpoint
}
run.State = state
run.UpdatedAtUnixMillis = now.UnixMilli()
checkpoint := work.AgentCheckpoint{
ID: work.AgentCheckpointID(checkpointID),
DelegationID: run.DelegationID,
RunID: run.ID,
State: state,
BlockerClass: blocker,
CompletedSummary: strings.TrimSpace(completed),
RemainingSummary: strings.TrimSpace(remaining),
TestSummary: strings.TrimSpace(tests),
BranchName: strings.TrimSpace(branch),
CommitHash: strings.TrimSpace(commit),
NextStep: strings.TrimSpace(next),
ArtifactRefs: append([]work.EvidenceRef{}, refs...),
RecordedAtUnixMillis: now.UnixMilli(),
}
if err := ValidateAgentCheckpoint(checkpoint); err != nil {
return work.AgentRun{}, work.AgentCheckpoint{}, err
}
return run, checkpoint, nil
}
func ValidateAgentCheckpoint(value work.AgentCheckpoint) error {
if value.ID == "" || value.DelegationID == "" || value.RunID == "" || value.State == "" || value.BlockerClass == "" || value.RecordedAtUnixMillis < 1 {
return ErrInvalidAgentCheckpoint
}
return nil
}
func CompleteRun(run work.AgentRun, summary, outcomeRef, verification string, refs []work.EvidenceRef, now time.Time) (work.AgentRun, work.AgentResult, error) {
if err := ValidateAgentRun(run); err != nil || now.IsZero() || strings.TrimSpace(summary) == "" {
return work.AgentRun{}, work.AgentResult{}, ErrInvalidAgentResult
}
resultID, err := ids.New()
if err != nil {
return work.AgentRun{}, work.AgentResult{}, err
}
run.State = work.AgentRunCompleted
run.UpdatedAtUnixMillis = now.UnixMilli()
run.CompletedAtUnixMillis = now.UnixMilli()
result := work.AgentResult{
ID: work.AgentResultID(resultID),
DelegationID: run.DelegationID,
RunID: run.ID,
State: work.AgentRunCompleted,
Summary: strings.TrimSpace(summary),
OutcomeRef: strings.TrimSpace(outcomeRef),
VerificationRequired: true,
VerificationSummary: nonEmpty(verification, "verify result before higher-level work completion"),
ArtifactRefs: append([]work.EvidenceRef{}, refs...),
RecordedAtUnixMillis: now.UnixMilli(),
}
if err := ValidateAgentResult(result); err != nil {
return work.AgentRun{}, work.AgentResult{}, err
}
return run, result, nil
}
func ValidateAgentResult(value work.AgentResult) error {
if value.ID == "" || value.DelegationID == "" || value.RunID == "" || value.State == "" ||
strings.TrimSpace(value.Summary) == "" || value.RecordedAtUnixMillis < 1 {
return ErrInvalidAgentResult
}
return nil
}
func ResumeDelegationRun(delegation work.Delegation, previous work.AgentRun, checkpoint work.AgentCheckpoint, now time.Time) (work.Delegation, work.AgentRun, error) {
if err := ValidateDelegation(delegation); err != nil {
return work.Delegation{}, work.AgentRun{}, ErrInvalidAgentRun
}
if err := ValidateAgentRun(previous); err != nil {
return work.Delegation{}, work.AgentRun{}, ErrInvalidAgentRun
}
if err := ValidateAgentCheckpoint(checkpoint); err != nil || now.IsZero() {
return work.Delegation{}, work.AgentRun{}, ErrInvalidAgentRun
}
if delegation.ID != previous.DelegationID || checkpoint.RunID != previous.ID {
return work.Delegation{}, work.AgentRun{}, ErrInvalidAgentRun
}
if previous.State != work.AgentRunExecutionWindowExhausted && previous.State != work.AgentRunBlocked && previous.State != work.AgentRunCheckpointed {
return work.Delegation{}, work.AgentRun{}, ErrInvalidAgentRun
}
runID, err := ids.New()
if err != nil {
return work.Delegation{}, work.AgentRun{}, err
}
delegation.State = work.DelegationRunning
delegation.UpdatedAtUnixMillis = now.UnixMilli()
delegation.LatestRunID = work.AgentRunID(runID)
run := work.AgentRun{
ID: work.AgentRunID(runID),
DelegationID: delegation.ID,
ImplementationID: previous.ImplementationID,
ImplementationRevision: previous.ImplementationRevision,
Protocol: previous.Protocol,
State: work.AgentRunStarted,
DerivedInstructionSummary: summarizeInstruction(checkpoint.NextStep),
StartedAtUnixMillis: now.UnixMilli(),
UpdatedAtUnixMillis: now.UnixMilli(),
}
if err := ValidateAgentRun(run); err != nil {
return work.Delegation{}, work.AgentRun{}, err
}
return delegation, run, nil
}
func VerifyDelegationResult(delegation work.Delegation, run work.AgentRun, result work.AgentResult, verified bool, summary string, refs []work.EvidenceRef, now time.Time) (work.Delegation, work.DelegationVerification, error) {
if err := ValidateDelegation(delegation); err != nil {
return work.Delegation{}, work.DelegationVerification{}, ErrInvalidDelegationVerification
}
if err := ValidateAgentRun(run); err != nil {
return work.Delegation{}, work.DelegationVerification{}, ErrInvalidDelegationVerification
}
if err := ValidateAgentResult(result); err != nil || now.IsZero() || strings.TrimSpace(summary) == "" {
return work.Delegation{}, work.DelegationVerification{}, ErrInvalidDelegationVerification
}
verificationID, err := ids.New()
if err != nil {
return work.Delegation{}, work.DelegationVerification{}, err
}
if verified {
delegation.State = work.DelegationCompleted
} else {
delegation.State = work.DelegationFailed
}
delegation.UpdatedAtUnixMillis = now.UnixMilli()
verification := work.DelegationVerification{
ID: work.DelegationVerificationID(verificationID),
DelegationID: delegation.ID,
RunID: run.ID,
ResultID: result.ID,
Verified: verified,
Summary: strings.TrimSpace(summary),
EvidenceRefs: append([]work.EvidenceRef{}, refs...),
RecordedAtUnixMillis: now.UnixMilli(),
}
if err := ValidateDelegationVerification(verification); err != nil {
return work.Delegation{}, work.DelegationVerification{}, err
}
return delegation, verification, nil
}
func ValidateDelegationVerification(value work.DelegationVerification) error {
if value.ID == "" || value.DelegationID == "" || value.RunID == "" || value.ResultID == "" || strings.TrimSpace(value.Summary) == "" || value.RecordedAtUnixMillis < 1 {
return ErrInvalidDelegationVerification
}
return nil
}
func protocolForImplementation(value capability.CapabilityImplementation) work.AgentExecutionProtocol {
if strings.HasPrefix(string(value.TargetRef), "codex://") {
return work.AgentProtocolCodexBridgeV1
}
return work.AgentProtocolCodexBridgeV1
}
func buildContextSummary(input DelegationRequest) string {
parts := []string{}
if input.Goal.ProjectDisplayName != "" {
parts = append(parts, "project="+input.Goal.ProjectDisplayName)
}
parts = append(parts, "human_intent="+strings.TrimSpace(input.OriginalIntentText))
if text := strings.TrimSpace(input.ContextSummary); text != "" {
parts = append(parts, "added_context="+text)
}
return strings.Join(parts, "; ")
}
func summarizeInstruction(value string) string {
value = strings.TrimSpace(value)
if value == "" {
return "derived execution context prepared from canonical intent, project context, and verification requirements"
}
if len(value) > 500 {
return value[:500]
}
return value
}
func nonEmpty(value, fallback string) string {
if strings.TrimSpace(value) == "" {
return fallback
}
return strings.TrimSpace(value)
}