Add cross-task content methods, visuals, and scoring
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>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# 交付物评测
|
||||
|
||||
仓内 `testdata/` 是脱敏短样例,用来确认评分卡能区分“结论先行”和“栏目式笔记”。
|
||||
|
||||
真实会议材料不要放进仓库。放到 `~/.agent-system/eval/`,或设置 `EVAL_DIR`。其中的 `.md` 会在 `go test ./eval/` 里被打分并打印,缺失该目录时测试跳过。
|
||||
|
||||
```
|
||||
cd modules/backend && go test ./eval/ ./internal/quality/ -count=1
|
||||
```
|
||||
@@ -0,0 +1,14 @@
|
||||
package eval
|
||||
|
||||
import "strings"
|
||||
|
||||
// MissingThemes 报告候选文本没有覆盖的参考主题。主题是短词,不是整句照抄。
|
||||
func MissingThemes(candidate string, themes []string) []string {
|
||||
var missing []string
|
||||
for _, theme := range themes {
|
||||
if !strings.Contains(candidate, theme) {
|
||||
missing = append(missing, theme)
|
||||
}
|
||||
}
|
||||
return missing
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// Package eval 用固定样例比较交付质量。真实会议材料放在仓外
|
||||
// ~/.agent-system/eval/,或用 EVAL_DIR 指向该目录;仓内只放脱敏短样例。
|
||||
package eval
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"agent-system-backend/internal/quality"
|
||||
)
|
||||
|
||||
func TestDesensitizedSampleBeatsColumnNotes(t *testing.T) {
|
||||
good := scoreFixture(t, "good.md")
|
||||
bad := scoreFixture(t, "bad.md")
|
||||
if !good.Passed {
|
||||
t.Fatalf("good fixture should pass: %+v", good)
|
||||
}
|
||||
if bad.Score >= good.Score {
|
||||
t.Fatalf("bad %d should be below good %d", bad.Score, good.Score)
|
||||
}
|
||||
missing := MissingThemes(readFixture(t, "good.md"), []string{"相关性", "标签", "未指明"})
|
||||
if len(missing) > 0 {
|
||||
t.Fatalf("good fixture missed themes %v", missing)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalEvalDirOptional(t *testing.T) {
|
||||
dir := os.Getenv("EVAL_DIR")
|
||||
if dir == "" {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Skip(err)
|
||||
}
|
||||
dir = filepath.Join(home, ".agent-system", "eval")
|
||||
}
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
t.Skip("no external eval dir")
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() || filepath.Ext(entry.Name()) != ".md" {
|
||||
continue
|
||||
}
|
||||
report := quality.ScoreFile(filepath.Join(dir, entry.Name()))
|
||||
t.Logf("%s score=%d passed=%v", entry.Name(), report.Score, report.Passed)
|
||||
}
|
||||
}
|
||||
|
||||
func scoreFixture(t *testing.T, name string) quality.Report {
|
||||
t.Helper()
|
||||
return quality.ScoreText(readFixture(t, name))
|
||||
}
|
||||
|
||||
func readFixture(t *testing.T, name string) string {
|
||||
t.Helper()
|
||||
data, err := os.ReadFile(filepath.Join("testdata", name))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
# 讨论过程
|
||||
|
||||
今天围绕文档上传聊了一会儿。大家说了很多,也有一些不同看法。后续再看吧。
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
# 上传文档应先判断相关性,再打标签入库
|
||||
|
||||
## 先校验,再生成
|
||||
说话人1指出,上传后的第一步是判断文档与项目是否相关。确认后再拆开打标签。
|
||||
一句话:没有这层记忆,后面的摘要和追溯都没有依据。
|
||||
|
||||
## 不要在上传时提示缺什么
|
||||
依据会议原话,缺项提示放到体系成型之后。
|
||||
一句话:上传节点是收集,不是验收。
|
||||
|
||||
## 基线要能迭代
|
||||
新内容和已有基线比对,冲突时先问人。
|
||||
一句话:一份基线反复补,而不是每次上传都新开一篇。
|
||||
|
||||
## 下一步
|
||||
事项是写出第一版需求。负责人是陈威。期限是周五前。说不清的一律写未指明。
|
||||
Reference in New Issue
Block a user