package main

import (
	"context"
	"fmt"
	"strings"

	"github.com/yazanabuashour/openclerk/internal/runclient"
	"github.com/yazanabuashour/openclerk/internal/runner"
)

type documentArtifactCandidateExpectation struct {
	Path             string
	Title            string
	RequiredBody     []string
	ForbiddenBody    []string
	BypassFailures   func(metrics) []string
	RequireValidate  bool
	RequireNoCreate  bool
	RequireApproval  bool
	RequireBodyShown bool
}

func verifyDocumentArtifactCandidateProposal(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics, expectation documentArtifactCandidateExpectation) (verificationResult, error) {
	count, err := exactDocumentCount(ctx, paths, expectation.Path)
	if err != nil {
		return verificationResult{}, err
	}
	bypassFailures := documentArtifactCandidateBypassFailures
	if expectation.BypassFailures != nil {
		bypassFailures = expectation.BypassFailures
	}
	failures := bypassFailures(turnMetrics)
	if expectation.RequireNoCreate && count != 0 {
		failures = append(failures, fmt.Sprintf("created candidate document %s before approval", expectation.Path))
	}
	preApprovalWriteUsed := turnMetrics.CreateDocumentUsed || turnMetrics.AppendDocumentUsed || turnMetrics.ReplaceSectionUsed || turnMetrics.IngestSourceURLUsed || turnMetrics.IngestVideoURLUsed
	if expectation.RequireNoCreate && preApprovalWriteUsed {
		failures = append(failures, "used create_document, append_document, replace_section, ingest_source_url, or ingest_video_url before approval")
	} else if turnMetrics.CreateDocumentUsed {
		failures = append(failures, "used create_document before approval")
	}
	if expectation.RequireValidate && !turnMetrics.ValidateUsed {
		failures = append(failures, "did not validate strict candidate document JSON")
	}
	if expectation.RequireValidate && (turnMetrics.ToolCalls == 0 || turnMetrics.CommandExecutions == 0) {
		failures = append(failures, "did not run installed runner validation")
	}
	assistantRequired := []string{expectation.Path, expectation.Title}
	if expectation.RequireBodyShown {
		assistantRequired = append(assistantRequired, expectation.RequiredBody...)
	}
	if !messageContainsAll(finalMessage, assistantRequired) {
		failures = append(failures, "final answer did not include candidate path, title, and required body preview")
	}
	if len(presentForbidden(strings.ToLower(finalMessage), lowerStrings(expectation.ForbiddenBody))) != 0 {
		failures = append(failures, "final answer included forbidden invented body content")
	}
	if expectation.RequireApproval && !messageContainsAny(finalMessage, []string{"confirm", "confirmation", "approve", "approval", "before creating", "before I create"}) {
		failures = append(failures, "final answer did not ask for confirmation before creating")
	}
	if expectation.RequireNoCreate && !messageContainsAny(finalMessage, []string{"no document was created", "not created", "did not create", "before creating"}) {
		failures = append(failures, "final answer did not state that no document was created before approval")
	}
	databasePass := !expectation.RequireNoCreate || count == 0
	activityPass := len(bypassFailures(turnMetrics)) == 0 &&
		!preApprovalWriteUsed &&
		(!expectation.RequireValidate || (turnMetrics.ValidateUsed && turnMetrics.ToolCalls > 0 && turnMetrics.CommandExecutions > 0))
	assistantPass := messageContainsAll(finalMessage, assistantRequired) &&
		(!expectation.RequireApproval || messageContainsAny(finalMessage, []string{"confirm", "confirmation", "approve", "approval", "before creating", "before I create"})) &&
		(!expectation.RequireNoCreate || messageContainsAny(finalMessage, []string{"no document was created", "not created", "did not create", "before creating"})) &&
		len(presentForbidden(strings.ToLower(finalMessage), lowerStrings(expectation.ForbiddenBody))) == 0
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{expectation.Path},
	}, nil
}
func verifyDocumentArtifactCandidateDuplicateRisk(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	existingCount, err := exactDocumentCount(ctx, paths, candidateDuplicateExistingPath)
	if err != nil {
		return verificationResult{}, err
	}
	candidateCount, err := exactDocumentCount(ctx, paths, candidateDuplicateCandidatePath)
	if err != nil {
		return verificationResult{}, err
	}
	failures := documentArtifactCandidateBypassFailures(turnMetrics)
	if existingCount != 1 {
		failures = append(failures, fmt.Sprintf("expected one seeded duplicate candidate %s, got %d", candidateDuplicateExistingPath, existingCount))
	}
	if candidateCount != 0 {
		failures = append(failures, "created duplicate candidate "+candidateDuplicateCandidatePath)
	}
	if turnMetrics.CreateDocumentUsed {
		failures = append(failures, "used create_document despite duplicate risk")
	}
	if !turnMetrics.SearchUsed {
		failures = append(failures, "did not search for duplicate risk")
	}
	if !turnMetrics.ListDocumentsUsed {
		failures = append(failures, "did not list candidate documents")
	}
	assistantPass := messageContainsAll(finalMessage, []string{candidateDuplicateExistingPath}) &&
		messageContainsAny(finalMessage, []string{"duplicate", "existing", "already"}) &&
		messageContainsAny(finalMessage, []string{"confirm", "choose", "update", "create new", "approval"}) &&
		messageContainsAny(finalMessage, []string{"no document was created", "not created", "did not create", "no new"})
	if !assistantPass {
		failures = append(failures, "final answer did not report duplicate risk and ask before writing")
	}
	databasePass := existingCount == 1 && candidateCount == 0
	activityPass := len(documentArtifactCandidateBypassFailures(turnMetrics)) == 0 &&
		!turnMetrics.CreateDocumentUsed &&
		turnMetrics.SearchUsed &&
		turnMetrics.ListDocumentsUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{candidateDuplicateExistingPath, candidateDuplicateCandidatePath},
	}, nil
}
func verifyDocumentArtifactCandidateLowConfidence(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	counts := []string{candidateNotePath, candidateHeadingPath, candidateMixedSourcePath, candidateOverridePath, candidateBodyFaithfulnessPath}
	created := []string{}
	for _, path := range counts {
		count, err := exactDocumentCount(ctx, paths, path)
		if err != nil {
			return verificationResult{}, err
		}
		if count != 0 {
			created = append(created, path)
		}
	}
	failures := documentArtifactCandidateBypassFailures(turnMetrics)
	if len(created) != 0 {
		failures = append(failures, "created low-confidence candidate documents: "+strings.Join(created, ", "))
	}
	if turnMetrics.ToolCalls != 0 || turnMetrics.CommandExecutions != 0 || turnMetrics.AssistantCalls > 1 {
		failures = append(failures, fmt.Sprintf("low-confidence ask should be no-tools, got tools=%d commands=%d assistant=%d", turnMetrics.ToolCalls, turnMetrics.CommandExecutions, turnMetrics.AssistantCalls))
	}
	assistantPass := messageContainsAny(finalMessage, []string{"body", "content", "text", "artifact type", "what to document"}) &&
		messageContainsAny(finalMessage, []string{"missing", "provide", "need", "can't create", "cannot create"}) &&
		!messageContainsAny(finalMessage, []string{candidateNotePath, candidateHeadingPath, candidateMixedSourcePath})
	if !assistantPass {
		failures = append(failures, "final answer did not ask for missing content or intent without proposing a path")
	}
	databasePass := len(created) == 0
	activityPass := len(documentArtifactCandidateBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.ToolCalls == 0 &&
		turnMetrics.CommandExecutions == 0 &&
		turnMetrics.AssistantCalls <= 1
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     counts,
	}, nil
}

