speccrew 0.6.28 → 0.6.30

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,523 @@
1
+ ---
2
+ name: speccrew-knowledge-bizs-api-graph-xml
3
+ description: Constructs knowledge graph data (nodes, edges, relationships) from API analysis results using XML workflow blocks. Generates graph JSON files and completion markers for the bizs knowledge pipeline.
4
+ tools: Read, Write, Glob, Grep, Bash
5
+ ---
6
+
7
+ # API Knowledge Graph Constructor (XML Workflow)
8
+
9
+ > **CRITICAL CONSTRAINT**: DO NOT create temporary scripts, batch files, or workaround code files (`.py`, `.bat`, `.sh`, `.ps1`, etc.) under any circumstances. If execution encounters errors, STOP and report the exact error. Fixes must be applied to the Skill definition or source scripts — not patched at runtime.
10
+
11
+ Construct knowledge graph data structures (nodes and edges) from API analysis results. This skill transforms structured API documentation into graph JSON format for knowledge base integration.
12
+
13
+ ## Language Adaptation
14
+
15
+ This skill automatically adapts to the user's input language. All documentation and output will be generated in the same language as the user's query.
16
+
17
+ ## Trigger Scenarios
18
+
19
+ - "Construct graph data from API analysis results"
20
+ - "Generate knowledge graph nodes and edges for API feature"
21
+ - "Write graph JSON for API controller"
22
+
23
+ ## Input Parameters
24
+
25
+ | Parameter | Required | Description | Example |
26
+ |-----------|----------|-------------|---------|
27
+ | `api_analysis_path` | Yes | Path to the API analysis document (from bizs-api-analyze) | `"speccrew-workspace/knowledges/bizs/admin-api/system/user/UserController.md"` |
28
+ | `platform_id` | Yes | Target platform identifier | `"admin-api"`, `"app-api"` |
29
+ | `output_dir` | Yes | Output directory for graph data | `"speccrew-workspace/knowledges/base/sync-state/knowledge-bizs/completed"` |
30
+ | `module` | Yes | Business module name | `"system"`, `"trade"`, `"ai"` |
31
+ | `fileName` | Yes | Controller class name (without extension) | `"UserController"` |
32
+ | `sourcePath` | Yes | Relative path to source file | `"yudao-module-system/.../UserController.java"` |
33
+ | `sourceFile` | Yes | Source features JSON filename | `"features-admin-api.json"` |
34
+ | `language` | Yes | Target language for content | `"zh"`, `"en"` |
35
+ | `subpath` | No | Subpath extracted from sourcePath (for marker naming) | `"controller-admin-user"` |
36
+
37
+ ## Output Variables
38
+
39
+ | Variable | Type | Description |
40
+ |----------|------|-------------|
41
+ | `{{status}}` | string | Graph construction status: `"success"` or `"failed"` |
42
+ | `{{graph_file}}` | string | Path to the generated graph JSON file |
43
+ | `{{node_count}}` | integer | Number of nodes generated |
44
+ | `{{edge_count}}` | integer | Number of edges generated |
45
+
46
+ ## Execution Requirements
47
+
48
+ This skill operates in **strict sequential execution mode**:
49
+ - Execute steps in exact order (Step 1 → Step 2 → ... → Step 6)
50
+ - Output step status after each step completion
51
+ - Do NOT skip any step
52
+
53
+ ## Output
54
+
55
+ **Generated Files:**
56
+ 1. `{{output_dir}}/{module}-{subpath}-{fileName}.graph.json` - Graph data with nodes and edges
57
+ 2. `{{output_dir}}/{module}-{subpath}-{fileName}.graph-done.json` - Graph completion marker
58
+
59
+ **Return Value:**
60
+ ```json
61
+ {
62
+ "status": "success|failed",
63
+ "module": "{{module}}",
64
+ "fileName": "{{fileName}}",
65
+ "graphFile": "{{output_dir}}/{module}-{subpath}-{fileName}.graph.json",
66
+ "nodeCount": 15,
67
+ "edgeCount": 23,
68
+ "message": "Generated graph data with 15 nodes and 23 edges"
69
+ }
70
+ ```
71
+
72
+ ## Workflow
73
+
74
+ <!--
75
+ == Block Types ==
76
+ input : Workflow input parameters (required=mandatory, default=default value)
77
+ output : Workflow output results (from=data source variable)
78
+ task : Execute action (action: run-skill | run-script | dispatch-to-worker)
79
+ gateway : Conditional branch/gate (mode: exclusive | guard | parallel)
80
+ loop : Iterate over collection (over=collection, as=current item)
81
+ event : Log/confirm/signal (action: log | confirm | signal)
82
+ error-handler : Exception handling (try > catch > finally)
83
+ checkpoint : Persistent milestone (name=checkpoint name, verify=verification condition)
84
+ rule : Constraint declaration (level: forbidden | mandatory | note)
85
+ -->
86
+
87
+ ```xml
88
+ <workflow name="api-knowledge-graph-construction" version="1.0">
89
+
90
+ <!-- Input Parameters -->
91
+ <input name="api_analysis_path" type="string" required="true" description="Path to the API analysis document"/>
92
+ <input name="platform_id" type="string" required="true" description="Target platform identifier"/>
93
+ <input name="output_dir" type="string" required="true" description="Output directory for graph data"/>
94
+ <input name="module" type="string" required="true" description="Business module name"/>
95
+ <input name="fileName" type="string" required="true" description="Controller class name without extension"/>
96
+ <input name="sourcePath" type="string" required="true" description="Relative path to source file"/>
97
+ <input name="sourceFile" type="string" required="true" description="Source features JSON filename"/>
98
+ <input name="language" type="string" required="true" description="Target language for content"/>
99
+ <input name="subpath" type="string" required="false" description="Subpath extracted from sourcePath"/>
100
+
101
+ <!-- Step 1: Read API Analysis Document -->
102
+ <checkpoint name="step-1-read-document">
103
+ <task action="read" target="{{api_analysis_path}}" output="apiAnalysisContent"/>
104
+ <task action="parse-endpoints" input="{{apiAnalysisContent}}" output="endpoints"/>
105
+ <task action="parse-service-references" input="{{apiAnalysisContent}}" output="serviceReferences"/>
106
+ <task action="parse-database-tables" input="{{apiAnalysisContent}}" output="databaseTables"/>
107
+ <task action="parse-dtos" input="{{apiAnalysisContent}}" output="dtos"/>
108
+ <task action="parse-business-rules" input="{{apiAnalysisContent}}" output="businessRules"/>
109
+ <event action="log" message="Step 1 Status: COMPLETED - Read {{api_analysis_path}} ({{lineCount}} lines), Found {{endpoints.count}} endpoints"/>
110
+ </checkpoint>
111
+
112
+ <!-- Step 2: Extract Graph Nodes -->
113
+ <checkpoint name="step-2-extract-nodes">
114
+ <!-- API Endpoint Nodes -->
115
+ <loop over="{{endpoints.list}}" as="endpoint">
116
+ <task action="construct-node" type="api" id="api-{{module}}-{{endpoint.name}}"
117
+ name="{{endpoint.displayName}}" module="{{module}}"
118
+ sourcePath="{{sourcePath}}" documentPath="{{api_analysis_path}}"
119
+ description="{{endpoint.description}}"
120
+ metadata-method="{{endpoint.method}}" metadata-path="{{endpoint.path}}"
121
+ metadata-permissions="{{endpoint.permissions}}"
122
+ output="apiNodes[]"/>
123
+ </loop>
124
+ <!-- Service Nodes -->
125
+ <loop over="{{serviceReferences.list}}" as="service">
126
+ <task action="construct-node" type="service" id="service-{{module}}-{{service.name}}"
127
+ name="{{service.className}}" module="{{module}}"
128
+ sourcePath="{{service.sourcePath}}" documentPath="{{api_analysis_path}}"
129
+ description="{{service.description}}"
130
+ metadata-methods="{{service.methods}}"
131
+ output="serviceNodes[]"/>
132
+ </loop>
133
+ <!-- Table Nodes -->
134
+ <loop over="{{databaseTables.list}}" as="table">
135
+ <task action="construct-node" type="table" id="table-{{module}}-{{table.name}}"
136
+ name="{{table.tableName}}" module="{{module}}"
137
+ sourcePath="" documentPath="{{api_analysis_path}}"
138
+ description="{{table.description}}"
139
+ metadata-fields="{{table.fields}}" metadata-indexes="{{table.indexes}}"
140
+ output="tableNodes[]"/>
141
+ </loop>
142
+ <!-- DTO Nodes -->
143
+ <loop over="{{dtos.list}}" as="dto">
144
+ <task action="construct-node" type="dto" id="dto-{{module}}-{{dto.name}}"
145
+ name="{{dto.className}}" module="{{module}}"
146
+ sourcePath="{{dto.sourcePath}}" documentPath="{{api_analysis_path}}"
147
+ description="{{dto.description}}"
148
+ metadata-fields="{{dto.fields}}" metadata-validation="{{dto.validation}}"
149
+ output="dtoNodes[]"/>
150
+ </loop>
151
+ <event action="log" message="Step 2 Status: COMPLETED - Extracted {{nodeCount}} graph nodes ({{apiNodes.count}} APIs, {{serviceNodes.count}} services, {{tableNodes.count}} tables, {{dtoNodes.count}} DTOs)"/>
152
+ </checkpoint>
153
+
154
+ <!-- Step 3: Extract Graph Edges -->
155
+ <checkpoint name="step-3-extract-edges">
156
+ <!-- API to Table Edges (operates) -->
157
+ <loop over="{{endpoints.list}}" as="endpoint">
158
+ <loop over="{{endpoint.tablesAccessed}}" as="tableRef">
159
+ <task action="construct-edge" source="api-{{module}}-{{endpoint.name}}"
160
+ target="table-{{module}}-{{tableRef.tableName}}" type="operates"
161
+ metadata-operation="{{tableRef.operation}}"
162
+ metadata-description="{{tableRef.description}}"
163
+ output="operatesEdges[]"/>
164
+ </loop>
165
+ </loop>
166
+ <!-- API to Service Edges (invokes) -->
167
+ <loop over="{{endpoints.list}}" as="endpoint">
168
+ <loop over="{{endpoint.servicesInvoked}}" as="serviceRef">
169
+ <task action="construct-edge" source="api-{{module}}-{{endpoint.name}}"
170
+ target="service-{{module}}-{{serviceRef.serviceName}}" type="invokes"
171
+ metadata-method="{{serviceRef.method}}"
172
+ metadata-description="{{serviceRef.description}}"
173
+ output="invokesEdges[]"/>
174
+ </loop>
175
+ </loop>
176
+ <!-- API to DTO Edges (references) -->
177
+ <loop over="{{endpoints.list}}" as="endpoint">
178
+ <loop over="{{endpoint.dtosUsed}}" as="dtoRef">
179
+ <task action="construct-edge" source="api-{{module}}-{{endpoint.name}}"
180
+ target="dto-{{module}}-{{dtoRef.dtoName}}" type="references"
181
+ metadata-usage="{{dtoRef.usage}}"
182
+ metadata-description="{{dtoRef.description}}"
183
+ output="referencesEdges[]"/>
184
+ </loop>
185
+ </loop>
186
+ <!-- Service to Service Edges (depends-on) -->
187
+ <loop over="{{serviceReferences.list}}" as="service">
188
+ <loop over="{{service.dependencies}}" as="dep">
189
+ <task action="construct-edge" source="service-{{module}}-{{service.name}}"
190
+ target="service-{{module}}-{{dep.serviceName}}" type="depends-on"
191
+ metadata-description="{{dep.description}}"
192
+ output="dependsOnEdges[]"/>
193
+ </loop>
194
+ </loop>
195
+ <!-- DTO to Table Edges (maps-to) -->
196
+ <loop over="{{dtos.list}}" as="dto">
197
+ <loop over="{{dto.mappedTables}}" as="mappedTable">
198
+ <task action="construct-edge" source="dto-{{module}}-{{dto.name}}"
199
+ target="table-{{module}}-{{mappedTable.tableName}}" type="maps-to"
200
+ metadata-description="{{mappedTable.description}}"
201
+ output="mapsToEdges[]"/>
202
+ </loop>
203
+ </loop>
204
+ <event action="log" message="Step 3 Status: COMPLETED - Extracted {{edgeCount}} graph edges"/>
205
+ </checkpoint>
206
+
207
+ <!-- Step 4: Write Graph JSON -->
208
+ <checkpoint name="step-4-write-graph-json" verify="valid-json-structure">
209
+ <task action="calculate-marker-filename" module="{{module}}" subpath="{{subpath}}"
210
+ fileName="{{fileName}}" output="markerFilename"/>
211
+ <task action="write" target="{{output_dir}}/{{markerFilename}}.graph.json">
212
+ <content>
213
+ {
214
+ "module": "{{module}}",
215
+ "nodes": [
216
+ {{#each apiNodes}}
217
+ {{this}}{{#unless @last}},{{/unless}}
218
+ {{/each}},
219
+ {{#each serviceNodes}}
220
+ {{this}}{{#unless @last}},{{/unless}}
221
+ {{/each}},
222
+ {{#each tableNodes}}
223
+ {{this}}{{#unless @last}},{{/unless}}
224
+ {{/each}},
225
+ {{#each dtoNodes}}
226
+ {{this}}{{#unless @last}},{{/unless}}
227
+ {{/each}}
228
+ ],
229
+ "edges": [
230
+ {{#each operatesEdges}}
231
+ {{this}}{{#unless @last}},{{/unless}}
232
+ {{/each}},
233
+ {{#each invokesEdges}}
234
+ {{this}}{{#unless @last}},{{/unless}}
235
+ {{/each}},
236
+ {{#each referencesEdges}}
237
+ {{this}}{{#unless @last}},{{/unless}}
238
+ {{/each}},
239
+ {{#each dependsOnEdges}}
240
+ {{this}}{{#unless @last}},{{/unless}}
241
+ {{/each}},
242
+ {{#each mapsToEdges}}
243
+ {{this}}{{#unless @last}},{{/unless}}
244
+ {{/each}}
245
+ ]
246
+ }
247
+ </content>
248
+ </task>
249
+ <event action="log" message="Step 4 Status: COMPLETED - Graph JSON written to {{output_dir}}/{{markerFilename}}.graph.json ({{fileSize}} bytes)"/>
250
+ </checkpoint>
251
+
252
+ <!-- Step 5: Write Graph Completion Marker -->
253
+ <checkpoint name="step-5-write-marker" verify="valid-marker-structure">
254
+ <task action="write" target="{{output_dir}}/{{markerFilename}}.graph-done.json">
255
+ <content>
256
+ {
257
+ "fileName": "{{fileName}}",
258
+ "module": "{{module}}",
259
+ "marker": "graph_completed",
260
+ "graphFile": "{{markerFilename}}.graph.json",
261
+ "nodeCount": {{node_count}},
262
+ "edgeCount": {{edge_count}},
263
+ "status": "completed"
264
+ }
265
+ </content>
266
+ </task>
267
+ <event action="log" message="Step 5 Status: COMPLETED - Graph completion marker written to {{output_dir}}/{{markerFilename}}.graph-done.json"/>
268
+ </checkpoint>
269
+
270
+ <!-- Step 6: Report Results -->
271
+ <checkpoint name="step-6-report-results">
272
+ <gateway mode="exclusive">
273
+ <branch condition="{{success}}">
274
+ <output name="status" from="success"/>
275
+ <output name="module" from="{{module}}"/>
276
+ <output name="fileName" from="{{fileName}}"/>
277
+ <output name="graphFile" from="{{output_dir}}/{{markerFilename}}.graph.json"/>
278
+ <output name="nodeCount" from="{{node_count}}"/>
279
+ <output name="edgeCount" from="{{edge_count}}"/>
280
+ <output name="message" from="Generated graph data with {{node_count}} nodes and {{edge_count}} edges"/>
281
+ <event action="log" message="Step 6 Status: COMPLETED - Graph construction success: Generated graph data with {{node_count}} nodes and {{edge_count}} edges"/>
282
+ </branch>
283
+ <branch condition="{{failure}}">
284
+ <output name="status" from="failed"/>
285
+ <output name="module" from="{{module}}"/>
286
+ <output name="fileName" from="{{fileName}}"/>
287
+ <output name="message" from="{{error_message}}"/>
288
+ <event action="log" message="Step 6 Status: COMPLETED - Graph construction failed: {{error_message}}"/>
289
+ </branch>
290
+ </gateway>
291
+ </checkpoint>
292
+
293
+ <!-- Constraints -->
294
+ <rule level="mandatory" description="Single Document Input - This skill processes ONE API analysis document at a time"/>
295
+ <rule level="mandatory" description="JSON Format - All output files MUST be valid JSON"/>
296
+ <rule level="mandatory" description="Module Field - The root-level module field is MANDATORY in graph JSON"/>
297
+ <rule level="mandatory" description="Node Uniqueness - Each node ID must be unique within the graph"/>
298
+ <rule level="mandatory" description="Edge Validity - Edge source/target must reference existing node IDs"/>
299
+ <rule level="mandatory" description="Path Format - Use relative paths, NEVER absolute paths in JSON content"/>
300
+
301
+ </workflow>
302
+ ```
303
+
304
+ ## Node ID Naming Convention
305
+
306
+ ```
307
+ {type}-{module}-{name}
308
+
309
+ Examples:
310
+ api-system-user-list
311
+ api-system-user-create
312
+ service-system-user-service
313
+ table-system-system_user
314
+ dto-system-user-create-req
315
+ ```
316
+
317
+ ## Marker File Naming Convention
318
+
319
+ ```
320
+ {output_dir}/{module}-{subpath}-{fileName}.graph.json
321
+ ```
322
+
323
+ **How to Extract Each Component:**
324
+
325
+ 1. **module**: Use `{{module}}` input variable directly (e.g., `system`, `trade`, `ai`)
326
+
327
+ 2. **subpath**: Extract from `{{sourcePath}}`:
328
+ - For Java: Remove package prefix up to the business layer (e.g., `controller/admin/`, `controller/app/`)
329
+ - Remove the file name at the end
330
+ - Replace path separators (`/`) with hyphens (`-`)
331
+ - If the file is at module root, subpath will be empty → omit from filename
332
+
333
+ 3. **fileName**: Use `{{fileName}}` input variable (class name WITHOUT extension)
334
+
335
+ **Examples:**
336
+
337
+ | sourcePath | module | subpath | fileName | Marker Filename |
338
+ |------------|--------|---------|----------|-----------------|
339
+ | `yudao-module-system/.../controller/admin/notify/NotifyMessageController.java` | `system` | `controller-admin-notify` | `NotifyMessageController` | `system-controller-admin-notify-NotifyMessageController.graph.json` |
340
+ | `yudao-module-system/.../controller/admin/user/UserController.java` | `system` | `controller-admin-user` | `UserController` | `system-controller-admin-user-UserController.graph.json` |
341
+ | `yudao-module-ai/.../controller/admin/chat/ChatConversationController.java` | `ai` | `controller-admin-chat` | `ChatConversationController` | `ai-controller-admin-chat-ChatConversationController.graph.json` |
342
+
343
+ ## Node Type Reference
344
+
345
+ | Type | Description | Required Metadata |
346
+ |------|-------------|-------------------|
347
+ | `api` | API endpoint | `method`, `path`, `permissions` |
348
+ | `service` | Service class | `methods` |
349
+ | `table` | Database table | `fields`, `indexes` |
350
+ | `dto` | Data Transfer Object | `fields`, `validation` |
351
+
352
+ ## Edge Type Reference
353
+
354
+ | Type | Description | Source → Target |
355
+ |------|-------------|-----------------|
356
+ | `operates` | API operates on table | api → table |
357
+ | `invokes` | API calls service | api → service |
358
+ | `references` | API uses DTO | api → dto |
359
+ | `depends-on` | Service dependency | service → service |
360
+ | `maps-to` | DTO maps to table | dto → table |
361
+
362
+ ## Node Structure Examples
363
+
364
+ ### API Node Example
365
+ ```json
366
+ {
367
+ "id": "api-{module}-{endpoint-name}",
368
+ "type": "api",
369
+ "name": "<display name>",
370
+ "module": "{{module}}",
371
+ "sourcePath": "{{sourcePath}}",
372
+ "documentPath": "{{api_analysis_path}}",
373
+ "description": "...",
374
+ "metadata": {
375
+ "method": "GET",
376
+ "path": "/admin-api/system/user/page",
377
+ "permissions": ["system:user:query"]
378
+ }
379
+ }
380
+ ```
381
+
382
+ ### Service Node Example
383
+ ```json
384
+ {
385
+ "id": "service-{module}-{service-name}",
386
+ "type": "service",
387
+ "name": "UserService",
388
+ "module": "{{module}}",
389
+ "sourcePath": "relative/path/to/UserService.java",
390
+ "description": "User business logic service",
391
+ "metadata": {
392
+ "methods": ["getUserPage", "createUser", "updateUser"]
393
+ }
394
+ }
395
+ ```
396
+
397
+ ### Table Node Example
398
+ ```json
399
+ {
400
+ "id": "table-{module}-{table-name}",
401
+ "type": "table",
402
+ "name": "system_user",
403
+ "module": "{{module}}",
404
+ "sourcePath": "",
405
+ "description": "User table",
406
+ "metadata": {
407
+ "fields": ["id", "username", "password", "status"],
408
+ "indexes": ["idx_username"]
409
+ }
410
+ }
411
+ ```
412
+
413
+ ### DTO Node Example
414
+ ```json
415
+ {
416
+ "id": "dto-{module}-{dto-name}",
417
+ "type": "dto",
418
+ "name": "UserCreateReqVO",
419
+ "module": "{{module}}",
420
+ "sourcePath": "relative/path/to/UserCreateReqVO.java",
421
+ "description": "Create user request DTO",
422
+ "metadata": {
423
+ "fields": ["username", "password", "nickname"],
424
+ "validation": ["@NotBlank username", "@Size(max=50) nickname"]
425
+ }
426
+ }
427
+ ```
428
+
429
+ ## Edge Structure Examples
430
+
431
+ ### API to Table Edge (operates)
432
+ ```json
433
+ {
434
+ "source": "api-system-user-list",
435
+ "target": "table-system-system_user",
436
+ "type": "operates",
437
+ "metadata": {
438
+ "operation": "SELECT",
439
+ "description": "Query user list with pagination"
440
+ }
441
+ }
442
+ ```
443
+
444
+ ### API to Service Edge (invokes)
445
+ ```json
446
+ {
447
+ "source": "api-system-user-create",
448
+ "target": "service-system-user-service",
449
+ "type": "invokes",
450
+ "metadata": {
451
+ "method": "createUser",
452
+ "description": "Create user business logic"
453
+ }
454
+ }
455
+ ```
456
+
457
+ ### API to DTO Edge (references)
458
+ ```json
459
+ {
460
+ "source": "api-system-user-create",
461
+ "target": "dto-system-user-create-req",
462
+ "type": "references",
463
+ "metadata": {
464
+ "usage": "request",
465
+ "description": "Create user request body"
466
+ }
467
+ }
468
+ ```
469
+
470
+ ### Service to Service Edge (depends-on)
471
+ ```json
472
+ {
473
+ "source": "service-system-user-service",
474
+ "target": "service-system-permission-service",
475
+ "type": "depends-on",
476
+ "metadata": {
477
+ "description": "User service depends on permission service for role checks"
478
+ }
479
+ }
480
+ ```
481
+
482
+ ### DTO to Table Edge (maps-to)
483
+ ```json
484
+ {
485
+ "source": "dto-system-user-do",
486
+ "target": "table-system-system_user",
487
+ "type": "maps-to",
488
+ "metadata": {
489
+ "description": "UserDO maps to system_user table"
490
+ }
491
+ }
492
+ ```
493
+
494
+ ## Pre-write Verification Checklist
495
+
496
+ ### Graph JSON Verification:
497
+ - [ ] Root-level `module` field is present (MANDATORY)
498
+ - [ ] `nodes` and `edges` are arrays (can be empty)
499
+ - [ ] Valid JSON (no trailing commas, all strings quoted)
500
+ - [ ] All node IDs are unique
501
+ - [ ] All edge source/target references point to valid node IDs
502
+
503
+ ### API Endpoint Coverage Check:
504
+ - [ ] ALL public API endpoint methods in the controller are represented as `api` nodes
505
+ - [ ] Status update endpoints (updateStatus, toggleEnable) are included
506
+ - [ ] Special operation endpoints (resetPassword, export, import, batch operations) are included
507
+ - [ ] Each `api` node has proper metadata with HTTP method and path
508
+ - [ ] No public endpoint method is left without a corresponding node
509
+
510
+ ### Completion Marker Verification:
511
+ - [ ] Filename follows `{module}-{subpath}-{fileName}.graph-done.json` pattern
512
+ - [ ] JSON is valid
513
+ - [ ] All required fields are present
514
+ - [ ] `nodeCount` and `edgeCount` match actual graph data
515
+
516
+ ## Constraints
517
+
518
+ 1. **Single Document Input**: This skill processes ONE API analysis document at a time
519
+ 2. **JSON Format**: All output files MUST be valid JSON
520
+ 3. **Module Field**: The root-level `module` field is MANDATORY in graph JSON
521
+ 4. **Node Uniqueness**: Each node ID must be unique within the graph
522
+ 5. **Edge Validity**: Edge source/target must reference existing node IDs
523
+ 6. **Path Format**: Use relative paths, NEVER absolute paths in JSON content