Files
Agent-System/internal/bizdev/task_result_status.go
T
weichenandCursor 900af79e14 fix(docgov): quality gate self-pollution, server repair budget, quality_failed UI
受控小队任务服务端启用修复预算;否定性自检引用不再误报;quality_failed 保持失败且不激活未过门禁稿。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 15:00:50 +00:00

155 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package bizdev
import (
"fmt"
"strings"
"chat-agent-system/internal/squad"
)
// Terminal task statuses projected to chat / workflow_runs.
const (
TaskStatusCompleted = "completed"
TaskStatusFailed = "failed"
TaskStatusQualityFailed = "quality_failed"
TaskStatusPendingAuthorConfirmation = "pending_author_confirmation"
)
// AwaitsAgentConfirmation reports high/critical revision candidate awaiting author decision.
// Distinct from DocGov change-proposal intercept (PendingProposal).
func (r *TaskRunResult) AwaitsAgentConfirmation() bool {
return r != nil && r.PendingAgentCandidateID > 0
}
// IsProposalIntercept reports claimed-document DocGov change-proposal interception.
func (r *TaskRunResult) IsProposalIntercept() bool {
return r != nil && r.PendingProposal != nil && r.RequiresAuthorApproval
}
// TerminalStatus maps TaskRunResult to a conversation/workflow terminal status.
// Pending agent confirmation is never "completed" until commit+projection.
// Quality failure stays quality_failed even when Success was cleared to block Materialize.
func (r *TaskRunResult) TerminalStatus() string {
if r == nil {
return TaskStatusFailed
}
if r.QualityReport != nil && !r.QualityReport.Passed {
return TaskStatusQualityFailed
}
if !r.Success {
return TaskStatusFailed
}
if r.AwaitsAgentConfirmation() {
return TaskStatusPendingAuthorConfirmation
}
return TaskStatusCompleted
}
// CompletionSummary builds the assistant-visible completion text for sync and async finalizers.
func (r *TaskRunResult) CompletionSummary() string {
if r == nil {
return "任务执行失败。"
}
title := r.ArtifactTitle
if title == "" && r.TaskKey != "" {
title = squad.TaskArtifactTitle(r.TaskKey)
}
if title == "" {
title = "交付文档"
}
status := r.TerminalStatus()
var b strings.Builder
switch status {
case TaskStatusPendingAuthorConfirmation:
fmt.Fprintf(&b, "《%s》文档候选已生成,待编制人确认。\n\n", title)
b.WriteString("当前状态:**待编制人确认**")
if r.PendingRiskLevel != "" {
fmt.Fprintf(&b, "(风险:%s)", r.PendingRiskLevel)
}
b.WriteString("\n正式正文仍为账本当前 head;候选正文仅保留在不可变快照中。请打开文档「待确认报告」确认提交或拒绝后,正式正文才会更新。")
if r.PendingConfirmationNote != "" {
fmt.Fprintf(&b, "\n%s", r.PendingConfirmationNote)
}
fmt.Fprintf(&b, "\n候选 ID:%d", r.PendingAgentCandidateID)
if r.PendingChangeReportID > 0 {
fmt.Fprintf(&b, " · 变更报告:%d", r.PendingChangeReportID)
}
case TaskStatusQualityFailed:
fmt.Fprintf(&b, "《%s》已生成。\n\n", title)
b.WriteString("当前状态:**质量检查未通过,待整改**")
if r.QualityReport != nil {
fmt.Fprintf(&b, "\n质量评分:%.0f/100", r.QualityReport.Score)
if len(r.QualityReport.Violations) > 0 {
fmt.Fprintf(&b, "\n主要问题:%s", strings.Join(r.QualityReport.Violations, ";"))
}
}
case TaskStatusCompleted:
fmt.Fprintf(&b, "《%s》已生成。\n\n", title)
b.WriteString("当前状态:**已完成**")
if r.QualityReport != nil && r.QualityReport.Passed {
fmt.Fprintf(&b, "\n质量评分:%.0f/100", r.QualityReport.Score)
}
default:
fmt.Fprintf(&b, "《%s》未成功落盘。\n\n", title)
if r.ErrorReason != "" {
fmt.Fprintf(&b, "执行未成功:%s", r.ErrorReason)
} else {
b.WriteString("任务执行失败。")
}
}
if r.DocRecord != nil && r.DocRecord.DocID != "" {
fmt.Fprintf(&b, "\n\n📄 受控文档:`%s`", r.DocRecord.DocID)
}
return b.String()
}
// ArtifactMetadata returns chat metadata fields for a clickable document entry.
func (r *TaskRunResult) ArtifactMetadata() map[string]any {
if r == nil {
return nil
}
docID := ""
if r.DocRecord != nil {
docID = r.DocRecord.DocID
}
if docID == "" {
return nil
}
title := r.ArtifactTitle
if title == "" && r.TaskKey != "" {
title = squad.TaskArtifactTitle(r.TaskKey)
}
out := map[string]any{
"doc_id": docID,
"title": title,
"task_key": r.TaskKey,
}
if r.WorkDir != "" {
out["workspace_id"] = r.WorkDir
}
if r.DocRecord != nil && r.DocRecord.ContentSHA256 != "" {
out["sha256"] = r.DocRecord.ContentSHA256
}
if r.QualityReport != nil {
out["quality_passed"] = r.QualityReport.Passed
out["quality_score"] = r.QualityReport.Score
if len(r.QualityReport.Violations) > 0 {
out["quality_violations"] = r.QualityReport.Violations
}
}
if r.AwaitsAgentConfirmation() {
out["pending_agent_candidate_id"] = r.PendingAgentCandidateID
if r.PendingChangeReportID > 0 {
out["pending_change_report_id"] = r.PendingChangeReportID
}
if r.PendingRiskLevel != "" {
out["pending_risk_level"] = r.PendingRiskLevel
}
out["awaiting_author_confirmation"] = true
}
return out
}