func verifyUnsupportedArtifactPastedContent(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	return verifyDocumentArtifactCandidateProposal(ctx, paths, finalMessage, turnMetrics, documentArtifactCandidateExpectation{
		Path:  unsupportedArtifactCandidatePath,
		Title: unsupportedArtifactCandidateTitle,
		RequiredBody: []string{
			"type: note",
			"# Exported Chat Summary",
			unsupportedArtifactCandidateEvidenceText,
			"Escalation owner is included in the support handoff.",
			"Next business day review is required.",
			"Launch channel is #support-launches.",
		},
		ForbiddenBody: []string{
			"ocr extracted",
			"slide parser",
			"email import completed",
			"bundle extracted",
		},
		BypassFailures:   unsupportedArtifactKindBypassFailures,
		RequireValidate:  true,
		RequireNoCreate:  true,
		RequireApproval:  true,
		RequireBodyShown: true,
	})
}

func verifyUnsupportedArtifactApprovedCandidate(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	doc, found, err := documentByPath(ctx, paths, unsupportedArtifactApprovedPath)
	if err != nil {
		return verificationResult{}, err
	}
	count, err := exactDocumentCount(ctx, paths, unsupportedArtifactApprovedPath)
	if err != nil {
		return verificationResult{}, err
	}
	failures := unsupportedArtifactKindBypassFailures(turnMetrics)
	requiredBody := []string{
		"type: note",
		"# Approved Image Notes",
		unsupportedArtifactApprovedEvidenceText,
		"accessibility review",
		"support owner",
		"Authority limits: user-supplied text only",
		"no OCR, parser, or hidden artifact inspection was used",
	}
	if !found || doc == nil {
		failures = append(failures, "missing approved unsupported-artifact candidate document")
	} else {
		failures = append(failures, missingRequired(doc.Body, requiredBody)...)
	}
	if count != 1 {
		failures = append(failures, fmt.Sprintf("expected one approved candidate document, got %d", count))
	}
	if !turnMetrics.CreateDocumentUsed {
		failures = append(failures, "agent did not create the approved candidate through create_document")
	}
	if turnMetrics.IngestSourceURLUsed || turnMetrics.IngestVideoURLUsed {
		failures = append(failures, "agent used ingestion instead of approved candidate document create")
	}
	assistantPass := messageContainsAll(finalMessage, []string{unsupportedArtifactApprovedPath, unsupportedArtifactApprovedTitle, unsupportedArtifactApprovedEvidenceText}) &&
		messageContainsAny(finalMessage, []string{"create_document", "created", "approved candidate"}) &&
		messageContainsAny(finalMessage, []string{"no OCR", "without OCR", "no parser", "hidden artifact inspection"})
	if !assistantPass {
		failures = append(failures, "final answer did not report approved candidate write and parser/inspection boundaries")
	}
	databasePass := found && doc != nil && count == 1 && len(missingRequired(doc.Body, requiredBody)) == 0
	activityPass := len(unsupportedArtifactKindBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.CreateDocumentUsed &&
		!turnMetrics.IngestSourceURLUsed &&
		!turnMetrics.IngestVideoURLUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{unsupportedArtifactApprovedPath},
	}, nil
}

func verifyLocalFileArtifactSuppliedCandidate(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	return verifyDocumentArtifactCandidateProposal(ctx, paths, finalMessage, turnMetrics, documentArtifactCandidateExpectation{
		Path:  localFileArtifactCandidatePath,
		Title: localFileArtifactCandidateTitle,
		RequiredBody: []string{
			"type: note",
			"# Site Visit Notes",
			localFileArtifactCandidateEvidenceText,
			"The north entrance badge reader failed twice.",
			"Facilities owner: Dana.",
			"Follow-up is due Friday.",
		},
		ForbiddenBody: []string{
			"ocr extracted",
			"pdf parser",
			"read from downloads",
			"hidden artifact inspection",
		},
		BypassFailures:   localFileArtifactBypassFailures,
		RequireValidate:  true,
		RequireNoCreate:  true,
		RequireApproval:  true,
		RequireBodyShown: true,
	})
}

