Prove A can run the full action chain and outsiders stay denied; assert audit Details carry duty_policy on all five transitions. Co-authored-by: Cursor <cursoragent@cursor.com>
92 lines
2.8 KiB
Go
92 lines
2.8 KiB
Go
package projectinstance
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"chat-agent-system/internal/workflowdef"
|
|
)
|
|
|
|
func TestEvaluateStageReadiness_DutyModes(t *testing.T) {
|
|
t.Parallel()
|
|
stageDef := &workflowdef.StageDef{
|
|
Key: "V0.1_triage",
|
|
DocTasks: []workflowdef.DocTaskDef{
|
|
{Key: "intake", BlockingWhenEnabled: true, CreatorConfigurable: true},
|
|
{Key: "research", CreatorConfigurable: true},
|
|
},
|
|
}
|
|
plan := StagePlan{
|
|
StageKey: "V0.1_triage",
|
|
Enabled: true,
|
|
DocTasks: []DocTaskPlan{
|
|
{TaskKey: "intake", Enabled: true, Duties: DocDuty{AuthorUserID: 1, ReviewerUserID: 2, ApproverUserID: 3}},
|
|
{TaskKey: "research", Enabled: true},
|
|
{TaskKey: "skipped", Enabled: false, Duties: DocDuty{AuthorUserID: 1, ReviewerUserID: 2, ApproverUserID: 3}},
|
|
},
|
|
}
|
|
|
|
ready, issues, items := evaluateStageReadiness(plan, stageDef, map[string]string{"research": "draft"})
|
|
if ready {
|
|
t.Fatal("full blocking doc missing approval must keep the gate closed")
|
|
}
|
|
if len(issues) != 1 || issues[0].TaskKey != "intake" {
|
|
t.Fatalf("only intake should block, got %+v", issues)
|
|
}
|
|
|
|
var research, intake *DocTaskReadiness
|
|
for i := range items {
|
|
switch items[i].TaskKey {
|
|
case "research":
|
|
research = &items[i]
|
|
case "intake":
|
|
intake = &items[i]
|
|
case "skipped":
|
|
t.Fatal("disabled docs must not participate")
|
|
}
|
|
}
|
|
if intake == nil || !intake.ApprovalManaged || !intake.Required {
|
|
t.Fatalf("full blocking doc: %+v", intake)
|
|
}
|
|
if research == nil || research.ApprovalManaged || research.Required || !research.Enabled {
|
|
t.Fatalf("none doc must stay enabled without approval management: %+v", research)
|
|
}
|
|
|
|
ready, issues, _ = evaluateStageReadiness(plan, stageDef, map[string]string{"intake": "approved"})
|
|
if !ready || len(issues) != 0 {
|
|
t.Fatalf("approved full + unmanaged none should be ready, issues=%+v", issues)
|
|
}
|
|
}
|
|
|
|
func TestEvaluateStageReadiness_AuthorOnlyIsManaged(t *testing.T) {
|
|
t.Parallel()
|
|
stageDef := &workflowdef.StageDef{
|
|
Key: "V0.1_triage",
|
|
DocTasks: []workflowdef.DocTaskDef{
|
|
{Key: "intake", BlockingWhenEnabled: true, CreatorConfigurable: true},
|
|
},
|
|
}
|
|
plan := StagePlan{
|
|
StageKey: "V0.1_triage",
|
|
Enabled: true,
|
|
DocTasks: []DocTaskPlan{{
|
|
TaskKey: "intake", Enabled: true,
|
|
DutyPolicy: DutyPolicyAuthorOnly,
|
|
Duties: DocDuty{AuthorUserID: 7},
|
|
}},
|
|
}
|
|
ready, issues, items := evaluateStageReadiness(plan, stageDef, map[string]string{})
|
|
if ready {
|
|
t.Fatal("author_only blocking doc without approval must keep gate closed")
|
|
}
|
|
if len(issues) != 1 || issues[0].TaskKey != "intake" {
|
|
t.Fatalf("issues=%+v", issues)
|
|
}
|
|
if len(items) != 1 || !items[0].ApprovalManaged || !items[0].Required {
|
|
t.Fatalf("author_only must be approval-managed: %+v", items)
|
|
}
|
|
ready, _, _ = evaluateStageReadiness(plan, stageDef, map[string]string{"intake": "approved"})
|
|
if !ready {
|
|
t.Fatal("approved author_only doc should open the gate")
|
|
}
|
|
}
|