@yeaft/webchat-agent 0.1.248 → 0.1.249
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/connection/message-router.js +0 -26
- package/index.js +0 -2
- package/package.json +1 -1
- package/conductor/actor.js +0 -478
- package/conductor/claudemd-generator.js +0 -194
- package/conductor/conductor-claude.js +0 -480
- package/conductor/index.js +0 -65
- package/conductor/orchestrator-flows.js +0 -498
- package/conductor/orchestrator.js +0 -888
- package/conductor/persistence.js +0 -297
- package/conductor/personas/dev.js +0 -97
- package/conductor/personas/index.js +0 -77
- package/conductor/personas/trading.js +0 -92
- package/conductor/personas/video.js +0 -75
- package/conductor/personas/writing.js +0 -82
- package/conductor/semaphore.js +0 -73
- package/conductor/session.js +0 -210
- package/conductor/specialties/common.js +0 -350
- package/conductor/specialties/index.js +0 -135
- package/conductor/specialties/trading.js +0 -165
- package/conductor/specialties/video.js +0 -175
- package/conductor/specialties/writing.js +0 -120
- package/conductor/task.js +0 -333
- package/conductor/ui-messages.js +0 -170
- package/conductor/worktree.js +0 -182
- package/conductor.js +0 -35
package/conductor/index.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conductor — Module Entry
|
|
3
|
-
*
|
|
4
|
-
* Exports three core subsystems:
|
|
5
|
-
* 1. Personas — 18 persona definitions (4 scenarios)
|
|
6
|
-
* 2. Specialties — specialty behavior definitions
|
|
7
|
-
* 3. CLAUDE.md Generator — dynamic 3-section generation
|
|
8
|
-
* 4. Actor — Claude instance create/manage/release
|
|
9
|
-
* 5. Worktree — per-task worktree management
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
// ---- Personas ----
|
|
13
|
-
export {
|
|
14
|
-
getPersonaById,
|
|
15
|
-
getPersonasByScenario,
|
|
16
|
-
getPersonaPoolForOrchestrator,
|
|
17
|
-
getAllPersonas,
|
|
18
|
-
getScenarios,
|
|
19
|
-
personasByScenario
|
|
20
|
-
} from './personas/index.js';
|
|
21
|
-
|
|
22
|
-
// ---- Specialties ----
|
|
23
|
-
export {
|
|
24
|
-
getSpecialty,
|
|
25
|
-
getSpecialtiesByScenario,
|
|
26
|
-
getThinkingMode,
|
|
27
|
-
isDivergent,
|
|
28
|
-
getPersonalizedBehavior,
|
|
29
|
-
getOutputFormat,
|
|
30
|
-
formatToolRules,
|
|
31
|
-
personaSupportsSpecialty,
|
|
32
|
-
allSpecialties,
|
|
33
|
-
scenarioSpecialties
|
|
34
|
-
} from './specialties/index.js';
|
|
35
|
-
|
|
36
|
-
// ---- CLAUDE.md Generator ----
|
|
37
|
-
export {
|
|
38
|
-
generateActorCLAUDEmd,
|
|
39
|
-
generateActorInstanceId,
|
|
40
|
-
generateActorDirName
|
|
41
|
-
} from './claudemd-generator.js';
|
|
42
|
-
|
|
43
|
-
// ---- Actor Management ----
|
|
44
|
-
export {
|
|
45
|
-
createActor,
|
|
46
|
-
sendToActor,
|
|
47
|
-
releaseActor,
|
|
48
|
-
releaseAllActors,
|
|
49
|
-
getActor,
|
|
50
|
-
getActiveActors,
|
|
51
|
-
getAllActors,
|
|
52
|
-
getActorPublicState,
|
|
53
|
-
getActorStates,
|
|
54
|
-
classifyActorError,
|
|
55
|
-
actorRegistry
|
|
56
|
-
} from './actor.js';
|
|
57
|
-
|
|
58
|
-
// ---- Worktree Management ----
|
|
59
|
-
export {
|
|
60
|
-
createTaskWorktree,
|
|
61
|
-
cleanupTaskWorktree,
|
|
62
|
-
cleanupAllConductorWorktrees,
|
|
63
|
-
getTaskWorktreePath,
|
|
64
|
-
getActorCwd
|
|
65
|
-
} from './worktree.js';
|
|
@@ -1,498 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conductor Orchestrator — 场景特化流程定义
|
|
3
|
-
*
|
|
4
|
-
* 4 大场景 (Dev / Writing / Trading / Video) 各自定义:
|
|
5
|
-
* - TRIAGE 判定逻辑
|
|
6
|
-
* - 每个 Phase 的 Actor 编排策略
|
|
7
|
-
* - Quality Gate 规则
|
|
8
|
-
* - Acceptance 验收方式
|
|
9
|
-
*
|
|
10
|
-
* 这些流程被 Orchestrator 状态机消费,驱动具体的 Actor 调度。
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { Phase, ThinkingMode } from './task.js';
|
|
14
|
-
|
|
15
|
-
// =====================================================================
|
|
16
|
-
// Specialty 思维模式映射
|
|
17
|
-
// =====================================================================
|
|
18
|
-
|
|
19
|
-
const DIVERGENT_SPECIALTIES = new Set([
|
|
20
|
-
'planning', 'discussion', 'pacing', 'scripting', 'macro-analysis'
|
|
21
|
-
]);
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 根据 specialty 返回思维模式
|
|
25
|
-
*/
|
|
26
|
-
export function getThinkingMode(specialty) {
|
|
27
|
-
return DIVERGENT_SPECIALTIES.has(specialty)
|
|
28
|
-
? ThinkingMode.DIVERGENT
|
|
29
|
-
: ThinkingMode.CONVERGENT;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// =====================================================================
|
|
33
|
-
// Dev 场景流程
|
|
34
|
-
// =====================================================================
|
|
35
|
-
|
|
36
|
-
const devFlow = {
|
|
37
|
-
scenario: 'dev',
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* TRIAGE: 判定任务复杂度
|
|
41
|
-
* 返回 'trivial' | 'small' | 'complex'
|
|
42
|
-
*/
|
|
43
|
-
triageRules: {
|
|
44
|
-
trivial: [
|
|
45
|
-
'任务描述少于 2 句话',
|
|
46
|
-
'明确指向单个文件/单个函数的修改',
|
|
47
|
-
'不涉及架构变化,不涉及多文件联动'
|
|
48
|
-
],
|
|
49
|
-
small: [
|
|
50
|
-
'任务目标清晰,不需要讨论方向',
|
|
51
|
-
'可能涉及多个文件,但变更模式明确',
|
|
52
|
-
'不需要先出设计方案'
|
|
53
|
-
],
|
|
54
|
-
complex: [
|
|
55
|
-
'任务描述模糊或有多种理解方式',
|
|
56
|
-
'涉及架构决策、技术选型、用户体验取舍',
|
|
57
|
-
'需要多角色的视角碰撞才能确定方向',
|
|
58
|
-
'涉及 UI/前端时通常需要先 design'
|
|
59
|
-
]
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* DISCUSSION 编排:创建哪些 actor,如何协作
|
|
64
|
-
*/
|
|
65
|
-
discussion: {
|
|
66
|
-
defaultActors: [
|
|
67
|
-
{ personaId: 'rams', specialty: 'design', condition: 'ui_involved' },
|
|
68
|
-
{ personaId: 'jobs', specialty: 'discussion' },
|
|
69
|
-
{ personaId: 'torvalds', specialty: 'discussion' }
|
|
70
|
-
],
|
|
71
|
-
outputTarget: 'memory' // 讨论结果写入 memory.md
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* PLANNING 编排
|
|
76
|
-
*/
|
|
77
|
-
planning: {
|
|
78
|
-
actors: [
|
|
79
|
-
{ personaId: 'jobs', specialty: 'planning', role: 'product' },
|
|
80
|
-
{ personaId: 'torvalds', specialty: 'planning', role: 'lead' }
|
|
81
|
-
],
|
|
82
|
-
lead: 'torvalds', // Lead 负责合并最终 plan
|
|
83
|
-
minPlanners: 2,
|
|
84
|
-
outputTarget: 'plan' // 产出写入 plan.json
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* EXECUTION 编排:按 plan step 创建 coding actor
|
|
89
|
-
*/
|
|
90
|
-
execution: {
|
|
91
|
-
primaryCoder: 'torvalds',
|
|
92
|
-
secondaryCoder: 'beck',
|
|
93
|
-
supportsParallel: true // 可并行步骤同时创建多个 actor
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* QUALITY GATE 编排
|
|
98
|
-
*/
|
|
99
|
-
qualityGate: {
|
|
100
|
-
reviewer: { personaId: 'martin', specialty: 'review' },
|
|
101
|
-
tester: { personaId: 'beck', specialty: 'testing' },
|
|
102
|
-
parallel: true, // review 和 testing 可并行
|
|
103
|
-
passThreshold: 9, // 10分制, ≥9 通过
|
|
104
|
-
maxRetries: 3, // 同一步骤 fail ≥3 次 → 升级 discussion(设计文档 6.2.2)
|
|
105
|
-
codingRequiresReview: true,
|
|
106
|
-
codingRequiresTesting: true,
|
|
107
|
-
designRequiresReview: false,
|
|
108
|
-
docRequiresReview: false
|
|
109
|
-
},
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* ACCEPTANCE 编排
|
|
113
|
-
*/
|
|
114
|
-
acceptance: {
|
|
115
|
-
verifier: { personaId: 'jobs', specialty: 'planning' },
|
|
116
|
-
focusAreas: ['用户体验达标', 'successCriteria 逐条检查']
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
// =====================================================================
|
|
121
|
-
// Writing 场景流程
|
|
122
|
-
// =====================================================================
|
|
123
|
-
|
|
124
|
-
const writingFlow = {
|
|
125
|
-
scenario: 'writing',
|
|
126
|
-
|
|
127
|
-
triageRules: {
|
|
128
|
-
trivial: [
|
|
129
|
-
'修改单章内容',
|
|
130
|
-
'调整已有文本的措辞/表达'
|
|
131
|
-
],
|
|
132
|
-
small: [
|
|
133
|
-
'续写已有章节(基于已有大纲)',
|
|
134
|
-
'为已有卷添加章节'
|
|
135
|
-
],
|
|
136
|
-
complex: [
|
|
137
|
-
'新卷/新书(需要完整的大纲设计)',
|
|
138
|
-
'涉及人物弧线调整或世界观修改'
|
|
139
|
-
]
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
discussion: {
|
|
143
|
-
defaultActors: [
|
|
144
|
-
{ personaId: 'maoni', specialty: 'discussion' },
|
|
145
|
-
{ personaId: 'zhouzi', specialty: 'discussion' },
|
|
146
|
-
{ personaId: 'jinyong', specialty: 'discussion' }
|
|
147
|
-
],
|
|
148
|
-
focusAreas: {
|
|
149
|
-
maoni: '故事结构、伏笔布局、人物弧线',
|
|
150
|
-
zhouzi: '节奏体感、笑点密度、读者情绪过山车',
|
|
151
|
-
jinyong: '人物厚度、武侠精神内核、大格局叙事'
|
|
152
|
-
},
|
|
153
|
-
outputTarget: 'memory'
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
planning: {
|
|
157
|
-
actors: [
|
|
158
|
-
{ personaId: 'maoni', specialty: 'planning', role: 'lead' },
|
|
159
|
-
{ personaId: 'zhouzi', specialty: 'planning', role: 'execution-review' },
|
|
160
|
-
{ personaId: 'zhouzi', specialty: 'pacing', role: 'pacing' }
|
|
161
|
-
],
|
|
162
|
-
lead: 'maoni',
|
|
163
|
-
minPlanners: 2,
|
|
164
|
-
outputTarget: 'plan'
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
execution: {
|
|
168
|
-
primaryWriter: 'zhouzi',
|
|
169
|
-
supportsParallel: false // 章节串行写作
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
qualityGate: {
|
|
173
|
-
reviewer: { personaId: 'maboyong', specialty: 'editing' },
|
|
174
|
-
tester: null, // Writing 无 tester
|
|
175
|
-
parallel: false,
|
|
176
|
-
checkAreas: ['设定一致性', '时间线', '人物逻辑', '爽点落地', '文字质量'],
|
|
177
|
-
maxRetries: 3
|
|
178
|
-
},
|
|
179
|
-
|
|
180
|
-
acceptance: {
|
|
181
|
-
verifier: { personaId: 'maoni', specialty: 'planning' },
|
|
182
|
-
focusAreas: ['伏笔按计划埋设/回收', '人物弧线推进', '卷级目标达成']
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// =====================================================================
|
|
187
|
-
// Trading 场景流程
|
|
188
|
-
// =====================================================================
|
|
189
|
-
|
|
190
|
-
const tradingFlow = {
|
|
191
|
-
scenario: 'trading',
|
|
192
|
-
|
|
193
|
-
triageRules: {
|
|
194
|
-
trivial: [
|
|
195
|
-
'紧急交易指令(明确的品种/方向/仓位)',
|
|
196
|
-
'已有策略的简单执行'
|
|
197
|
-
],
|
|
198
|
-
small: [
|
|
199
|
-
'已有策略调整(参数微调、止损调整)',
|
|
200
|
-
'单一品种分析'
|
|
201
|
-
],
|
|
202
|
-
complex: [
|
|
203
|
-
'新策略制定',
|
|
204
|
-
'跨资产组合分析',
|
|
205
|
-
'市场拐点判断'
|
|
206
|
-
]
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Trading 特有:发散分析阶段(替代标准 discussion)
|
|
211
|
-
* 宏观分析和技术分析并行,然后进入 planning
|
|
212
|
-
*/
|
|
213
|
-
discussion: {
|
|
214
|
-
defaultActors: [
|
|
215
|
-
{ personaId: 'dalio', specialty: 'macro-analysis' },
|
|
216
|
-
{ personaId: 'livermore', specialty: 'technical-analysis' }
|
|
217
|
-
],
|
|
218
|
-
parallel: true,
|
|
219
|
-
outputTarget: 'memory'
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
planning: {
|
|
223
|
-
actors: [
|
|
224
|
-
{ personaId: 'soros', specialty: 'planning', role: 'lead' }
|
|
225
|
-
],
|
|
226
|
-
lead: 'soros',
|
|
227
|
-
minPlanners: 1,
|
|
228
|
-
outputTarget: 'plan'
|
|
229
|
-
},
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Trading 特有:对抗性讨论(PLANNING 之后自动进入)
|
|
233
|
-
* 设计文档 6.2.5: PLANNING → DISCUSSION(对抗性审查)→ QG → EXECUTION
|
|
234
|
-
*/
|
|
235
|
-
postPlanningDiscussion: {
|
|
236
|
-
actors: [
|
|
237
|
-
{ personaId: 'soros', specialty: 'discussion' },
|
|
238
|
-
{ personaId: 'taleb', specialty: 'discussion' }
|
|
239
|
-
],
|
|
240
|
-
purpose: '策略反脆弱压力测试',
|
|
241
|
-
challengePoints: [
|
|
242
|
-
'假设完全相反会怎样?',
|
|
243
|
-
'信念越强越需要警惕确认偏误',
|
|
244
|
-
'加仓条件是否是在沉船上往里跳?'
|
|
245
|
-
],
|
|
246
|
-
outputTarget: 'memory'
|
|
247
|
-
},
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Trading 特有:QG 在 EXECUTION 之前(风控审查通过才能执行)
|
|
251
|
-
* 设计文档 6.2.5: QG pass → 执行 / fail → 打回修改策略
|
|
252
|
-
*/
|
|
253
|
-
qualityGateBeforeExecution: true,
|
|
254
|
-
|
|
255
|
-
qualityGate: {
|
|
256
|
-
reviewer: { personaId: 'taleb', specialty: 'risk-review' },
|
|
257
|
-
tester: null,
|
|
258
|
-
parallel: false,
|
|
259
|
-
riskThresholds: {
|
|
260
|
-
maxPositionSize: 0.02, // 单仓 ≤ 2%
|
|
261
|
-
maxTotalExposure: 0.10, // 总敞口 ≤ 10%
|
|
262
|
-
minConvexity: 3, // 凸性 ≥ 3:1
|
|
263
|
-
requireTailHedge: true
|
|
264
|
-
},
|
|
265
|
-
maxRetries: 3
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
execution: {
|
|
269
|
-
executor: 'jones',
|
|
270
|
-
executorSpecialty: 'execution',
|
|
271
|
-
supportsParallel: false
|
|
272
|
-
},
|
|
273
|
-
|
|
274
|
-
acceptance: {
|
|
275
|
-
verifier: { personaId: 'soros', specialty: 'planning' },
|
|
276
|
-
focusAreas: ['假设是否仍成立', '信念强度变化', '风险回报比']
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
// =====================================================================
|
|
281
|
-
// Video 场景流程
|
|
282
|
-
// =====================================================================
|
|
283
|
-
|
|
284
|
-
const videoFlow = {
|
|
285
|
-
scenario: 'video',
|
|
286
|
-
|
|
287
|
-
triageRules: {
|
|
288
|
-
trivial: [
|
|
289
|
-
'调整单段 prompt 的参数或措辞',
|
|
290
|
-
'修改单个分镜细节'
|
|
291
|
-
],
|
|
292
|
-
small: [
|
|
293
|
-
'修改已有脚本/分镜',
|
|
294
|
-
'局部调整一致性锚点'
|
|
295
|
-
],
|
|
296
|
-
complex: [
|
|
297
|
-
'新视频项目(需要完整流程)',
|
|
298
|
-
'涉及风格方向变更'
|
|
299
|
-
]
|
|
300
|
-
},
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Video 使用 planning 阶段确定整体方案,不走标准 discussion
|
|
304
|
-
*/
|
|
305
|
-
discussion: {
|
|
306
|
-
defaultActors: [
|
|
307
|
-
{ personaId: 'jia', specialty: 'discussion' },
|
|
308
|
-
{ personaId: 'shi', specialty: 'discussion' }
|
|
309
|
-
],
|
|
310
|
-
outputTarget: 'memory'
|
|
311
|
-
},
|
|
312
|
-
|
|
313
|
-
planning: {
|
|
314
|
-
actors: [
|
|
315
|
-
{ personaId: 'jia', specialty: 'planning', role: 'lead' }
|
|
316
|
-
],
|
|
317
|
-
lead: 'jia',
|
|
318
|
-
minPlanners: 1,
|
|
319
|
-
outputTarget: 'plan'
|
|
320
|
-
},
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Video EXECUTION: 严格串行的三阶段
|
|
324
|
-
*
|
|
325
|
-
* Stage A: scripting (史铁生) → jia review
|
|
326
|
-
* Stage B: storyboarding (徐克) → jia review
|
|
327
|
-
* Stage C: prompt-assembly (顾长卫)
|
|
328
|
-
*/
|
|
329
|
-
execution: {
|
|
330
|
-
strictSerial: true,
|
|
331
|
-
stages: [
|
|
332
|
-
{
|
|
333
|
-
name: 'scripting',
|
|
334
|
-
actor: { personaId: 'shi', specialty: 'scripting' },
|
|
335
|
-
reviewAfter: { personaId: 'jia', specialty: 'review' },
|
|
336
|
-
description: '基于方案写分段脚本'
|
|
337
|
-
},
|
|
338
|
-
{
|
|
339
|
-
name: 'storyboarding',
|
|
340
|
-
actor: { personaId: 'tsui', specialty: 'storyboarding' },
|
|
341
|
-
reviewAfter: { personaId: 'jia', specialty: 'review' },
|
|
342
|
-
description: '基于脚本设计分镜'
|
|
343
|
-
},
|
|
344
|
-
{
|
|
345
|
-
name: 'prompt-assembly',
|
|
346
|
-
actor: { personaId: 'gu', specialty: 'prompt-assembly' },
|
|
347
|
-
reviewAfter: null,
|
|
348
|
-
description: '组装最终 AI 视频 prompt'
|
|
349
|
-
}
|
|
350
|
-
],
|
|
351
|
-
supportsParallel: false
|
|
352
|
-
},
|
|
353
|
-
|
|
354
|
-
qualityGate: {
|
|
355
|
-
reviewer: { personaId: 'gu', specialty: 'continuity-check' },
|
|
356
|
-
tester: null,
|
|
357
|
-
parallel: false,
|
|
358
|
-
checkAreas: ['锚点完整性', '色调统一', '角色描述一致', '时长合理'],
|
|
359
|
-
maxRetries: 3
|
|
360
|
-
},
|
|
361
|
-
|
|
362
|
-
acceptance: {
|
|
363
|
-
verifier: { personaId: 'jia', specialty: 'planning' },
|
|
364
|
-
focusAreas: ['叙事弧线完整', '情绪曲线合理', '视觉一致性', '整体感觉']
|
|
365
|
-
}
|
|
366
|
-
};
|
|
367
|
-
|
|
368
|
-
// =====================================================================
|
|
369
|
-
// Flow Registry
|
|
370
|
-
// =====================================================================
|
|
371
|
-
|
|
372
|
-
const FLOWS = new Map([
|
|
373
|
-
['dev', devFlow],
|
|
374
|
-
['writing', writingFlow],
|
|
375
|
-
['trading', tradingFlow],
|
|
376
|
-
['video', videoFlow]
|
|
377
|
-
]);
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* 获取场景流程定义
|
|
381
|
-
* @param {string} scenario — 'dev' | 'writing' | 'trading' | 'video'
|
|
382
|
-
* @returns {ScenarioFlow}
|
|
383
|
-
*/
|
|
384
|
-
export function getFlow(scenario) {
|
|
385
|
-
const flow = FLOWS.get(scenario);
|
|
386
|
-
if (!flow) {
|
|
387
|
-
throw new Error(`Unknown scenario: ${scenario}. Available: ${[...FLOWS.keys()].join(', ')}`);
|
|
388
|
-
}
|
|
389
|
-
return flow;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* 获取所有已注册场景
|
|
394
|
-
*/
|
|
395
|
-
export function getAvailableScenarios() {
|
|
396
|
-
return [...FLOWS.keys()];
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// =====================================================================
|
|
400
|
-
// Flow Query Helpers
|
|
401
|
-
// =====================================================================
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* 获取 discussion 阶段应创建的 actor 列表
|
|
405
|
-
* @param {ScenarioFlow} flow
|
|
406
|
-
* @param {object} context — { uiInvolved: boolean }
|
|
407
|
-
* @returns {Array<{personaId, specialty}>}
|
|
408
|
-
*/
|
|
409
|
-
export function getDiscussionActors(flow, context = {}) {
|
|
410
|
-
const actors = flow.discussion.defaultActors || [];
|
|
411
|
-
return actors.filter(a => {
|
|
412
|
-
if (a.condition === 'ui_involved') return context.uiInvolved;
|
|
413
|
-
return true;
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* 获取 planning 阶段应创建的 actor 列表
|
|
419
|
-
*/
|
|
420
|
-
export function getPlanningActors(flow) {
|
|
421
|
-
return flow.planning.actors || [];
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* 获取 planning lead persona ID
|
|
426
|
-
*/
|
|
427
|
-
export function getPlanningLead(flow) {
|
|
428
|
-
return flow.planning.lead;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* 获取 quality gate 配置
|
|
433
|
-
*/
|
|
434
|
-
export function getQualityGateConfig(flow) {
|
|
435
|
-
return flow.qualityGate;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
/**
|
|
439
|
-
* 获取 acceptance verifier
|
|
440
|
-
*/
|
|
441
|
-
export function getAcceptanceVerifier(flow) {
|
|
442
|
-
return flow.acceptance.verifier;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* 判断某个步骤是否需要经过 quality gate
|
|
447
|
-
*
|
|
448
|
-
* @param {ScenarioFlow} flow
|
|
449
|
-
* @param {string} specialty — 该步骤 actor 的 specialty
|
|
450
|
-
* @returns {boolean}
|
|
451
|
-
*/
|
|
452
|
-
export function needsQualityGate(flow, specialty) {
|
|
453
|
-
const qg = flow.qualityGate;
|
|
454
|
-
if (specialty === 'coding') {
|
|
455
|
-
return qg.codingRequiresReview !== false || qg.codingRequiresTesting !== false;
|
|
456
|
-
}
|
|
457
|
-
if (specialty === 'writing') {
|
|
458
|
-
return !!qg.reviewer;
|
|
459
|
-
}
|
|
460
|
-
if (specialty === 'design') {
|
|
461
|
-
return qg.designRequiresReview === true;
|
|
462
|
-
}
|
|
463
|
-
if (specialty === 'execution') {
|
|
464
|
-
// Trading: execution actor 的产出需要风控审查(如果配置了 QG before execution)
|
|
465
|
-
// 但如果 QG 已在 execution 之前跑过了,这里就不需要重复
|
|
466
|
-
// 其他场景中 execution specialty 不存在,直接返回 false
|
|
467
|
-
return flow.qualityGateBeforeExecution !== true
|
|
468
|
-
&& flow.scenario === 'trading'
|
|
469
|
-
&& !!qg.reviewer;
|
|
470
|
-
}
|
|
471
|
-
// 其他 specialty(prompt-assembly 等)— 检查是否有 reviewer
|
|
472
|
-
return false;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* 获取 post-planning discussion 配置(Trading 对抗性审查)
|
|
477
|
-
* PLANNING 完成后自动进入此 discussion
|
|
478
|
-
*/
|
|
479
|
-
export function getPostPlanningDiscussion(flow) {
|
|
480
|
-
return flow.postPlanningDiscussion || null;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
* 该场景的 QG 是否在 EXECUTION 之前(Trading: 风控通过才能交易)
|
|
485
|
-
*/
|
|
486
|
-
export function isQualityGateBeforeExecution(flow) {
|
|
487
|
-
return flow.qualityGateBeforeExecution === true;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
/**
|
|
491
|
-
* Video 特有:获取严格串行 stages
|
|
492
|
-
*/
|
|
493
|
-
export function getExecutionStages(flow) {
|
|
494
|
-
if (flow.execution?.strictSerial) {
|
|
495
|
-
return flow.execution.stages || [];
|
|
496
|
-
}
|
|
497
|
-
return null;
|
|
498
|
-
}
|