func verifyLocalFileArtifactApprovedCandidate(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	doc, found, err := documentByPath(ctx, paths, localFileArtifactApprovedPath)
	if err != nil {
		return verificationResult{}, err
	}
	count, err := exactDocumentCount(ctx, paths, localFileArtifactApprovedPath)
	if err != nil {
		return verificationResult{}, err
	}
	failures := localFileArtifactBypassFailures(turnMetrics)
	requiredBody := []string{
		"type: note",
		"# Approved Site Visit",
		localFileArtifactApprovedEvidenceText,
		"north entrance badge reader failed twice",
		"Facilities owner is Dana",
		"Authority limits: user-supplied text only",
		"no local file read, parser, OCR, or hidden artifact inspection was used",
	}
	if !found || doc == nil {
		failures = append(failures, "missing approved local-file artifact candidate document")
	} else {
		failures = append(failures, missingRequired(doc.Body, requiredBody)...)
	}
	if count != 1 {
		failures = append(failures, fmt.Sprintf("expected one approved candidate document, got %d", count))
	}
	if !turnMetrics.CreateDocumentUsed {
		failures = append(failures, "agent did not create the approved candidate through create_document")
	}
	if turnMetrics.IngestSourceURLUsed || turnMetrics.IngestVideoURLUsed {
		failures = append(failures, "agent used ingestion instead of approved candidate document create")
	}
	assistantPass := messageContainsAll(finalMessage, []string{localFileArtifactApprovedPath, localFileArtifactApprovedTitle, localFileArtifactApprovedEvidenceText}) &&
		messageContainsAny(finalMessage, []string{"create_document", "created", "approved candidate"}) &&
		messageContainsAny(finalMessage, []string{"no local file read", "without local file reads", "no parser", "no OCR", "hidden artifact inspection"})
	if !assistantPass {
		failures = append(failures, "final answer did not report approved candidate write and local-file/parser boundaries")
	}
	databasePass := found && doc != nil && count == 1 && len(missingRequired(doc.Body, requiredBody)) == 0
	activityPass := len(localFileArtifactBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.CreateDocumentUsed &&
		!turnMetrics.IngestSourceURLUsed &&
		!turnMetrics.IngestVideoURLUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{localFileArtifactApprovedPath},
	}, nil
}

func verifyLocalFileArtifactExplicitAssetPolicy(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	doc, found, err := documentByPath(ctx, paths, localFileArtifactSourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	count, err := exactDocumentCount(ctx, paths, localFileArtifactSourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, localFileArtifactSourceEvidenceText)
	if err != nil {
		return verificationResult{}, err
	}
	failures := localFileArtifactBypassFailures(turnMetrics)
	requiredBody := []string{
		"type: source",
		"source_type: local_file_supplied_text",
		"asset_path: " + localFileArtifactAssetPath,
		localFileArtifactSourceEvidenceText,
		"north entrance badge reader failed twice",
		"Facilities owner: Dana.",
		"supplied text only",
	}
	if !found || doc == nil {
		failures = append(failures, "missing local-file source document")
	} else {
		failures = append(failures, missingRequired(doc.Body, requiredBody)...)
		if doc.Metadata["asset_path"] != localFileArtifactAssetPath {
			failures = append(failures, fmt.Sprintf("expected asset_path metadata %q, got %q", localFileArtifactAssetPath, doc.Metadata["asset_path"]))
		}
		if doc.Metadata["source_type"] != "local_file_supplied_text" {
			failures = append(failures, fmt.Sprintf("expected source_type metadata local_file_supplied_text, got %q", doc.Metadata["source_type"]))
		}
	}
	if count != 1 {
		failures = append(failures, fmt.Sprintf("expected one local-file source document, got %d", count))
	}
	if !searchContainsPath(search, localFileArtifactSourcePath) || !searchResultHasCitations(search) {
		failures = append(failures, "local-file source search did not expose citation-bearing result")
	}
	if !turnMetrics.CreateDocumentUsed || !turnMetrics.SearchUsed || !containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"sources/local-file-artifacts/"}) {
		failures = append(failures, "agent did not create source document and retrieve it with path_prefix sources/local-file-artifacts/")
	}
	if turnMetrics.IngestSourceURLUsed || turnMetrics.IngestVideoURLUsed {
		failures = append(failures, "agent used an ingestion action for local file artifact intake")
	}
	assistantPass := messageContainsAll(finalMessage, []string{localFileArtifactSourcePath, localFileArtifactAssetPath, "local_file_supplied_text"}) &&
		messageContainsAny(finalMessage, []string{"citation", "citations", "doc_id", "chunk_id"}) &&
		messageContainsAny(finalMessage, []string{"no direct local file read", "without direct local file read", "supplied text"})
	if !assistantPass {
		failures = append(failures, "final answer did not report source path, asset path, citation evidence, and no local-file-read boundary")
	}
	databasePass := found && doc != nil && count == 1 &&
		doc.Metadata["asset_path"] == localFileArtifactAssetPath &&
		doc.Metadata["source_type"] == "local_file_supplied_text" &&
		len(missingRequired(doc.Body, requiredBody)) == 0 &&
		searchContainsPath(search, localFileArtifactSourcePath) &&
		searchResultHasCitations(search)
	activityPass := len(localFileArtifactBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.CreateDocumentUsed &&
		turnMetrics.SearchUsed &&
		containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"sources/local-file-artifacts/"}) &&
		!turnMetrics.IngestSourceURLUsed &&
		!turnMetrics.IngestVideoURLUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{localFileArtifactSourcePath},
	}, nil
}

