forked from niuniu/llm-intelligence
feat(runtime): harden daily pipeline audit and verification
Tighten real-ingestion success rules, separate scheduled reports from historical rebuilds, and persist source-level runtime audit across daily pipeline runs. Also add the Phase 5 CI workflow contract plus verification updates and supporting docs so the full uncommitted change set can be validated together.
This commit is contained in:
@@ -22,6 +22,13 @@ import (
|
||||
|
||||
var logger *slog.Logger
|
||||
|
||||
type ReportRunContext struct {
|
||||
RunKind string
|
||||
TriggerSource string
|
||||
IsOfficialDaily bool
|
||||
RuntimeAudit string
|
||||
}
|
||||
|
||||
func init() {
|
||||
logger = slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo}))
|
||||
}
|
||||
@@ -89,6 +96,14 @@ func run() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runContext := resolveReportRunContext(
|
||||
date,
|
||||
time.Now(),
|
||||
os.Getenv("REPORT_RUN_KIND"),
|
||||
os.Getenv("REPORT_TRIGGER_SOURCE"),
|
||||
os.Getenv("REPORT_IS_OFFICIAL_DAILY"),
|
||||
os.Getenv("REPORT_RUNTIME_AUDIT"),
|
||||
)
|
||||
|
||||
// 1. 获取报告数据(使用新schema)
|
||||
report, err := generateReportDataV3(db, date)
|
||||
@@ -122,7 +137,7 @@ func run() error {
|
||||
}
|
||||
|
||||
// 6. 同步写入日报状态与运行轨迹
|
||||
if err := saveReportTrackingV3(db, report, mdPath); err != nil {
|
||||
if err := saveReportTrackingV3(db, report, mdPath, runContext); err != nil {
|
||||
logger.Warn("保存日报记录失败", "error", err)
|
||||
}
|
||||
|
||||
@@ -165,6 +180,43 @@ func resolveReportDate(now time.Time, args []string, envDate string) (string, er
|
||||
return parsed.Format("2006-01-02"), nil
|
||||
}
|
||||
|
||||
func resolveReportRunContext(reportDate string, now time.Time, envRunKind, envTriggerSource, envOfficialDaily, envRuntimeAudit string) ReportRunContext {
|
||||
runKind := strings.TrimSpace(envRunKind)
|
||||
if runKind == "" {
|
||||
runKind = "manual"
|
||||
}
|
||||
|
||||
triggerSource := strings.TrimSpace(envTriggerSource)
|
||||
if triggerSource == "" {
|
||||
triggerSource = "cli"
|
||||
}
|
||||
|
||||
isOfficialDaily := strings.EqualFold(strings.TrimSpace(envOfficialDaily), "true")
|
||||
if strings.TrimSpace(envOfficialDaily) == "" && reportDate == now.Format("2006-01-02") && runKind == "scheduled" {
|
||||
isOfficialDaily = true
|
||||
}
|
||||
|
||||
return ReportRunContext{
|
||||
RunKind: runKind,
|
||||
TriggerSource: triggerSource,
|
||||
IsOfficialDaily: isOfficialDaily,
|
||||
RuntimeAudit: strings.TrimSpace(envRuntimeAudit),
|
||||
}
|
||||
}
|
||||
|
||||
func composeTrackedSummary(summary string, runContext ReportRunContext) string {
|
||||
runtimeAudit := strings.TrimSpace(runContext.RuntimeAudit)
|
||||
summary = strings.TrimSpace(summary)
|
||||
|
||||
if runtimeAudit == "" {
|
||||
return summary
|
||||
}
|
||||
if summary == "" {
|
||||
return runtimeAudit
|
||||
}
|
||||
return runtimeAudit + "\n" + summary
|
||||
}
|
||||
|
||||
// ============ 数据模型 ============
|
||||
|
||||
const (
|
||||
@@ -2869,11 +2921,12 @@ th {
|
||||
return t.Execute(f, r)
|
||||
}
|
||||
|
||||
func saveReportTrackingV3(db *sql.DB, r *ReportV3, mdPath string) error {
|
||||
func saveReportTrackingV3(db *sql.DB, r *ReportV3, mdPath string, runContext ReportRunContext) error {
|
||||
summary := r.HeroSummary
|
||||
if summary == "" {
|
||||
summary = fmt.Sprintf("models=%d free=%d intl=%d domestic=%d", r.TotalModels, len(r.FreeModels), len(r.IntlTop5), len(r.DomesticTop10))
|
||||
}
|
||||
summary = composeTrackedSummary(summary, runContext)
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -2881,24 +2934,39 @@ func saveReportTrackingV3(db *sql.DB, r *ReportV3, mdPath string) error {
|
||||
defer tx.Rollback()
|
||||
|
||||
if _, err := tx.Exec(`
|
||||
INSERT INTO daily_report (report_date, status, model_count, new_models, free_models, summary_md, output_path, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW())
|
||||
INSERT INTO daily_report (report_date, status, model_count, new_models, free_models, summary_md, output_path, run_kind, trigger_source, is_official_daily, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, NOW())
|
||||
ON CONFLICT (report_date) DO UPDATE SET
|
||||
status = EXCLUDED.status,
|
||||
model_count = EXCLUDED.model_count,
|
||||
free_models = EXCLUDED.free_models,
|
||||
summary_md = EXCLUDED.summary_md,
|
||||
output_path = EXCLUDED.output_path,
|
||||
run_kind = CASE
|
||||
WHEN EXCLUDED.is_official_daily THEN EXCLUDED.run_kind
|
||||
WHEN daily_report.trigger_source = 'legacy_backfill' THEN EXCLUDED.run_kind
|
||||
ELSE daily_report.run_kind
|
||||
END,
|
||||
trigger_source = CASE
|
||||
WHEN EXCLUDED.is_official_daily THEN EXCLUDED.trigger_source
|
||||
WHEN daily_report.trigger_source = 'legacy_backfill' THEN EXCLUDED.trigger_source
|
||||
ELSE daily_report.trigger_source
|
||||
END,
|
||||
is_official_daily = CASE
|
||||
WHEN EXCLUDED.is_official_daily THEN TRUE
|
||||
WHEN daily_report.trigger_source = 'legacy_backfill' THEN EXCLUDED.is_official_daily
|
||||
ELSE daily_report.is_official_daily
|
||||
END,
|
||||
error_message = NULL,
|
||||
updated_at = NOW()
|
||||
`, r.Date, "generated", r.TotalModels, 0, len(r.FreeModels), summary, mdPath); err != nil {
|
||||
`, r.Date, "generated", r.TotalModels, 0, len(r.FreeModels), summary, mdPath, runContext.RunKind, runContext.TriggerSource, runContext.IsOfficialDaily); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(`
|
||||
INSERT INTO report_runs (source, report_date, status, summary_md, output_path, error_message)
|
||||
VALUES ($1, $2, $3, $4, $5, NULL)
|
||||
`, "generate_daily_report", r.Date, "generated", summary, mdPath); err != nil {
|
||||
INSERT INTO report_runs (source, report_date, status, summary_md, output_path, error_message, run_kind, trigger_source, is_official_daily)
|
||||
VALUES ($1, $2, $3, $4, $5, NULL, $6, $7, $8)
|
||||
`, "generate_daily_report", r.Date, "generated", summary, mdPath, runContext.RunKind, runContext.TriggerSource, runContext.IsOfficialDaily); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user