Files
isphere-ai-bridge/internal/uiaselector/report.go
2026-07-09 16:14:14 +08:00

103 lines
3.0 KiB
Go

package uiaselector
import "time"
const (
StrictExitOK = 0
StrictExitReportGenerationFailure = 1
StrictExitUnmatched = 2
StrictExitAmbiguous = 3
StrictExitInvalidCatalog = 4
)
type Report struct {
OK bool `json:"ok"`
SourceDump string `json:"source_dump"`
CatalogSize int `json:"catalog_size"`
MatchedCount int `json:"matched_count"`
UnmatchedCount int `json:"unmatched_count"`
AmbiguousCount int `json:"ambiguous_count"`
GeneratedAtUTC string `json:"generated_at_utc"`
Selectors []SelectorReport `json:"selectors"`
Warnings []string `json:"warnings"`
Error *ReportError `json:"error,omitempty"`
}
type ReportError struct {
Code string `json:"code"`
Message string `json:"message"`
}
type SelectorReport struct {
SelectorID string `json:"selector_id"`
Description string `json:"description"`
AllowedUse string `json:"allowed_use"`
StabilityScore int `json:"stability_score"`
Evidence Evidence `json:"evidence"`
Matched bool `json:"matched"`
MatchCount int `json:"match_count"`
Matches []NodeMatch `json:"matches"`
Warnings []string `json:"warnings"`
}
func RunCatalogReport(sourceDump string, root *Node, catalog []Selector, generatedAt time.Time) Report {
report := Report{
OK: true,
SourceDump: sourceDump,
CatalogSize: len(catalog),
GeneratedAtUTC: generatedAt.UTC().Format(time.RFC3339),
Warnings: []string{},
}
if root == nil {
report.OK = false
report.Error = &ReportError{Code: "NO_ROOT", Message: "UIA dump root is nil"}
return report
}
for _, selector := range catalog {
if selector.AllowedUse != AllowedUseReadOnlyLocate {
report.OK = false
report.Error = &ReportError{Code: "INVALID_CATALOG", Message: "selector is not read-only: " + selector.ID}
return report
}
match := MatchSelector(root, catalog, selector.ID)
selectorReport := SelectorReport{
SelectorID: selector.ID,
Description: selector.Description,
AllowedUse: selector.AllowedUse,
StabilityScore: selector.StabilityScore,
Evidence: selector.Evidence,
Matched: match.Matched,
MatchCount: match.MatchCount,
Matches: match.Matches,
Warnings: append([]string{}, match.Warnings...),
}
report.Selectors = append(report.Selectors, selectorReport)
if match.Matched {
report.MatchedCount++
} else {
report.UnmatchedCount++
}
if match.MatchCount > 1 {
report.AmbiguousCount++
}
}
return report
}
func StrictExitCode(report Report) int {
if !report.OK {
if report.Error != nil && report.Error.Code == "INVALID_CATALOG" {
return StrictExitInvalidCatalog
}
return StrictExitReportGenerationFailure
}
if report.UnmatchedCount > 0 {
return StrictExitUnmatched
}
if report.AmbiguousCount > 0 {
return StrictExitAmbiguous
}
return StrictExitOK
}