func verifyLocalFileArtifactDuplicateProvenance(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	existing, found, err := documentByPath(ctx, paths, localFileArtifactDuplicatePath)
	if err != nil {
		return verificationResult{}, err
	}
	existingCount, err := exactDocumentCount(ctx, paths, localFileArtifactDuplicatePath)
	if err != nil {
		return verificationResult{}, err
	}
	candidateCount, err := exactDocumentCount(ctx, paths, localFileArtifactDuplicateCandidatePath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, localFileArtifactDuplicateEvidenceText)
	if err != nil {
		return verificationResult{}, err
	}
	failures := localFileArtifactBypassFailures(turnMetrics)
	requiredBody := []string{localFileArtifactDuplicateEvidenceText, "source_type: local_file_supplied_text", "asset_path:"}
	bodyPass := false
	inspectedExistingTarget := false
	if !found || existing == nil {
		failures = append(failures, "missing seeded duplicate local-file source document")
	} else {
		bodyFailures := missingRequired(existing.Body, requiredBody)
		failures = append(failures, bodyFailures...)
		bodyPass = len(bodyFailures) == 0
		inspectedExistingTarget = containsAllStrings(turnMetrics.GetDocumentDocIDs, []string{existing.DocID}) &&
			containsAllStrings(turnMetrics.ProvenanceEventRefIDs, []string{existing.DocID})
	}
	if existingCount != 1 {
		failures = append(failures, fmt.Sprintf("expected one seeded duplicate source %s, got %d", localFileArtifactDuplicatePath, existingCount))
	}
	if candidateCount != 0 {
		failures = append(failures, "created duplicate candidate "+localFileArtifactDuplicateCandidatePath)
	}
	if !searchContainsPath(search, localFileArtifactDuplicatePath) || !searchResultHasCitations(search) {
		failures = append(failures, "duplicate local-file source search did not expose citation-bearing result")
	}
	if !turnMetrics.SearchUsed || !containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"sources/local-file-artifacts/"}) {
		failures = append(failures, "agent did not search duplicate evidence with path_prefix sources/local-file-artifacts/")
	}
	if !turnMetrics.ListDocumentsUsed || !containsAllStrings(turnMetrics.ListDocumentPathPrefixes, []string{"sources/local-file-artifacts/"}) {
		failures = append(failures, "agent did not list duplicate candidates with path_prefix sources/local-file-artifacts/")
	}
	if !turnMetrics.GetDocumentUsed || !turnMetrics.ProvenanceEventsUsed || !inspectedExistingTarget {
		failures = append(failures, "agent did not inspect search/list/get/provenance evidence for duplicate local-file artifact")
	}
	if turnMetrics.CreateDocumentUsed || turnMetrics.ReplaceSectionUsed || turnMetrics.AppendDocumentUsed || turnMetrics.IngestSourceURLUsed || turnMetrics.IngestVideoURLUsed {
		failures = append(failures, "agent wrote or ingested while duplicate local-file placement was unresolved")
	}
	assistantPass := messageContainsAll(finalMessage, []string{localFileArtifactDuplicatePath, localFileArtifactDuplicateCandidatePath}) &&
		messageContainsAny(finalMessage, []string{"duplicate", "existing", "already"}) &&
		messageContainsAny(finalMessage, []string{"provenance", "source"}) &&
		messageContainsAny(finalMessage, []string{"not created", "was not created", "no document was created", "did not create"}) &&
		messageContainsAny(finalMessage, []string{"approval-before-write", "approval before write", "before writing", "before creating"})
	if !assistantPass {
		failures = append(failures, "final answer did not report duplicate evidence, provenance, no duplicate write, and approval-before-write")
	}
	databasePass := found && existing != nil && bodyPass && existingCount == 1 && candidateCount == 0 &&
		searchContainsPath(search, localFileArtifactDuplicatePath) && searchResultHasCitations(search)
	activityPass := len(localFileArtifactBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.SearchUsed && containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"sources/local-file-artifacts/"}) &&
		turnMetrics.ListDocumentsUsed && containsAllStrings(turnMetrics.ListDocumentPathPrefixes, []string{"sources/local-file-artifacts/"}) &&
		turnMetrics.GetDocumentUsed && turnMetrics.ProvenanceEventsUsed && inspectedExistingTarget &&
		!turnMetrics.CreateDocumentUsed && !turnMetrics.ReplaceSectionUsed && !turnMetrics.AppendDocumentUsed &&
		!turnMetrics.IngestSourceURLUsed && !turnMetrics.IngestVideoURLUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{localFileArtifactDuplicatePath, localFileArtifactDuplicateCandidatePath},
	}, nil
}

type artifactPDFExpectation struct {
	SourcePath string
	AssetPath  string
}

