feat(app): wire projectinstance duties into bizdev

Composition-root adapter maps live instance DocTasks to bizdev's narrow
InstanceDutySource without crossing module boundaries.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-17 09:59:38 +00:00
co-authored by Cursor
parent 5b9b46ee8d
commit 750b904439
2 changed files with 47 additions and 0 deletions
+1
View File
@@ -222,6 +222,7 @@ func Assemble(cfg *config.Config, svc *bizdev.Service) (*Runtime, error) {
})
if instSvc != nil {
instSvc.SetAuthorOnlyPolicySource(&sysadminAuthorOnlyPolicyAdapter{svc: rt.SysAdmin})
svc.SetInstanceDutySource(&projectInstanceDutyAdapter{inst: instSvc})
}
rt.DocNotify = &docnotify.Subscriber{Notify: rt.Notify, Docs: parts.Gov}
rt.DocNotify.SkipWrite = func(ctx context.Context) bool {
+46
View File
@@ -0,0 +1,46 @@
package app
import (
"context"
"strings"
"chat-agent-system/internal/projectinstance"
)
// projectInstanceDutyAdapter 将活跃工作流实例的逐文档职责投影为 bizdev 窄接口,
// 避免 bizdev 导入 projectinstance。
type projectInstanceDutyAdapter struct {
inst *projectinstance.Service
}
func (a *projectInstanceDutyAdapter) ResolveGovernedDuty(ctx context.Context, projectID int64, taskKey string) (author, reviewer, approver int64, dutyPolicy string, governed bool, err error) {
if a == nil || a.inst == nil || projectID <= 0 {
return 0, 0, 0, "", false, nil
}
taskKey = strings.TrimSpace(taskKey)
if taskKey == "" {
return 0, 0, 0, "", false, nil
}
detail, _, derr := a.inst.GetLiveInstanceDetail(ctx, projectID)
if derr != nil || detail == nil {
// 无活跃实例(规划中/legacy)→ 不受治理,非错误
return 0, 0, 0, "", false, nil
}
for _, st := range detail.Instance.ConfigSnapshot.Stages {
for _, dt := range st.DocTasks {
if dt.TaskKey != taskKey || !dt.Enabled {
continue
}
mode, effective, isAuthorOnly := projectinstance.ResolveDocTaskDuty(dt)
if mode != projectinstance.DutyModeFull {
return 0, 0, 0, "", false, nil
}
policy := projectinstance.DutyPolicySeparated
if isAuthorOnly {
policy = projectinstance.DutyPolicyAuthorOnly
}
return effective.AuthorUserID, effective.ReviewerUserID, effective.ApproverUserID, policy, true, nil
}
}
return 0, 0, 0, "", false, nil
}