claude-code-workflow 6.3.2 → 6.3.5

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.
Files changed (80) hide show
  1. package/.claude/CLAUDE.md +9 -1
  2. package/.claude/commands/{clean.md → workflow/clean.md} +5 -5
  3. package/.claude/commands/workflow/docs/analyze.md +1467 -0
  4. package/.claude/commands/workflow/docs/copyright.md +1265 -0
  5. package/.claude/commands/workflow/lite-plan.md +1 -1
  6. package/.claude/commands/workflow/tools/conflict-resolution.md +76 -240
  7. package/.claude/commands/workflow/tools/task-generate-agent.md +81 -8
  8. package/.claude/skills/_shared/mermaid-utils.md +584 -0
  9. package/.claude/skills/copyright-docs/SKILL.md +132 -0
  10. package/.claude/skills/copyright-docs/phases/01-metadata-collection.md +78 -0
  11. package/.claude/skills/copyright-docs/phases/02-deep-analysis.md +454 -0
  12. package/.claude/skills/copyright-docs/phases/02.5-consolidation.md +192 -0
  13. package/.claude/skills/copyright-docs/phases/04-document-assembly.md +261 -0
  14. package/.claude/skills/copyright-docs/phases/05-compliance-refinement.md +192 -0
  15. package/.claude/skills/copyright-docs/specs/cpcc-requirements.md +121 -0
  16. package/.claude/skills/copyright-docs/templates/agent-base.md +200 -0
  17. package/.claude/skills/project-analyze/SKILL.md +162 -0
  18. package/.claude/skills/project-analyze/phases/01-requirements-discovery.md +79 -0
  19. package/.claude/skills/project-analyze/phases/02-project-exploration.md +75 -0
  20. package/.claude/skills/project-analyze/phases/03-deep-analysis.md +640 -0
  21. package/.claude/skills/project-analyze/phases/03.5-consolidation.md +208 -0
  22. package/.claude/skills/project-analyze/phases/04-report-generation.md +217 -0
  23. package/.claude/skills/project-analyze/phases/05-iterative-refinement.md +124 -0
  24. package/.claude/skills/project-analyze/specs/quality-standards.md +115 -0
  25. package/.claude/skills/project-analyze/specs/writing-style.md +152 -0
  26. package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +79 -65
  27. package/.claude/workflows/cli-tools-usage.md +515 -516
  28. package/README.md +11 -1
  29. package/ccw/dist/cli.d.ts.map +1 -1
  30. package/ccw/dist/cli.js +7 -1
  31. package/ccw/dist/cli.js.map +1 -1
  32. package/ccw/dist/commands/cli.d.ts +1 -1
  33. package/ccw/dist/commands/cli.d.ts.map +1 -1
  34. package/ccw/dist/commands/cli.js +116 -14
  35. package/ccw/dist/commands/cli.js.map +1 -1
  36. package/ccw/dist/core/routes/cli-routes.js +2 -2
  37. package/ccw/dist/core/routes/cli-routes.js.map +1 -1
  38. package/ccw/dist/tools/claude-cli-tools.d.ts +7 -3
  39. package/ccw/dist/tools/claude-cli-tools.d.ts.map +1 -1
  40. package/ccw/dist/tools/claude-cli-tools.js +31 -17
  41. package/ccw/dist/tools/claude-cli-tools.js.map +1 -1
  42. package/ccw/dist/tools/cli-executor.d.ts.map +1 -1
  43. package/ccw/dist/tools/cli-executor.js +19 -7
  44. package/ccw/dist/tools/cli-executor.js.map +1 -1
  45. package/ccw/dist/tools/cli-history-store.d.ts +33 -0
  46. package/ccw/dist/tools/cli-history-store.d.ts.map +1 -1
  47. package/ccw/dist/tools/cli-history-store.js +89 -5
  48. package/ccw/dist/tools/cli-history-store.js.map +1 -1
  49. package/ccw/dist/tools/smart-search.d.ts +25 -0
  50. package/ccw/dist/tools/smart-search.d.ts.map +1 -1
  51. package/ccw/dist/tools/smart-search.js +121 -17
  52. package/ccw/dist/tools/smart-search.js.map +1 -1
  53. package/ccw/src/cli.ts +264 -258
  54. package/ccw/src/commands/cli.ts +1009 -884
  55. package/ccw/src/core/routes/cli-routes.ts +3 -3
  56. package/ccw/src/templates/dashboard-js/components/cli-history.js +40 -13
  57. package/ccw/src/templates/dashboard-js/components/cli-status.js +26 -2
  58. package/ccw/src/templates/dashboard-js/views/cli-manager.js +5 -0
  59. package/ccw/src/templates/dashboard-js/views/history.js +19 -4
  60. package/ccw/src/tools/claude-cli-tools.ts +37 -20
  61. package/ccw/src/tools/cli-executor.ts +20 -7
  62. package/ccw/src/tools/cli-history-store.ts +125 -5
  63. package/ccw/src/tools/smart-search.ts +157 -16
  64. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  65. package/codex-lens/src/codexlens/config.py +8 -0
  66. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  67. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  68. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  69. package/codex-lens/src/codexlens/search/chain_search.py +71 -1
  70. package/codex-lens/src/codexlens/search/hybrid_search.py +144 -11
  71. package/codex-lens/src/codexlens/search/ranking.py +540 -274
  72. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  73. package/codex-lens/src/codexlens/semantic/chunker.py +55 -10
  74. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
  75. package/codex-lens/src/codexlens/storage/__pycache__/global_index.cpython-313.pyc +0 -0
  76. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  77. package/codex-lens/src/codexlens/storage/dir_index.py +1888 -1850
  78. package/codex-lens/src/codexlens/storage/global_index.py +365 -0
  79. package/codex-lens/src/codexlens/storage/index_tree.py +83 -10
  80. package/package.json +2 -2
