speccrew 0.1.0

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 (153) hide show
  1. package/.speccrew/agents/speccrew-feature-designer.md +142 -0
  2. package/.speccrew/agents/speccrew-product-manager.md +61 -0
  3. package/.speccrew/agents/speccrew-system-designer.md +200 -0
  4. package/.speccrew/agents/speccrew-system-developer.md +238 -0
  5. package/.speccrew/agents/speccrew-task-worker.md +80 -0
  6. package/.speccrew/agents/speccrew-team-leader.md +92 -0
  7. package/.speccrew/agents/speccrew-test-manager.md +313 -0
  8. package/.speccrew/skills/speccrew-create-agents/SKILL.md +98 -0
  9. package/.speccrew/skills/speccrew-create-agents/templates/agents/designer-agent.md +54 -0
  10. package/.speccrew/skills/speccrew-create-agents/templates/agents/dev-agent.md +79 -0
  11. package/.speccrew/skills/speccrew-create-agents/templates/agents/test-agent.md +80 -0
  12. package/.speccrew/skills/speccrew-dev-backend/SKILL.md +205 -0
  13. package/.speccrew/skills/speccrew-dev-backend/templates/TASK-RECORD-TEMPLATE.md +118 -0
  14. package/.speccrew/skills/speccrew-dev-desktop/SKILL.md +258 -0
  15. package/.speccrew/skills/speccrew-dev-desktop/templates/TASK-RECORD-TEMPLATE.md +161 -0
  16. package/.speccrew/skills/speccrew-dev-frontend/SKILL.md +202 -0
  17. package/.speccrew/skills/speccrew-dev-frontend/templates/TASK-RECORD-TEMPLATE.md +115 -0
  18. package/.speccrew/skills/speccrew-dev-mobile/SKILL.md +200 -0
  19. package/.speccrew/skills/speccrew-dev-mobile/templates/TASK-RECORD-TEMPLATE.md +125 -0
  20. package/.speccrew/skills/speccrew-fd-api-contract/SKILL.md +73 -0
  21. package/.speccrew/skills/speccrew-fd-api-contract/templates/API-CONTRACT-TEMPLATE.md +96 -0
  22. package/.speccrew/skills/speccrew-fd-feature-design/SKILL.md +395 -0
  23. package/.speccrew/skills/speccrew-fd-feature-design/templates/FEATURE-SPEC-TEMPLATE.md +387 -0
  24. package/.speccrew/skills/speccrew-get-timestamp/SKILL.md +80 -0
  25. package/.speccrew/skills/speccrew-get-timestamp/scripts/get-timestamp.js +35 -0
  26. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/SKILL.md +1116 -0
  27. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-FASTAPI.md +462 -0
  28. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-JAVA.md +480 -0
  29. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-NET.md +464 -0
  30. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE.md +480 -0
  31. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/MODULE-OVERVIEW-TEMPLATE.md +367 -0
  32. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/SKILL.md +667 -0
  33. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/STATUS-FORMATS.md +74 -0
  34. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/batch-orchestrator.js +176 -0
  35. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-next-batch.js +150 -0
  36. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-pending-features.js +106 -0
  37. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/mark-stale.js +249 -0
  38. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/process-batch-results.js +848 -0
  39. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/update-feature-status.js +226 -0
  40. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/SKILL.md +264 -0
  41. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/examples/features.json +34 -0
  42. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js +867 -0
  43. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/test-inventory.js +26 -0
  44. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/SKILL.md +165 -0
  45. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/apply-module-mapping.js +208 -0
  46. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/extract-module-summary.js +180 -0
  47. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/reindex-modules.js +358 -0
  48. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/SKILL.md +1055 -0
  49. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-DESKTOP.md +303 -0
  50. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-ELECTRON.md +327 -0
  51. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-MINIAPP.md +292 -0
  52. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-MOBILE.md +281 -0
  53. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI.md +324 -0
  54. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/SKILL.md +270 -0
  55. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/COMPONENT-PATTERN-TEMPLATE.md +33 -0
  56. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/LAYOUT-PATTERN-TEMPLATE.md +33 -0
  57. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/PAGE-TYPE-TEMPLATE.md +33 -0
  58. package/.speccrew/skills/speccrew-knowledge-graph-query/SKILL.md +229 -0
  59. package/.speccrew/skills/speccrew-knowledge-graph-query/scripts/graph-query.js +549 -0
  60. package/.speccrew/skills/speccrew-knowledge-graph-write/SKILL.md +181 -0
  61. package/.speccrew/skills/speccrew-knowledge-graph-write/scripts/graph-write.js +651 -0
  62. package/.speccrew/skills/speccrew-knowledge-module-summarize/SKILL.md +305 -0
  63. package/.speccrew/skills/speccrew-knowledge-module-summarize/templates/MODULE-OVERVIEW-TEMPLATE.md +400 -0
  64. package/.speccrew/skills/speccrew-knowledge-system-summarize/SKILL.md +351 -0
  65. package/.speccrew/skills/speccrew-knowledge-system-summarize/templates/SYSTEM-OVERVIEW-TEMPLATE.md +294 -0
  66. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/SKILL.md +683 -0
  67. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/STATUS-FORMATS.md +550 -0
  68. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/templates/techs-manifest-EXAMPLE.json +35 -0
  69. package/.speccrew/skills/speccrew-knowledge-techs-generate/SKILL.md +1087 -0
  70. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/ARCHITECTURE-TEMPLATE.md +240 -0
  71. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/COLOR-SYSTEM-TEMPLATE.md +68 -0
  72. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/COMPONENT-LIBRARY-TEMPLATE.md +86 -0
  73. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-BUILD-TEMPLATE.md +466 -0
  74. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DATA-TEMPLATE.md +432 -0
  75. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DESIGN-TEMPLATE.md +1209 -0
  76. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DEV-TEMPLATE.md +1433 -0
  77. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-SYSTEM-TEST-TEMPLATE.md +1052 -0
  78. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-UNIT-TEST-TEMPLATE.md +946 -0
  79. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/INDEX-TEMPLATE.md +29 -0
  80. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/PAGE-LAYOUTS-TEMPLATE.md +69 -0
  81. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/PAGE-TYPE-SUMMARY-TEMPLATE.md +74 -0
  82. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/TECH-STACK-TEMPLATE.md +232 -0
  83. package/.speccrew/skills/speccrew-knowledge-techs-generate-conventions/SKILL.md +628 -0
  84. package/.speccrew/skills/speccrew-knowledge-techs-generate-ui-style/SKILL.md +392 -0
  85. package/.speccrew/skills/speccrew-knowledge-techs-index/SKILL.md +489 -0
  86. package/.speccrew/skills/speccrew-knowledge-techs-index/templates/INDEX-TEMPLATE.md +243 -0
  87. package/.speccrew/skills/speccrew-knowledge-techs-init/SKILL.md +269 -0
  88. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/SKILL.md +562 -0
  89. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/BUSINESS-COMPONENTS-TEMPLATE.md +171 -0
  90. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMMON-COMPONENTS-TEMPLATE.md +177 -0
  91. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMPONENT-INDIVIDUAL-TEMPLATE.md +80 -0
  92. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMPONENT-LIBRARY-TEMPLATE.md +118 -0
  93. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/LAYOUT-INDIVIDUAL-TEMPLATE.md +97 -0
  94. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/LAYOUT-PATTERNS-TEMPLATE.md +208 -0
  95. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/NAVIGATION-PATTERNS-TEMPLATE.md +157 -0
  96. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/PAGE-TYPE-INDIVIDUAL-TEMPLATE.md +123 -0
  97. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/PAGE-TYPE-SUMMARY-TEMPLATE.md +58 -0
  98. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/SPACING-TEMPLATE.md +119 -0
  99. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/STYLE-SYSTEM-TEMPLATE.md +117 -0
  100. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/TYPOGRAPHY-TEMPLATE.md +107 -0
  101. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/UI-STYLE-GUIDE-TEMPLATE.md +171 -0
  102. package/.speccrew/skills/speccrew-pm-requirement-analysis/SKILL.md +434 -0
  103. package/.speccrew/skills/speccrew-pm-requirement-analysis/templates/BIZS-MODELING-TEMPLATE.md +332 -0
  104. package/.speccrew/skills/speccrew-pm-requirement-analysis/templates/PRD-TEMPLATE.md +200 -0
  105. package/.speccrew/skills/speccrew-pm-requirement-assess/SKILL.md +195 -0
  106. package/.speccrew/skills/speccrew-project-diagnosis/SKILL.md +208 -0
  107. package/.speccrew/skills/speccrew-project-diagnosis/templates/DIAGNOSIS-REPORT-TEMPLATE.md +202 -0
  108. package/.speccrew/skills/speccrew-sd-backend/SKILL.md +188 -0
  109. package/.speccrew/skills/speccrew-sd-backend/templates/INDEX-TEMPLATE.md +85 -0
  110. package/.speccrew/skills/speccrew-sd-backend/templates/SD-BACKEND-TEMPLATE.md +269 -0
  111. package/.speccrew/skills/speccrew-sd-desktop/SKILL.md +192 -0
  112. package/.speccrew/skills/speccrew-sd-desktop/templates/INDEX-TEMPLATE.md +271 -0
  113. package/.speccrew/skills/speccrew-sd-desktop/templates/SD-DESKTOP-TEMPLATE.md +673 -0
  114. package/.speccrew/skills/speccrew-sd-frontend/SKILL.md +176 -0
  115. package/.speccrew/skills/speccrew-sd-frontend/templates/INDEX-TEMPLATE.md +184 -0
  116. package/.speccrew/skills/speccrew-sd-frontend/templates/SD-FRONTEND-TEMPLATE.md +382 -0
  117. package/.speccrew/skills/speccrew-sd-mobile/SKILL.md +189 -0
  118. package/.speccrew/skills/speccrew-sd-mobile/templates/INDEX-TEMPLATE.md +219 -0
  119. package/.speccrew/skills/speccrew-sd-mobile/templates/SD-MOBILE-TEMPLATE.md +534 -0
  120. package/.speccrew/skills/speccrew-test-case-design/SKILL.md +284 -0
  121. package/.speccrew/skills/speccrew-test-case-design/templates/TEST-CASE-DESIGN-TEMPLATE.md +263 -0
  122. package/.speccrew/skills/speccrew-test-code-gen/SKILL.md +313 -0
  123. package/.speccrew/skills/speccrew-test-code-gen/templates/TEST-CODE-PLAN-TEMPLATE.md +180 -0
  124. package/.speccrew/skills/speccrew-test-execute/SKILL.md +283 -0
  125. package/.speccrew/skills/speccrew-test-execute/templates/BUG-REPORT-TEMPLATE.md +50 -0
  126. package/.speccrew/skills/speccrew-test-execute/templates/TEST-REPORT-TEMPLATE.md +57 -0
  127. package/.speccrew/skills/speccrew-workflow-diagnose/SKILL.md +155 -0
  128. package/LICENSE +21 -0
  129. package/README.ar.md +318 -0
  130. package/README.en.md +318 -0
  131. package/README.es.md +318 -0
  132. package/README.md +340 -0
  133. package/bin/cli.js +62 -0
  134. package/lib/commands/doctor.js +138 -0
  135. package/lib/commands/init.js +231 -0
  136. package/lib/commands/list.js +114 -0
  137. package/lib/commands/uninstall.js +117 -0
  138. package/lib/commands/update.js +351 -0
  139. package/lib/ide-adapters.js +73 -0
  140. package/lib/utils.js +104 -0
  141. package/package.json +28 -0
  142. package/workspace-template/docs/configs/document-templates.json +667 -0
  143. package/workspace-template/docs/configs/platform-mapping.json +194 -0
  144. package/workspace-template/docs/configs/tech-stack-mappings.json +313 -0
  145. package/workspace-template/docs/configs/validation-rules.json +87 -0
  146. package/workspace-template/docs/rules/mermaid-rule.md +114 -0
  147. package/workspace-template/docs/solutions/Agent/346/212/200/350/203/275/345/256/232/344/271/211+/351/234/200/346/261/202/346/226/207/346/241/243+UML/344/275/277/347/224/250/346/250/241/346/235/277/357/274/210ISA-95/345/205/255/346/256/265/345/274/217/350/236/215/345/220/210/347/211/210/357/274/211.md +586 -0
  148. package/workspace-template/docs/solutions/agent-knowledge-map.md +238 -0
  149. package/workspace-template/docs/solutions/bizs-knowledge-pipeline.md +678 -0
  150. package/workspace-template/docs/solutions/harness.md +410 -0
  151. package/workspace-template/docs/solutions/knowledge-incremental-sync-spec.md +943 -0
  152. package/workspace-template/docs/solutions/techs-knowledge-pipeline.md +803 -0
  153. package/workspace-template/docs/solutions/workspace-structure.md +318 -0
