Why: Layout rules alone do not produce conclusion-first documents, extra views, or infographics, and nothing scored a deliverable before it was returned. Evidence: go test ./internal/prompts/ ./internal/quality/ ./internal/tools/ ./internal/squadadapter/ ./eval/ -count=1 and the house-style unittest passed in the previous session. Impact: Every task inherits content rules. Meetings, reports, and comparisons can name a view family. Long documents without a visual summary warn. quality_review and the squad checker share one scorecard. Refs: deliverable-quality-system A1-A5 Co-authored-by: Cursor <cursoragent@cursor.com>
52 lines
1.6 KiB
Go
52 lines
1.6 KiB
Go
package tools
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"agent-system-backend/internal/quality"
|
|
core "agent-system-core"
|
|
)
|
|
|
|
func registerQualityReview(r *Registry) error {
|
|
return r.Register(core.ToolDesc{
|
|
Name: "quality_review",
|
|
Description: "按结论先行、结构、完整性、证据、可执行性、可读性给交付物打分,并附上版式检查。不通过时按 violations 改一版再登记",
|
|
Source: core.SourceBuiltin,
|
|
Parameters: json.RawMessage(`{"type":"object","properties":{"path":{"type":"string","description":"会话工作区内的相对路径"}},"required":["path"]}`),
|
|
}, func(rc ToolExecCtx, args json.RawMessage) (string, error) {
|
|
var a struct {
|
|
Path string `json:"path"`
|
|
}
|
|
if err := json.Unmarshal(args, &a); err != nil {
|
|
return "", err
|
|
}
|
|
path, err := workspaceFile(rc.WorkspaceRoot(), a.Path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
report := quality.ScoreFile(path)
|
|
out, err := json.Marshal(report)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(out), nil
|
|
})
|
|
}
|
|
|
|
func workspaceFile(root, rel string) (string, error) {
|
|
if strings.TrimSpace(root) == "" {
|
|
return "", fmt.Errorf("quality_review: workspace is not configured")
|
|
}
|
|
if rel == "" || filepath.IsAbs(rel) {
|
|
return "", fmt.Errorf("quality_review: path must be a relative path inside the workspace")
|
|
}
|
|
clean := filepath.Clean(rel)
|
|
if clean == ".." || strings.HasPrefix(clean, ".."+string(filepath.Separator)) {
|
|
return "", fmt.Errorf("quality_review: path escapes the workspace")
|
|
}
|
|
return filepath.Join(root, clean), nil
|
|
}
|