codarch 0.0.0-stage → 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.
package/package.json CHANGED
@@ -1,6 +1,44 @@
1
1
  {
2
2
  "name": "codarch",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Mapa de arquitectura para equipos y agentes de IA",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "codarch": "./index.js"
9
+ },
10
+ "files": [
11
+ "index.js",
12
+ "styles.css",
13
+ "client.js",
14
+ "LICENSE",
15
+ "README.md"
16
+ ],
17
+ "engines": {
18
+ "node": ">=22"
19
+ },
20
+ "keywords": [
21
+ "architecture",
22
+ "code-analysis",
23
+ "treemap",
24
+ "typescript",
25
+ "mcp"
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/jaminsmoke/codarch.git",
30
+ "directory": "apps/cli"
31
+ },
32
+ "homepage": "https://github.com/jaminsmoke/codarch",
33
+ "bugs": {
34
+ "url": "https://github.com/jaminsmoke/codarch/issues"
35
+ },
36
+ "dependencies": {
37
+ "ignore": "^7.0.13",
38
+ "minimatch": "^10.2.6",
39
+ "tree-sitter": "0.21.1",
40
+ "tree-sitter-typescript": "0.23.2",
41
+ "typescript": "^5.9.0",
42
+ "yaml": "^2.9.1"
43
+ }
44
+ }
package/styles.css ADDED
@@ -0,0 +1,441 @@
1
+ :root {
2
+ --bg: #f7f5f1;
3
+ --panel: #ffffff;
4
+ --ink: #1a1a1a;
5
+ --muted: #6f6a62;
6
+ --hair: #e2ded6;
7
+ --hair-strong: #cfc9be;
8
+ --accent: #1a1a1a;
9
+ --error: #a42e2c;
10
+ --warn: #b3731c;
11
+ --info: #4a6b8a;
12
+ --mono: ui-monospace, SFMono-Regular, "Cascadia Mono", Menlo, Consolas, monospace;
13
+ --sans: ui-sans-serif, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
14
+ }
15
+ * { box-sizing: border-box; }
16
+ html, body { height: 100%; }
17
+ body {
18
+ margin: 0;
19
+ background: var(--bg);
20
+ color: var(--ink);
21
+ font-family: var(--sans);
22
+ font-size: 13px;
23
+ -webkit-font-smoothing: antialiased;
24
+ overflow: hidden;
25
+ }
26
+ button, input, select { font: inherit; }
27
+ .app {
28
+ display: grid;
29
+ grid-template-columns: minmax(0, 1fr) 340px;
30
+ grid-template-rows: 56px 38px minmax(0, 1fr) 38px;
31
+ height: 100vh;
32
+ }
33
+
34
+ /* ---------- header ---------- */
35
+ header {
36
+ grid-column: 1 / -1;
37
+ display: flex;
38
+ align-items: center;
39
+ gap: 18px;
40
+ padding: 0 18px;
41
+ background: var(--panel);
42
+ border-bottom: 1px solid var(--hair);
43
+ min-width: 0;
44
+ }
45
+ .brand {
46
+ font-weight: 700;
47
+ letter-spacing: -0.02em;
48
+ font-size: 16px;
49
+ white-space: nowrap;
50
+ }
51
+ .repo {
52
+ display: flex;
53
+ align-items: baseline;
54
+ gap: 8px;
55
+ min-width: 0;
56
+ color: var(--muted);
57
+ font-size: 12px;
58
+ overflow: hidden;
59
+ }
60
+ .repo b {
61
+ color: var(--ink);
62
+ font-weight: 600;
63
+ overflow: hidden;
64
+ text-overflow: ellipsis;
65
+ white-space: nowrap;
66
+ }
67
+ .repo > span:not(.commit) {
68
+ overflow: hidden;
69
+ text-overflow: ellipsis;
70
+ white-space: nowrap;
71
+ }
72
+ .commit {
73
+ font-family: var(--mono);
74
+ font-size: 11px;
75
+ padding: 2px 6px;
76
+ border: 1px solid var(--hair);
77
+ color: var(--muted);
78
+ white-space: nowrap;
79
+ }
80
+ .spacer { flex: 1; }
81
+ .lenses {
82
+ display: flex;
83
+ gap: 2px;
84
+ background: var(--bg);
85
+ padding: 2px;
86
+ flex: none;
87
+ }
88
+ .lens {
89
+ border: 0;
90
+ background: transparent;
91
+ color: var(--muted);
92
+ font: 500 12px var(--sans);
93
+ padding: 6px 11px;
94
+ cursor: pointer;
95
+ white-space: nowrap;
96
+ }
97
+ .lens:hover { color: var(--ink); }
98
+ .lens[aria-selected="true"] {
99
+ background: var(--panel);
100
+ color: var(--ink);
101
+ box-shadow: inset 0 -2px 0 var(--ink);
102
+ }
103
+ .metric-pick {
104
+ display: inline-flex;
105
+ align-items: center;
106
+ gap: 6px;
107
+ border: 1px solid var(--hair);
108
+ background: var(--bg);
109
+ padding: 4px 8px;
110
+ color: var(--muted);
111
+ font-size: 11px;
112
+ flex: none;
113
+ }
114
+ .metric-pick[hidden] { display: none; }
115
+ .metric-pick select {
116
+ border: 0;
117
+ background: transparent;
118
+ color: var(--ink);
119
+ outline: 0;
120
+ max-width: 180px;
121
+ font-size: 11px;
122
+ cursor: pointer;
123
+ }
124
+ .search {
125
+ display: flex;
126
+ align-items: center;
127
+ gap: 6px;
128
+ border: 1px solid var(--hair);
129
+ background: var(--bg);
130
+ padding: 5px 8px;
131
+ width: 190px;
132
+ flex: none;
133
+ }
134
+ .search input {
135
+ border: 0;
136
+ background: transparent;
137
+ outline: 0;
138
+ font: 12px var(--sans);
139
+ color: var(--ink);
140
+ width: 100%;
141
+ min-width: 0;
142
+ }
143
+ .search svg { flex: none; }
144
+
145
+ /* ---------- findings ---------- */
146
+ .findings {
147
+ grid-column: 1;
148
+ display: flex;
149
+ align-items: center;
150
+ gap: 16px;
151
+ padding: 0 18px;
152
+ border-bottom: 1px solid var(--hair);
153
+ background: var(--bg);
154
+ overflow: hidden;
155
+ }
156
+ .finding {
157
+ display: inline-flex;
158
+ align-items: center;
159
+ gap: 6px;
160
+ font: 11.5px var(--sans);
161
+ color: var(--muted);
162
+ white-space: nowrap;
163
+ cursor: pointer;
164
+ border: 0;
165
+ background: transparent;
166
+ padding: 0;
167
+ }
168
+ .finding b { color: var(--ink); font-weight: 600; }
169
+ .finding.static { cursor: default; }
170
+ .finding:hover { color: var(--ink); }
171
+ .finding.static:hover { color: var(--muted); }
172
+ .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
173
+ .dot.error { background: var(--error); }
174
+ .dot.warn { background: var(--warn); }
175
+ .dot.info { background: var(--info); }
176
+ .dot.neutral { background: var(--hair-strong); }
177
+ .search-status {
178
+ font-family: var(--mono);
179
+ font-size: 10.5px;
180
+ color: var(--info);
181
+ white-space: nowrap;
182
+ }
183
+ .run-meta {
184
+ font-family: var(--mono);
185
+ font-size: 10.5px;
186
+ color: #8d877d;
187
+ white-space: nowrap;
188
+ }
189
+
190
+ /* ---------- map ---------- */
191
+ .map-wrap { position: relative; min-height: 0; overflow: hidden; grid-column: 1; }
192
+ .map { position: absolute; inset: 10px; }
193
+ #map { width: 100%; height: 100%; display: block; }
194
+ #map text { pointer-events: none; }
195
+
196
+ .canvas { fill: var(--bg); }
197
+
198
+ .folder > .fr {
199
+ fill: var(--panel);
200
+ stroke: var(--hair-strong);
201
+ stroke-width: 1;
202
+ vector-effect: non-scaling-stroke;
203
+ shape-rendering: crispEdges;
204
+ }
205
+ .folder > .fh {
206
+ fill: #fbfaf7;
207
+ stroke: var(--hair);
208
+ stroke-width: 0.6;
209
+ vector-effect: non-scaling-stroke;
210
+ cursor: pointer;
211
+ shape-rendering: crispEdges;
212
+ }
213
+ .folder > .ft {
214
+ font: 600 11.5px var(--sans);
215
+ fill: var(--ink);
216
+ pointer-events: none;
217
+ }
218
+ .folder > .fn {
219
+ font: 9.5px var(--mono);
220
+ fill: #8d877d;
221
+ pointer-events: none;
222
+ text-anchor: end;
223
+ }
224
+ .folder.focused > .fr { stroke: var(--ink); stroke-width: 2; }
225
+ .folder.outside { opacity: 0.22; }
226
+ .folder.dim { opacity: 0.18; }
227
+ .folder.hit-folder > .fh { stroke: var(--info); stroke-width: 2; }
228
+
229
+ #map rect[data-i] {
230
+ cursor: pointer;
231
+ stroke: rgba(255, 255, 255, 0.5);
232
+ stroke-width: 0.6;
233
+ vector-effect: non-scaling-stroke;
234
+ shape-rendering: crispEdges;
235
+ }
236
+ #map .a { font: 500 12.5px var(--sans); letter-spacing: -0.01em; }
237
+ #map .b { font: 10px var(--mono); opacity: 0.72; }
238
+ #map rect[data-i]:hover { stroke: var(--ink); stroke-width: 1.6; }
239
+ #map rect[data-i].selected { stroke: var(--ink); stroke-width: 2.4; }
240
+ #map rect[data-i].related { stroke: rgba(26, 26, 26, 0.45); stroke-width: 1.4; }
241
+ #map rect[data-i].dim { opacity: 0.14; }
242
+ #map rect[data-i].outside { opacity: 0.1; }
243
+ #map rect[data-i].hit { opacity: 1; }
244
+ #map rect[data-i].hit { stroke: var(--info); stroke-width: 2.4; }
245
+
246
+ #edges {
247
+ position: absolute;
248
+ inset: 0;
249
+ pointer-events: none;
250
+ z-index: 8;
251
+ overflow: visible;
252
+ }
253
+
254
+ .tooltip {
255
+ position: fixed;
256
+ z-index: 50;
257
+ pointer-events: none;
258
+ background: #1a1a1a;
259
+ color: #f4f1ea;
260
+ padding: 6px 8px;
261
+ font-size: 11px;
262
+ line-height: 1.45;
263
+ display: none;
264
+ max-width: 300px;
265
+ }
266
+ .tooltip b { font-weight: 600; }
267
+ .tooltip .t-metrics {
268
+ font-family: var(--mono);
269
+ font-size: 10px;
270
+ color: #bdb7ab;
271
+ word-break: break-word;
272
+ }
273
+
274
+ /* ---------- inspector ---------- */
275
+ aside {
276
+ grid-column: 2;
277
+ grid-row: 2 / 4;
278
+ background: var(--panel);
279
+ border-left: 1px solid var(--hair);
280
+ overflow-y: auto;
281
+ min-height: 0;
282
+ }
283
+ .insp { padding: 16px; border-bottom: 1px solid var(--hair); }
284
+ .insp-path {
285
+ font-family: var(--mono);
286
+ font-size: 11px;
287
+ line-height: 1.5;
288
+ word-break: break-all;
289
+ margin-bottom: 8px;
290
+ }
291
+ .tags { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 14px; }
292
+ .tag {
293
+ font-size: 9.5px;
294
+ letter-spacing: 0.04em;
295
+ text-transform: uppercase;
296
+ padding: 2px 5px;
297
+ border: 1px solid var(--hair-strong);
298
+ color: var(--muted);
299
+ }
300
+ .tag.bad { border-color: var(--error); color: var(--error); }
301
+ .metrics {
302
+ display: grid;
303
+ grid-template-columns: 1fr 1fr;
304
+ gap: 1px;
305
+ background: var(--hair);
306
+ margin-bottom: 14px;
307
+ }
308
+ .metric { background: var(--panel); padding: 8px 9px; min-width: 0; }
309
+ .metric dt {
310
+ font-size: 9.5px;
311
+ color: var(--muted);
312
+ margin: 0 0 2px;
313
+ letter-spacing: 0.03em;
314
+ text-transform: uppercase;
315
+ overflow: hidden;
316
+ text-overflow: ellipsis;
317
+ white-space: nowrap;
318
+ }
319
+ .metric dd { margin: 0; font-family: var(--mono); font-size: 15px; }
320
+ .metric dd small { font-size: 10px; color: var(--muted); }
321
+
322
+ .risk-row { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 4px; }
323
+ .risk-row span {
324
+ font-size: 10px;
325
+ text-transform: uppercase;
326
+ letter-spacing: 0.04em;
327
+ color: var(--muted);
328
+ }
329
+ .risk-row b { font-family: var(--mono); font-size: 13px; }
330
+ .risk-track { height: 4px; background: var(--bg); margin-bottom: 16px; }
331
+ .risk-fill { height: 100%; background: linear-gradient(90deg, #e9cd98, #d68a54, #a42e2c); }
332
+
333
+ h4 {
334
+ margin: 0 0 6px;
335
+ font-size: 10px;
336
+ letter-spacing: 0.06em;
337
+ text-transform: uppercase;
338
+ color: var(--muted);
339
+ }
340
+ .deps { list-style: none; margin: 0 0 16px; padding: 0; }
341
+ .deps li {
342
+ display: flex;
343
+ align-items: center;
344
+ gap: 7px;
345
+ padding: 4px 0;
346
+ border-bottom: 1px solid #f1eee8;
347
+ font-family: var(--mono);
348
+ font-size: 10.5px;
349
+ cursor: pointer;
350
+ color: #3c3832;
351
+ min-width: 0;
352
+ }
353
+ .deps li:hover { color: var(--ink); }
354
+ .deps li .sw { width: 6px; height: 6px; flex: none; }
355
+ .deps li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
356
+ .deps li em { margin-left: auto; font-style: normal; color: #a39d92; font-size: 9.5px; }
357
+ .empty { color: #a39d92; font-size: 11px; font-family: var(--mono); }
358
+
359
+ .violation {
360
+ border-left: 2px solid var(--error);
361
+ background: #fbf1f0;
362
+ padding: 8px 9px;
363
+ font-size: 11px;
364
+ line-height: 1.45;
365
+ color: #6d2322;
366
+ margin-bottom: 14px;
367
+ }
368
+ .violation b { display: block; margin-bottom: 2px; }
369
+
370
+ .summary { padding: 16px; }
371
+ .summary p { color: var(--muted); font-size: 11.5px; line-height: 1.55; margin: 0 0 16px; }
372
+ .summary .big { font-family: var(--mono); font-size: 26px; letter-spacing: -0.02em; }
373
+ .summary .sub {
374
+ font-size: 10px;
375
+ color: var(--muted);
376
+ text-transform: uppercase;
377
+ letter-spacing: 0.05em;
378
+ }
379
+ .summary h4 { margin-top: 18px; }
380
+
381
+ /* ---------- footer ---------- */
382
+ footer {
383
+ grid-column: 1 / -1;
384
+ display: flex;
385
+ align-items: center;
386
+ gap: 14px;
387
+ padding: 0 14px 0 18px;
388
+ border-top: 1px solid var(--hair);
389
+ background: var(--panel);
390
+ font-size: 11px;
391
+ color: var(--muted);
392
+ overflow: hidden;
393
+ }
394
+ .crumbs {
395
+ font-family: var(--mono);
396
+ font-size: 10.5px;
397
+ color: #6f6a62;
398
+ overflow: hidden;
399
+ text-overflow: ellipsis;
400
+ white-space: nowrap;
401
+ min-width: 0;
402
+ }
403
+ .crumbs b { color: var(--ink); font-weight: 500; }
404
+ .crumbs .sep { color: #c3bdb2; }
405
+ .hint {
406
+ font-family: var(--mono);
407
+ font-size: 10px;
408
+ color: #a39d92;
409
+ white-space: nowrap;
410
+ flex: none;
411
+ }
412
+ .legend {
413
+ display: flex;
414
+ align-items: center;
415
+ gap: 7px;
416
+ margin-left: auto;
417
+ min-width: 0;
418
+ overflow: hidden;
419
+ white-space: nowrap;
420
+ }
421
+ .legend .bar { width: 110px; height: 6px; flex: none; }
422
+ .legend .mono { font-family: var(--mono); font-size: 10px; }
423
+ .legend .sws { display: flex; gap: 7px; overflow: hidden; }
424
+ .legend .sws span { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
425
+ .legend .sws i { width: 7px; height: 7px; display: inline-block; flex: none; }
426
+
427
+ @media (max-width: 1050px) {
428
+ .app { grid-template-columns: minmax(0, 1fr) 300px; }
429
+ .search { width: 150px; }
430
+ .repo > span:not(.commit) { display: none; }
431
+ .metric-pick span { display: none; }
432
+ }
433
+ @media (max-width: 860px) {
434
+ .app { grid-template-columns: 1fr; grid-template-rows: auto 38px minmax(0, 1fr) 38px; }
435
+ header { grid-column: 1; flex-wrap: wrap; padding: 8px 12px; gap: 10px; }
436
+ .findings { grid-column: 1; }
437
+ aside { display: none; }
438
+ .map-wrap { grid-column: 1; }
439
+ footer { grid-column: 1; }
440
+ .legend { display: none; }
441
+ }