@goodandready/dsh-agent-orchestrator 0.1.6

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.
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Idempotent Preset & Role Self-Synchronization Engine (Issue #107).
3
+ * Runtime Scenario Validation Connected (Issue #132).
4
+ *
5
+ * Implements:
6
+ * 1. Automatic, zero-external-script self-healing synchronization on plugin apply(ctx).
7
+ * 2. Non-destructive merge: preserves user modifications (custom systemPrompt, model, temperature, enabled)
8
+ * while adding newly introduced canonical roles or presets from scenarios.js.
9
+ * 3. Validates scenarios via validateScenario() and filters out corrupt/cyclic scenarios safely.
10
+ * 4. Sanitizes any orphaned/stale references safely.
11
+ */
12
+
13
+ import { getDefaultRoles, getDefaultScenarios, validateScenario } from './scenarios.js'
14
+ import { toRolesArray } from './delegation.js'
15
+
16
+ /**
17
+ * Idempotently merges default roles and scenarios into existing configuration.
18
+ *
19
+ * @param {object} params
20
+ * @param {Array<object>|object} [params.currentRoles] Existing configured roles
21
+ * @param {object} [params.currentScenarios] Existing configured scenarios
22
+ * @param {object} [params.logger] Optional logger for diagnostics
23
+ * @returns {{ roles: Array<object>, scenarios: object, addedRolesCount: number, addedScenariosCount: number }}
24
+ */
25
+ export function syncDefaultPresets({ currentRoles, currentScenarios, logger } = {}) {
26
+ const defaultRoles = toRolesArray(getDefaultRoles())
27
+ const defaultScenarios = getDefaultScenarios()
28
+
29
+ // 1. Normalize current roles
30
+ const roleList = toRolesArray(currentRoles)
31
+ const existingRoleIds = new Set(roleList.map((r) => r.id))
32
+ let addedRolesCount = 0
33
+
34
+ // 2. Add missing default roles without mutating existing ones
35
+ for (const defRole of defaultRoles) {
36
+ if (!existingRoleIds.has(defRole.id)) {
37
+ roleList.push({ ...defRole, enabled: defRole.enabled !== false })
38
+ existingRoleIds.add(defRole.id)
39
+ addedRolesCount++
40
+ }
41
+ }
42
+
43
+ // 3. Normalize, validate & sync scenarios
44
+ const scenarioMap = {}
45
+ if (currentScenarios && typeof currentScenarios === 'object') {
46
+ for (const [sId, sc] of Object.entries(currentScenarios)) {
47
+ if (sc && typeof sc === 'object' && sc.id) {
48
+ if (Array.isArray(sc.stages) && sc.stages.length > 0) {
49
+ try {
50
+ validateScenario(sc)
51
+ } catch (err) {
52
+ if (logger?.warn) {
53
+ logger.warn(`[PresetSync] Discarding invalid existing scenario "${sId}": ${err.message}`)
54
+ }
55
+ continue
56
+ }
57
+ }
58
+ scenarioMap[sId] = sc
59
+ }
60
+ }
61
+ }
62
+
63
+ let addedScenariosCount = 0
64
+ for (const [sId, defScenario] of Object.entries(defaultScenarios)) {
65
+ if (!scenarioMap[sId]) {
66
+ try {
67
+ validateScenario(defScenario)
68
+ scenarioMap[sId] = { ...defScenario }
69
+ addedScenariosCount++
70
+ } catch (err) {
71
+ if (logger?.error) {
72
+ logger.error(`[PresetSync] Default scenario "${sId}" failed validation: ${err.message}`)
73
+ }
74
+ }
75
+ }
76
+ }
77
+
78
+ return {
79
+ roles: roleList,
80
+ scenarios: scenarioMap,
81
+ addedRolesCount,
82
+ addedScenariosCount,
83
+ }
84
+ }
@@ -0,0 +1,468 @@
1
+ /**
2
+ * Predefined Scenarios & Agent Role Profiles for DSH Multi-Agent Orchestrator.
3
+ *
4
+ * All agent profiles and scenarios are self-contained within plugin settings (no external path dependencies).
5
+ * Roles enforce strict separation of duties (e.g. backend and frontend/design are separate agents and stages).
6
+ */
7
+
8
+ import { validateGraph } from './dag-engine.js'
9
+
10
+ export const ROLE_IDS = {
11
+ SPEC: 'spec',
12
+ ARCHITECTURE: 'architecture',
13
+ UI_DESIGN: 'ui_design',
14
+ FRONTEND: 'frontend',
15
+ BACKEND: 'backend',
16
+ FULLSTACK: 'fullstack',
17
+ QA_TESTS: 'qa_tests',
18
+ BUGFIX: 'bugfix',
19
+ DOCS: 'docs',
20
+ REFACTORING: 'refactoring',
21
+ RESEARCH: 'research',
22
+ DEVOPS: 'devops',
23
+ }
24
+
25
+ export const FULL_TOOL_SUITE = [
26
+ // DSH Native Tools
27
+ 'read',
28
+ 'write',
29
+ 'edit',
30
+ 'glob',
31
+ 'grep',
32
+ 'bash',
33
+ // Agent & Antigravity Aliases
34
+ 'view_file',
35
+ 'replace_file_content',
36
+ 'write_to_file',
37
+ 'run_command',
38
+ 'grep_search',
39
+ 'find_by_name',
40
+ 'list_dir',
41
+ 'read_url_content',
42
+ 'search_web',
43
+ ]
44
+
45
+ /**
46
+ * 12 Built-in specialized agent roles stored purely inside plugin settings.
47
+ */
48
+ export function getDefaultRoles() {
49
+ return {
50
+ [ROLE_IDS.SPEC]: {
51
+ id: ROLE_IDS.SPEC,
52
+ name: 'Technical Spec Analyst',
53
+ category: 'Requirements & Functional Bounds',
54
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
55
+ reasoningEffort: 'high',
56
+ skills: ['project-design-contract', 'planning-with-files'],
57
+ tools: [...FULL_TOOL_SUITE],
58
+ systemPrompt: [
59
+ 'You are the Lead Technical Spec Analyst.',
60
+ 'Responsibilities: Formulate exhaustive, unambiguous functional requirements, acceptance criteria (DoD), input/output schemas, and error boundaries.',
61
+ 'Strict Boundaries: NEVER write production implementation code, never create styling, never merge code. Deliver only clean, structured technical specifications.',
62
+ ].join(' '),
63
+ temperature: 0.2,
64
+ maxTokens: 4096,
65
+ },
66
+ [ROLE_IDS.ARCHITECTURE]: {
67
+ id: ROLE_IDS.ARCHITECTURE,
68
+ name: 'System Architect',
69
+ category: 'System Design & Contracts',
70
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
71
+ reasoningEffort: 'high',
72
+ skills: ['project-design-contract', 'dsh-plugin-authoring', 'ponytail'],
73
+ tools: [...FULL_TOOL_SUITE],
74
+ systemPrompt: [
75
+ 'You are the Principal System Architect.',
76
+ 'Responsibilities: Design modular architectures adhering strictly to DSH conventions, Cordis service lifecycles, and standard library primitives. Deliver DESIGN.md, ADR, and interface contracts.',
77
+ 'Strict Boundaries: NEVER implement full production code, never deploy, never mix frontend styles into backend architecture.',
78
+ ].join(' '),
79
+ temperature: 0.2,
80
+ maxTokens: 4096,
81
+ },
82
+ [ROLE_IDS.UI_DESIGN]: {
83
+ id: ROLE_IDS.UI_DESIGN,
84
+ name: 'UI/UX Interface Designer',
85
+ category: 'UI/UX & Slot Integrations',
86
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
87
+ reasoningEffort: 'medium',
88
+ skills: ['dsh-ui-design', 'minimalist-ui', 'design-taste-frontend'],
89
+ tools: [...FULL_TOOL_SUITE],
90
+ systemPrompt: [
91
+ 'You are the Lead Interface & Slot Designer.',
92
+ 'Responsibilities: Craft clean, native UI surfaces for DSH. Specify layout hierarchy, theme CSS variables (--dsw-alias-*), prefix isolation (.dso-*), and interactive states (loading, empty, ready, error).',
93
+ 'Strict Boundaries: NEVER write backend Cordis services, database logic, or server routes. Focus exclusively on visual interface design and token contracts.',
94
+ ].join(' '),
95
+ temperature: 0.3,
96
+ maxTokens: 8192,
97
+ },
98
+ [ROLE_IDS.FRONTEND]: {
99
+ id: ROLE_IDS.FRONTEND,
100
+ name: 'Frontend Developer',
101
+ category: 'Client Components & Interaction',
102
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
103
+ reasoningEffort: 'medium',
104
+ skills: ['dsh-ui-design', 'full-output-enforcement'],
105
+ tools: [...FULL_TOOL_SUITE],
106
+ systemPrompt: [
107
+ 'You are the Senior Frontend Developer.',
108
+ 'Responsibilities: Implement React client components, hook state management, DOM event listeners, and slot registrations according to UI design specs. Keep bundle size below 250 KiB.',
109
+ 'Strict Boundaries: NEVER modify backend server routes or database schemas. Do not invent design tokens that violate the designer specification.',
110
+ ].join(' '),
111
+ temperature: 0.2,
112
+ maxTokens: 8192,
113
+ },
114
+ [ROLE_IDS.BACKEND]: {
115
+ id: ROLE_IDS.BACKEND,
116
+ name: 'Backend Developer',
117
+ category: 'Server Logic & Services',
118
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
119
+ reasoningEffort: 'medium',
120
+ skills: ['dsh-plugin-authoring', 'full-output-enforcement', 'ponytail'],
121
+ tools: [...FULL_TOOL_SUITE],
122
+ systemPrompt: [
123
+ 'You are the Senior Backend Developer.',
124
+ 'Responsibilities: Implement host Cordis modules, WebServer routes, store persistence, credentials resolution, and tools definitions. Use Node.js ESM and standard library.',
125
+ 'Strict Boundaries: NEVER write React UI JSX or client CSS styles. Server and client remain strictly decoupled.',
126
+ ].join(' '),
127
+ temperature: 0.2,
128
+ maxTokens: 8192,
129
+ },
130
+ [ROLE_IDS.FULLSTACK]: {
131
+ id: ROLE_IDS.FULLSTACK,
132
+ name: 'Fullstack Integrator',
133
+ category: 'End-to-End Feature Assembly',
134
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
135
+ reasoningEffort: 'medium',
136
+ skills: ['dsh-plugin-authoring', 'dsh-ui-design', 'full-output-enforcement'],
137
+ tools: [...FULL_TOOL_SUITE],
138
+ systemPrompt: [
139
+ 'You are the Fullstack Integration Engineer.',
140
+ 'Responsibilities: Assemble client-server contracts, wire HTTP endpoints with client hooks, and ensure seamless end-to-end data flow between backend services and UI slots.',
141
+ 'Strict Boundaries: Always respect modular file boundaries (max 500-600 lines per file). Never bypass established architectural contracts.',
142
+ ].join(' '),
143
+ temperature: 0.2,
144
+ maxTokens: 8192,
145
+ },
146
+ [ROLE_IDS.QA_TESTS]: {
147
+ id: ROLE_IDS.QA_TESTS,
148
+ name: 'QA Automation Engineer',
149
+ category: 'Automated Testing & Security',
150
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
151
+ reasoningEffort: 'medium',
152
+ skills: ['dsh-plugin-authoring', 'ponytail-review'],
153
+ tools: [...FULL_TOOL_SUITE],
154
+ systemPrompt: [
155
+ 'You are the QA Automation Specialist.',
156
+ 'Responsibilities: Write pure unit tests (`node --test test/*.test.mjs`), boundary condition verifications, rate-limit recovery mocks, and cycle detection checks with zero external network dependencies.',
157
+ 'Strict Boundaries: Deliver exhaustive verification suites and pinpoint edge-case defects.',
158
+ ].join(' '),
159
+ temperature: 0.2,
160
+ maxTokens: 4096,
161
+ },
162
+ [ROLE_IDS.BUGFIX]: {
163
+ id: ROLE_IDS.BUGFIX,
164
+ name: 'Hotfix & Triage Engineer',
165
+ category: 'Diagnostic & Defect Elimination',
166
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
167
+ reasoningEffort: 'low',
168
+ skills: ['dsh-plugin-authoring', 'ponytail'],
169
+ tools: [...FULL_TOOL_SUITE],
170
+ systemPrompt: [
171
+ 'You are the Hotfix Engineer.',
172
+ 'Responsibilities: Perform root-cause diagnosis of defects, apply targeted minimal fixes, verify that no regressions are introduced, and confirm the fix passes test suites.',
173
+ 'Strict Boundaries: Minimal blast radius, laser-targeted code modifications.',
174
+ ].join(' '),
175
+ temperature: 0.1,
176
+ maxTokens: 4096,
177
+ },
178
+ [ROLE_IDS.DOCS]: {
179
+ id: ROLE_IDS.DOCS,
180
+ name: 'Documentation Specialist',
181
+ category: 'Technical Writing & Releases',
182
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
183
+ reasoningEffort: 'low',
184
+ skills: ['dsh-documentation-standard', 'dhs-plugin-release-workflow'],
185
+ tools: [...FULL_TOOL_SUITE],
186
+ systemPrompt: [
187
+ 'You are the Lead Technical Writer.',
188
+ 'Responsibilities: Produce rich technical documentation following the additive gate standard. Maintain README in English, Russian, and Chinese, documenting features, settings, API endpoints, and verification evidence.',
189
+ 'Strict Boundaries: Never delete or overwrite previous feature documentation; update by addition.',
190
+ ].join(' '),
191
+ temperature: 0.3,
192
+ maxTokens: 4096,
193
+ },
194
+ [ROLE_IDS.REFACTORING]: {
195
+ id: ROLE_IDS.REFACTORING,
196
+ name: 'Refactoring & Optimization Specialist',
197
+ category: 'Complexity Reduction & Performance',
198
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
199
+ reasoningEffort: 'medium',
200
+ skills: ['ponytail', 'ponytail-review', 'full-output-enforcement'],
201
+ tools: [...FULL_TOOL_SUITE],
202
+ systemPrompt: [
203
+ 'You are the Refactoring Specialist.',
204
+ 'Responsibilities: Hunt for complexity, remove dead flexibility, replace custom helpers with native standard library methods, reduce bundle size below 250 KiB, and verify that all test suites remain 100% green.',
205
+ 'Strict Boundaries: Maintain full backward compatibility and zero regressions.',
206
+ ].join(' '),
207
+ temperature: 0.2,
208
+ maxTokens: 8192,
209
+ },
210
+ [ROLE_IDS.RESEARCH]: {
211
+ id: ROLE_IDS.RESEARCH,
212
+ name: 'Research & Spike Engineer',
213
+ category: 'Exploration & Technology Evaluation',
214
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
215
+ reasoningEffort: 'high',
216
+ skills: ['planning-with-files'],
217
+ tools: [...FULL_TOOL_SUITE],
218
+ systemPrompt: [
219
+ 'You are the Research & Spike Specialist.',
220
+ 'Responsibilities: Conduct technical evaluations, evaluate trade-offs between libraries or model providers, benchmark latency/cost, and build isolated proof-of-concepts.',
221
+ 'Strict Boundaries: Deliver clear findings, benchmarks, and actionable recommendations.',
222
+ ].join(' '),
223
+ temperature: 0.3,
224
+ maxTokens: 4096,
225
+ },
226
+ [ROLE_IDS.DEVOPS]: {
227
+ id: ROLE_IDS.DEVOPS,
228
+ name: 'DevOps & Tooling Engineer',
229
+ category: 'Packaging, CI & Environment',
230
+ defaultModel: { provider: 'deepseek', model: 'deepseek-chat' },
231
+ reasoningEffort: 'low',
232
+ skills: ['dhs-plugin-release-workflow'],
233
+ tools: [...FULL_TOOL_SUITE],
234
+ systemPrompt: [
235
+ 'You are the DevOps & Tooling Specialist.',
236
+ 'Responsibilities: Configure package manifests, verify npm pack file sizes (<256 KiB), maintain build scripts, validate systemd units, and automate verification workflows.',
237
+ 'Strict Boundaries: Never expose credentials or private network IPs. Use credential references exclusively.',
238
+ ].join(' '),
239
+ temperature: 0.1,
240
+ maxTokens: 4096,
241
+ },
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Default scenario topologies: hotfix (1), simple (2), medium (3-4), complex (5-6), enterprise (7+).
247
+ */
248
+ export function getDefaultScenarios() {
249
+ return {
250
+ hotfix: {
251
+ id: 'hotfix',
252
+ title: 'Hotfix / Trivial (1 Stage)',
253
+ description: 'Instant defect elimination or single-parameter tweak with direct verification.',
254
+ stages: [
255
+ {
256
+ id: 'stage_hotfix',
257
+ name: 'Hotfix Implementation & Smoke Test',
258
+ roleId: ROLE_IDS.BUGFIX,
259
+ dependsOn: [],
260
+ isParallelAllowed: false,
261
+ subtaskScope: 'Locate the defect, apply targeted minimal fix, and verify zero regressions.',
262
+ },
263
+ ],
264
+ },
265
+ simple: {
266
+ id: 'simple',
267
+ title: 'Simple Scenario (2 Stages)',
268
+ description: 'Clarification/Spec followed by targeted execution (e.g. Design, Backend fix, or Docs).',
269
+ stages: [
270
+ {
271
+ id: 'stage_spec',
272
+ name: 'Task Discussion & Scope Specification',
273
+ roleId: ROLE_IDS.SPEC,
274
+ dependsOn: [],
275
+ isParallelAllowed: false,
276
+ subtaskScope: 'Clarify objectives, formulate acceptance criteria, and establish boundary constraints.',
277
+ },
278
+ {
279
+ id: 'stage_exec',
280
+ name: 'Targeted Implementation',
281
+ roleId: ROLE_IDS.UI_DESIGN,
282
+ dependsOn: ['stage_spec'],
283
+ isParallelAllowed: false,
284
+ subtaskScope: 'Execute the agreed specification with complete, production-ready deliverables.',
285
+ },
286
+ ],
287
+ },
288
+ medium: {
289
+ id: 'medium',
290
+ title: 'Medium Scenario (3–4 Stages)',
291
+ description: 'Standard feature development with strict separation of design, implementation, and testing.',
292
+ stages: [
293
+ {
294
+ id: 'stage_spec',
295
+ name: '1. Specification & Requirements',
296
+ roleId: ROLE_IDS.SPEC,
297
+ dependsOn: [],
298
+ isParallelAllowed: false,
299
+ subtaskScope: 'Define technical specification, schemas, and DoD criteria.',
300
+ },
301
+ {
302
+ id: 'stage_design',
303
+ name: '2. UI Design & Layouts',
304
+ roleId: ROLE_IDS.UI_DESIGN,
305
+ dependsOn: ['stage_spec'],
306
+ isParallelAllowed: false,
307
+ subtaskScope: 'Create UI layouts, theme CSS variables, and slot specifications.',
308
+ },
309
+ {
310
+ id: 'stage_frontend',
311
+ name: '3. Frontend Code Implementation',
312
+ roleId: ROLE_IDS.FRONTEND,
313
+ dependsOn: ['stage_design'],
314
+ isParallelAllowed: false,
315
+ subtaskScope: 'Implement client React components based strictly on the approved design.',
316
+ },
317
+ {
318
+ id: 'stage_tests',
319
+ name: '4. Automated Verification & QA',
320
+ roleId: ROLE_IDS.QA_TESTS,
321
+ dependsOn: ['stage_frontend'],
322
+ isParallelAllowed: false,
323
+ subtaskScope: 'Verify frontend logic, mock APIs, and ensure edge cases pass cleanly.',
324
+ },
325
+ ],
326
+ },
327
+ complex: {
328
+ id: 'complex',
329
+ title: 'Complex Scenario (5–6 Stages)',
330
+ description: 'Full multi-agent engineering lifecycle: Spec -> Architecture -> Design -> Code -> QA -> Trilingual Docs.',
331
+ stages: [
332
+ {
333
+ id: 'stage_1_spec',
334
+ name: '1. Technical Specification',
335
+ roleId: ROLE_IDS.SPEC,
336
+ dependsOn: [],
337
+ isParallelAllowed: false,
338
+ subtaskScope: 'Draft functional requirements, acceptance criteria, and boundary constraints.',
339
+ },
340
+ {
341
+ id: 'stage_2_architecture',
342
+ name: '2. System Design & DESIGN.md',
343
+ roleId: ROLE_IDS.ARCHITECTURE,
344
+ dependsOn: ['stage_1_spec'],
345
+ isParallelAllowed: false,
346
+ subtaskScope: 'Produce DESIGN.md, define Cordis service interfaces, and structure module boundaries.',
347
+ },
348
+ {
349
+ id: 'stage_3_ui_design',
350
+ name: '3. UI/UX Interface Design',
351
+ roleId: ROLE_IDS.UI_DESIGN,
352
+ dependsOn: ['stage_2_architecture'],
353
+ isParallelAllowed: true,
354
+ subtaskScope: 'Design client components, CSS theme variables, and interactive states.',
355
+ },
356
+ {
357
+ id: 'stage_4_code',
358
+ name: '4. Code Implementation',
359
+ roleId: ROLE_IDS.FRONTEND,
360
+ dependsOn: ['stage_2_architecture', 'stage_3_ui_design'],
361
+ isParallelAllowed: false,
362
+ subtaskScope: 'Implement software modules adhering to architectural contracts and design layouts.',
363
+ },
364
+ {
365
+ id: 'stage_5_qa_tests',
366
+ name: '5. Automated Testing & Verification',
367
+ roleId: ROLE_IDS.QA_TESTS,
368
+ dependsOn: ['stage_4_code'],
369
+ isParallelAllowed: false,
370
+ subtaskScope: 'Develop and execute exhaustive unit tests (`node --test test/*.test.mjs`).',
371
+ },
372
+ {
373
+ id: 'stage_6_docs',
374
+ name: '6. Trilingual Documentation & Release Notes',
375
+ roleId: ROLE_IDS.DOCS,
376
+ dependsOn: ['stage_4_code', 'stage_5_qa_tests'],
377
+ isParallelAllowed: false,
378
+ subtaskScope: 'Update README in English, Russian, and Chinese following additive documentation gate.',
379
+ },
380
+ ],
381
+ },
382
+ enterprise: {
383
+ id: 'enterprise',
384
+ title: 'Enterprise / Deep R&D (7 Stages)',
385
+ description: 'Full exploratory and fullstack lifecycle with parallel backend/frontend branches and QA gate.',
386
+ stages: [
387
+ {
388
+ id: 'stage_1_research',
389
+ name: '1. Spike & Technology Research',
390
+ roleId: ROLE_IDS.RESEARCH,
391
+ dependsOn: [],
392
+ isParallelAllowed: false,
393
+ subtaskScope: 'Investigate libraries, external APIs, and evaluate trade-offs.',
394
+ },
395
+ {
396
+ id: 'stage_2_spec',
397
+ name: '2. Specification & Contracts',
398
+ roleId: ROLE_IDS.SPEC,
399
+ dependsOn: ['stage_1_research'],
400
+ isParallelAllowed: false,
401
+ subtaskScope: 'Draft technical specification and formal acceptance contracts.',
402
+ },
403
+ {
404
+ id: 'stage_3_arch',
405
+ name: '3. System Architecture & DESIGN.md',
406
+ roleId: ROLE_IDS.ARCHITECTURE,
407
+ dependsOn: ['stage_2_spec'],
408
+ isParallelAllowed: false,
409
+ subtaskScope: 'Formulate system architecture and define decoupled API interfaces.',
410
+ },
411
+ {
412
+ id: 'stage_4_backend',
413
+ name: '4. Backend Services & Routes',
414
+ roleId: ROLE_IDS.BACKEND,
415
+ dependsOn: ['stage_3_arch'],
416
+ isParallelAllowed: true,
417
+ subtaskScope: 'Implement Cordis host services, WebServer routes, and data persistence.',
418
+ },
419
+ {
420
+ id: 'stage_4_design',
421
+ name: '4. UI/UX Interface Design',
422
+ roleId: ROLE_IDS.UI_DESIGN,
423
+ dependsOn: ['stage_3_arch'],
424
+ isParallelAllowed: true,
425
+ subtaskScope: 'Design client components, slot registrations, and theme tokens.',
426
+ },
427
+ {
428
+ id: 'stage_5_frontend',
429
+ name: '5. Frontend Assembly',
430
+ roleId: ROLE_IDS.FRONTEND,
431
+ dependsOn: ['stage_4_backend', 'stage_4_design'],
432
+ isParallelAllowed: false,
433
+ subtaskScope: 'Assemble client React components and wire with backend API routes.',
434
+ },
435
+ {
436
+ id: 'stage_6_qa',
437
+ name: '6. End-to-End & Automated QA',
438
+ roleId: ROLE_IDS.QA_TESTS,
439
+ dependsOn: ['stage_5_frontend'],
440
+ isParallelAllowed: false,
441
+ subtaskScope: 'Execute full test suite verifying backend, frontend contracts, and error resilience.',
442
+ },
443
+ {
444
+ id: 'stage_7_docs',
445
+ name: '7. Trilingual Docs & Release Gate',
446
+ roleId: ROLE_IDS.DOCS,
447
+ dependsOn: ['stage_6_qa'],
448
+ isParallelAllowed: false,
449
+ subtaskScope: 'Produce comprehensive multi-language documentation and prepare release manifest.',
450
+ },
451
+ ],
452
+ },
453
+ }
454
+ }
455
+
456
+ /**
457
+ * Validates a scenario object and its DAG stages.
458
+ */
459
+ export function validateScenario(scenario) {
460
+ if (!scenario || typeof scenario !== 'object') {
461
+ throw new Error('Scenario must be an object')
462
+ }
463
+ if (!scenario.id || !Array.isArray(scenario.stages)) {
464
+ throw new Error('Scenario must have an id and a stages array')
465
+ }
466
+ validateGraph(scenario.stages)
467
+ return true
468
+ }