@@ -0,0 +1,549 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Knowledge Graph Query Operations
4
+ * Query the knowledge graph to find nodes, edges, and trace relationships.
5
+ * All data read from {GraphRoot}/ directory.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ // ── Parse Arguments ─────────────────────────────────────────────────────────
12
+
13
+ function parseArgs() {
14
+ const args = process.argv.slice(2);
15
+ const parsed = {};
16
+
17
+ for (let i = 0; i < args.length; i++) {
18
+ const arg = args[i];
19
+ if (arg.startsWith('--')) {
20
+ const key = arg.slice(2);
21
+ const nextArg = args[i + 1];
22
+ if (nextArg && !nextArg.startsWith('--')) {
23
+ parsed[key] = nextArg;
24
+ i++;
25
+ } else {
26
+ parsed[key] = true;
27
+ }
28
+ }
29
+ }
30
+
31
+ return parsed;
32
+ }
33
+
34
+ const args = parseArgs();
35
+
36
+ // Validate required parameters
37
+ const validActions = ['get-node', 'query-nodes', 'get-edges', 'search', 'trace-upstream', 'trace-downstream'];
38
+ if (!args.action || !validActions.includes(args.action)) {
39
+ console.error(JSON.stringify({
40
+ status: 'error',
41
+ message: `Invalid or missing action. Must be one of: ${validActions.join(', ')}`
42
+ }));
43
+ process.exit(1);
44
+ }
45
+
46
+ if (!args.graphRoot) {
47
+ console.error(JSON.stringify({
48
+ status: 'error',
49
+ message: 'Missing required parameter: --graphRoot'
50
+ }));
51
+ process.exit(1);
52
+ }
53
+
54
+ // Set defaults
55
+ const action = args.action;
56
+ const id = args.id;
57
+ const nodeId = args.nodeId || args['node-id'];
58
+ const module = args.module;
59
+ const type = args.type;
60
+ const keyword = args.keyword;
61
+ const direction = args.direction || 'both';
62
+ const depth = parseInt(args.depth, 10) || 2;
63
+ const graphRoot = args.graphRoot;
64
+
65
+ // ── Helpers ──────────────────────────────────────────────────────────────────
66
+
67
+ function readJsonFile(filePath) {
68
+ try {
69
+ if (fs.existsSync(filePath)) {
70
+ const content = fs.readFileSync(filePath, 'utf-8');
71
+ return JSON.parse(content);
72
+ }
73
+ } catch (e) {
74
+ // Return null on error
75
+ }
76
+ return null;
77
+ }
78
+
79
+ function getModuleFromId(nodeId) {
80
+ const parts = nodeId.split('-');
81
+ if (parts.length >= 2) {
82
+ return parts[1];
83
+ }
84
+ return null;
85
+ }
86
+
87
+ function getIndexPath() {
88
+ return path.join(graphRoot, 'indices', 'index.json');
89
+ }
90
+
91
+ function getNodesPath(mod) {
92
+ return path.join(graphRoot, 'nodes', `${mod}.json`);
93
+ }
94
+
95
+ function getEdgesPath(mod) {
96
+ return path.join(graphRoot, 'edges', `${mod}.json`);
97
+ }
98
+
99
+ function getCrossEdgesPath() {
100
+ return path.join(graphRoot, 'edges', 'cross-module.json');
101
+ }
102
+
103
+ function getAllEdgesForModule(mod) {
104
+ const edges = [];
105
+
106
+ // Module edges
107
+ const ep = getEdgesPath(mod);
108
+ const data = readJsonFile(ep);
109
+ if (data && data.edges) {
110
+ edges.push(...data.edges);
111
+ }
112
+
113
+ // Cross-module edges
114
+ const cp = getCrossEdgesPath();
115
+ const crossData = readJsonFile(cp);
116
+ if (crossData && crossData.edges) {
117
+ edges.push(...crossData.edges);
118
+ }
119
+
120
+ return edges;
121
+ }
122
+
123
+ function findNodeById(nodeId) {
124
+ const mod = getModuleFromId(nodeId);
125
+ if (!mod) return null;
126
+
127
+ const np = getNodesPath(mod);
128
+ const data = readJsonFile(np);
129
+ if (data && data.nodes) {
130
+ for (const n of data.nodes) {
131
+ if (n.id === nodeId) {
132
+ return n;
133
+ }
134
+ }
135
+ }
136
+
137
+ // Fallback: search index first, then node file
138
+ const index = readJsonFile(getIndexPath());
139
+ if (index && index[nodeId]) {
140
+ const indexMod = index[nodeId].module;
141
+ if (indexMod !== mod) {
142
+ const np2 = getNodesPath(indexMod);
143
+ const data2 = readJsonFile(np2);
144
+ if (data2 && data2.nodes) {
145
+ for (const n of data2.nodes) {
146
+ if (n.id === nodeId) {
147
+ return n;
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+
154
+ return null;
155
+ }
156
+
157
+ function getAllModuleNames() {
158
+ const nodesDir = path.join(graphRoot, 'nodes');
159
+ const modules = [];
160
+
161
+ try {
162
+ if (fs.existsSync(nodesDir)) {
163
+ const files = fs.readdirSync(nodesDir);
164
+ for (const file of files) {
165
+ if (file.endsWith('.json')) {
166
+ modules.push(path.basename(file, '.json'));
167
+ }
168
+ }
169
+ }
170
+ } catch (e) {
171
+ // Ignore errors
172
+ }
173
+
174
+ return modules;
175
+ }
176
+
177
+ function getAllEdges() {
178
+ const allEdges = [];
179
+ const modules = getAllModuleNames();
180
+
181
+ // Get edges from all modules
182
+ for (const mod of modules) {
183
+ const ep = getEdgesPath(mod);
184
+ const data = readJsonFile(ep);
185
+ if (data && data.edges) {
186
+ allEdges.push(...data.edges);
187
+ }
188
+ }
189
+
190
+ // Cross-module edges
191
+ const cp = getCrossEdgesPath();
192
+ const crossData = readJsonFile(cp);
193
+ if (crossData && crossData.edges) {
194
+ allEdges.push(...crossData.edges);
195
+ }
196
+
197
+ return allEdges;
198
+ }
199
+
200
+ // ── Actions ──────────────────────────────────────────────────────────────────
201
+
202
+ function invokeGetNode(nodeId) {
203
+ const node = findNodeById(nodeId);
204
+
205
+ if (node) {
206
+ return {
207
+ status: 'success',
208
+ action: 'get-node',
209
+ resultCount: 1,
210
+ data: node
211
+ };
212
+ } else {
213
+ return {
214
+ status: 'not-found',
215
+ action: 'get-node',
216
+ resultCount: 0,
217
+ data: null,
218
+ message: `Node '${nodeId}' not found`
219
+ };
220
+ }
221
+ }
222
+
223
+ function invokeQueryNodes(mod, nodeType) {
224
+ const results = [];
225
+ const nodesDir = path.join(graphRoot, 'nodes');
226
+
227
+ if (!fs.existsSync(nodesDir)) {
228
+ return {
229
+ status: 'success',
230
+ action: 'query-nodes',
231
+ resultCount: 0,
232
+ data: []
233
+ };
234
+ }
235
+
236
+ const files = [];
237
+ if (mod) {
238
+ const mp = getNodesPath(mod);
239
+ if (fs.existsSync(mp)) {
240
+ files.push(mp);
241
+ }
242
+ } else {
243
+ const allFiles = fs.readdirSync(nodesDir);
244
+ for (const f of allFiles) {
245
+ if (f.endsWith('.json')) {
246
+ files.push(path.join(nodesDir, f));
247
+ }
248
+ }
249
+ }
250
+
251
+ for (const f of files) {
252
+ const data = readJsonFile(f);
253
+ if (data && data.nodes) {
254
+ for (const n of data.nodes) {
255
+ if (nodeType && n.type !== nodeType) {
256
+ continue;
257
+ }
258
+ results.push(n);
259
+ }
260
+ }
261
+ }
262
+
263
+ return {
264
+ status: 'success',
265
+ action: 'query-nodes',
266
+ resultCount: results.length,
267
+ data: results
268
+ };
269
+ }
270
+
271
+ function invokeGetEdges(nid, dir) {
272
+ const mod = getModuleFromId(nid);
273
+ const allEdges = getAllEdgesForModule(mod);
274
+ const results = [];
275
+
276
+ for (const e of allEdges) {
277
+ switch (dir) {
278
+ case 'out':
279
+ if (e.source === nid) {
280
+ results.push(e);
281
+ }
282
+ break;
283
+ case 'in':
284
+ if (e.target === nid) {
285
+ results.push(e);
286
+ }
287
+ break;
288
+ case 'both':
289
+ default:
290
+ if (e.source === nid || e.target === nid) {
291
+ results.push(e);
292
+ }
293
+ break;
294
+ }
295
+ }
296
+
297
+ return {
298
+ status: 'success',
299
+ action: 'get-edges',
300
+ resultCount: results.length,
301
+ data: results
302
+ };
303
+ }
304
+
305
+ function invokeSearch(kw, nodeType, mod) {
306
+ const results = [];
307
+ const nodesDir = path.join(graphRoot, 'nodes');
308
+ const kwLower = kw.toLowerCase();
309
+
310
+ if (!fs.existsSync(nodesDir)) {
311
+ return {
312
+ status: 'success',
313
+ action: 'search',
314
+ resultCount: 0,
315
+ data: []
316
+ };
317
+ }
318
+
319
+ const files = [];
320
+ if (mod) {
321
+ const mp = getNodesPath(mod);
322
+ if (fs.existsSync(mp)) {
323
+ files.push(mp);
324
+ }
325
+ } else {
326
+ const allFiles = fs.readdirSync(nodesDir);
327
+ for (const f of allFiles) {
328
+ if (f.endsWith('.json')) {
329
+ files.push(path.join(nodesDir, f));
330
+ }
331
+ }
332
+ }
333
+
334
+ for (const f of files) {
335
+ const data = readJsonFile(f);
336
+ if (data && data.nodes) {
337
+ for (const n of data.nodes) {
338
+ if (nodeType && n.type !== nodeType) {
339
+ continue;
340
+ }
341
+
342
+ let match = false;
343
+
344
+ // Search in id, name, description
345
+ if (n.id && n.id.toLowerCase().includes(kwLower)) {
346
+ match = true;
347
+ }
348
+ if (!match && n.name && n.name.toLowerCase().includes(kwLower)) {
349
+ match = true;
350
+ }
351
+ if (!match && n.description && n.description.toLowerCase().includes(kwLower)) {
352
+ match = true;
353
+ }
354
+
355
+ // Search in tags
356
+ if (!match && n.tags && Array.isArray(n.tags)) {
357
+ for (const tag of n.tags) {
358
+ if (tag && tag.toLowerCase().includes(kwLower)) {
359
+ match = true;
360
+ break;
361
+ }
362
+ }
363
+ }
364
+
365
+ // Search in keywords
366
+ if (!match && n.keywords && Array.isArray(n.keywords)) {
367
+ for (const k of n.keywords) {
368
+ if (k && k.toLowerCase().includes(kwLower)) {
369
+ match = true;
370
+ break;
371
+ }
372
+ }
373
+ }
374
+
375
+ if (match) {
376
+ results.push(n);
377
+ }
378
+ }
379
+ }
380
+ }
381
+
382
+ return {
383
+ status: 'success',
384
+ action: 'search',
385
+ keyword: kw,
386
+ resultCount: results.length,
387
+ data: results
388
+ };
389
+ }
390
+
391
+ function invokeTrace(nodeId, maxDepth, traceDirection) {
392
+ // traceDirection: "upstream" = find who points TO this node (incoming edges)
393
+ // "downstream" = find what this node points TO (outgoing edges)
394
+
395
+ const visited = new Set();
396
+ const rootNode = findNodeById(nodeId);
397
+
398
+ if (!rootNode) {
399
+ return {
400
+ status: 'not-found',
401
+ action: `trace-${traceDirection}`,
402
+ message: `Node '${nodeId}' not found`
403
+ };
404
+ }
405
+
406
+ function traceRecursive(nid, currentDepth) {
407
+ if (currentDepth > maxDepth) {
408
+ return [];
409
+ }
410
+ if (visited.has(nid)) {
411
+ return [];
412
+ }
413
+ visited.add(nid);
414
+
415
+ // Get all edges from all modules for cross-module tracing
416
+ const allEdges = getAllEdges();
417
+
418
+ const connectedEdges = [];
419
+ if (traceDirection === 'upstream') {
420
+ for (const e of allEdges) {
421
+ if (e.target === nid) {
422
+ connectedEdges.push(e);
423
+ }
424
+ }
425
+ } else {
426
+ for (const e of allEdges) {
427
+ if (e.source === nid) {
428
+ connectedEdges.push(e);
429
+ }
430
+ }
431
+ }
432
+
433
+ const children = [];
434
+ for (const edge of connectedEdges) {
435
+ const nextId = traceDirection === 'upstream' ? edge.source : edge.target;
436
+ const nextNode = findNodeById(nextId);
437
+
438
+ let childTrace = [];
439
+ if (currentDepth + 1 <= maxDepth) {
440
+ childTrace = traceRecursive(nextId, currentDepth + 1);
441
+ }
442
+
443
+ const child = {
444
+ node: nextNode || { id: nextId },
445
+ edge: {
446
+ type: edge.type,
447
+ metadata: edge.metadata
448
+ },
449
+ depth: currentDepth
450
+ };
451
+
452
+ if (traceDirection === 'upstream') {
453
+ child.upstream = childTrace;
454
+ } else {
455
+ child.downstream = childTrace;
456
+ }
457
+
458
+ children.push(child);
459
+ }
460
+
461
+ return children;
462
+ }
463
+
464
+ const traceResult = traceRecursive(nodeId, 1);
465
+
466
+ const output = {
467
+ status: 'success',
468
+ action: `trace-${traceDirection}`,
469
+ root: rootNode
470
+ };
471
+
472
+ output[traceDirection] = traceResult;
473
+
474
+ return output;
475
+ }
476
+
477
+ // ── Main ─────────────────────────────────────────────────────────────────────
478
+
479
+ let result;
480
+
481
+ switch (action) {
482
+ case 'get-node':
483
+ if (!id) {
484
+ console.error(JSON.stringify({
485
+ status: 'error',
486
+ message: 'Missing required parameter: --id'
487
+ }));
488
+ process.exit(1);
489
+ }
490
+ result = invokeGetNode(id);
491
+ break;
492
+
493
+ case 'query-nodes':
494
+ result = invokeQueryNodes(module, type);
495
+ break;
496
+
497
+ case 'get-edges':
498
+ if (!nodeId) {
499
+ console.error(JSON.stringify({
500
+ status: 'error',
501
+ message: 'Missing required parameter: --nodeId'
502
+ }));
503
+ process.exit(1);
504
+ }
505
+ result = invokeGetEdges(nodeId, direction);
506
+ break;
507
+
508
+ case 'search':
509
+ if (!keyword) {
510
+ console.error(JSON.stringify({
511
+ status: 'error',
512
+ message: 'Missing required parameter: --keyword'
513
+ }));
514
+ process.exit(1);
515
+ }
516
+ result = invokeSearch(keyword, type, module);
517
+ break;
518
+
519
+ case 'trace-upstream':
520
+ if (!id) {
521
+ console.error(JSON.stringify({
522
+ status: 'error',
523
+ message: 'Missing required parameter: --id'
524
+ }));
525
+ process.exit(1);
526
+ }
527
+ result = invokeTrace(id, depth, 'upstream');
528
+ break;
529
+
530
+ case 'trace-downstream':
531
+ if (!id) {
532
+ console.error(JSON.stringify({
533
+ status: 'error',
534
+ message: 'Missing required parameter: --id'
535
+ }));
536
+ process.exit(1);
537
+ }
538
+ result = invokeTrace(id, depth, 'downstream');
539
+ break;
540
+
541
+ default:
542
+ console.error(JSON.stringify({
543
+ status: 'error',
544
+ message: `Unknown action: ${action}`
545
+ }));
546
+ process.exit(1);
547
+ }
548
+
549
+ console.log(JSON.stringify(result, null, 0));