package docrevision import "context" // CoverageResolver reports whether the trace index can support a no-impact claim. // nil or an empty result means the index has not run; that must not be shown as no impact. func (s *Service) formalCommitReportLocked(ctx context.Context, docID string, fromID, toID int64, hunks []DiffHunk) *ChangeReport { impacts := s.impactLocked(ctx, docID) coverage := ImpactIndexPending if s.CoverageResolver != nil { if got := s.CoverageResolver(ctx, docID); got != "" { coverage = got } } rep := fallbackReport("", "", RuleRiskFloor(hunks, impacts), impacts, hunks, "formal commit") rep.DocID = docID rep.FromSnapshotID = fromID rep.ToSnapshotID = toID rep.AnalysisStatus = AnalysisFallback rep.Authority = ReportAuthoritative rep.Lifecycle = ReportCommitted if rep.DeterministicFacts == nil { rep.DeterministicFacts = map[string]any{} } rep.DeterministicFacts["coverage_status"] = coverage rep.DeterministicFacts["suggested_actions"] = formalSuggestions(coverage, len(impacts) > 0) switch coverage { case ImpactNoKnown: rep.Summary = append(rep.Summary, "索引已覆盖,未发现已知关联") case ImpactConfirmed, ImpactPossible: rep.Summary = append(rep.Summary, "这次修改可能影响其他文档,见 document_impacts") default: rep.Summary = append(rep.Summary, "分析尚未完成或失败,不能判断为无影响") rep.OpenQuestions = append(rep.OpenQuestions, "不能判断为无影响") } stampReportDisposition(rep) return rep } func formalSuggestions(coverage string, hasImpact bool) []string { switch coverage { case ImpactIndexPending, ImpactPartial, ImpactFailed: return []string{"wait_index"} } out := []string{"no_change"} if hasImpact || coverage == ImpactPossible || coverage == ImpactConfirmed { out = append(out, "l1_revise", "l2_reopen") } return out }