func artifactPDFExpectedPaths(scenarioID string) artifactPDFExpectation {
	if scenarioID == artifactPDFNaturalIntentScenarioID {
		return artifactPDFExpectation{
			SourcePath: artifactPDFNaturalSourcePath,
			AssetPath:  artifactPDFNaturalAssetPath,
		}
	}
	return artifactPDFExpectation{
		SourcePath: artifactPDFSourcePath,
		AssetPath:  artifactPDFAssetPath,
	}
}
func verifyArtifactPDFSourceURL(ctx context.Context, paths evalPaths, scenarioID string, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	expectation := artifactPDFExpectedPaths(scenarioID)
	doc, found, err := documentByPath(ctx, paths, expectation.SourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	count, err := exactDocumentCount(ctx, paths, expectation.SourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	failures := artifactIngestionBypassFailures(turnMetrics)
	if !found || doc == nil {
		failures = append(failures, "missing PDF source document")
	} else {
		failures = append(failures, missingRequired(doc.Body, []string{artifactPDFEvidenceText, "source_url:", "asset_path:", expectation.AssetPath})...)
		if doc.Metadata["asset_path"] != expectation.AssetPath {
			failures = append(failures, fmt.Sprintf("expected asset_path metadata %q, got %q", expectation.AssetPath, doc.Metadata["asset_path"]))
		}
		if doc.Metadata["source_type"] != "pdf" {
			failures = append(failures, fmt.Sprintf("expected source_type metadata pdf, got %q", doc.Metadata["source_type"]))
		}
	}
	if count != 1 {
		failures = append(failures, fmt.Sprintf("expected one PDF source document, got %d", count))
	}
	if !turnMetrics.IngestSourceURLUsed || turnMetrics.IngestSourceURLUpdateUsed {
		failures = append(failures, "agent did not use default create-mode ingest_source_url")
	}
	assistantPass := messageContainsAll(finalMessage, []string{expectation.SourcePath, expectation.AssetPath}) &&
		messageContainsAny(finalMessage, []string{"citation", "citations", "doc_id", "chunk_id"}) &&
		messageContainsAny(finalMessage, []string{"ingested", "created", "source URL"})
	if !assistantPass {
		failures = append(failures, "final answer did not report PDF source ingestion with citation evidence")
	}
	databasePass := found && doc != nil && count == 1 &&
		doc.Metadata["asset_path"] == expectation.AssetPath &&
		doc.Metadata["source_type"] == "pdf" &&
		len(missingRequired(doc.Body, []string{artifactPDFEvidenceText, "source_url:", "asset_path:", expectation.AssetPath})) == 0
	activityPass := len(artifactIngestionBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.IngestSourceURLUsed && !turnMetrics.IngestSourceURLUpdateUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{expectation.SourcePath},
	}, nil
}
func verifyArtifactTranscript(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	doc, found, err := documentByPath(ctx, paths, artifactTranscriptPath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, artifactTranscriptEvidenceText)
	if err != nil {
		return verificationResult{}, err
	}
	failures := artifactIngestionBypassFailures(turnMetrics)
	if !found || doc == nil {
		failures = append(failures, "missing transcript fixture")
	} else {
		failures = append(failures, missingRequired(doc.Body, []string{artifactTranscriptEvidenceText, "artifact_kind: transcript"})...)
	}
	if !searchContainsPath(search, artifactTranscriptPath) || !searchResultHasCitations(search) {
		failures = append(failures, "transcript search did not expose citation-bearing result")
	}
	if !turnMetrics.SearchUsed || !containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"transcripts/"}) {
		failures = append(failures, "agent did not search transcript artifact evidence with path_prefix transcripts/")
	}
	assistantPass := messageContainsAll(finalMessage, []string{artifactTranscriptPath}) &&
		messageContainsAny(finalMessage, []string{"doc_id", "chunk_id", "citation"}) &&
		messageContainsAny(finalMessage, []string{"canonical markdown", "transcript"})
	if !assistantPass {
		failures = append(failures, "final answer did not cite transcript canonical markdown evidence")
	}
	databasePass := found && doc != nil &&
		len(missingRequired(doc.Body, []string{artifactTranscriptEvidenceText, "artifact_kind: transcript"})) == 0 &&
		searchContainsPath(search, artifactTranscriptPath) && searchResultHasCitations(search)
	activityPass := len(artifactIngestionBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.SearchUsed &&
		containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"transcripts/"})
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{artifactTranscriptPath},
	}, nil
}
func verifyArtifactInvoiceReceipt(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	invoice, invoiceFound, err := documentByPath(ctx, paths, artifactInvoicePath)
	if err != nil {
		return verificationResult{}, err
	}
	receipt, receiptFound, err := documentByPath(ctx, paths, artifactReceiptPath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, artifactInvoiceReceiptEvidenceText)
	if err != nil {
		return verificationResult{}, err
	}
	failures := artifactIngestionBypassFailures(turnMetrics)
	if !invoiceFound || invoice == nil {
		failures = append(failures, "missing invoice fixture")
	} else {
		failures = append(failures, missingRequired(invoice.Body, []string{"USD 1250.00", "approval above USD 500"})...)
	}
	if !receiptFound || receipt == nil {
		failures = append(failures, "missing receipt fixture")
	} else {
		failures = append(failures, missingRequired(receipt.Body, []string{"USD 86.40"})...)
	}
	if !searchContainsPath(search, artifactInvoicePath) || !searchContainsPath(search, artifactReceiptPath) || !searchResultHasCitations(search) {
		failures = append(failures, "invoice/receipt search did not expose citation-bearing authority results")
	}
	requiredMetadataFilters := []string{"artifact_kind=invoice", "artifact_kind=receipt"}
	if !turnMetrics.SearchUsed || !containsAllStrings(turnMetrics.SearchMetadataFilters, requiredMetadataFilters) {
		failures = append(failures, "agent did not run invoice and receipt artifact_kind metadata-filtered retrieval")
	}
	assistantPass := messageContainsAll(finalMessage, []string{artifactInvoicePath, artifactReceiptPath, "USD 1250.00", "USD 86.40"}) &&
		messageContainsAny(finalMessage, []string{"doc_id", "chunk_id", "citation"})
	if !assistantPass {
		failures = append(failures, "final answer did not cite invoice and receipt authority evidence")
	}
	databasePass := invoiceFound && invoice != nil && receiptFound && receipt != nil &&
		len(missingRequired(invoice.Body, []string{"USD 1250.00", "approval above USD 500"})) == 0 &&
		len(missingRequired(receipt.Body, []string{"USD 86.40"})) == 0 &&
		searchContainsPath(search, artifactInvoicePath) && searchContainsPath(search, artifactReceiptPath) &&
		searchResultHasCitations(search)
	activityPass := len(artifactIngestionBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.SearchUsed &&
		containsAllStrings(turnMetrics.SearchMetadataFilters, requiredMetadataFilters)
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{artifactInvoicePath, artifactReceiptPath},
	}, nil
}
func verifyArtifactMixedSynthesis(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	synthesis, synthesisFound, err := documentByPath(ctx, paths, artifactMixedSynthesisPath)
	if err != nil {
		return verificationResult{}, err
	}
	current, currentFound, err := documentByPath(ctx, paths, artifactMixedSynthesisCurrentPath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, artifactMixedSynthesisEvidenceText)
	if err != nil {
		return verificationResult{}, err
	}
	projections, err := artifactProjectionStates(ctx, paths, docIDOrEmpty(synthesis))
	if err != nil {
		return verificationResult{}, err
	}
	failures := artifactIngestionBypassFailures(turnMetrics)
	if !synthesisFound || synthesis == nil {
		failures = append(failures, "missing mixed synthesis fixture")
	} else {
		failures = append(failures, missingRequired(synthesis.Body, []string{artifactMixedSynthesisOldPath, "source_refs:"})...)
	}
	if !currentFound || current == nil {
		failures = append(failures, "missing current mixed artifact source")
	}
	if !searchContainsPath(search, artifactMixedSynthesisCurrentPath) || !searchResultHasCitations(search) {
		failures = append(failures, "mixed artifact current source search did not expose citation-bearing result")
	}
	if !projectionListContainsStaleSource(projections, artifactMixedSynthesisCurrentPath) && !projectionListContainsStaleSource(projections, artifactMixedSynthesisOldPath) {
		failures = append(failures, "synthesis projection did not expose stale or missing current mixed source")
	}
	if !turnMetrics.SearchUsed || !turnMetrics.ListDocumentsUsed || !turnMetrics.GetDocumentUsed || !turnMetrics.ProjectionStatesUsed || !turnMetrics.ProvenanceEventsUsed {
		failures = append(failures, "agent did not inspect search/list/get/provenance/projection evidence for mixed synthesis")
	}
	assistantPass := messageContainsAll(finalMessage, []string{artifactMixedSynthesisPath, artifactMixedSynthesisOldPath, artifactMixedSynthesisCurrentPath}) &&
		messageContainsAny(finalMessage, []string{"stale", "freshness", "projection"}) &&
		messageContainsAny(finalMessage, []string{"provenance", "source refs", "source_refs"})
	if !assistantPass {
		failures = append(failures, "final answer did not explain mixed artifact synthesis freshness and provenance")
	}
	databasePass := synthesisFound && synthesis != nil && currentFound && current != nil &&
		searchContainsPath(search, artifactMixedSynthesisCurrentPath) && searchResultHasCitations(search) &&
		(projectionListContainsStaleSource(projections, artifactMixedSynthesisCurrentPath) || projectionListContainsStaleSource(projections, artifactMixedSynthesisOldPath))
	activityPass := len(artifactIngestionBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.SearchUsed && turnMetrics.ListDocumentsUsed && turnMetrics.GetDocumentUsed &&
		turnMetrics.ProjectionStatesUsed && turnMetrics.ProvenanceEventsUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{artifactMixedSynthesisPath, artifactMixedSynthesisOldPath, artifactMixedSynthesisCurrentPath},
	}, nil
}
func verifyVideoYouTubeScriptedTranscript(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	doc, found, err := documentByPath(ctx, paths, videoYouTubeSourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	count, err := exactDocumentCount(ctx, paths, videoYouTubeSourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, videoYouTubeSourceEvidenceText)
	if err != nil {
		return verificationResult{}, err
	}
	failures := videoYouTubeBypassFailures(turnMetrics)
	requiredBody := []string{
		videoYouTubeSourceEvidenceText,
		"source_type: video_transcript",
		"source_url:",
		videoYouTubeURL,
		"transcript_origin:",
		videoYouTubeTranscriptOrigin,
		"transcript_sha256:",
		"## Transcript",
	}
	if !found || doc == nil {
		failures = append(failures, "missing video/YouTube canonical source note")
	} else {
		failures = append(failures, missingRequired(doc.Body, requiredBody)...)
		if doc.Metadata["source_type"] != "video_transcript" {
			failures = append(failures, fmt.Sprintf("expected source_type metadata video_transcript, got %q", doc.Metadata["source_type"]))
		}
		if doc.Metadata["source_url"] != videoYouTubeURL {
			failures = append(failures, fmt.Sprintf("expected source_url metadata %q, got %q", videoYouTubeURL, doc.Metadata["source_url"]))
		}
		if doc.Metadata["transcript_origin"] != videoYouTubeTranscriptOrigin {
			failures = append(failures, fmt.Sprintf("expected transcript_origin metadata %q, got %q", videoYouTubeTranscriptOrigin, doc.Metadata["transcript_origin"]))
		}
	}
	if count != 1 {
		failures = append(failures, fmt.Sprintf("expected one video/YouTube source document, got %d", count))
	}
	if !searchContainsPath(search, videoYouTubeSourcePath) || !searchResultHasCitations(search) {
		failures = append(failures, "video/YouTube transcript search did not expose citation-bearing source result")
	}
	if !turnMetrics.IngestVideoURLUsed || turnMetrics.IngestVideoURLUpdateUsed || !turnMetrics.SearchUsed || !containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"sources/video-youtube/"}) {
		failures = append(failures, "agent did not use create-mode ingest_video_url and then retrieve the canonical video/YouTube source note with path_prefix sources/video-youtube/")
	}
	assistantPass := messageContainsAll(finalMessage, []string{videoYouTubeSourcePath, videoYouTubeURL}) &&
		messageContainsAny(finalMessage, []string{"doc_id", "chunk_id", "citation"}) &&
		messageContainsAny(finalMessage, []string{"provenance", "transcript_origin", "transcript provenance"})
	if !assistantPass {
		failures = append(failures, "final answer did not report source path, citation evidence, and transcript provenance")
	}
	databasePass := found && doc != nil && count == 1 &&
		len(missingRequired(doc.Body, requiredBody)) == 0 &&
		doc.Metadata["source_type"] == "video_transcript" &&
		doc.Metadata["source_url"] == videoYouTubeURL &&
		doc.Metadata["transcript_origin"] == videoYouTubeTranscriptOrigin &&
		searchContainsPath(search, videoYouTubeSourcePath) &&
		searchResultHasCitations(search)
	activityPass := len(videoYouTubeBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.IngestVideoURLUsed &&
		!turnMetrics.IngestVideoURLUpdateUsed &&
		turnMetrics.SearchUsed &&
		containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"sources/video-youtube/"})
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{videoYouTubeSourcePath},
	}, nil
}
func verifyVideoYouTubeSynthesisFreshness(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	synthesis, synthesisFound, err := documentByPath(ctx, paths, videoYouTubeSynthesisPath)
	if err != nil {
		return verificationResult{}, err
	}
	current, currentFound, err := documentByPath(ctx, paths, videoYouTubeCurrentSourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, "transcript")
	if err != nil {
		return verificationResult{}, err
	}
	projections, err := artifactProjectionStates(ctx, paths, docIDOrEmpty(synthesis))
	if err != nil {
		return verificationResult{}, err
	}
	failures := videoYouTubeBypassFailures(turnMetrics)
	if !synthesisFound || synthesis == nil {
		failures = append(failures, "missing video/YouTube synthesis fixture")
	} else {
		failures = append(failures, missingRequired(synthesis.Body, []string{videoYouTubeCurrentSourcePath, "source_refs:"})...)
	}
	if !currentFound || current == nil {
		failures = append(failures, "missing current video/YouTube source fixture")
	} else if current.Metadata["captured_at"] != "2026-04-27T01:00:00Z" {
		failures = append(failures, "current video/YouTube source was not updated to the changed transcript capture time")
	}
	if !searchContainsPath(search, videoYouTubeCurrentSourcePath) || !searchResultHasCitations(search) {
		failures = append(failures, "video/YouTube source search did not expose citation-bearing result after update")
	}
	if !projectionListContainsStaleSource(projections, videoYouTubeCurrentSourcePath) {
		failures = append(failures, "synthesis projection did not expose stale current video/YouTube source after changed transcript update")
	}
	if !turnMetrics.IngestVideoURLUpdateUsed || !turnMetrics.SearchUsed || !turnMetrics.ListDocumentsUsed || !turnMetrics.GetDocumentUsed || !turnMetrics.ProjectionStatesUsed || !turnMetrics.ProvenanceEventsUsed {
		failures = append(failures, "agent did not update supplied transcript and inspect search/list/get/provenance/projection evidence for video/YouTube synthesis")
	}
	if turnMetrics.CreateDocumentUsed || turnMetrics.ReplaceSectionUsed || turnMetrics.AppendDocumentUsed {
		failures = append(failures, "agent mutated synthesis during video/YouTube source update freshness inspection")
	}
	assistantPass := messageContainsAll(finalMessage, []string{videoYouTubeSynthesisPath, videoYouTubeCurrentSourcePath}) &&
		messageContainsAny(finalMessage, []string{"stale", "freshness", "projection"}) &&
		messageContainsAny(finalMessage, []string{"provenance", "source refs", "source_refs"}) &&
		messageContainsAny(finalMessage, []string{"no-op", "same hash", "same transcript", "changed transcript", "updated transcript"})
	if !assistantPass {
		failures = append(failures, "final answer did not explain no-op/update video/YouTube synthesis freshness and provenance")
	}
	databasePass := synthesisFound && synthesis != nil && currentFound && current != nil &&
		current.Metadata["captured_at"] == "2026-04-27T01:00:00Z" &&
		searchContainsPath(search, videoYouTubeCurrentSourcePath) &&
		searchResultHasCitations(search) &&
		projectionListContainsStaleSource(projections, videoYouTubeCurrentSourcePath)
	activityPass := len(videoYouTubeBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.IngestVideoURLUpdateUsed &&
		turnMetrics.SearchUsed && turnMetrics.ListDocumentsUsed && turnMetrics.GetDocumentUsed &&
		turnMetrics.ProjectionStatesUsed && turnMetrics.ProvenanceEventsUsed &&
		!turnMetrics.CreateDocumentUsed && !turnMetrics.ReplaceSectionUsed && !turnMetrics.AppendDocumentUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{videoYouTubeSynthesisPath, videoYouTubeCurrentSourcePath},
	}, nil
}
func verifyNativeMediaSuppliedTranscript(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	doc, found, err := documentByPath(ctx, paths, nativeMediaSourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	count, err := exactDocumentCount(ctx, paths, nativeMediaSourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, nativeMediaSourceEvidenceText)
	if err != nil {
		return verificationResult{}, err
	}
	failures := nativeMediaTranscriptBypassFailures(turnMetrics)
	requiredBody := []string{
		nativeMediaSourceEvidenceText,
		"source_type: video_transcript",
		"source_url:",
		nativeMediaURL,
		"transcript_origin:",
		nativeMediaTranscriptOrigin,
		"transcript_sha256:",
		"## Transcript",
	}
	if !found || doc == nil {
		failures = append(failures, "missing native media canonical source note")
	} else {
		failures = append(failures, missingRequired(doc.Body, requiredBody)...)
		if doc.Metadata["source_type"] != "video_transcript" {
			failures = append(failures, fmt.Sprintf("expected source_type metadata video_transcript, got %q", doc.Metadata["source_type"]))
		}
		if doc.Metadata["source_url"] != nativeMediaURL {
			failures = append(failures, fmt.Sprintf("expected source_url metadata %q, got %q", nativeMediaURL, doc.Metadata["source_url"]))
		}
		if doc.Metadata["transcript_origin"] != nativeMediaTranscriptOrigin {
			failures = append(failures, fmt.Sprintf("expected transcript_origin metadata %q, got %q", nativeMediaTranscriptOrigin, doc.Metadata["transcript_origin"]))
		}
	}
	if count != 1 {
		failures = append(failures, fmt.Sprintf("expected one native media source document, got %d", count))
	}
	if !searchContainsPath(search, nativeMediaSourcePath) || !searchResultHasCitations(search) {
		failures = append(failures, "native media transcript search did not expose citation-bearing source result")
	}
	if !turnMetrics.IngestVideoURLUsed || turnMetrics.IngestVideoURLUpdateUsed || !turnMetrics.SearchUsed || !containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"sources/native-media/"}) {
		failures = append(failures, "agent did not use create-mode ingest_video_url and then retrieve the canonical native media source note with path_prefix sources/native-media/")
	}
	assistantPass := messageContainsAll(finalMessage, []string{nativeMediaSourcePath, nativeMediaURL}) &&
		messageContainsAny(finalMessage, []string{"doc_id", "chunk_id", "citation"}) &&
		messageContainsAny(finalMessage, []string{"provenance", "transcript_origin", "transcript provenance"}) &&
		messageContainsAny(finalMessage, []string{"no native", "no separate native", "no downloader", "no stt", "no transcript api", "no remote extraction"})
	if !assistantPass {
		failures = append(failures, "final answer did not report source path, citation evidence, transcript provenance, and no native acquisition")
	}
	databasePass := found && doc != nil && count == 1 &&
		len(missingRequired(doc.Body, requiredBody)) == 0 &&
		doc.Metadata["source_type"] == "video_transcript" &&
		doc.Metadata["source_url"] == nativeMediaURL &&
		doc.Metadata["transcript_origin"] == nativeMediaTranscriptOrigin &&
		searchContainsPath(search, nativeMediaSourcePath) &&
		searchResultHasCitations(search)
	activityPass := len(nativeMediaTranscriptBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.IngestVideoURLUsed &&
		!turnMetrics.IngestVideoURLUpdateUsed &&
		turnMetrics.SearchUsed &&
		containsAllStrings(turnMetrics.SearchPathPrefixes, []string{"sources/native-media/"})
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{nativeMediaSourcePath},
	}, nil
}
func verifyNativeMediaFreshness(ctx context.Context, paths evalPaths, finalMessage string, turnMetrics metrics) (verificationResult, error) {
	synthesis, synthesisFound, err := documentByPath(ctx, paths, nativeMediaSynthesisPath)
	if err != nil {
		return verificationResult{}, err
	}
	current, currentFound, err := documentByPath(ctx, paths, nativeMediaCurrentSourcePath)
	if err != nil {
		return verificationResult{}, err
	}
	search, err := artifactSearch(ctx, paths, nativeMediaSynthesisUpdatedEvidenceText)
	if err != nil {
		return verificationResult{}, err
	}
	projections, err := artifactProjectionStates(ctx, paths, docIDOrEmpty(synthesis))
	if err != nil {
		return verificationResult{}, err
	}
	failures := nativeMediaTranscriptBypassFailures(turnMetrics)
	if !synthesisFound || synthesis == nil {
		failures = append(failures, "missing native media synthesis fixture")
	} else {
		failures = append(failures, missingRequired(synthesis.Body, []string{nativeMediaCurrentSourcePath, "source_refs:"})...)
	}
	if !currentFound || current == nil {
		failures = append(failures, "missing current native media source fixture")
	} else if current.Metadata["captured_at"] != "2026-04-30T01:00:00Z" {
		failures = append(failures, "current native media source was not updated to the changed transcript capture time")
	}
	if !searchContainsPath(search, nativeMediaCurrentSourcePath) || !searchResultHasCitations(search) {
		failures = append(failures, "native media source search did not expose citation-bearing result after update")
	}
	if !projectionListContainsStaleSource(projections, nativeMediaCurrentSourcePath) {
		failures = append(failures, "synthesis projection did not expose stale current native media source after changed transcript update")
	}
	if !turnMetrics.IngestVideoURLUpdateUsed || !turnMetrics.SearchUsed || !turnMetrics.ListDocumentsUsed || !turnMetrics.GetDocumentUsed || !turnMetrics.ProjectionStatesUsed || !turnMetrics.ProvenanceEventsUsed {
		failures = append(failures, "agent did not update supplied transcript and inspect search/list/get/provenance/projection evidence for native media synthesis")
	}
	if turnMetrics.CreateDocumentUsed || turnMetrics.ReplaceSectionUsed || turnMetrics.AppendDocumentUsed {
		failures = append(failures, "agent mutated synthesis during native media source update freshness inspection")
	}
	assistantPass := messageContainsAll(finalMessage, []string{nativeMediaSynthesisPath, nativeMediaCurrentSourcePath}) &&
		messageContainsAny(finalMessage, []string{"stale", "freshness", "projection"}) &&
		messageContainsAny(finalMessage, []string{"provenance", "source refs", "source_refs"}) &&
		messageContainsAny(finalMessage, []string{"no-op", "same hash", "same transcript", "changed transcript", "updated transcript"}) &&
		messageContainsAny(finalMessage, []string{"no native", "no separate native", "no dependency", "no downloader", "no stt", "no transcript api"})
	if !assistantPass {
		failures = append(failures, "final answer did not explain no-op/update native media freshness, provenance, and no native acquisition dependency")
	}
	databasePass := synthesisFound && synthesis != nil && currentFound && current != nil &&
		current.Metadata["captured_at"] == "2026-04-30T01:00:00Z" &&
		searchContainsPath(search, nativeMediaCurrentSourcePath) &&
		searchResultHasCitations(search) &&
		projectionListContainsStaleSource(projections, nativeMediaCurrentSourcePath)
	activityPass := len(nativeMediaTranscriptBypassFailures(turnMetrics)) == 0 &&
		turnMetrics.IngestVideoURLUpdateUsed &&
		turnMetrics.SearchUsed && turnMetrics.ListDocumentsUsed && turnMetrics.GetDocumentUsed &&
		turnMetrics.ProjectionStatesUsed && turnMetrics.ProvenanceEventsUsed &&
		!turnMetrics.CreateDocumentUsed && !turnMetrics.ReplaceSectionUsed && !turnMetrics.AppendDocumentUsed
	return verificationResult{
		Passed:        databasePass && assistantPass && activityPass,
		DatabasePass:  databasePass,
		AssistantPass: assistantPass && activityPass,
		Details:       missingDetails(failures),
		Documents:     []string{nativeMediaSynthesisPath, nativeMediaCurrentSourcePath},
	}, nil
}
func artifactSearch(ctx context.Context, paths evalPaths, text string) (runner.RetrievalTaskResult, error) {
	cfg := runclient.Config{DatabasePath: paths.DatabasePath}
	return runner.RunRetrievalTask(ctx, cfg, runner.RetrievalTaskRequest{
		Action: runner.RetrievalTaskActionSearch,
		Search: runner.SearchOptions{
			Text:  text,
			Limit: 10,
		},
	})
}
func artifactProjectionStates(ctx context.Context, paths evalPaths, synthesisDocID string) (runner.ProjectionStateList, error) {
	cfg := runclient.Config{DatabasePath: paths.DatabasePath}
	result, err := runner.RunRetrievalTask(ctx, cfg, runner.RetrievalTaskRequest{
		Action: runner.RetrievalTaskActionProjectionStates,
		Projection: runner.ProjectionStateOptions{
			Projection: "synthesis",
			RefKind:    "document",
			RefID:      synthesisDocID,
			Limit:      5,
		},
	})
	if err != nil {
		return runner.ProjectionStateList{}, err
	}
	if result.Projections == nil {
		return runner.ProjectionStateList{}, nil
	}
	return *result.Projections, nil
}
func projectionListContainsStaleSource(list runner.ProjectionStateList, path string) bool {
	for _, projection := range list.Projections {
		if projection.Freshness == "stale" &&
			(projectionDetailContains(projection.Details, "stale_source_refs", path) ||
				projectionDetailContains(projection.Details, "current_source_refs", path) ||
				projectionDetailContains(projection.Details, "missing_source_refs", path)) {
			return true
		}
	}
	return false
}
func agentChosenBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func pathTitleBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func captureLowRiskBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func captureExplicitOverridesBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func captureDuplicateCandidateBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func captureSaveThisNoteBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func captureDocumentLinksBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func documentThisBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func documentArtifactCandidateBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func artifactIngestionBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func unsupportedArtifactKindBypassFailures(turnMetrics metrics) []string {
	failures := artifactIngestionBypassFailures(turnMetrics)
	if turnMetrics.ManualHTTPFetch {
		failures = append(failures, "agent used manual HTTP fetch")
	}
	if turnMetrics.BrowserAutomation {
		failures = append(failures, "agent used browser automation")
	}
	if turnMetrics.FileInspectionCommands != 0 {
		failures = append(failures, "agent used direct file inspection")
	}
	return failures
}
func localFileArtifactBypassFailures(turnMetrics metrics) []string {
	return unsupportedArtifactKindBypassFailures(turnMetrics)
}
func videoYouTubeBypassFailures(turnMetrics metrics) []string {
	return populatedBypassFailures(turnMetrics)
}
func nativeMediaTranscriptBypassFailures(turnMetrics metrics) []string {
	failures := populatedBypassFailures(turnMetrics)
	if turnMetrics.ManualHTTPFetch {
		failures = append(failures, "agent used manual HTTP fetch")
	}
	if turnMetrics.BrowserAutomation {
		failures = append(failures, "agent used browser automation")
	}
	if turnMetrics.FileInspectionCommands != 0 {
		failures = append(failures, "agent used direct file inspection")
	}
	if turnMetrics.NativeMediaAcquisition {
		failures = append(failures, "agent used native media acquisition tooling")
	}
	return failures
}