@@ -0,0 +1,584 @@
1
+ # Mermaid Utilities Library
2
+
3
+ Shared utilities for generating and validating Mermaid diagrams across all analysis skills.
4
+
5
+ ## Sanitization Functions
6
+
7
+ ### sanitizeId
8
+
9
+ Convert any text to a valid Mermaid node ID.
10
+
11
+ ```javascript
12
+ /**
13
+ * Sanitize text to valid Mermaid node ID
14
+ * - Only alphanumeric and underscore allowed
15
+ * - Cannot start with number
16
+ * - Truncates to 50 chars max
17
+ *
18
+ * @param {string} text - Input text
19
+ * @returns {string} - Valid Mermaid ID
20
+ */
21
+ function sanitizeId(text) {
22
+ if (!text) return '_empty';
23
+ return text
24
+ .replace(/[^a-zA-Z0-9_\u4e00-\u9fa5]/g, '_') // Allow Chinese chars
25
+ .replace(/^[0-9]/, '_$&') // Prefix number with _
26
+ .replace(/_+/g, '_') // Collapse multiple _
27
+ .substring(0, 50); // Limit length
28
+ }
29
+
30
+ // Examples:
31
+ // sanitizeId("User-Service") → "User_Service"
32
+ // sanitizeId("3rdParty") → "_3rdParty"
33
+ // sanitizeId("用户服务") → "用户服务"
34
+ ```
35
+
36
+ ### escapeLabel
37
+
38
+ Escape special characters for Mermaid labels.
39
+
40
+ ```javascript
41
+ /**
42
+ * Escape special characters in Mermaid labels
43
+ * Uses HTML entity encoding for problematic chars
44
+ *
45
+ * @param {string} text - Label text
46
+ * @returns {string} - Escaped label
47
+ */
48
+ function escapeLabel(text) {
49
+ if (!text) return '';
50
+ return text
51
+ .replace(/"/g, "'") // Avoid quote issues
52
+ .replace(/\(/g, '#40;') // (
53
+ .replace(/\)/g, '#41;') // )
54
+ .replace(/\{/g, '#123;') // {
55
+ .replace(/\}/g, '#125;') // }
56
+ .replace(/\[/g, '#91;') // [
57
+ .replace(/\]/g, '#93;') // ]
58
+ .replace(/</g, '#60;') // <
59
+ .replace(/>/g, '#62;') // >
60
+ .replace(/\|/g, '#124;') // |
61
+ .substring(0, 80); // Limit length
62
+ }
63
+
64
+ // Examples:
65
+ // escapeLabel("Process(data)") → "Process#40;data#41;"
66
+ // escapeLabel("Check {valid?}") → "Check #123;valid?#125;"
67
+ ```
68
+
69
+ ### sanitizeType
70
+
71
+ Sanitize type names for class diagrams.
72
+
73
+ ```javascript
74
+ /**
75
+ * Sanitize type names for Mermaid classDiagram
76
+ * Removes generics syntax that causes issues
77
+ *
78
+ * @param {string} type - Type name
79
+ * @returns {string} - Sanitized type
80
+ */
81
+ function sanitizeType(type) {
82
+ if (!type) return 'any';
83
+ return type
84
+ .replace(/<[^>]*>/g, '') // Remove generics <T>
85
+ .replace(/\|/g, ' or ') // Union types
86
+ .replace(/&/g, ' and ') // Intersection types
87
+ .replace(/\[\]/g, 'Array') // Array notation
88
+ .substring(0, 30);
89
+ }
90
+
91
+ // Examples:
92
+ // sanitizeType("Array<string>") → "Array"
93
+ // sanitizeType("string | number") → "string or number"
94
+ ```
95
+
96
+ ## Diagram Generation Functions
97
+
98
+ ### generateFlowchartNode
99
+
100
+ Generate a flowchart node with proper shape.
101
+
102
+ ```javascript
103
+ /**
104
+ * Generate flowchart node with shape
105
+ *
106
+ * @param {string} id - Node ID
107
+ * @param {string} label - Display label
108
+ * @param {string} type - Node type: start|end|process|decision|io|subroutine
109
+ * @returns {string} - Mermaid node definition
110
+ */
111
+ function generateFlowchartNode(id, label, type = 'process') {
112
+ const safeId = sanitizeId(id);
113
+ const safeLabel = escapeLabel(label);
114
+
115
+ const shapes = {
116
+ start: `${safeId}(["${safeLabel}"])`, // Stadium shape
117
+ end: `${safeId}(["${safeLabel}"])`, // Stadium shape
118
+ process: `${safeId}["${safeLabel}"]`, // Rectangle
119
+ decision: `${safeId}{"${safeLabel}"}`, // Diamond
120
+ io: `${safeId}[/"${safeLabel}"/]`, // Parallelogram
121
+ subroutine: `${safeId}[["${safeLabel}"]]`, // Subroutine
122
+ database: `${safeId}[("${safeLabel}")]`, // Cylinder
123
+ manual: `${safeId}[/"${safeLabel}"\\]` // Trapezoid
124
+ };
125
+
126
+ return shapes[type] || shapes.process;
127
+ }
128
+ ```
129
+
130
+ ### generateFlowchartEdge
131
+
132
+ Generate a flowchart edge with optional label.
133
+
134
+ ```javascript
135
+ /**
136
+ * Generate flowchart edge
137
+ *
138
+ * @param {string} from - Source node ID
139
+ * @param {string} to - Target node ID
140
+ * @param {string} label - Edge label (optional)
141
+ * @param {string} style - Edge style: solid|dashed|thick
142
+ * @returns {string} - Mermaid edge definition
143
+ */
144
+ function generateFlowchartEdge(from, to, label = '', style = 'solid') {
145
+ const safeFrom = sanitizeId(from);
146
+ const safeTo = sanitizeId(to);
147
+ const safeLabel = label ? `|"${escapeLabel(label)}"|` : '';
148
+
149
+ const arrows = {
150
+ solid: '-->',
151
+ dashed: '-.->',
152
+ thick: '==>'
153
+ };
154
+
155
+ const arrow = arrows[style] || arrows.solid;
156
+ return ` ${safeFrom} ${arrow}${safeLabel} ${safeTo}`;
157
+ }
158
+ ```
159
+
160
+ ### generateAlgorithmFlowchart (Enhanced)
161
+
162
+ Generate algorithm flowchart with branch/loop support.
163
+
164
+ ```javascript
165
+ /**
166
+ * Generate algorithm flowchart with decision support
167
+ *
168
+ * @param {Object} algorithm - Algorithm definition
169
+ * - name: Algorithm name
170
+ * - inputs: [{name, type}]
171
+ * - outputs: [{name, type}]
172
+ * - steps: [{id, description, type, next: [id], conditions: [text]}]
173
+ * @returns {string} - Complete Mermaid flowchart
174
+ */
175
+ function generateAlgorithmFlowchart(algorithm) {
176
+ let mermaid = 'flowchart TD\n';
177
+
178
+ // Start node
179
+ mermaid += ` START(["开始: ${escapeLabel(algorithm.name)}"])\n`;
180
+
181
+ // Input node (if has inputs)
182
+ if (algorithm.inputs?.length > 0) {
183
+ const inputList = algorithm.inputs.map(i => `${i.name}: ${i.type}`).join(', ');
184
+ mermaid += ` INPUT[/"输入: ${escapeLabel(inputList)}"/]\n`;
185
+ mermaid += ` START --> INPUT\n`;
186
+ }
187
+
188
+ // Process nodes
189
+ const steps = algorithm.steps || [];
190
+ for (const step of steps) {
191
+ const nodeId = sanitizeId(step.id || `STEP_${step.step_num}`);
192
+
193
+ if (step.type === 'decision') {
194
+ mermaid += ` ${nodeId}{"${escapeLabel(step.description)}"}\n`;
195
+ } else if (step.type === 'io') {
196
+ mermaid += ` ${nodeId}[/"${escapeLabel(step.description)}"/]\n`;
197
+ } else if (step.type === 'loop_start') {
198
+ mermaid += ` ${nodeId}[["循环: ${escapeLabel(step.description)}"]]\n`;
199
+ } else {
200
+ mermaid += ` ${nodeId}["${escapeLabel(step.description)}"]\n`;
201
+ }
202
+ }
203
+
204
+ // Output node
205
+ const outputDesc = algorithm.outputs?.map(o => o.name).join(', ') || '结果';
206
+ mermaid += ` OUTPUT[/"输出: ${escapeLabel(outputDesc)}"/]\n`;
207
+ mermaid += ` END_(["结束"])\n`;
208
+
209
+ // Connect first step to input/start
210
+ if (steps.length > 0) {
211
+ const firstStep = sanitizeId(steps[0].id || 'STEP_1');
212
+ if (algorithm.inputs?.length > 0) {
213
+ mermaid += ` INPUT --> ${firstStep}\n`;
214
+ } else {
215
+ mermaid += ` START --> ${firstStep}\n`;
216
+ }
217
+ }
218
+
219
+ // Connect steps based on next array
220
+ for (const step of steps) {
221
+ const nodeId = sanitizeId(step.id || `STEP_${step.step_num}`);
222
+
223
+ if (step.next && step.next.length > 0) {
224
+ step.next.forEach((nextId, index) => {
225
+ const safeNextId = sanitizeId(nextId);
226
+ const condition = step.conditions?.[index];
227
+
228
+ if (condition) {
229
+ mermaid += ` ${nodeId} -->|"${escapeLabel(condition)}"| ${safeNextId}\n`;
230
+ } else {
231
+ mermaid += ` ${nodeId} --> ${safeNextId}\n`;
232
+ }
233
+ });
234
+ } else if (!step.type?.includes('end')) {
235
+ // Default: connect to next step or output
236
+ const stepIndex = steps.indexOf(step);
237
+ if (stepIndex < steps.length - 1) {
238
+ const nextStep = sanitizeId(steps[stepIndex + 1].id || `STEP_${stepIndex + 2}`);
239
+ mermaid += ` ${nodeId} --> ${nextStep}\n`;
240
+ } else {
241
+ mermaid += ` ${nodeId} --> OUTPUT\n`;
242
+ }
243
+ }
244
+ }
245
+
246
+ // Connect output to end
247
+ mermaid += ` OUTPUT --> END_\n`;
248
+
249
+ return mermaid;
250
+ }
251
+ ```
252
+
253
+ ## Diagram Validation
254
+
255
+ ### validateMermaidSyntax
256
+
257
+ Comprehensive Mermaid syntax validation.
258
+
259
+ ```javascript
260
+ /**
261
+ * Validate Mermaid diagram syntax
262
+ *
263
+ * @param {string} content - Mermaid diagram content
264
+ * @returns {Object} - {valid: boolean, issues: string[]}
265
+ */
266
+ function validateMermaidSyntax(content) {
267
+ const issues = [];
268
+
269
+ // Check 1: Diagram type declaration
270
+ if (!content.match(/^(graph|flowchart|classDiagram|sequenceDiagram|stateDiagram|erDiagram|gantt|pie|mindmap)/m)) {
271
+ issues.push('Missing diagram type declaration');
272
+ }
273
+
274
+ // Check 2: Undefined values
275
+ if (content.includes('undefined') || content.includes('null')) {
276
+ issues.push('Contains undefined/null values');
277
+ }
278
+
279
+ // Check 3: Invalid arrow syntax
280
+ if (content.match(/-->\s*-->/)) {
281
+ issues.push('Double arrow syntax error');
282
+ }
283
+
284
+ // Check 4: Unescaped special characters in labels
285
+ const labelMatches = content.match(/\["[^"]*[(){}[\]<>][^"]*"\]/g);
286
+ if (labelMatches?.some(m => !m.includes('#'))) {
287
+ issues.push('Unescaped special characters in labels');
288
+ }
289
+
290
+ // Check 5: Node ID starts with number
291
+ if (content.match(/\n\s*[0-9][a-zA-Z0-9_]*[\[\({]/)) {
292
+ issues.push('Node ID cannot start with number');
293
+ }
294
+
295
+ // Check 6: Nested subgraph syntax error
296
+ if (content.match(/subgraph\s+\S+\s*\n[^e]*subgraph/)) {
297
+ // This is actually valid, only flag if brackets don't match
298
+ const subgraphCount = (content.match(/subgraph/g) || []).length;
299
+ const endCount = (content.match(/\bend\b/g) || []).length;
300
+ if (subgraphCount > endCount) {
301
+ issues.push('Unbalanced subgraph/end blocks');
302
+ }
303
+ }
304
+
305
+ // Check 7: Invalid arrow type for diagram type
306
+ const diagramType = content.match(/^(graph|flowchart|classDiagram|sequenceDiagram)/m)?.[1];
307
+ if (diagramType === 'classDiagram' && content.includes('-->|')) {
308
+ issues.push('Invalid edge label syntax for classDiagram');
309
+ }
310
+
311
+ // Check 8: Empty node labels
312
+ if (content.match(/\[""\]|\{\}|\(\)/)) {
313
+ issues.push('Empty node labels detected');
314
+ }
315
+
316
+ // Check 9: Reserved keywords as IDs
317
+ const reserved = ['end', 'graph', 'subgraph', 'direction', 'class', 'click'];
318
+ for (const keyword of reserved) {
319
+ const pattern = new RegExp(`\\n\\s*${keyword}\\s*[\\[\\(\\{]`, 'i');
320
+ if (content.match(pattern)) {
321
+ issues.push(`Reserved keyword "${keyword}" used as node ID`);
322
+ }
323
+ }
324
+
325
+ // Check 10: Line length (Mermaid has issues with very long lines)
326
+ const lines = content.split('\n');
327
+ for (let i = 0; i < lines.length; i++) {
328
+ if (lines[i].length > 500) {
329
+ issues.push(`Line ${i + 1} exceeds 500 characters`);
330
+ }
331
+ }
332
+
333
+ return {
334
+ valid: issues.length === 0,
335
+ issues
336
+ };
337
+ }
338
+ ```
339
+
340
+ ### validateDiagramDirectory
341
+
342
+ Validate all diagrams in a directory.
343
+
344
+ ```javascript
345
+ /**
346
+ * Validate all Mermaid diagrams in directory
347
+ *
348
+ * @param {string} diagramDir - Path to diagrams directory
349
+ * @returns {Object[]} - Array of {file, valid, issues}
350
+ */
351
+ function validateDiagramDirectory(diagramDir) {
352
+ const files = Glob(`${diagramDir}/*.mmd`);
353
+ const results = [];
354
+
355
+ for (const file of files) {
356
+ const content = Read(file);
357
+ const validation = validateMermaidSyntax(content);
358
+
359
+ results.push({
360
+ file: file.split('/').pop(),
361
+ path: file,
362
+ valid: validation.valid,
363
+ issues: validation.issues,
364
+ lines: content.split('\n').length
365
+ });
366
+ }
367
+
368
+ return results;
369
+ }
370
+ ```
371
+
372
+ ## Class Diagram Utilities
373
+
374
+ ### generateClassDiagram
375
+
376
+ Generate class diagram with relationships.
377
+
378
+ ```javascript
379
+ /**
380
+ * Generate class diagram from analysis data
381
+ *
382
+ * @param {Object} analysis - Data structure analysis
383
+ * - entities: [{name, type, properties, methods}]
384
+ * - relationships: [{from, to, type, label}]
385
+ * @param {Object} options - Generation options
386
+ * - maxClasses: Max classes to include (default: 15)
387
+ * - maxProperties: Max properties per class (default: 8)
388
+ * - maxMethods: Max methods per class (default: 6)
389
+ * @returns {string} - Mermaid classDiagram
390
+ */
391
+ function generateClassDiagram(analysis, options = {}) {
392
+ const maxClasses = options.maxClasses || 15;
393
+ const maxProperties = options.maxProperties || 8;
394
+ const maxMethods = options.maxMethods || 6;
395
+
396
+ let mermaid = 'classDiagram\n';
397
+
398
+ const entities = (analysis.entities || []).slice(0, maxClasses);
399
+
400
+ // Generate classes
401
+ for (const entity of entities) {
402
+ const className = sanitizeId(entity.name);
403
+ mermaid += ` class ${className} {\n`;
404
+
405
+ // Properties
406
+ for (const prop of (entity.properties || []).slice(0, maxProperties)) {
407
+ const vis = {public: '+', private: '-', protected: '#'}[prop.visibility] || '+';
408
+ const type = sanitizeType(prop.type);
409
+ mermaid += ` ${vis}${type} ${prop.name}\n`;
410
+ }
411
+
412
+ // Methods
413
+ for (const method of (entity.methods || []).slice(0, maxMethods)) {
414
+ const vis = {public: '+', private: '-', protected: '#'}[method.visibility] || '+';
415
+ const params = (method.params || []).map(p => p.name).join(', ');
416
+ const returnType = sanitizeType(method.returnType || 'void');
417
+ mermaid += ` ${vis}${method.name}(${params}) ${returnType}\n`;
418
+ }
419
+
420
+ mermaid += ' }\n';
421
+
422
+ // Add stereotype if applicable
423
+ if (entity.type === 'interface') {
424
+ mermaid += ` <<interface>> ${className}\n`;
425
+ } else if (entity.type === 'abstract') {
426
+ mermaid += ` <<abstract>> ${className}\n`;
427
+ }
428
+ }
429
+
430
+ // Generate relationships
431
+ const arrows = {
432
+ inheritance: '--|>',
433
+ implementation: '..|>',
434
+ composition: '*--',
435
+ aggregation: 'o--',
436
+ association: '-->',
437
+ dependency: '..>'
438
+ };
439
+
440
+ for (const rel of (analysis.relationships || [])) {
441
+ const from = sanitizeId(rel.from);
442
+ const to = sanitizeId(rel.to);
443
+ const arrow = arrows[rel.type] || '-->';
444
+ const label = rel.label ? ` : ${escapeLabel(rel.label)}` : '';
445
+
446
+ // Only include if both entities exist
447
+ if (entities.some(e => sanitizeId(e.name) === from) &&
448
+ entities.some(e => sanitizeId(e.name) === to)) {
449
+ mermaid += ` ${from} ${arrow} ${to}${label}\n`;
450
+ }
451
+ }
452
+
453
+ return mermaid;
454
+ }
455
+ ```
456
+
457
+ ## Sequence Diagram Utilities
458
+
459
+ ### generateSequenceDiagram
460
+
461
+ Generate sequence diagram from scenario.
462
+
463
+ ```javascript
464
+ /**
465
+ * Generate sequence diagram from scenario
466
+ *
467
+ * @param {Object} scenario - Sequence scenario
468
+ * - name: Scenario name
469
+ * - actors: [{id, name, type}]
470
+ * - messages: [{from, to, description, type}]
471
+ * - blocks: [{type, condition, messages}]
472
+ * @returns {string} - Mermaid sequenceDiagram
473
+ */
474
+ function generateSequenceDiagram(scenario) {
475
+ let mermaid = 'sequenceDiagram\n';
476
+
477
+ // Title
478
+ if (scenario.name) {
479
+ mermaid += ` title ${escapeLabel(scenario.name)}\n`;
480
+ }
481
+
482
+ // Participants
483
+ for (const actor of scenario.actors || []) {
484
+ const actorType = actor.type === 'external' ? 'actor' : 'participant';
485
+ mermaid += ` ${actorType} ${sanitizeId(actor.id)} as ${escapeLabel(actor.name)}\n`;
486
+ }
487
+
488
+ mermaid += '\n';
489
+
490
+ // Messages
491
+ for (const msg of scenario.messages || []) {
492
+ const from = sanitizeId(msg.from);
493
+ const to = sanitizeId(msg.to);
494
+ const desc = escapeLabel(msg.description);
495
+
496
+ let arrow;
497
+ switch (msg.type) {
498
+ case 'async': arrow = '->>'; break;
499
+ case 'response': arrow = '-->>'; break;
500
+ case 'create': arrow = '->>+'; break;
501
+ case 'destroy': arrow = '->>-'; break;
502
+ case 'self': arrow = '->>'; break;
503
+ default: arrow = '->>';
504
+ }
505
+
506
+ mermaid += ` ${from}${arrow}${to}: ${desc}\n`;
507
+
508
+ // Activation
509
+ if (msg.activate) {
510
+ mermaid += ` activate ${to}\n`;
511
+ }
512
+ if (msg.deactivate) {
513
+ mermaid += ` deactivate ${from}\n`;
514
+ }
515
+
516
+ // Notes
517
+ if (msg.note) {
518
+ mermaid += ` Note over ${to}: ${escapeLabel(msg.note)}\n`;
519
+ }
520
+ }
521
+
522
+ // Blocks (loops, alt, opt)
523
+ for (const block of scenario.blocks || []) {
524
+ switch (block.type) {
525
+ case 'loop':
526
+ mermaid += ` loop ${escapeLabel(block.condition)}\n`;
527
+ break;
528
+ case 'alt':
529
+ mermaid += ` alt ${escapeLabel(block.condition)}\n`;
530
+ break;
531
+ case 'opt':
532
+ mermaid += ` opt ${escapeLabel(block.condition)}\n`;
533
+ break;
534
+ }
535
+
536
+ for (const m of block.messages || []) {
537
+ mermaid += ` ${sanitizeId(m.from)}->>${sanitizeId(m.to)}: ${escapeLabel(m.description)}\n`;
538
+ }
539
+
540
+ mermaid += ' end\n';
541
+ }
542
+
543
+ return mermaid;
544
+ }
545
+ ```
546
+
547
+ ## Usage Examples
548
+
549
+ ### Example 1: Algorithm with Branches
550
+
551
+ ```javascript
552
+ const algorithm = {
553
+ name: "用户认证流程",
554
+ inputs: [{name: "credentials", type: "Object"}],
555
+ outputs: [{name: "token", type: "JWT"}],
556
+ steps: [
557
+ {id: "validate", description: "验证输入格式", type: "process"},
558
+ {id: "check_user", description: "用户是否存在?", type: "decision",
559
+ next: ["verify_pwd", "error_user"], conditions: ["是", "否"]},
560
+ {id: "verify_pwd", description: "验证密码", type: "process"},
561
+ {id: "pwd_ok", description: "密码正确?", type: "decision",
562
+ next: ["gen_token", "error_pwd"], conditions: ["是", "否"]},
563
+ {id: "gen_token", description: "生成 JWT Token", type: "process"},
564
+ {id: "error_user", description: "返回用户不存在", type: "io"},
565
+ {id: "error_pwd", description: "返回密码错误", type: "io"}
566
+ ]
567
+ };
568
+
569
+ const flowchart = generateAlgorithmFlowchart(algorithm);
570
+ ```
571
+
572
+ ### Example 2: Validate Before Output
573
+
574
+ ```javascript
575
+ const diagram = generateClassDiagram(analysis);
576
+ const validation = validateMermaidSyntax(diagram);
577
+
578
+ if (!validation.valid) {
579
+ console.log("Diagram has issues:", validation.issues);
580
+ // Fix issues or regenerate
581
+ } else {
582
+ Write(`${outputDir}/class-diagram.mmd`, diagram);
583
+ }
584
+ ```