@a-company/paradigm 3.24.0 → 3.25.2

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 (35) hide show
  1. package/dist/{accept-orchestration-AAYFKS74.js → accept-orchestration-6EM5EHXA.js} +4 -4
  2. package/dist/{auto-B22FVSQI.js → auto-24ICVUH4.js} +1 -1
  3. package/dist/{chunk-EZ6XW6FB.js → chunk-7IJ5JVKT.js} +1 -1
  4. package/dist/{chunk-6EQRU7WC.js → chunk-J26YQVAK.js} +1 -1
  5. package/dist/{chunk-VHSTF72C.js → chunk-N6RNYCZD.js} +1 -1
  6. package/dist/{chunk-6UV47VRD.js → chunk-SCC77UUP.js} +83 -63
  7. package/dist/chunk-UPLDI7CN.js +1334 -0
  8. package/dist/{chunk-GC6X3YM7.js → chunk-ZOH24ZPF.js} +5 -5
  9. package/dist/{diff-QC7PWIPF.js → diff-AH7L4PRQ.js} +4 -4
  10. package/dist/discipline-5F5OVTXB.js +24 -0
  11. package/dist/{doctor-RVODPMHJ.js → doctor-INBOLZC7.js} +1 -1
  12. package/dist/index.js +53 -25
  13. package/dist/{list-CAL7KS7B.js → list-QTFWN35D.js} +3 -2
  14. package/dist/mcp.js +4 -3
  15. package/dist/{orchestrate-NNNWNELP.js → orchestrate-HMSQ2CED.js} +4 -4
  16. package/dist/{providers-NKGY36QF.js → providers-YW3FG6DA.js} +1 -1
  17. package/dist/{reindex-CMZARW5K.js → reindex-YG3KIXAK.js} +1 -1
  18. package/dist/{shift-G42AEUHE.js → shift-DRF5M3G6.js} +23 -17
  19. package/dist/{spawn-52PASJJL.js → spawn-DIY7T4QW.js} +2 -2
  20. package/dist/{team-JZHIH7H5.js → team-YOGT2Q2X.js} +5 -5
  21. package/dist/{timeline-B6TMGWRU.js → timeline-RKXNRMKF.js} +4 -3
  22. package/dist/university-content/courses/.purpose +4 -4
  23. package/dist/university-content/courses/para-101.json +1 -1
  24. package/dist/university-content/courses/para-201.json +18 -2
  25. package/dist/university-content/plsat/.purpose +18 -0
  26. package/dist/university-content/plsat/v3.0.json +105 -0
  27. package/dist/university-ui/assets/{index-BV7lKIqO.js → index-BPzqnvrg.js} +2 -2
  28. package/dist/university-ui/assets/{index-BV7lKIqO.js.map → index-BPzqnvrg.js.map} +1 -1
  29. package/dist/university-ui/index.html +1 -1
  30. package/package.json +1 -1
  31. package/templates/paradigm/config.yaml +1 -0
  32. package/dist/chunk-CHSHON3O.js +0 -669
  33. package/dist/{chunk-7WTOOH23.js → chunk-5SXMV4SP.js} +0 -0
  34. package/dist/{chunk-4UC6AQOC.js → chunk-C5ZE6WEX.js} +0 -0
  35. package/dist/{flow-KZKMMXJC.js → flow-UFMPVOEM.js} +1 -1
