@tekyzinc/gsd-t 2.50.12 → 2.53.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +379 -372
- package/bin/component-registry.js +250 -0
- package/bin/graph-cgc.js +510 -510
- package/bin/graph-indexer.js +147 -147
- package/bin/graph-overlay.js +195 -195
- package/bin/graph-parsers.js +327 -327
- package/bin/graph-query.js +453 -452
- package/bin/graph-store.js +154 -154
- package/bin/qa-calibrator.js +194 -0
- package/bin/scan-data-collector.js +153 -153
- package/bin/scan-diagrams-generators.js +187 -187
- package/bin/scan-diagrams.js +79 -79
- package/bin/scan-renderer.js +92 -92
- package/bin/scan-report-sections.js +121 -121
- package/bin/scan-report.js +184 -184
- package/bin/scan-schema-parsers.js +199 -199
- package/bin/scan-schema.js +103 -103
- package/bin/token-budget.js +246 -0
- package/commands/Claude-md.md +10 -10
- package/commands/branch.md +15 -15
- package/commands/checkin.md +45 -45
- package/commands/global-change.md +209 -209
- package/commands/gsd-t-audit.md +199 -0
- package/commands/gsd-t-backlog-add.md +94 -94
- package/commands/gsd-t-backlog-edit.md +111 -111
- package/commands/gsd-t-backlog-list.md +63 -63
- package/commands/gsd-t-backlog-move.md +94 -94
- package/commands/gsd-t-backlog-promote.md +123 -123
- package/commands/gsd-t-backlog-remove.md +86 -86
- package/commands/gsd-t-backlog-settings.md +158 -158
- package/commands/gsd-t-complete-milestone.md +528 -515
- package/commands/gsd-t-debug.md +506 -399
- package/commands/gsd-t-discuss.md +174 -174
- package/commands/gsd-t-execute.md +758 -634
- package/commands/gsd-t-feature.md +276 -276
- package/commands/gsd-t-health.md +142 -142
- package/commands/gsd-t-help.md +465 -457
- package/commands/gsd-t-impact.md +302 -302
- package/commands/gsd-t-init.md +320 -280
- package/commands/gsd-t-integrate.md +365 -249
- package/commands/gsd-t-milestone.md +87 -87
- package/commands/gsd-t-partition.md +442 -361
- package/commands/gsd-t-pause.md +82 -82
- package/commands/gsd-t-plan.md +345 -344
- package/commands/gsd-t-populate.md +111 -111
- package/commands/gsd-t-prd.md +326 -326
- package/commands/gsd-t-project.md +211 -211
- package/commands/gsd-t-promote-debt.md +123 -123
- package/commands/gsd-t-prompt.md +137 -137
- package/commands/gsd-t-qa.md +266 -266
- package/commands/gsd-t-quick.md +357 -234
- package/commands/gsd-t-reflect.md +134 -134
- package/commands/gsd-t-resume.md +72 -72
- package/commands/gsd-t-scan.md +615 -615
- package/commands/gsd-t-setup.md +76 -0
- package/commands/gsd-t-status.md +192 -166
- package/commands/gsd-t-test-sync.md +381 -381
- package/commands/gsd-t-triage-and-merge.md +171 -171
- package/commands/gsd-t-verify.md +382 -382
- package/commands/gsd-t-visualize.md +118 -118
- package/commands/gsd-t-wave.md +401 -378
- package/docs/GSD-T-README.md +425 -422
- package/docs/architecture.md +385 -369
- package/docs/harness-design-analysis.md +371 -0
- package/docs/infrastructure.md +205 -205
- package/docs/prd-graph-engine.md +398 -398
- package/docs/prd-gsd2-hybrid.md +559 -559
- package/docs/prd-harness-evolution.md +583 -0
- package/docs/requirements.md +14 -0
- package/docs/workflows.md +226 -226
- package/examples/.gsd-t/domains/example-domain/scope.md +13 -13
- package/package.json +40 -40
- package/scripts/gsd-t-auto-route.js +39 -39
- package/scripts/gsd-t-dashboard-mockup.html +1143 -1143
- package/scripts/gsd-t-dashboard-server.js +171 -171
- package/scripts/gsd-t-dashboard.html +262 -262
- package/scripts/gsd-t-event-writer.js +128 -128
- package/scripts/gsd-t-statusline.js +94 -94
- package/scripts/gsd-t-tools.js +175 -175
- package/templates/CLAUDE-global.md +639 -614
- package/templates/CLAUDE-project.md +24 -0
- package/templates/backlog-settings.md +18 -18
- package/templates/backlog.md +1 -1
- package/templates/progress.md +40 -40
- package/templates/shared-services-contract.md +60 -60
- package/templates/stacks/desktop.ini +2 -2
- package/bin/desktop.ini +0 -2
- package/commands/desktop.ini +0 -2
- package/docs/ci-examples/desktop.ini +0 -2
- package/docs/desktop.ini +0 -2
- package/examples/.gsd-t/contracts/desktop.ini +0 -2
- package/examples/.gsd-t/desktop.ini +0 -2
- package/examples/.gsd-t/domains/desktop.ini +0 -2
- package/examples/.gsd-t/domains/example-domain/desktop.ini +0 -2
- package/examples/desktop.ini +0 -2
- package/examples/rules/desktop.ini +0 -2
- package/scripts/desktop.ini +0 -2
- package/templates/desktop.ini +0 -2
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function genSystemArchitecture(analysisData) {
|
|
4
|
-
try {
|
|
5
|
-
const services = (analysisData.services || []).slice(0, 4);
|
|
6
|
-
if (services.length >= 2) {
|
|
7
|
-
const lines = ['graph TB',
|
|
8
|
-
' classDef user fill:#0d2035,stroke:#06b6d4,color:#a5f3fc',
|
|
9
|
-
' classDef svc fill:#1a0f3a,stroke:#7c3aed,color:#ddd6fe',
|
|
10
|
-
' classDef db fill:#0a2318,stroke:#10b981,color:#a7f3d0',
|
|
11
|
-
' User(["👤 User"]):::user'];
|
|
12
|
-
services.forEach((s, i) => { lines.push(' S' + i + '["' + s + '"]:::svc'); lines.push(' User --> S' + i); });
|
|
13
|
-
return lines.join('\n');
|
|
14
|
-
}
|
|
15
|
-
return `graph TB
|
|
16
|
-
classDef user fill:#0d2035,stroke:#06b6d4,color:#a5f3fc
|
|
17
|
-
classDef app fill:#0f1d3a,stroke:#3b82f6,color:#bfdbfe
|
|
18
|
-
classDef api fill:#1a0f3a,stroke:#7c3aed,color:#ddd6fe
|
|
19
|
-
classDef db fill:#0a2318,stroke:#10b981,color:#a7f3d0
|
|
20
|
-
classDef ext fill:#111827,stroke:#374151,color:#9ca3af
|
|
21
|
-
USER(["👤 User\\nweb & mobile"]):::user
|
|
22
|
-
subgraph PLATFORM[" Application Platform "]
|
|
23
|
-
APP["🌐 Frontend\\nUser Interface"]:::app
|
|
24
|
-
API["⚡ Backend\\nApplication Logic"]:::api
|
|
25
|
-
DB[("🗃 Database\\nPrimary Store")]:::db
|
|
26
|
-
end
|
|
27
|
-
EXT["🌎 External Services\\nAPIs & Integrations"]:::ext
|
|
28
|
-
USER -->|"HTTPS"| APP
|
|
29
|
-
APP -->|"REST / JSON"| API
|
|
30
|
-
API -->|"reads / writes"| DB
|
|
31
|
-
API -->|"calls"| EXT
|
|
32
|
-
style PLATFORM fill:#0a0f1e,stroke:#1e3a5f,color:#e2e8f0`;
|
|
33
|
-
} catch { return 'graph TB\n App[Application] --> DB[(Database)]'; }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function genAppArchitecture(analysisData) {
|
|
37
|
-
try {
|
|
38
|
-
const layers = (analysisData.layers || []).slice(0, 5);
|
|
39
|
-
if (layers.length >= 3) {
|
|
40
|
-
const lines = ['graph TB'];
|
|
41
|
-
const colors = ['#0f1d3a,#3b82f6', '#1a0f3a,#7c3aed', '#0a2318,#10b981', '#1f1505,#f59e0b', '#12102a,#6366f1'];
|
|
42
|
-
layers.forEach((l, i) => {
|
|
43
|
-
const [bg, stroke] = colors[i % colors.length].split(',');
|
|
44
|
-
lines.push(` L${i}["${l}"]`);
|
|
45
|
-
lines.push(` style L${i} fill:${bg},stroke:${stroke},color:#e2e8f0`);
|
|
46
|
-
if (i > 0) lines.push(` L${i - 1} --> L${i}`);
|
|
47
|
-
});
|
|
48
|
-
return lines.join('\n');
|
|
49
|
-
}
|
|
50
|
-
return `graph TB
|
|
51
|
-
classDef client fill:#0d2035,stroke:#06b6d4,color:#a5f3fc
|
|
52
|
-
classDef ctrl fill:#0f1d3a,stroke:#3b82f6,color:#bfdbfe
|
|
53
|
-
classDef svc fill:#1a0f3a,stroke:#7c3aed,color:#ddd6fe
|
|
54
|
-
classDef repo fill:#1a0f3a,stroke:#8b5cf6,color:#ddd6fe
|
|
55
|
-
classDef db fill:#0a2318,stroke:#10b981,color:#a7f3d0
|
|
56
|
-
subgraph CL[" Clients "]
|
|
57
|
-
WEB["🌐 Web App"]:::client
|
|
58
|
-
MOB["📱 Mobile"]:::client
|
|
59
|
-
end
|
|
60
|
-
subgraph CTR[" Controller Layer "]
|
|
61
|
-
AC["AuthController"]:::ctrl
|
|
62
|
-
TC["TasksController"]:::ctrl
|
|
63
|
-
PC["ProjectsController"]:::ctrl
|
|
64
|
-
end
|
|
65
|
-
subgraph SVC[" Service Layer "]
|
|
66
|
-
AS["AuthService"]:::svc
|
|
67
|
-
TS["TasksService"]:::svc
|
|
68
|
-
PS["ProjectsService"]:::svc
|
|
69
|
-
end
|
|
70
|
-
DB[("🗃 Database")]:::db
|
|
71
|
-
WEB & MOB --> CTR --> SVC --> DB
|
|
72
|
-
style CL fill:#080e1a,stroke:#0e2035
|
|
73
|
-
style CTR fill:#080e1a,stroke:#1e3a5f
|
|
74
|
-
style SVC fill:#080e1a,stroke:#2d1a5e`;
|
|
75
|
-
} catch { return 'graph TB\n subgraph App\n Controllers --> Services --> Repositories\n end'; }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function genWorkflow(analysisData) {
|
|
79
|
-
try {
|
|
80
|
-
const states = (analysisData.states || []).slice(0, 6);
|
|
81
|
-
if (states.length >= 3) {
|
|
82
|
-
const lines = ['stateDiagram-v2', ' direction LR', ' [*] --> ' + states[0]];
|
|
83
|
-
states.forEach((s, i) => { if (i < states.length - 1) lines.push(` ${s} --> ${states[i + 1]}`); });
|
|
84
|
-
lines.push(' ' + states[states.length - 1] + ' --> [*]');
|
|
85
|
-
return lines.join('\n');
|
|
86
|
-
}
|
|
87
|
-
return `stateDiagram-v2
|
|
88
|
-
direction LR
|
|
89
|
-
[*] --> Draft : create
|
|
90
|
-
Draft --> Open : submit
|
|
91
|
-
Draft --> [*] : discard
|
|
92
|
-
Open --> InProgress : assign
|
|
93
|
-
Open --> Cancelled : cancel
|
|
94
|
-
InProgress --> Review : mark done
|
|
95
|
-
InProgress --> Blocked : flag blocker
|
|
96
|
-
InProgress --> Open : unassign
|
|
97
|
-
Blocked --> InProgress : resolve
|
|
98
|
-
Review --> Done : approve
|
|
99
|
-
Review --> InProgress : reject
|
|
100
|
-
Done --> [*]
|
|
101
|
-
Cancelled --> [*]
|
|
102
|
-
note right of Blocked
|
|
103
|
-
No SLA timeout —
|
|
104
|
-
can stagnate here
|
|
105
|
-
end note`;
|
|
106
|
-
} catch { return 'stateDiagram-v2\n [*] --> Active\n Active --> Done\n Done --> [*]'; }
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function genDataFlow(analysisData) {
|
|
110
|
-
try {
|
|
111
|
-
const endpoints = (analysisData.endpoints || []).slice(0, 1);
|
|
112
|
-
const ep = endpoints[0] || 'POST /api/resource';
|
|
113
|
-
return `flowchart TD
|
|
114
|
-
classDef user fill:#0d2035,stroke:#06b6d4,color:#a5f3fc
|
|
115
|
-
classDef fe fill:#0f1d3a,stroke:#3b82f6,color:#bfdbfe
|
|
116
|
-
classDef api fill:#1a0f3a,stroke:#7c3aed,color:#ddd6fe
|
|
117
|
-
classDef db fill:#0a2318,stroke:#10b981,color:#a7f3d0
|
|
118
|
-
classDef queue fill:#1f1505,stroke:#f59e0b,color:#fde68a
|
|
119
|
-
classDef ok fill:#0a2318,stroke:#10b981,color:#a7f3d0
|
|
120
|
-
USR(["👤 User"]):::user
|
|
121
|
-
subgraph FE["Frontend"]
|
|
122
|
-
FORM["Form\\n+ Client Validation"]:::fe
|
|
123
|
-
end
|
|
124
|
-
subgraph API["API Server"]
|
|
125
|
-
PIPE["ValidationPipe\\n+ Sanitize"]:::api
|
|
126
|
-
CTRL["Controller\\n${ep}"]:::api
|
|
127
|
-
SVC["Service\\nbusiness logic"]:::api
|
|
128
|
-
REPO["Repository\\nINSERT / UPDATE"]:::api
|
|
129
|
-
end
|
|
130
|
-
DB[("🗃 Database")]:::db
|
|
131
|
-
RD[("⚡ Queue")]:::queue
|
|
132
|
-
RES(["✓ Response"]):::ok
|
|
133
|
-
USR --> FORM --> PIPE --> CTRL --> SVC --> REPO --> DB
|
|
134
|
-
SVC --> RD
|
|
135
|
-
DB --> RES
|
|
136
|
-
style FE fill:#080e1a,stroke:#1e3a5f
|
|
137
|
-
style API fill:#080e1a,stroke:#2d1a5e`;
|
|
138
|
-
} catch { return 'flowchart TD\n Input --> Validate --> Process --> Store --> Respond'; }
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function genSequence(analysisData) {
|
|
142
|
-
try {
|
|
143
|
-
const ep = ((analysisData.endpoints || [])[0]) || 'POST /api/resource';
|
|
144
|
-
return `sequenceDiagram
|
|
145
|
-
autonumber
|
|
146
|
-
actor User
|
|
147
|
-
participant Client
|
|
148
|
-
participant API as API Server
|
|
149
|
-
participant DB as Database
|
|
150
|
-
participant Queue
|
|
151
|
-
User->>Client: Submit form
|
|
152
|
-
Client->>API: ${ep}
|
|
153
|
-
API->>API: validate & sanitize
|
|
154
|
-
alt invalid input
|
|
155
|
-
API-->>Client: 400 Bad Request
|
|
156
|
-
else valid
|
|
157
|
-
API->>DB: INSERT record
|
|
158
|
-
DB-->>API: record id
|
|
159
|
-
API->>Queue: enqueue background job
|
|
160
|
-
API-->>Client: 201 Created
|
|
161
|
-
Client-->>User: Success feedback
|
|
162
|
-
end`;
|
|
163
|
-
} catch { return 'sequenceDiagram\n Client->>Server: Request\n Server->>DB: Query\n DB-->>Server: Result\n Server-->>Client: Response'; }
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function genDatabaseSchema(schemaData) {
|
|
167
|
-
try {
|
|
168
|
-
if (!schemaData || !schemaData.detected || !schemaData.entities || schemaData.entities.length === 0) return '';
|
|
169
|
-
const relMap = { 'one-to-many': '||--o{', 'many-to-one': '}o--||', 'many-to-many': '}o--o{', 'one-to-one': '||--||' };
|
|
170
|
-
const lines = ['erDiagram'];
|
|
171
|
-
for (const entity of schemaData.entities.slice(0, 8)) {
|
|
172
|
-
lines.push(' ' + entity.name + ' {');
|
|
173
|
-
for (const f of (entity.fields || []).slice(0, 10)) {
|
|
174
|
-
lines.push(' ' + (f.type || 'string') + ' ' + f.name);
|
|
175
|
-
}
|
|
176
|
-
lines.push(' }');
|
|
177
|
-
}
|
|
178
|
-
for (const entity of schemaData.entities) {
|
|
179
|
-
for (const rel of (entity.relations || [])) {
|
|
180
|
-
lines.push(' ' + rel.fromEntity + ' ' + (relMap[rel.type] || '||--o{') + ' ' + rel.toEntity + ' : "has"');
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return lines.join('\n');
|
|
184
|
-
} catch { return ''; }
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
module.exports = { genSystemArchitecture, genAppArchitecture, genWorkflow, genDataFlow, genSequence, genDatabaseSchema };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function genSystemArchitecture(analysisData) {
|
|
4
|
+
try {
|
|
5
|
+
const services = (analysisData.services || []).slice(0, 4);
|
|
6
|
+
if (services.length >= 2) {
|
|
7
|
+
const lines = ['graph TB',
|
|
8
|
+
' classDef user fill:#0d2035,stroke:#06b6d4,color:#a5f3fc',
|
|
9
|
+
' classDef svc fill:#1a0f3a,stroke:#7c3aed,color:#ddd6fe',
|
|
10
|
+
' classDef db fill:#0a2318,stroke:#10b981,color:#a7f3d0',
|
|
11
|
+
' User(["👤 User"]):::user'];
|
|
12
|
+
services.forEach((s, i) => { lines.push(' S' + i + '["' + s + '"]:::svc'); lines.push(' User --> S' + i); });
|
|
13
|
+
return lines.join('\n');
|
|
14
|
+
}
|
|
15
|
+
return `graph TB
|
|
16
|
+
classDef user fill:#0d2035,stroke:#06b6d4,color:#a5f3fc
|
|
17
|
+
classDef app fill:#0f1d3a,stroke:#3b82f6,color:#bfdbfe
|
|
18
|
+
classDef api fill:#1a0f3a,stroke:#7c3aed,color:#ddd6fe
|
|
19
|
+
classDef db fill:#0a2318,stroke:#10b981,color:#a7f3d0
|
|
20
|
+
classDef ext fill:#111827,stroke:#374151,color:#9ca3af
|
|
21
|
+
USER(["👤 User\\nweb & mobile"]):::user
|
|
22
|
+
subgraph PLATFORM[" Application Platform "]
|
|
23
|
+
APP["🌐 Frontend\\nUser Interface"]:::app
|
|
24
|
+
API["⚡ Backend\\nApplication Logic"]:::api
|
|
25
|
+
DB[("🗃 Database\\nPrimary Store")]:::db
|
|
26
|
+
end
|
|
27
|
+
EXT["🌎 External Services\\nAPIs & Integrations"]:::ext
|
|
28
|
+
USER -->|"HTTPS"| APP
|
|
29
|
+
APP -->|"REST / JSON"| API
|
|
30
|
+
API -->|"reads / writes"| DB
|
|
31
|
+
API -->|"calls"| EXT
|
|
32
|
+
style PLATFORM fill:#0a0f1e,stroke:#1e3a5f,color:#e2e8f0`;
|
|
33
|
+
} catch { return 'graph TB\n App[Application] --> DB[(Database)]'; }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function genAppArchitecture(analysisData) {
|
|
37
|
+
try {
|
|
38
|
+
const layers = (analysisData.layers || []).slice(0, 5);
|
|
39
|
+
if (layers.length >= 3) {
|
|
40
|
+
const lines = ['graph TB'];
|
|
41
|
+
const colors = ['#0f1d3a,#3b82f6', '#1a0f3a,#7c3aed', '#0a2318,#10b981', '#1f1505,#f59e0b', '#12102a,#6366f1'];
|
|
42
|
+
layers.forEach((l, i) => {
|
|
43
|
+
const [bg, stroke] = colors[i % colors.length].split(',');
|
|
44
|
+
lines.push(` L${i}["${l}"]`);
|
|
45
|
+
lines.push(` style L${i} fill:${bg},stroke:${stroke},color:#e2e8f0`);
|
|
46
|
+
if (i > 0) lines.push(` L${i - 1} --> L${i}`);
|
|
47
|
+
});
|
|
48
|
+
return lines.join('\n');
|
|
49
|
+
}
|
|
50
|
+
return `graph TB
|
|
51
|
+
classDef client fill:#0d2035,stroke:#06b6d4,color:#a5f3fc
|
|
52
|
+
classDef ctrl fill:#0f1d3a,stroke:#3b82f6,color:#bfdbfe
|
|
53
|
+
classDef svc fill:#1a0f3a,stroke:#7c3aed,color:#ddd6fe
|
|
54
|
+
classDef repo fill:#1a0f3a,stroke:#8b5cf6,color:#ddd6fe
|
|
55
|
+
classDef db fill:#0a2318,stroke:#10b981,color:#a7f3d0
|
|
56
|
+
subgraph CL[" Clients "]
|
|
57
|
+
WEB["🌐 Web App"]:::client
|
|
58
|
+
MOB["📱 Mobile"]:::client
|
|
59
|
+
end
|
|
60
|
+
subgraph CTR[" Controller Layer "]
|
|
61
|
+
AC["AuthController"]:::ctrl
|
|
62
|
+
TC["TasksController"]:::ctrl
|
|
63
|
+
PC["ProjectsController"]:::ctrl
|
|
64
|
+
end
|
|
65
|
+
subgraph SVC[" Service Layer "]
|
|
66
|
+
AS["AuthService"]:::svc
|
|
67
|
+
TS["TasksService"]:::svc
|
|
68
|
+
PS["ProjectsService"]:::svc
|
|
69
|
+
end
|
|
70
|
+
DB[("🗃 Database")]:::db
|
|
71
|
+
WEB & MOB --> CTR --> SVC --> DB
|
|
72
|
+
style CL fill:#080e1a,stroke:#0e2035
|
|
73
|
+
style CTR fill:#080e1a,stroke:#1e3a5f
|
|
74
|
+
style SVC fill:#080e1a,stroke:#2d1a5e`;
|
|
75
|
+
} catch { return 'graph TB\n subgraph App\n Controllers --> Services --> Repositories\n end'; }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function genWorkflow(analysisData) {
|
|
79
|
+
try {
|
|
80
|
+
const states = (analysisData.states || []).slice(0, 6);
|
|
81
|
+
if (states.length >= 3) {
|
|
82
|
+
const lines = ['stateDiagram-v2', ' direction LR', ' [*] --> ' + states[0]];
|
|
83
|
+
states.forEach((s, i) => { if (i < states.length - 1) lines.push(` ${s} --> ${states[i + 1]}`); });
|
|
84
|
+
lines.push(' ' + states[states.length - 1] + ' --> [*]');
|
|
85
|
+
return lines.join('\n');
|
|
86
|
+
}
|
|
87
|
+
return `stateDiagram-v2
|
|
88
|
+
direction LR
|
|
89
|
+
[*] --> Draft : create
|
|
90
|
+
Draft --> Open : submit
|
|
91
|
+
Draft --> [*] : discard
|
|
92
|
+
Open --> InProgress : assign
|
|
93
|
+
Open --> Cancelled : cancel
|
|
94
|
+
InProgress --> Review : mark done
|
|
95
|
+
InProgress --> Blocked : flag blocker
|
|
96
|
+
InProgress --> Open : unassign
|
|
97
|
+
Blocked --> InProgress : resolve
|
|
98
|
+
Review --> Done : approve
|
|
99
|
+
Review --> InProgress : reject
|
|
100
|
+
Done --> [*]
|
|
101
|
+
Cancelled --> [*]
|
|
102
|
+
note right of Blocked
|
|
103
|
+
No SLA timeout —
|
|
104
|
+
can stagnate here
|
|
105
|
+
end note`;
|
|
106
|
+
} catch { return 'stateDiagram-v2\n [*] --> Active\n Active --> Done\n Done --> [*]'; }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function genDataFlow(analysisData) {
|
|
110
|
+
try {
|
|
111
|
+
const endpoints = (analysisData.endpoints || []).slice(0, 1);
|
|
112
|
+
const ep = endpoints[0] || 'POST /api/resource';
|
|
113
|
+
return `flowchart TD
|
|
114
|
+
classDef user fill:#0d2035,stroke:#06b6d4,color:#a5f3fc
|
|
115
|
+
classDef fe fill:#0f1d3a,stroke:#3b82f6,color:#bfdbfe
|
|
116
|
+
classDef api fill:#1a0f3a,stroke:#7c3aed,color:#ddd6fe
|
|
117
|
+
classDef db fill:#0a2318,stroke:#10b981,color:#a7f3d0
|
|
118
|
+
classDef queue fill:#1f1505,stroke:#f59e0b,color:#fde68a
|
|
119
|
+
classDef ok fill:#0a2318,stroke:#10b981,color:#a7f3d0
|
|
120
|
+
USR(["👤 User"]):::user
|
|
121
|
+
subgraph FE["Frontend"]
|
|
122
|
+
FORM["Form\\n+ Client Validation"]:::fe
|
|
123
|
+
end
|
|
124
|
+
subgraph API["API Server"]
|
|
125
|
+
PIPE["ValidationPipe\\n+ Sanitize"]:::api
|
|
126
|
+
CTRL["Controller\\n${ep}"]:::api
|
|
127
|
+
SVC["Service\\nbusiness logic"]:::api
|
|
128
|
+
REPO["Repository\\nINSERT / UPDATE"]:::api
|
|
129
|
+
end
|
|
130
|
+
DB[("🗃 Database")]:::db
|
|
131
|
+
RD[("⚡ Queue")]:::queue
|
|
132
|
+
RES(["✓ Response"]):::ok
|
|
133
|
+
USR --> FORM --> PIPE --> CTRL --> SVC --> REPO --> DB
|
|
134
|
+
SVC --> RD
|
|
135
|
+
DB --> RES
|
|
136
|
+
style FE fill:#080e1a,stroke:#1e3a5f
|
|
137
|
+
style API fill:#080e1a,stroke:#2d1a5e`;
|
|
138
|
+
} catch { return 'flowchart TD\n Input --> Validate --> Process --> Store --> Respond'; }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function genSequence(analysisData) {
|
|
142
|
+
try {
|
|
143
|
+
const ep = ((analysisData.endpoints || [])[0]) || 'POST /api/resource';
|
|
144
|
+
return `sequenceDiagram
|
|
145
|
+
autonumber
|
|
146
|
+
actor User
|
|
147
|
+
participant Client
|
|
148
|
+
participant API as API Server
|
|
149
|
+
participant DB as Database
|
|
150
|
+
participant Queue
|
|
151
|
+
User->>Client: Submit form
|
|
152
|
+
Client->>API: ${ep}
|
|
153
|
+
API->>API: validate & sanitize
|
|
154
|
+
alt invalid input
|
|
155
|
+
API-->>Client: 400 Bad Request
|
|
156
|
+
else valid
|
|
157
|
+
API->>DB: INSERT record
|
|
158
|
+
DB-->>API: record id
|
|
159
|
+
API->>Queue: enqueue background job
|
|
160
|
+
API-->>Client: 201 Created
|
|
161
|
+
Client-->>User: Success feedback
|
|
162
|
+
end`;
|
|
163
|
+
} catch { return 'sequenceDiagram\n Client->>Server: Request\n Server->>DB: Query\n DB-->>Server: Result\n Server-->>Client: Response'; }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function genDatabaseSchema(schemaData) {
|
|
167
|
+
try {
|
|
168
|
+
if (!schemaData || !schemaData.detected || !schemaData.entities || schemaData.entities.length === 0) return '';
|
|
169
|
+
const relMap = { 'one-to-many': '||--o{', 'many-to-one': '}o--||', 'many-to-many': '}o--o{', 'one-to-one': '||--||' };
|
|
170
|
+
const lines = ['erDiagram'];
|
|
171
|
+
for (const entity of schemaData.entities.slice(0, 8)) {
|
|
172
|
+
lines.push(' ' + entity.name + ' {');
|
|
173
|
+
for (const f of (entity.fields || []).slice(0, 10)) {
|
|
174
|
+
lines.push(' ' + (f.type || 'string') + ' ' + f.name);
|
|
175
|
+
}
|
|
176
|
+
lines.push(' }');
|
|
177
|
+
}
|
|
178
|
+
for (const entity of schemaData.entities) {
|
|
179
|
+
for (const rel of (entity.relations || [])) {
|
|
180
|
+
lines.push(' ' + rel.fromEntity + ' ' + (relMap[rel.type] || '||--o{') + ' ' + rel.toEntity + ' : "has"');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return lines.join('\n');
|
|
184
|
+
} catch { return ''; }
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = { genSystemArchitecture, genAppArchitecture, genWorkflow, genDataFlow, genSequence, genDatabaseSchema };
|
package/bin/scan-diagrams.js
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
genSystemArchitecture,
|
|
5
|
-
genAppArchitecture,
|
|
6
|
-
genWorkflow,
|
|
7
|
-
genDataFlow,
|
|
8
|
-
genSequence,
|
|
9
|
-
genDatabaseSchema
|
|
10
|
-
} = require('./scan-diagrams-generators');
|
|
11
|
-
|
|
12
|
-
const PLACEHOLDER_HTML = '<div class="diagram-placeholder">\n <p>Diagram unavailable — rendering tools not found</p>\n <p>Install: <code>npm install -g @mermaid-js/mermaid-cli</code></p>\n</div>';
|
|
13
|
-
|
|
14
|
-
const NOTES = {
|
|
15
|
-
'system-architecture': 'C4-style context diagram showing services, databases, and external integrations',
|
|
16
|
-
'app-architecture': 'Layered diagram showing framework architecture and component boundaries',
|
|
17
|
-
'workflow': 'State machine derived from status enums and state transition logic',
|
|
18
|
-
'data-flow': 'Data flow from user input through validation, persistence, and async processing',
|
|
19
|
-
'sequence': 'Request/response sequence for the primary API endpoint',
|
|
20
|
-
'database-schema': 'Schema diagram generated from ORM, document DB, vector store, or raw SQL definitions'
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const DIAGRAM_DEFS = [
|
|
24
|
-
{ type: 'system-architecture', title: 'System Architecture', typeBadge: 'graph TB', gen: (a) => genSystemArchitecture(a) },
|
|
25
|
-
{ type: 'app-architecture', title: 'Application Architecture', typeBadge: 'graph TB', gen: (a) => genAppArchitecture(a) },
|
|
26
|
-
{ type: 'workflow', title: 'Workflow', typeBadge: 'stateDiagram-v2', gen: (a) => genWorkflow(a) },
|
|
27
|
-
{ type: 'data-flow', title: 'Data Flow', typeBadge: 'flowchart TD', gen: (a) => genDataFlow(a) },
|
|
28
|
-
{ type: 'sequence', title: 'Sequence', typeBadge: 'sequenceDiagram', gen: (a) => genSequence(a) },
|
|
29
|
-
{ type: 'database-schema', title: 'Database Schema', typeBadge: 'erDiagram', gen: (_, s) => genDatabaseSchema(s) }
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
function buildPlaceholder(def, mmd) {
|
|
33
|
-
return {
|
|
34
|
-
type: def.type,
|
|
35
|
-
title: def.title,
|
|
36
|
-
typeBadge: def.typeBadge,
|
|
37
|
-
svgContent: PLACEHOLDER_HTML,
|
|
38
|
-
mmdSource: mmd || '',
|
|
39
|
-
note: NOTES[def.type] || '',
|
|
40
|
-
rendered: false,
|
|
41
|
-
rendererUsed: 'placeholder'
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function generateDiagrams(analysisData, schemaData, options) {
|
|
46
|
-
try {
|
|
47
|
-
const { renderDiagram } = require('./scan-renderer');
|
|
48
|
-
const results = [];
|
|
49
|
-
for (const def of DIAGRAM_DEFS) {
|
|
50
|
-
try {
|
|
51
|
-
const mmd = def.gen(analysisData, schemaData);
|
|
52
|
-
const isDbSchema = def.type === 'database-schema';
|
|
53
|
-
const noSchema = !schemaData || !schemaData.detected || !mmd;
|
|
54
|
-
if (isDbSchema && noSchema) {
|
|
55
|
-
results.push(buildPlaceholder(def, ''));
|
|
56
|
-
} else {
|
|
57
|
-
const rendered = renderDiagram(mmd, def.type, options || {});
|
|
58
|
-
results.push({
|
|
59
|
-
type: def.type,
|
|
60
|
-
title: def.title,
|
|
61
|
-
typeBadge: def.typeBadge,
|
|
62
|
-
svgContent: rendered.svgContent,
|
|
63
|
-
mmdSource: mmd,
|
|
64
|
-
note: NOTES[def.type] || '',
|
|
65
|
-
rendered: rendered.rendered,
|
|
66
|
-
rendererUsed: rendered.rendererUsed
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
} catch {
|
|
70
|
-
results.push(buildPlaceholder(def, ''));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return results;
|
|
74
|
-
} catch {
|
|
75
|
-
return DIAGRAM_DEFS.map(def => buildPlaceholder(def));
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
module.exports = { generateDiagrams };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
genSystemArchitecture,
|
|
5
|
+
genAppArchitecture,
|
|
6
|
+
genWorkflow,
|
|
7
|
+
genDataFlow,
|
|
8
|
+
genSequence,
|
|
9
|
+
genDatabaseSchema
|
|
10
|
+
} = require('./scan-diagrams-generators');
|
|
11
|
+
|
|
12
|
+
const PLACEHOLDER_HTML = '<div class="diagram-placeholder">\n <p>Diagram unavailable — rendering tools not found</p>\n <p>Install: <code>npm install -g @mermaid-js/mermaid-cli</code></p>\n</div>';
|
|
13
|
+
|
|
14
|
+
const NOTES = {
|
|
15
|
+
'system-architecture': 'C4-style context diagram showing services, databases, and external integrations',
|
|
16
|
+
'app-architecture': 'Layered diagram showing framework architecture and component boundaries',
|
|
17
|
+
'workflow': 'State machine derived from status enums and state transition logic',
|
|
18
|
+
'data-flow': 'Data flow from user input through validation, persistence, and async processing',
|
|
19
|
+
'sequence': 'Request/response sequence for the primary API endpoint',
|
|
20
|
+
'database-schema': 'Schema diagram generated from ORM, document DB, vector store, or raw SQL definitions'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const DIAGRAM_DEFS = [
|
|
24
|
+
{ type: 'system-architecture', title: 'System Architecture', typeBadge: 'graph TB', gen: (a) => genSystemArchitecture(a) },
|
|
25
|
+
{ type: 'app-architecture', title: 'Application Architecture', typeBadge: 'graph TB', gen: (a) => genAppArchitecture(a) },
|
|
26
|
+
{ type: 'workflow', title: 'Workflow', typeBadge: 'stateDiagram-v2', gen: (a) => genWorkflow(a) },
|
|
27
|
+
{ type: 'data-flow', title: 'Data Flow', typeBadge: 'flowchart TD', gen: (a) => genDataFlow(a) },
|
|
28
|
+
{ type: 'sequence', title: 'Sequence', typeBadge: 'sequenceDiagram', gen: (a) => genSequence(a) },
|
|
29
|
+
{ type: 'database-schema', title: 'Database Schema', typeBadge: 'erDiagram', gen: (_, s) => genDatabaseSchema(s) }
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
function buildPlaceholder(def, mmd) {
|
|
33
|
+
return {
|
|
34
|
+
type: def.type,
|
|
35
|
+
title: def.title,
|
|
36
|
+
typeBadge: def.typeBadge,
|
|
37
|
+
svgContent: PLACEHOLDER_HTML,
|
|
38
|
+
mmdSource: mmd || '',
|
|
39
|
+
note: NOTES[def.type] || '',
|
|
40
|
+
rendered: false,
|
|
41
|
+
rendererUsed: 'placeholder'
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function generateDiagrams(analysisData, schemaData, options) {
|
|
46
|
+
try {
|
|
47
|
+
const { renderDiagram } = require('./scan-renderer');
|
|
48
|
+
const results = [];
|
|
49
|
+
for (const def of DIAGRAM_DEFS) {
|
|
50
|
+
try {
|
|
51
|
+
const mmd = def.gen(analysisData, schemaData);
|
|
52
|
+
const isDbSchema = def.type === 'database-schema';
|
|
53
|
+
const noSchema = !schemaData || !schemaData.detected || !mmd;
|
|
54
|
+
if (isDbSchema && noSchema) {
|
|
55
|
+
results.push(buildPlaceholder(def, ''));
|
|
56
|
+
} else {
|
|
57
|
+
const rendered = renderDiagram(mmd, def.type, options || {});
|
|
58
|
+
results.push({
|
|
59
|
+
type: def.type,
|
|
60
|
+
title: def.title,
|
|
61
|
+
typeBadge: def.typeBadge,
|
|
62
|
+
svgContent: rendered.svgContent,
|
|
63
|
+
mmdSource: mmd,
|
|
64
|
+
note: NOTES[def.type] || '',
|
|
65
|
+
rendered: rendered.rendered,
|
|
66
|
+
rendererUsed: rendered.rendererUsed
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
results.push(buildPlaceholder(def, ''));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return results;
|
|
74
|
+
} catch {
|
|
75
|
+
return DIAGRAM_DEFS.map(def => buildPlaceholder(def));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = { generateDiagrams };
|