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>
53 lines
2.0 KiB
Go
53 lines
2.0 KiB
Go
package tools
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
core "agent-system-core"
|
|
)
|
|
|
|
type qualityCtx struct{ root string }
|
|
|
|
func (c qualityCtx) ProjectID() string { return "p" }
|
|
func (c qualityCtx) ConversationID() string { return "c" }
|
|
func (c qualityCtx) Retrieve(core.RetrievalQuery) ([]core.RetrievalHit, error) {
|
|
return nil, nil
|
|
}
|
|
func (c qualityCtx) WriteArtifact(string, string, string, []byte) (core.Artifact, error) {
|
|
return core.Artifact{}, nil
|
|
}
|
|
func (c qualityCtx) PeerConversations() ([]core.Conversation, error) { return nil, nil }
|
|
func (c qualityCtx) PeerConversationMessages(string, int) ([]core.Message, error) {
|
|
return nil, nil
|
|
}
|
|
func (c qualityCtx) OwnerID() string { return "o" }
|
|
func (c qualityCtx) WorkspaceRoot() string { return c.root }
|
|
func (c qualityCtx) SettingBool(string, bool) bool { return false }
|
|
|
|
func TestQualityReviewStaysInsideWorkspace(t *testing.T) {
|
|
dir := t.TempDir()
|
|
body := "# 上传应先入库再生成\n\n## 判断\n说话人1认为要先看相关性。\n一句话:先建记忆。\n\n## 行动\n负责人陈威,期限周五;不清楚的写未指明。这份说明写长一点,保证完整性维度能够通过,因为过短的正文会被当成没有覆盖决定。需要把依据、行动和收束都写清楚,读者只看标题也知道下一步是什么。\n"
|
|
if err := os.WriteFile(filepath.Join(dir, "note.md"), []byte(body), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
reg := NewRegistry()
|
|
if err := reg.RegisterBuiltin(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
res := reg.Execute(qualityCtx{root: dir}, core.ToolCallRequest{
|
|
CallID: "q", Name: "quality_review", Arguments: json.RawMessage(`{"path":"note.md"}`),
|
|
})
|
|
if res.Status != "ok" {
|
|
t.Fatalf("review: %s", res.Output)
|
|
}
|
|
escaped := reg.Execute(qualityCtx{root: dir}, core.ToolCallRequest{
|
|
CallID: "q2", Name: "quality_review", Arguments: json.RawMessage(`{"path":"../secret.md"}`),
|
|
})
|
|
if escaped.Status != "error" {
|
|
t.Fatalf("escape should fail, got %s", escaped.Output)
|
|
}
|
|
}
|