@@ -0,0 +1,1334 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/discipline.ts
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ function detectDiscipline(rootDir) {
7
+ const pkg = readPackageJson(rootDir);
8
+ const pkgDeps = pkg?.dependencies ?? {};
9
+ const pkgDevDeps = pkg?.devDependencies ?? {};
10
+ const deps = { ...pkgDeps, ...pkgDevDeps };
11
+ const hasDep = (name) => name in deps;
12
+ if (pkg?.workspaces || fs.existsSync(path.join(rootDir, "pnpm-workspace.yaml")) || fs.existsSync(path.join(rootDir, "lerna.json"))) {
13
+ return "monorepo";
14
+ }
15
+ if (pkg) {
16
+ if (pkg.bin && !hasUICode(rootDir, deps)) {
17
+ return "cli";
18
+ }
19
+ if ((pkg.exports || pkg.main) && !pkg.bin && !hasUIDeps(deps) && !hasServerDeps(deps)) {
20
+ return "library";
21
+ }
22
+ if (hasDep("react-native") || hasDep("expo")) {
23
+ return "mobile";
24
+ }
25
+ if (hasDep("next") || hasDep("nuxt") || hasDep("@sveltejs/kit") || hasDep("remix") || hasDep("@remix-run/node") || hasDep("astro")) {
26
+ return "fullstack";
27
+ }
28
+ if (hasUIDeps(deps) && !hasServerDeps(deps)) {
29
+ return "web";
30
+ }
31
+ if (hasServerDeps(deps) && !hasUIDeps(deps)) {
32
+ return "api";
33
+ }
34
+ if (hasUIDeps(deps) && hasServerDeps(deps)) {
35
+ return "fullstack";
36
+ }
37
+ if (hasDep("@tensorflow/tfjs") || hasDep("onnxruntime-node")) {
38
+ return "ml";
39
+ }
40
+ }
41
+ const pyProject = readFileIfExists(rootDir, "pyproject.toml");
42
+ const requirements = readFileIfExists(rootDir, "requirements.txt");
43
+ const pyDeps = (pyProject || "") + (requirements || "");
44
+ if (pyDeps) {
45
+ if (/torch|tensorflow|scikit-learn|transformers|jax/i.test(pyDeps)) {
46
+ return "ml";
47
+ }
48
+ if (/dbt|airflow|prefect|dagster|spark|pandas(?!.*flask)(?!.*django)/i.test(pyDeps)) {
49
+ return "data";
50
+ }
51
+ if (fs.existsSync(path.join(rootDir, "manage.py")) && fs.existsSync(path.join(rootDir, "templates"))) {
52
+ return "fullstack";
53
+ }
54
+ if (/fastapi|flask|django-rest-framework|djangorestframework|starlette/i.test(pyDeps)) {
55
+ return "api";
56
+ }
57
+ if (fs.existsSync(path.join(rootDir, "manage.py"))) {
58
+ return "fullstack";
59
+ }
60
+ if (/click|typer|argparse|fire/i.test(pyDeps) && !fs.existsSync(path.join(rootDir, "manage.py"))) {
61
+ return "cli";
62
+ }
63
+ }
64
+ if (fs.existsSync(path.join(rootDir, "go.mod"))) {
65
+ if (fs.existsSync(path.join(rootDir, "cmd"))) {
66
+ return "cli";
67
+ }
68
+ const goMod = readFileIfExists(rootDir, "go.mod") || "";
69
+ if (/gin|echo|fiber|chi|gorilla\/mux/i.test(goMod)) {
70
+ return "api";
71
+ }
72
+ return "backend";
73
+ }
74
+ const cargoToml = readFileIfExists(rootDir, "Cargo.toml");
75
+ if (cargoToml) {
76
+ if (/embedded-hal|no_std|cortex-m/i.test(cargoToml)) {
77
+ return "embedded";
78
+ }
79
+ if (/clap|structopt/i.test(cargoToml)) {
80
+ return "cli";
81
+ }
82
+ if (/actix-web|axum|rocket|warp/i.test(cargoToml)) {
83
+ return "api";
84
+ }
85
+ if (/bevy|ggez|macroquad/i.test(cargoToml)) {
86
+ return "game";
87
+ }
88
+ if (/tauri/i.test(cargoToml)) {
89
+ return "fullstack";
90
+ }
91
+ return "backend";
92
+ }
93
+ if (fs.existsSync(path.join(rootDir, "pubspec.yaml"))) {
94
+ return "mobile";
95
+ }
96
+ if (fs.existsSync(path.join(rootDir, "ios")) && fs.existsSync(path.join(rootDir, "android"))) {
97
+ return "mobile";
98
+ }
99
+ if (fs.existsSync(path.join(rootDir, "project.godot")) || fs.existsSync(path.join(rootDir, "ProjectSettings")) || // Unity
100
+ hasFilesMatching(rootDir, ".pretend")) {
101
+ return "game";
102
+ }
103
+ if (fs.existsSync(path.join(rootDir, "terraform")) || fs.existsSync(path.join(rootDir, "main.tf")) || fs.existsSync(path.join(rootDir, "pulumi")) || fs.existsSync(path.join(rootDir, "ansible.cfg")) || fs.existsSync(path.join(rootDir, "Dockerfile")) && !pkg) {
104
+ return "devops";
105
+ }
106
+ if (fs.existsSync(path.join(rootDir, "platformio.ini"))) {
107
+ return "embedded";
108
+ }
109
+ return "backend";
110
+ }
111
+ var DISCIPLINE_MAPPINGS = {
112
+ web: {
113
+ symbolMapping: {
114
+ "components/**": "#",
115
+ "pages/**": "#",
116
+ "views/**": "#",
117
+ "hooks/**": "#",
118
+ "stores/**": "#",
119
+ "state/**": "#",
120
+ "utils/**": "#",
121
+ "lib/**": "#",
122
+ "services/**": "#",
123
+ "middleware/**": "^",
124
+ "auth/**": "^",
125
+ "guards/**": "^",
126
+ "events/**": "!",
127
+ "handlers/**": "!",
128
+ "flows/**": "$",
129
+ "aspects/**": "~",
130
+ "rules/**": "~"
131
+ },
132
+ purposeRequired: [
133
+ { pattern: "src/components/*", depth: 1 },
134
+ { pattern: "src/pages/*", depth: 1 },
135
+ { pattern: "src/features/*", depth: 1 }
136
+ ],
137
+ examples: {
138
+ "#": ["#LoginForm", "#useAuth", "#CartStore", "#api-client"],
139
+ "$": ["$checkout-flow", "$onboarding"],
140
+ "^": ["^authenticated", "^admin-only"],
141
+ "!": ["!form-submit", "!notification-sent"],
142
+ "~": ["~rate-limited", "~csrf-protected"]
143
+ }
144
+ },
145
+ backend: {
146
+ symbolMapping: {
147
+ "services/**": "#",
148
+ "routes/**": "#",
149
+ "api/**": "#",
150
+ "models/**": "#",
151
+ "lib/**": "#",
152
+ "utils/**": "#",
153
+ "core/**": "#",
154
+ "config/**": "#",
155
+ "middleware/**": "^",
156
+ "auth/**": "^",
157
+ "guards/**": "^",
158
+ "policies/**": "^",
159
+ "events/**": "!",
160
+ "handlers/**": "!",
161
+ "listeners/**": "!",
162
+ "flows/**": "$",
163
+ "workflows/**": "$",
164
+ "pipelines/**": "$",
165
+ "aspects/**": "~",
166
+ "rules/**": "~"
167
+ },
168
+ purposeRequired: [
169
+ { pattern: "src/services/*", depth: 1 },
170
+ { pattern: "src/routes/*", depth: 1 },
171
+ { pattern: "src/api/*", depth: 1 }
172
+ ],
173
+ examples: {
174
+ "#": ["#users-create", "#database", "#cache", "#postgres-client"],
175
+ "$": ["$order-fulfillment", "$data-sync"],
176
+ "^": ["^api-key-required", "^rate-limited"],
177
+ "!": ["!order-created", "!email-sent"],
178
+ "~": ["~audit-logged", "~encrypted"]
179
+ }
180
+ },
181
+ fullstack: {
182
+ symbolMapping: {
183
+ "components/**": "#",
184
+ "pages/**": "#",
185
+ "views/**": "#",
186
+ "hooks/**": "#",
187
+ "stores/**": "#",
188
+ "services/**": "#",
189
+ "routes/**": "#",
190
+ "api/**": "#",
191
+ "models/**": "#",
192
+ "lib/**": "#",
193
+ "utils/**": "#",
194
+ "core/**": "#",
195
+ "config/**": "#",
196
+ "middleware/**": "^",
197
+ "auth/**": "^",
198
+ "guards/**": "^",
199
+ "policies/**": "^",
200
+ "events/**": "!",
201
+ "handlers/**": "!",
202
+ "listeners/**": "!",
203
+ "flows/**": "$",
204
+ "workflows/**": "$",
205
+ "aspects/**": "~",
206
+ "rules/**": "~"
207
+ },
208
+ purposeRequired: [
209
+ { pattern: "src/components/*", depth: 1 },
210
+ { pattern: "src/pages/*", depth: 1 },
211
+ { pattern: "src/api/*", depth: 1 },
212
+ { pattern: "src/services/*", depth: 1 }
213
+ ],
214
+ examples: {
215
+ "#": ["#LoginPage", "#api-users", "#UserService", "#stripe-client"],
216
+ "$": ["$checkout-flow", "$auth-flow"],
217
+ "^": ["^authenticated", "^admin-only"],
218
+ "!": ["!order-created", "!notification-sent"],
219
+ "~": ["~rate-limited", "~audit-required"]
220
+ }
221
+ },
222
+ api: {
223
+ symbolMapping: {
224
+ "routes/**": "#",
225
+ "endpoints/**": "#",
226
+ "controllers/**": "#",
227
+ "services/**": "#",
228
+ "models/**": "#",
229
+ "lib/**": "#",
230
+ "utils/**": "#",
231
+ "core/**": "#",
232
+ "config/**": "#",
233
+ "middleware/**": "^",
234
+ "auth/**": "^",
235
+ "guards/**": "^",
236
+ "policies/**": "^",
237
+ "events/**": "!",
238
+ "handlers/**": "!",
239
+ "listeners/**": "!",
240
+ "webhooks/**": "!",
241
+ "flows/**": "$",
242
+ "workflows/**": "$",
243
+ "pipelines/**": "$",
244
+ "aspects/**": "~",
245
+ "rules/**": "~"
246
+ },
247
+ purposeRequired: [
248
+ { pattern: "src/routes/*", depth: 1 },
249
+ { pattern: "src/services/*", depth: 1 },
250
+ { pattern: "src/endpoints/*", depth: 1 }
251
+ ],
252
+ examples: {
253
+ "#": ["#users-endpoint", "#OrderService", "#database", "#redis-client"],
254
+ "$": ["$order-processing", "$webhook-ingestion"],
255
+ "^": ["^api-key-required", "^rate-limited", "^authenticated"],
256
+ "!": ["!request-received", "!order-created"],
257
+ "~": ["~audit-logged", "~validated", "~idempotent"]
258
+ }
259
+ },
260
+ cli: {
261
+ symbolMapping: {
262
+ "commands/**": "#",
263
+ "cmd/**": "#",
264
+ "lib/**": "#",
265
+ "utils/**": "#",
266
+ "core/**": "#",
267
+ "config/**": "#",
268
+ "handlers/**": "!",
269
+ "events/**": "!",
270
+ "flows/**": "$",
271
+ "workflows/**": "$",
272
+ "aspects/**": "~",
273
+ "rules/**": "~"
274
+ },
275
+ purposeRequired: [
276
+ { pattern: "src/commands/*", depth: 1 },
277
+ { pattern: "cmd/*", depth: 1 }
278
+ ],
279
+ examples: {
280
+ "#": ["#init-command", "#config-loader", "#output-formatter"],
281
+ "$": ["$setup-flow", "$migration-flow"],
282
+ "^": ["^config-valid", "^version-check"],
283
+ "!": ["!command-complete", "!error-occurred"],
284
+ "~": ["~logged", "~validated"]
285
+ }
286
+ },
287
+ ml: {
288
+ symbolMapping: {
289
+ "models/**": "#",
290
+ "data/**": "#",
291
+ "experiments/**": "#",
292
+ "notebooks/**": "#",
293
+ "features/**": "#",
294
+ "utils/**": "#",
295
+ "lib/**": "#",
296
+ "config/**": "#",
297
+ "pipelines/**": "$",
298
+ "training/**": "$",
299
+ "evaluation/**": "#",
300
+ "preprocessing/**": "#",
301
+ "auth/**": "^",
302
+ "events/**": "!",
303
+ "aspects/**": "~"
304
+ },
305
+ purposeRequired: [
306
+ { pattern: "models/*", depth: 1 },
307
+ { pattern: "pipelines/*", depth: 1 },
308
+ { pattern: "experiments/*", depth: 1 }
309
+ ],
310
+ examples: {
311
+ "#": ["#classifier-v2", "#dataloader", "#feature-extractor", "#wandb-client"],
312
+ "$": ["$training-pipeline", "$data-ingestion", "$evaluation-pipeline"],
313
+ "^": ["^data-scientist", "^production-only"],
314
+ "!": ["!epoch-complete", "!drift-detected", "!training-finished"],
315
+ "~": ["~reproducible", "~versioned"]
316
+ }
317
+ },
318
+ mobile: {
319
+ symbolMapping: {
320
+ "screens/**": "#",
321
+ "components/**": "#",
322
+ "widgets/**": "#",
323
+ "services/**": "#",
324
+ "stores/**": "#",
325
+ "state/**": "#",
326
+ "hooks/**": "#",
327
+ "utils/**": "#",
328
+ "lib/**": "#",
329
+ "native/**": "#",
330
+ "navigation/**": "$",
331
+ "flows/**": "$",
332
+ "middleware/**": "^",
333
+ "auth/**": "^",
334
+ "permissions/**": "^",
335
+ "events/**": "!",
336
+ "handlers/**": "!",
337
+ "aspects/**": "~"
338
+ },
339
+ purposeRequired: [
340
+ { pattern: "src/screens/*", depth: 1 },
341
+ { pattern: "src/components/*", depth: 1 }
342
+ ],
343
+ examples: {
344
+ "#": ["#home-screen", "#camera-capture", "#bottom-sheet", "#push-service"],
345
+ "$": ["$onboarding", "$purchase-flow"],
346
+ "^": ["^camera-permission", "^premium-user"],
347
+ "!": ["!push-received", "!app-backgrounded"],
348
+ "~": ["~offline-capable", "~encrypted-storage"]
349
+ }
350
+ },
351
+ game: {
352
+ symbolMapping: {
353
+ "gameplay/**": "#",
354
+ "systems/**": "#",
355
+ "entities/**": "#",
356
+ "components/**": "#",
357
+ "scenes/**": "#",
358
+ "ui/**": "#",
359
+ "utils/**": "#",
360
+ "lib/**": "#",
361
+ "core/**": "#",
362
+ "config/**": "#",
363
+ "events/**": "!",
364
+ "triggers/**": "!",
365
+ "flows/**": "$",
366
+ "sequences/**": "$",
367
+ "auth/**": "^",
368
+ "aspects/**": "~"
369
+ },
370
+ purposeRequired: [
371
+ { pattern: "gameplay/*", depth: 1 },
372
+ { pattern: "systems/*", depth: 1 },
373
+ { pattern: "entities/*", depth: 1 }
374
+ ],
375
+ examples: {
376
+ "#": ["#attack", "#inventory", "#player", "#enemy-ai"],
377
+ "$": ["$combat-loop", "$tutorial-sequence"],
378
+ "^": ["^multiplayer-session", "^dev-mode"],
379
+ "!": ["!enemy-killed", "!level-complete"],
380
+ "~": ["~deterministic", "~network-synced"]
381
+ }
382
+ },
383
+ embedded: {
384
+ symbolMapping: {
385
+ "drivers/**": "#",
386
+ "hal/**": "#",
387
+ "bsp/**": "#",
388
+ "src/**": "#",
389
+ "lib/**": "#",
390
+ "utils/**": "#",
391
+ "config/**": "#",
392
+ "protocols/**": "$",
393
+ "flows/**": "$",
394
+ "auth/**": "^",
395
+ "security/**": "^",
396
+ "events/**": "!",
397
+ "interrupts/**": "!",
398
+ "aspects/**": "~"
399
+ },
400
+ purposeRequired: [
401
+ { pattern: "src/drivers/*", depth: 1 },
402
+ { pattern: "src/*", depth: 1 }
403
+ ],
404
+ examples: {
405
+ "#": ["#spi-driver", "#gpio-handler", "#mqtt-client", "#read-sensor"],
406
+ "$": ["$boot-sequence", "$handshake", "$firmware-update"],
407
+ "^": ["^secure-boot", "^authenticated-cmd"],
408
+ "!": ["!data-ready", "!watchdog-timeout"],
409
+ "~": ["~power-optimized", "~real-time"]
410
+ }
411
+ },
412
+ devops: {
413
+ symbolMapping: {
414
+ "modules/**": "#",
415
+ "terraform/**": "#",
416
+ "ansible/**": "#",
417
+ "scripts/**": "#",
418
+ "lib/**": "#",
419
+ "config/**": "#",
420
+ "pipelines/**": "$",
421
+ "workflows/**": "$",
422
+ "ci/**": "$",
423
+ "auth/**": "^",
424
+ "policies/**": "^",
425
+ "alerts/**": "!",
426
+ "monitoring/**": "!",
427
+ "aspects/**": "~",
428
+ "rules/**": "~"
429
+ },
430
+ purposeRequired: [
431
+ { pattern: "modules/*", depth: 1 },
432
+ { pattern: "terraform/*", depth: 1 },
433
+ { pattern: "pipelines/*", depth: 1 }
434
+ ],
435
+ examples: {
436
+ "#": ["#vpc-module", "#backup-script", "#deploy", "#aws-client"],
437
+ "$": ["$release-pipeline", "$disaster-recovery"],
438
+ "^": ["^admin-access", "^vpc-restricted"],
439
+ "!": ["!high-cpu", "!deployment-failed"],
440
+ "~": ["~immutable-infra", "~zero-downtime"]
441
+ }
442
+ },
443
+ data: {
444
+ symbolMapping: {
445
+ "models/**": "#",
446
+ "dbt/**": "#",
447
+ "transforms/**": "#",
448
+ "sources/**": "#",
449
+ "utils/**": "#",
450
+ "lib/**": "#",
451
+ "config/**": "#",
452
+ "pipelines/**": "$",
453
+ "dags/**": "$",
454
+ "workflows/**": "$",
455
+ "orchestration/**": "$",
456
+ "auth/**": "^",
457
+ "policies/**": "^",
458
+ "events/**": "!",
459
+ "alerts/**": "!",
460
+ "aspects/**": "~",
461
+ "tests/**": "~"
462
+ },
463
+ purposeRequired: [
464
+ { pattern: "models/*", depth: 1 },
465
+ { pattern: "pipelines/*", depth: 1 },
466
+ { pattern: "dags/*", depth: 1 }
467
+ ],
468
+ examples: {
469
+ "#": ["#users-model", "#data-source", "#transform-revenue", "#snowflake-client"],
470
+ "$": ["$etl-pipeline", "$daily-refresh", "$data-quality-check"],
471
+ "^": ["^analyst-only", "^pii-access"],
472
+ "!": ["!pipeline-complete", "!data-quality-fail"],
473
+ "~": ["~idempotent", "~schema-validated"]
474
+ }
475
+ },
476
+ library: {
477
+ symbolMapping: {
478
+ "src/**": "#",
479
+ "lib/**": "#",
480
+ "utils/**": "#",
481
+ "core/**": "#",
482
+ "config/**": "#",
483
+ "events/**": "!",
484
+ "handlers/**": "!",
485
+ "flows/**": "$",
486
+ "aspects/**": "~"
487
+ },
488
+ purposeRequired: [
489
+ { pattern: "src/*", depth: 1 },
490
+ { pattern: "lib/*", depth: 1 }
491
+ ],
492
+ examples: {
493
+ "#": ["#parser", "#formatter", "#validator", "#client"],
494
+ "$": ["$build-pipeline", "$publish-flow"],
495
+ "^": ["^version-check", "^config-valid"],
496
+ "!": ["!parse-error", "!validation-failed"],
497
+ "~": ["~tree-shakeable", "~backwards-compatible"]
498
+ }
499
+ },
500
+ monorepo: {
501
+ symbolMapping: {
502
+ "packages/**": "#",
503
+ "apps/**": "#",
504
+ "services/**": "#",
505
+ "libs/**": "#",
506
+ "shared/**": "#",
507
+ "tools/**": "#",
508
+ "config/**": "#",
509
+ "middleware/**": "^",
510
+ "auth/**": "^",
511
+ "events/**": "!",
512
+ "handlers/**": "!",
513
+ "flows/**": "$",
514
+ "pipelines/**": "$",
515
+ "aspects/**": "~",
516
+ "rules/**": "~"
517
+ },
518
+ purposeRequired: [
519
+ { pattern: "packages/*", depth: 1 },
520
+ { pattern: "apps/*", depth: 1 }
521
+ ],
522
+ examples: {
523
+ "#": ["#web-app", "#api-server", "#shared-ui", "#config-loader"],
524
+ "$": ["$deploy-all", "$release-pipeline"],
525
+ "^": ["^authenticated", "^admin-only"],
526
+ "!": ["!build-complete", "!package-published"],
527
+ "~": ["~consistent-versions", "~shared-config"]
528
+ }
529
+ }
530
+ };
531
+ var GENERIC_SYMBOL_MAPPING = {
532
+ "features/**": "#",
533
+ "routes/**": "#",
534
+ "api/**": "#",
535
+ "endpoints/**": "#",
536
+ "commands/**": "#",
537
+ "models/**": "#",
538
+ "components/**": "#",
539
+ "lib/**": "#",
540
+ "utils/**": "#",
541
+ "services/**": "#",
542
+ "core/**": "#",
543
+ "drivers/**": "#",
544
+ "systems/**": "#",
545
+ "stores/**": "#",
546
+ "state/**": "#",
547
+ "reducers/**": "#",
548
+ "config/**": "#",
549
+ "integrations/**": "#",
550
+ "external/**": "#",
551
+ "vendors/**": "#",
552
+ "middleware/**": "^",
553
+ "auth/**": "^",
554
+ "guards/**": "^",
555
+ "policies/**": "^",
556
+ "events/**": "!",
557
+ "handlers/**": "!",
558
+ "listeners/**": "!",
559
+ "hooks/**": "!",
560
+ "flows/**": "$",
561
+ "sagas/**": "$",
562
+ "workflows/**": "$",
563
+ "pipelines/**": "$",
564
+ "aspects/**": "~",
565
+ "rules/**": "~"
566
+ };
567
+ function getDisciplineConfig(discipline) {
568
+ if (discipline === "auto" || discipline === "custom") {
569
+ return {
570
+ symbolMapping: GENERIC_SYMBOL_MAPPING,
571
+ purposeRequired: [
572
+ { pattern: "src/*", depth: 1 },
573
+ { pattern: "lib/*", depth: 1 },
574
+ { pattern: "packages/*", depth: 1 }
575
+ ],
576
+ examples: {
577
+ "#": ["#checkout", "#login-handler", "#Button", "#stripe-client"],
578
+ "$": ["$checkout-flow", "$onboarding", "$auth-flow"],
579
+ "^": ["^authenticated", "^admin-only", "^rate-limited"],
580
+ "!": ["!login-success", "!payment-failed", "!rate-limited"],
581
+ "~": ["~audit-required", "~rate-limited", "~cached"]
582
+ }
583
+ };
584
+ }
585
+ return DISCIPLINE_MAPPINGS[discipline];
586
+ }
587
+ function getDisciplineScanPatterns(discipline) {
588
+ const base = {
589
+ components: [],
590
+ routes: [],
591
+ auth: []
592
+ };
593
+ switch (discipline) {
594
+ case "ml":
595
+ base.components.push("models/**/*.py", "notebooks/**/*.ipynb", "experiments/**/*.py", "data/**/*.py");
596
+ base.routes.push("pipelines/**/*.py", "training/**/*.py");
597
+ break;
598
+ case "game":
599
+ base.components.push("entities/**/*.{ts,rs,cs,gd}", "systems/**/*.{ts,rs,cs,gd}", "gameplay/**/*.{ts,rs,cs,gd}", "scenes/**/*.{ts,rs,cs,gd}");
600
+ break;
601
+ case "embedded":
602
+ base.components.push("drivers/**/*.{c,h,rs}", "hal/**/*.{c,h,rs}", "bsp/**/*.{c,h}");
603
+ base.routes.push("protocols/**/*.{c,h,rs}");
604
+ break;
605
+ case "data":
606
+ base.components.push("models/**/*.sql", "dbt/**/*.sql", "transforms/**/*.{py,sql}", "sources/**/*.yml");
607
+ base.routes.push("dags/**/*.py", "pipelines/**/*.py", "orchestration/**/*.py");
608
+ break;
609
+ case "devops":
610
+ base.components.push("modules/**/*.tf", "terraform/**/*.tf", "ansible/**/*.yml", "scripts/**/*.sh");
611
+ base.routes.push("pipelines/**/*.yml", "workflows/**/*.yml", ".github/workflows/**/*.yml");
612
+ break;
613
+ case "cli":
614
+ base.components.push("commands/**/*.{ts,go,rs,py}", "cmd/**/*.go");
615
+ break;
616
+ case "mobile":
617
+ base.components.push("screens/**/*.{tsx,dart,swift,kt}", "widgets/**/*.dart");
618
+ base.routes.push("navigation/**/*.{ts,tsx,dart}");
619
+ break;
620
+ case "monorepo":
621
+ base.components.push("packages/*/src/**/*.{ts,tsx}", "apps/*/src/**/*.{ts,tsx}");
622
+ break;
623
+ default:
624
+ break;
625
+ }
626
+ return base;
627
+ }
628
+ function readPackageJson(rootDir) {
629
+ const pkgPath = path.join(rootDir, "package.json");
630
+ try {
631
+ return JSON.parse(fs.readFileSync(pkgPath, "utf8"));
632
+ } catch {
633
+ return null;
634
+ }
635
+ }
636
+ function readFileIfExists(rootDir, filename) {
637
+ const filePath = path.join(rootDir, filename);
638
+ try {
639
+ return fs.readFileSync(filePath, "utf8");
640
+ } catch {
641
+ return null;
642
+ }
643
+ }
644
+ function hasUIDeps(deps) {
645
+ const uiPackages = ["react", "vue", "@angular/core", "svelte", "solid-js", "preact", "lit"];
646
+ return uiPackages.some((p) => p in deps);
647
+ }
648
+ function hasServerDeps(deps) {
649
+ const serverPackages = ["express", "fastify", "hono", "koa", "nestjs", "@nestjs/core", "hapi", "@hapi/hapi"];
650
+ return serverPackages.some((p) => p in deps);
651
+ }
652
+ function hasUICode(rootDir, deps) {
653
+ if (hasUIDeps(deps)) return true;
654
+ return fs.existsSync(path.join(rootDir, "src", "components")) || fs.existsSync(path.join(rootDir, "src", "pages"));
655
+ }
656
+ function hasFilesMatching(rootDir, extension) {
657
+ try {
658
+ const entries = fs.readdirSync(rootDir);
659
+ return entries.some((e) => e.endsWith(extension));
660
+ } catch {
661
+ return false;
662
+ }
663
+ }
664
+ var STACK_PRESETS = {
665
+ // --- Fullstack ---
666
+ nextjs: {
667
+ id: "nextjs",
668
+ name: "Next.js",
669
+ discipline: "fullstack",
670
+ symbolMapping: {
671
+ "app/**/page.tsx": "#",
672
+ "app/**/layout.tsx": "#",
673
+ "app/**/loading.tsx": "#",
674
+ "app/**/error.tsx": "#",
675
+ "app/api/**": "#",
676
+ "pages/**": "#",
677
+ "pages/api/**": "#",
678
+ "components/**": "#",
679
+ "lib/**": "#",
680
+ "hooks/**": "#",
681
+ "stores/**": "#",
682
+ "utils/**": "#",
683
+ "services/**": "#",
684
+ "config/**": "#",
685
+ "middleware.ts": "^",
686
+ "app/api/auth/**": "^",
687
+ "events/**": "!",
688
+ "handlers/**": "!",
689
+ "flows/**": "$",
690
+ "aspects/**": "~",
691
+ "rules/**": "~"
692
+ },
693
+ purposeRequired: [
694
+ { pattern: "app/*", depth: 1 },
695
+ { pattern: "app/api/*", depth: 1 },
696
+ { pattern: "components/*", depth: 1 },
697
+ { pattern: "lib/*", depth: 1 }
698
+ ],
699
+ scanHints: {
700
+ componentPatterns: ["app/**/page.tsx", "app/**/layout.tsx", "components/**/*.tsx", "pages/**/*.tsx"],
701
+ routePatterns: ["app/api/**/route.ts", "app/**/page.tsx", "pages/api/**/*.ts"],
702
+ authPatterns: ["middleware.ts", "app/api/auth/**", "lib/auth.*"],
703
+ statePatterns: ["stores/**", "lib/*store*", "lib/*context*"]
704
+ },
705
+ detectFn: (dir) => {
706
+ try {
707
+ return fs.readdirSync(dir).some((f) => f.startsWith("next.config"));
708
+ } catch {
709
+ return false;
710
+ }
711
+ }
712
+ },
713
+ remix: {
714
+ id: "remix",
715
+ name: "Remix",
716
+ discipline: "fullstack",
717
+ symbolMapping: {
718
+ "app/routes/**": "#",
719
+ "app/components/**": "#",
720
+ "app/models/**": "#",
721
+ "app/utils/**": "#",
722
+ "app/lib/**": "#",
723
+ "app/services/**": "#",
724
+ "app/hooks/**": "#",
725
+ "app/stores/**": "#",
726
+ "app/config/**": "#",
727
+ "app/middleware/**": "^",
728
+ "app/auth/**": "^",
729
+ "app/events/**": "!",
730
+ "app/flows/**": "$",
731
+ "app/aspects/**": "~"
732
+ },
733
+ purposeRequired: [
734
+ { pattern: "app/routes/*", depth: 1 },
735
+ { pattern: "app/components/*", depth: 1 },
736
+ { pattern: "app/models/*", depth: 1 }
737
+ ],
738
+ scanHints: {
739
+ componentPatterns: ["app/routes/**/*.tsx", "app/components/**/*.tsx"],
740
+ routePatterns: ["app/routes/**/*.tsx"],
741
+ authPatterns: ["app/utils/auth.*", "app/services/auth.*"],
742
+ statePatterns: ["app/utils/*session*", "app/models/**"]
743
+ },
744
+ detectFn: (dir) => {
745
+ try {
746
+ return fs.readdirSync(dir).some((f) => f.startsWith("remix.config"));
747
+ } catch {
748
+ return false;
749
+ }
750
+ }
751
+ },
752
+ nuxt: {
753
+ id: "nuxt",
754
+ name: "Nuxt",
755
+ discipline: "fullstack",
756
+ symbolMapping: {
757
+ "pages/**": "#",
758
+ "components/**": "#",
759
+ "composables/**": "#",
760
+ "server/api/**": "#",
761
+ "server/routes/**": "#",
762
+ "server/utils/**": "#",
763
+ "utils/**": "#",
764
+ "stores/**": "#",
765
+ "plugins/**": "#",
766
+ "layouts/**": "#",
767
+ "server/middleware/**": "^",
768
+ "middleware/**": "^",
769
+ "server/plugins/**": "!",
770
+ "flows/**": "$",
771
+ "aspects/**": "~"
772
+ },
773
+ purposeRequired: [
774
+ { pattern: "pages/*", depth: 1 },
775
+ { pattern: "components/*", depth: 1 },
776
+ { pattern: "server/api/*", depth: 1 }
777
+ ],
778
+ scanHints: {
779
+ componentPatterns: ["pages/**/*.vue", "components/**/*.vue", "layouts/**/*.vue"],
780
+ routePatterns: ["server/api/**/*.ts", "server/routes/**/*.ts", "pages/**/*.vue"],
781
+ authPatterns: ["server/middleware/auth.*", "middleware/auth.*", "server/utils/auth.*"],
782
+ statePatterns: ["stores/**/*.ts", "composables/use*State*"]
783
+ },
784
+ detectFn: (dir) => {
785
+ try {
786
+ return fs.readdirSync(dir).some((f) => f.startsWith("nuxt.config"));
787
+ } catch {
788
+ return false;
789
+ }
790
+ }
791
+ },
792
+ sveltekit: {
793
+ id: "sveltekit",
794
+ name: "SvelteKit",
795
+ discipline: "fullstack",
796
+ symbolMapping: {
797
+ "src/routes/**": "#",
798
+ "src/lib/**": "#",
799
+ "src/lib/components/**": "#",
800
+ "src/lib/server/**": "#",
801
+ "src/lib/stores/**": "#",
802
+ "src/lib/utils/**": "#",
803
+ "src/hooks.*": "^",
804
+ "src/lib/auth/**": "^",
805
+ "src/lib/events/**": "!",
806
+ "src/lib/flows/**": "$",
807
+ "src/lib/aspects/**": "~"
808
+ },
809
+ purposeRequired: [
810
+ { pattern: "src/routes/*", depth: 1 },
811
+ { pattern: "src/lib/components/*", depth: 1 },
812
+ { pattern: "src/lib/server/*", depth: 1 }
813
+ ],
814
+ scanHints: {
815
+ componentPatterns: ["src/routes/**/+page.svelte", "src/lib/components/**/*.svelte"],
816
+ routePatterns: ["src/routes/**/+server.ts", "src/routes/**/+page.server.ts"],
817
+ authPatterns: ["src/hooks.server.ts", "src/lib/auth/**", "src/lib/server/auth.*"],
818
+ statePatterns: ["src/lib/stores/**"]
819
+ },
820
+ detectFn: (dir) => {
821
+ try {
822
+ return fs.readdirSync(dir).some((f) => f.startsWith("svelte.config"));
823
+ } catch {
824
+ return false;
825
+ }
826
+ }
827
+ },
828
+ astro: {
829
+ id: "astro",
830
+ name: "Astro",
831
+ discipline: "fullstack",
832
+ symbolMapping: {
833
+ "src/pages/**": "#",
834
+ "src/components/**": "#",
835
+ "src/layouts/**": "#",
836
+ "src/content/**": "#",
837
+ "src/lib/**": "#",
838
+ "src/utils/**": "#",
839
+ "src/middleware.*": "^",
840
+ "src/events/**": "!",
841
+ "src/flows/**": "$",
842
+ "src/aspects/**": "~"
843
+ },
844
+ purposeRequired: [
845
+ { pattern: "src/pages/*", depth: 1 },
846
+ { pattern: "src/components/*", depth: 1 }
847
+ ],
848
+ scanHints: {
849
+ componentPatterns: ["src/pages/**/*.astro", "src/components/**/*.astro", "src/layouts/**/*.astro"],
850
+ routePatterns: ["src/pages/**/*.astro", "src/pages/api/**/*.ts"],
851
+ authPatterns: ["src/middleware.*"],
852
+ statePatterns: ["src/content/**"]
853
+ },
854
+ detectFn: (dir) => {
855
+ try {
856
+ return fs.readdirSync(dir).some((f) => f.startsWith("astro.config"));
857
+ } catch {
858
+ return false;
859
+ }
860
+ }
861
+ },
862
+ // --- Web (SPA) ---
863
+ "react-spa": {
864
+ id: "react-spa",
865
+ name: "React SPA",
866
+ discipline: "web",
867
+ symbolMapping: {
868
+ "src/components/**": "#",
869
+ "src/pages/**": "#",
870
+ "src/views/**": "#",
871
+ "src/hooks/**": "#",
872
+ "src/stores/**": "#",
873
+ "src/state/**": "#",
874
+ "src/utils/**": "#",
875
+ "src/lib/**": "#",
876
+ "src/services/**": "#",
877
+ "src/api/**": "#",
878
+ "src/config/**": "#",
879
+ "src/middleware/**": "^",
880
+ "src/auth/**": "^",
881
+ "src/guards/**": "^",
882
+ "src/events/**": "!",
883
+ "src/handlers/**": "!",
884
+ "src/flows/**": "$",
885
+ "src/aspects/**": "~",
886
+ "src/rules/**": "~"
887
+ },
888
+ purposeRequired: [
889
+ { pattern: "src/components/*", depth: 1 },
890
+ { pattern: "src/pages/*", depth: 1 },
891
+ { pattern: "src/features/*", depth: 1 }
892
+ ],
893
+ scanHints: {
894
+ componentPatterns: ["src/components/**/*.tsx", "src/pages/**/*.tsx", "src/views/**/*.tsx"],
895
+ routePatterns: ["src/routes.*", "src/App.tsx"],
896
+ authPatterns: ["src/auth/**", "src/guards/**", "src/hooks/useAuth*"],
897
+ statePatterns: ["src/stores/**", "src/state/**", "src/hooks/use*Store*"]
898
+ },
899
+ detectFn: (dir) => {
900
+ const pkg = readPackageJson(dir);
901
+ if (!pkg) return false;
902
+ const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
903
+ return "react" in deps && !("next" in deps) && !("remix" in deps) && !("react-native" in deps);
904
+ }
905
+ },
906
+ "vue-spa": {
907
+ id: "vue-spa",
908
+ name: "Vue SPA",
909
+ discipline: "web",
910
+ symbolMapping: {
911
+ "src/components/**": "#",
912
+ "src/views/**": "#",
913
+ "src/pages/**": "#",
914
+ "src/composables/**": "#",
915
+ "src/stores/**": "#",
916
+ "src/utils/**": "#",
917
+ "src/lib/**": "#",
918
+ "src/services/**": "#",
919
+ "src/api/**": "#",
920
+ "src/config/**": "#",
921
+ "src/router/**": "$",
922
+ "src/middleware/**": "^",
923
+ "src/auth/**": "^",
924
+ "src/guards/**": "^",
925
+ "src/events/**": "!",
926
+ "src/flows/**": "$",
927
+ "src/aspects/**": "~"
928
+ },
929
+ purposeRequired: [
930
+ { pattern: "src/components/*", depth: 1 },
931
+ { pattern: "src/views/*", depth: 1 },
932
+ { pattern: "src/stores/*", depth: 1 }
933
+ ],
934
+ scanHints: {
935
+ componentPatterns: ["src/components/**/*.vue", "src/views/**/*.vue"],
936
+ routePatterns: ["src/router/**/*.ts"],
937
+ authPatterns: ["src/auth/**", "src/guards/**", "src/router/guards*"],
938
+ statePatterns: ["src/stores/**/*.ts", "src/composables/**/*.ts"]
939
+ },
940
+ detectFn: (dir) => {
941
+ const pkg = readPackageJson(dir);
942
+ if (!pkg) return false;
943
+ const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
944
+ return "vue" in deps && !("nuxt" in deps);
945
+ }
946
+ },
947
+ // --- API ---
948
+ express: {
949
+ id: "express",
950
+ name: "Express",
951
+ discipline: "api",
952
+ symbolMapping: {
953
+ "src/routes/**": "#",
954
+ "src/controllers/**": "#",
955
+ "src/services/**": "#",
956
+ "src/models/**": "#",
957
+ "src/lib/**": "#",
958
+ "src/utils/**": "#",
959
+ "src/config/**": "#",
960
+ "src/middleware/**": "^",
961
+ "src/auth/**": "^",
962
+ "src/guards/**": "^",
963
+ "src/policies/**": "^",
964
+ "src/events/**": "!",
965
+ "src/handlers/**": "!",
966
+ "src/listeners/**": "!",
967
+ "src/webhooks/**": "!",
968
+ "src/flows/**": "$",
969
+ "src/workflows/**": "$",
970
+ "src/aspects/**": "~",
971
+ "src/rules/**": "~"
972
+ },
973
+ purposeRequired: [
974
+ { pattern: "src/routes/*", depth: 1 },
975
+ { pattern: "src/services/*", depth: 1 },
976
+ { pattern: "src/controllers/*", depth: 1 }
977
+ ],
978
+ scanHints: {
979
+ componentPatterns: ["src/routes/**/*.ts", "src/controllers/**/*.ts", "src/services/**/*.ts"],
980
+ routePatterns: ["src/routes/**/*.ts", "src/index.ts", "src/app.ts"],
981
+ authPatterns: ["src/middleware/auth*", "src/auth/**"],
982
+ statePatterns: ["src/models/**/*.ts"]
983
+ },
984
+ detectFn: (dir) => {
985
+ const pkg = readPackageJson(dir);
986
+ if (!pkg) return false;
987
+ const deps = { ...pkg.dependencies ?? {} };
988
+ return "express" in deps;
989
+ }
990
+ },
991
+ fastify: {
992
+ id: "fastify",
993
+ name: "Fastify",
994
+ discipline: "api",
995
+ symbolMapping: {
996
+ "src/routes/**": "#",
997
+ "src/plugins/**": "#",
998
+ "src/services/**": "#",
999
+ "src/models/**": "#",
1000
+ "src/schemas/**": "#",
1001
+ "src/lib/**": "#",
1002
+ "src/utils/**": "#",
1003
+ "src/config/**": "#",
1004
+ "src/hooks/**": "^",
1005
+ "src/auth/**": "^",
1006
+ "src/decorators/**": "^",
1007
+ "src/events/**": "!",
1008
+ "src/handlers/**": "!",
1009
+ "src/flows/**": "$",
1010
+ "src/aspects/**": "~"
1011
+ },
1012
+ purposeRequired: [
1013
+ { pattern: "src/routes/*", depth: 1 },
1014
+ { pattern: "src/plugins/*", depth: 1 },
1015
+ { pattern: "src/services/*", depth: 1 }
1016
+ ],
1017
+ scanHints: {
1018
+ componentPatterns: ["src/routes/**/*.ts", "src/plugins/**/*.ts", "src/services/**/*.ts"],
1019
+ routePatterns: ["src/routes/**/*.ts"],
1020
+ authPatterns: ["src/hooks/auth*", "src/auth/**", "src/decorators/auth*"],
1021
+ statePatterns: ["src/models/**/*.ts", "src/schemas/**/*.ts"]
1022
+ },
1023
+ detectFn: (dir) => {
1024
+ const pkg = readPackageJson(dir);
1025
+ if (!pkg) return false;
1026
+ const deps = { ...pkg.dependencies ?? {} };
1027
+ return "fastify" in deps;
1028
+ }
1029
+ },
1030
+ fastapi: {
1031
+ id: "fastapi",
1032
+ name: "FastAPI",
1033
+ discipline: "api",
1034
+ symbolMapping: {
1035
+ "routers/**": "#",
1036
+ "routes/**": "#",
1037
+ "api/**": "#",
1038
+ "services/**": "#",
1039
+ "models/**": "#",
1040
+ "schemas/**": "#",
1041
+ "crud/**": "#",
1042
+ "core/**": "#",
1043
+ "utils/**": "#",
1044
+ "config/**": "#",
1045
+ "deps/**": "^",
1046
+ "middleware/**": "^",
1047
+ "auth/**": "^",
1048
+ "events/**": "!",
1049
+ "handlers/**": "!",
1050
+ "flows/**": "$",
1051
+ "aspects/**": "~"
1052
+ },
1053
+ purposeRequired: [
1054
+ { pattern: "routers/*", depth: 1 },
1055
+ { pattern: "services/*", depth: 1 },
1056
+ { pattern: "models/*", depth: 1 }
1057
+ ],
1058
+ scanHints: {
1059
+ componentPatterns: ["routers/**/*.py", "api/**/*.py", "services/**/*.py"],
1060
+ routePatterns: ["routers/**/*.py", "api/**/*.py", "main.py", "app.py"],
1061
+ authPatterns: ["deps/**/*.py", "auth/**/*.py", "middleware/**/*.py"],
1062
+ statePatterns: ["models/**/*.py", "schemas/**/*.py"]
1063
+ },
1064
+ detectFn: (dir) => {
1065
+ const pyDeps = (readFileIfExists(dir, "pyproject.toml") || "") + (readFileIfExists(dir, "requirements.txt") || "");
1066
+ return /fastapi/i.test(pyDeps);
1067
+ }
1068
+ },
1069
+ django: {
1070
+ id: "django",
1071
+ name: "Django",
1072
+ discipline: "api",
1073
+ symbolMapping: {
1074
+ "**/views/**": "#",
1075
+ "**/views.py": "#",
1076
+ "**/serializers/**": "#",
1077
+ "**/models/**": "#",
1078
+ "**/models.py": "#",
1079
+ "**/admin.py": "#",
1080
+ "**/forms.py": "#",
1081
+ "**/urls.py": "$",
1082
+ "**/management/**": "#",
1083
+ "**/utils/**": "#",
1084
+ "**/middleware/**": "^",
1085
+ "**/permissions/**": "^",
1086
+ "**/signals/**": "!",
1087
+ "**/tasks/**": "$",
1088
+ "**/aspects/**": "~"
1089
+ },
1090
+ purposeRequired: [
1091
+ { pattern: "*/views/*", depth: 1 },
1092
+ { pattern: "*/models/*", depth: 1 }
1093
+ ],
1094
+ scanHints: {
1095
+ componentPatterns: ["**/views.py", "**/views/**/*.py", "**/serializers.py"],
1096
+ routePatterns: ["**/urls.py"],
1097
+ authPatterns: ["**/permissions.py", "**/permissions/**/*.py", "**/middleware/**/*.py"],
1098
+ statePatterns: ["**/models.py", "**/models/**/*.py"]
1099
+ },
1100
+ detectFn: (dir) => {
1101
+ return fs.existsSync(path.join(dir, "manage.py"));
1102
+ }
1103
+ },
1104
+ gin: {
1105
+ id: "gin",
1106
+ name: "Gin (Go)",
1107
+ discipline: "api",
1108
+ symbolMapping: {
1109
+ "handlers/**": "#",
1110
+ "controllers/**": "#",
1111
+ "services/**": "#",
1112
+ "models/**": "#",
1113
+ "repository/**": "#",
1114
+ "pkg/**": "#",
1115
+ "internal/**": "#",
1116
+ "cmd/**": "#",
1117
+ "config/**": "#",
1118
+ "middleware/**": "^",
1119
+ "auth/**": "^",
1120
+ "events/**": "!",
1121
+ "flows/**": "$",
1122
+ "aspects/**": "~"
1123
+ },
1124
+ purposeRequired: [
1125
+ { pattern: "handlers/*", depth: 1 },
1126
+ { pattern: "services/*", depth: 1 },
1127
+ { pattern: "cmd/*", depth: 1 }
1128
+ ],
1129
+ scanHints: {
1130
+ componentPatterns: ["handlers/**/*.go", "controllers/**/*.go", "services/**/*.go"],
1131
+ routePatterns: ["cmd/**/*.go", "routes/**/*.go", "router/**/*.go"],
1132
+ authPatterns: ["middleware/**/*.go", "auth/**/*.go"],
1133
+ statePatterns: ["models/**/*.go", "repository/**/*.go"]
1134
+ },
1135
+ detectFn: (dir) => {
1136
+ const goMod = readFileIfExists(dir, "go.mod") || "";
1137
+ return /gin-gonic\/gin/i.test(goMod);
1138
+ }
1139
+ },
1140
+ axum: {
1141
+ id: "axum",
1142
+ name: "Axum (Rust)",
1143
+ discipline: "api",
1144
+ symbolMapping: {
1145
+ "src/handlers/**": "#",
1146
+ "src/routes/**": "#",
1147
+ "src/services/**": "#",
1148
+ "src/models/**": "#",
1149
+ "src/db/**": "#",
1150
+ "src/lib.rs": "#",
1151
+ "src/config/**": "#",
1152
+ "src/middleware/**": "^",
1153
+ "src/auth/**": "^",
1154
+ "src/extractors/**": "^",
1155
+ "src/events/**": "!",
1156
+ "src/flows/**": "$",
1157
+ "src/aspects/**": "~"
1158
+ },
1159
+ purposeRequired: [
1160
+ { pattern: "src/handlers/*", depth: 1 },
1161
+ { pattern: "src/services/*", depth: 1 }
1162
+ ],
1163
+ scanHints: {
1164
+ componentPatterns: ["src/handlers/**/*.rs", "src/routes/**/*.rs", "src/services/**/*.rs"],
1165
+ routePatterns: ["src/routes/**/*.rs", "src/main.rs", "src/lib.rs"],
1166
+ authPatterns: ["src/middleware/**/*.rs", "src/auth/**/*.rs", "src/extractors/**/*.rs"],
1167
+ statePatterns: ["src/models/**/*.rs", "src/db/**/*.rs"]
1168
+ },
1169
+ detectFn: (dir) => {
1170
+ const cargo = readFileIfExists(dir, "Cargo.toml") || "";
1171
+ return /axum/i.test(cargo);
1172
+ }
1173
+ },
1174
+ // --- Mobile ---
1175
+ "swift-ios": {
1176
+ id: "swift-ios",
1177
+ name: "Swift iOS",
1178
+ discipline: "mobile",
1179
+ symbolMapping: {
1180
+ "**/Views/**": "#",
1181
+ "**/Screens/**": "#",
1182
+ "**/Components/**": "#",
1183
+ "**/ViewModels/**": "#",
1184
+ "**/Models/**": "#",
1185
+ "**/Services/**": "#",
1186
+ "**/Managers/**": "#",
1187
+ "**/Helpers/**": "#",
1188
+ "**/Utils/**": "#",
1189
+ "**/Extensions/**": "#",
1190
+ "**/Networking/**": "#",
1191
+ "**/Coordinators/**": "$",
1192
+ "**/Navigation/**": "$",
1193
+ "**/Flows/**": "$",
1194
+ "**/Auth/**": "^",
1195
+ "**/Middleware/**": "^",
1196
+ "**/Events/**": "!",
1197
+ "**/Notifications/**": "!",
1198
+ "**/Aspects/**": "~"
1199
+ },
1200
+ purposeRequired: [
1201
+ { pattern: "**/Views/*", depth: 1 },
1202
+ { pattern: "**/Screens/*", depth: 1 },
1203
+ { pattern: "**/Services/*", depth: 1 }
1204
+ ],
1205
+ scanHints: {
1206
+ componentPatterns: ["**/*.swift"],
1207
+ routePatterns: ["**/Navigation/**/*.swift", "**/Coordinators/**/*.swift"],
1208
+ authPatterns: ["**/Auth/**/*.swift", "**/Keychain*"],
1209
+ statePatterns: ["**/ViewModels/**/*.swift", "**/Models/**/*.swift", "**/Stores/**/*.swift"]
1210
+ },
1211
+ detectFn: (dir) => {
1212
+ const hasXcodeproj = hasFilesMatching(dir, ".xcodeproj") || hasFilesMatching(dir, ".xcworkspace");
1213
+ const hasSwift = fs.existsSync(path.join(dir, "Package.swift")) || fs.existsSync(path.join(dir, "Sources")) && hasFilesMatching(path.join(dir, "Sources"), ".swift");
1214
+ return hasXcodeproj || hasSwift;
1215
+ }
1216
+ },
1217
+ "kotlin-android": {
1218
+ id: "kotlin-android",
1219
+ name: "Kotlin Android",
1220
+ discipline: "mobile",
1221
+ symbolMapping: {
1222
+ "**/ui/**": "#",
1223
+ "**/screens/**": "#",
1224
+ "**/components/**": "#",
1225
+ "**/viewmodel/**": "#",
1226
+ "**/viewmodels/**": "#",
1227
+ "**/model/**": "#",
1228
+ "**/models/**": "#",
1229
+ "**/data/**": "#",
1230
+ "**/repository/**": "#",
1231
+ "**/service/**": "#",
1232
+ "**/network/**": "#",
1233
+ "**/api/**": "#",
1234
+ "**/util/**": "#",
1235
+ "**/utils/**": "#",
1236
+ "**/di/**": "#",
1237
+ "**/navigation/**": "$",
1238
+ "**/auth/**": "^",
1239
+ "**/middleware/**": "^",
1240
+ "**/events/**": "!",
1241
+ "**/flows/**": "$",
1242
+ "**/aspects/**": "~"
1243
+ },
1244
+ purposeRequired: [
1245
+ { pattern: "**/ui/*", depth: 1 },
1246
+ { pattern: "**/screens/*", depth: 1 },
1247
+ { pattern: "**/data/*", depth: 1 }
1248
+ ],
1249
+ scanHints: {
1250
+ componentPatterns: ["**/*.kt"],
1251
+ routePatterns: ["**/navigation/**/*.kt"],
1252
+ authPatterns: ["**/auth/**/*.kt"],
1253
+ statePatterns: ["**/viewmodel/**/*.kt", "**/viewmodels/**/*.kt", "**/model/**/*.kt", "**/repository/**/*.kt"]
1254
+ },
1255
+ detectFn: (dir) => {
1256
+ return fs.existsSync(path.join(dir, "build.gradle.kts")) || fs.existsSync(path.join(dir, "build.gradle"));
1257
+ }
1258
+ },
1259
+ flutter: {
1260
+ id: "flutter",
1261
+ name: "Flutter",
1262
+ discipline: "mobile",
1263
+ symbolMapping: {
1264
+ "lib/screens/**": "#",
1265
+ "lib/pages/**": "#",
1266
+ "lib/widgets/**": "#",
1267
+ "lib/components/**": "#",
1268
+ "lib/models/**": "#",
1269
+ "lib/services/**": "#",
1270
+ "lib/providers/**": "#",
1271
+ "lib/repositories/**": "#",
1272
+ "lib/utils/**": "#",
1273
+ "lib/config/**": "#",
1274
+ "lib/routes/**": "$",
1275
+ "lib/navigation/**": "$",
1276
+ "lib/auth/**": "^",
1277
+ "lib/middleware/**": "^",
1278
+ "lib/events/**": "!",
1279
+ "lib/flows/**": "$",
1280
+ "lib/aspects/**": "~"
1281
+ },
1282
+ purposeRequired: [
1283
+ { pattern: "lib/screens/*", depth: 1 },
1284
+ { pattern: "lib/widgets/*", depth: 1 },
1285
+ { pattern: "lib/services/*", depth: 1 }
1286
+ ],
1287
+ scanHints: {
1288
+ componentPatterns: ["lib/**/*.dart"],
1289
+ routePatterns: ["lib/routes/**/*.dart", "lib/navigation/**/*.dart"],
1290
+ authPatterns: ["lib/auth/**/*.dart"],
1291
+ statePatterns: ["lib/providers/**/*.dart", "lib/models/**/*.dart", "lib/repositories/**/*.dart"]
1292
+ },
1293
+ detectFn: (dir) => {
1294
+ return fs.existsSync(path.join(dir, "pubspec.yaml"));
1295
+ }
1296
+ }
1297
+ };
1298
+ function detectStack(rootDir) {
1299
+ for (const [id, preset] of Object.entries(STACK_PRESETS)) {
1300
+ if (preset.detectFn(rootDir)) {
1301
+ return id;
1302
+ }
1303
+ }
1304
+ return null;
1305
+ }
1306
+ function getStackConfig(stackId) {
1307
+ const preset = STACK_PRESETS[stackId];
1308
+ if (!preset) return null;
1309
+ const base = getDisciplineConfig(preset.discipline);
1310
+ return {
1311
+ symbolMapping: { ...base.symbolMapping, ...preset.symbolMapping },
1312
+ purposeRequired: preset.purposeRequired,
1313
+ examples: base.examples
1314
+ };
1315
+ }
1316
+ function listStackPresets(discipline) {
1317
+ const presets = Object.values(STACK_PRESETS);
1318
+ if (discipline) {
1319
+ return presets.filter((p) => p.discipline === discipline);
1320
+ }
1321
+ return presets;
1322
+ }
1323
+
1324
+ export {
1325
+ detectDiscipline,
1326
+ DISCIPLINE_MAPPINGS,
1327
+ GENERIC_SYMBOL_MAPPING,
1328
+ getDisciplineConfig,
1329
+ getDisciplineScanPatterns,
1330
+ STACK_PRESETS,
1331
+ detectStack,
1332
+ getStackConfig,
1333
+ listStackPresets
1334
+ };