package domain import ( "testing" "time" "git.cin.su/m/Assistant/contracts/work" ) func TestGovernedSelfDevelopmentRequiresIndependentVerifierBeforeCanary(t *testing.T) { gate := work.DevelopmentGate{ID: "dev-1", Stage: work.DevelopmentEvidenceCollected, EvidenceRefs: []string{"obs-1"}, ProposalRef: "proposal-1", TaskPacketRef: "task-1", WorktreeRef: "worktree-1", ProducerRunRefs: []work.AgentRunID{"producer"}, VerifierRunRefs: []work.AgentRunID{"verifier"}, VerificationEvidence: "verify-1", CanaryEvidence: "canary-1", PromotionRef: "promotion-1"} for _, stage := range []work.DevelopmentStage{work.DevelopmentProposalCreated, work.DevelopmentTaskAdmitted, work.DevelopmentIsolated, work.DevelopmentVerified, work.DevelopmentCanary, work.DevelopmentPromoted} { var err error gate, err = AdvanceDevelopmentGate(gate, stage) if err != nil { t.Fatalf("stage %s: %v", stage, err) } } if _, err := AdvanceDevelopmentGate(gate, work.DevelopmentRolledBack); err == nil { t.Fatal("promoted gate must be terminal") } } func TestBuildExtensionProposalRequiresRepeatedEvidenceAndRetainsLineage(t *testing.T) { proposal, err := BuildExtensionProposal([]work.ExtensionEvidence{ {Ref: "reflection-1", SignalKey: "send-email-gap"}, {Ref: "reflection-2", SignalKey: "send-email-gap"}, {Ref: "reflection-2", SignalKey: "send-email-gap"}, }, work.ExtensionProposalRequest{ ID: "proposal-1", DesiredOutcome: "connect a reviewed email capability", SmallestChangeLayer: "capability-adapter", AffectedOwners: []string{"capability", "commit"}, AffectedContracts: []string{"CapabilityImplementation@v1"}, RiskTier: "D", EvaluationPlan: []string{"fake transport", "adversarial corpus"}, Alternatives: []string{"keep capability gap"}, RollbackPlan: "restore previous implementation reference", Assumptions: []string{"human promotion required"}, CreatedAt: time.UnixMilli(42), }) if err != nil { t.Fatal(err) } if proposal.Stage != work.ExtensionProposalProposed || len(proposal.EvidenceRefs) != 2 || len(proposal.DeduplicatedSignalKeys) != 1 || proposal.CreatedAtUnixMillis != 42 { t.Fatalf("unexpected proposal: %+v", proposal) } } func TestBuildExtensionProposalRejectsSingleFailureAndIncompleteGovernance(t *testing.T) { request := work.ExtensionProposalRequest{ID: "proposal-1", DesiredOutcome: "x", SmallestChangeLayer: "skill", AffectedOwners: []string{"capability"}, AffectedContracts: []string{"Skill@v1"}, RiskTier: "B", EvaluationPlan: []string{"test"}, Alternatives: []string{"keep current behavior"}, RollbackPlan: "disable", Assumptions: []string{"human review"}, CreatedAt: time.UnixMilli(42)} if _, err := BuildExtensionProposal([]work.ExtensionEvidence{{Ref: "failure-1", SignalKey: "same"}}, request); err != ErrInsufficientExtensionEvidence { t.Fatalf("single failure must be rejected, got %v", err) } request.Assumptions = nil if _, err := BuildExtensionProposal([]work.ExtensionEvidence{{Ref: "failure-1", SignalKey: "same"}, {Ref: "failure-2", SignalKey: "same"}}, request); err != ErrInvalidExtensionProposal { t.Fatalf("missing assumptions must be rejected, got %v", err) } } func TestBuildDevelopmentScaffoldFailsClosedForProtectedScope(t *testing.T) { base := work.DevelopmentScaffoldRequest{ID: "scaffold-1", ProposalRef: "proposal-1", BaseRepoRevision: "abc123", WorktreeRef: "worktree-1", TaskIntent: "add reviewed adapter", Modules: []string{"capability"}, AllowedPaths: []string{"modules/capability/**"}, ForbiddenPaths: []string{"security/**"}, ProtectedPaths: []string{"architecture/**", "deploy/**"}, RequiredTests: []string{"go test ./..."}, ArtifactLineageRefs: []string{"proposal-1"}, ProtectedMainAccess: "DENIED", ProductionAccess: "DENIED", SecretAccess: "DENIED", CreatedAt: time.UnixMilli(1)} scaffold, err := BuildDevelopmentScaffold(base) if err != nil || scaffold.Stage != work.DevelopmentScaffoldSandboxed { t.Fatalf("valid scaffold rejected: %+v %v", scaffold, err) } base.AllowedPaths = []string{"deploy/docker-compose.prod.yml"} if _, err := BuildDevelopmentScaffold(base); err != ErrInvalidDevelopmentScaffold { t.Fatalf("protected path must fail closed, got %v", err) } base.AllowedPaths = []string{"modules/capability/../security"} if _, err := BuildDevelopmentScaffold(base); err != ErrInvalidDevelopmentScaffold { t.Fatalf("traversal path must fail closed, got %v", err) } } func TestGovernedSelfDevelopmentRejectsSameProducerAndVerifier(t *testing.T) { gate := work.DevelopmentGate{ID: "dev-1", Stage: work.DevelopmentIsolated, EvidenceRefs: []string{"obs-1"}, ProducerRunRefs: []work.AgentRunID{"same"}, VerifierRunRefs: []work.AgentRunID{"same"}, VerificationEvidence: "verify-1"} if _, err := AdvanceDevelopmentGate(gate, work.DevelopmentVerified); err == nil { t.Fatal("same run cannot verify its own output") } }