chati-dev 4.2.2 → 4.3.1

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 (221) hide show
  1. package/README.md +80 -53
  2. package/bin/chati.js +170 -5
  3. package/framework/agents/build/dev.md +509 -76
  4. package/framework/agents/deploy/devops.md +40 -25
  5. package/framework/agents/discover/brief.md +158 -22
  6. package/framework/agents/discover/brownfield-wu.md +26 -14
  7. package/framework/agents/discover/greenfield-wu.md +102 -14
  8. package/framework/agents/plan/architect-data-engineer.md +6 -6
  9. package/framework/agents/plan/architect-system.md +46 -12
  10. package/framework/agents/plan/architect.md +40 -20
  11. package/framework/agents/plan/detail.md +38 -24
  12. package/framework/agents/plan/phases.md +36 -26
  13. package/framework/agents/plan/tasks.md +114 -33
  14. package/framework/agents/plan/ux-brand-architect.md +240 -8
  15. package/framework/agents/plan/ux-component-engineer.md +28 -13
  16. package/framework/agents/plan/ux-researcher.md +7 -6
  17. package/framework/agents/plan/ux.md +55 -22
  18. package/framework/agents/quality/qa-implementation.md +143 -74
  19. package/framework/agents/quality/qa-planning.md +115 -42
  20. package/framework/agents/quality/qa-visual.md +448 -0
  21. package/framework/agents/shared/visualizer.md +128 -0
  22. package/framework/config.yaml +7 -6
  23. package/framework/constitution.md +127 -44
  24. package/framework/context/governance.md +12 -7
  25. package/framework/context/quality.md +6 -5
  26. package/framework/context/root.md +6 -6
  27. package/framework/data/entity-registry.yaml +377 -4
  28. package/framework/data/model-limits.json +19 -0
  29. package/framework/domains/agents/qa-visual.yaml +74 -0
  30. package/framework/domains/constitution.yaml +46 -2
  31. package/framework/domains/workflows/greenfield-fullstack.yaml +2 -2
  32. package/framework/hooks/advance-trigger.js +131 -0
  33. package/framework/hooks/brief-validator.js +83 -0
  34. package/framework/hooks/constitution-guard.js +24 -5
  35. package/framework/hooks/license-guard.js +62 -27
  36. package/framework/hooks/mode-governance.js +13 -2
  37. package/framework/hooks/model-governance.js +1 -0
  38. package/framework/hooks/post-dev.js +207 -0
  39. package/framework/hooks/prism-engine.js +274 -105
  40. package/framework/hooks/reasoning-escalator.js +371 -0
  41. package/framework/hooks/reference-trigger.js +117 -0
  42. package/framework/hooks/session-digest.js +50 -1
  43. package/framework/hooks/settings.json +32 -1
  44. package/framework/hooks/style-guard.js +25 -6
  45. package/framework/hooks/team-quality-gate.js +19 -12
  46. package/framework/hooks/undercover-guard.js +4 -2
  47. package/framework/i18n/en.yaml +3 -3
  48. package/framework/i18n/es.yaml +3 -3
  49. package/framework/i18n/fr.yaml +3 -3
  50. package/framework/i18n/pt.yaml +3 -3
  51. package/framework/intelligence/context-engine.md +4 -5
  52. package/framework/intelligence/decision-engine.md +1 -1
  53. package/framework/intelligence/hooks-performance.md +3 -3
  54. package/framework/migrations/v1.0-to-v1.1.yaml +1 -1
  55. package/framework/migrations/v1.4-to-v2.0.yaml +11 -11
  56. package/framework/migrations/v4.0-to-v4.1.yaml +2 -2
  57. package/framework/migrations/v4.2-to-v4.3.yaml +29 -0
  58. package/framework/orchestrator/chati-router.js +441 -0
  59. package/framework/orchestrator/chati-update.md +40 -40
  60. package/framework/orchestrator/chati.md +295 -94
  61. package/framework/rules/human-writing-style.md +47 -0
  62. package/framework/scaffold/motion-premium/README.md +99 -0
  63. package/framework/scaffold/motion-premium/app/globals.css.template +400 -0
  64. package/framework/scaffold/motion-premium/app/layout.tsx.template +110 -0
  65. package/framework/scaffold/motion-premium/components/animation/BackgroundCrossfadeProvider.tsx.template +170 -0
  66. package/framework/scaffold/motion-premium/components/animation/LenisProvider.tsx.template +49 -0
  67. package/framework/scaffold/motion-premium/components/animation/PageTransitionWrapper.tsx.template +83 -0
  68. package/framework/scaffold/motion-premium/components/animation/Preloader.tsx.template +171 -0
  69. package/framework/scaffold/motion-premium/components/ui/Container.tsx.template +69 -0
  70. package/framework/scaffold/motion-premium/components/ui/PageSection.tsx.template +74 -0
  71. package/framework/scaffold/motion-premium/lib/animations/gsap.ts.template +112 -0
  72. package/framework/scaffold/motion-premium/lib/animations/refreshCoordinator.ts.template +75 -0
  73. package/framework/scaffold/motion-premium/lib/animations/tokens.ts.template +119 -0
  74. package/framework/scaffold/motion-premium/lib/animations/useGsapContext.ts.template +92 -0
  75. package/framework/scaffold/motion-premium/lib/animations/useScrollSnapStepper.ts.template +265 -0
  76. package/framework/scaffold/motion-premium/lib/animations/useSmoothScroll.ts.template +67 -0
  77. package/framework/scaffold/motion-premium/lib/brand.ts.template +43 -0
  78. package/framework/scaffold/motion-premium/scaffold.yaml +178 -0
  79. package/framework/scaffold/motion-premium-3d/README.md +90 -0
  80. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoCanvas.tsx.template +81 -0
  81. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoClient.tsx.template +75 -0
  82. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/page.tsx.template +26 -0
  83. package/framework/scaffold/motion-premium-3d/components/3d/CameraRig.tsx.template +100 -0
  84. package/framework/scaffold/motion-premium-3d/components/3d/CanvasProvider.tsx.template +85 -0
  85. package/framework/scaffold/motion-premium-3d/components/3d/InvalidateOnScroll.tsx.template +51 -0
  86. package/framework/scaffold/motion-premium-3d/components/3d/MeshCrossfade.tsx.template +79 -0
  87. package/framework/scaffold/motion-premium-3d/components/3d/ScrollCrossfade.tsx.template +88 -0
  88. package/framework/scaffold/motion-premium-3d/components/3d/ScrollScene.tsx.template +121 -0
  89. package/framework/scaffold/motion-premium-3d/components/webgl/SceneFallback.tsx.template +65 -0
  90. package/framework/scaffold/motion-premium-3d/components/webgl/WebGLContext.tsx.template +68 -0
  91. package/framework/scaffold/motion-premium-3d/lib/webgl/detect.ts.template +69 -0
  92. package/framework/scaffold/motion-premium-3d/scaffold.yaml +136 -0
  93. package/framework/schemas/session.schema.json +109 -21
  94. package/framework/scripts/reference-capture.js +430 -0
  95. package/framework/scripts/visual-qa.js +686 -0
  96. package/framework/tasks/orchestrator-handoff.md +1 -1
  97. package/framework/tasks/orchestrator-resume.md +1 -1
  98. package/framework/tasks/orchestrator-route.md +1 -1
  99. package/framework/tasks/orchestrator-status.md +3 -3
  100. package/framework/tasks/qa-planning-gate-define.md +1 -1
  101. package/framework/templates/brandbook-html-tmpl.md +2 -2
  102. package/framework/templates/brandbook-tmpl.yaml +1 -1
  103. package/framework/templates/component-spec-tmpl.yaml +1 -1
  104. package/framework/templates/design-token-tmpl.yaml +1 -1
  105. package/framework/templates/icon-system-tmpl.yaml +1 -1
  106. package/framework/templates/team-planning-tasks.yaml +6 -5
  107. package/framework/workflows/brownfield-discovery.yaml +2 -2
  108. package/framework/workflows/brownfield-fullstack.yaml +15 -11
  109. package/framework/workflows/brownfield-service.yaml +14 -10
  110. package/framework/workflows/brownfield-ui.yaml +15 -11
  111. package/framework/workflows/greenfield-fullstack.yaml +16 -13
  112. package/framework/workflows/quick-flow.yaml +3 -3
  113. package/framework/workflows/standard-flow.yaml +12 -9
  114. package/package.json +12 -6
  115. package/src/autonomy/autonomous-gate.js +1 -0
  116. package/src/autonomy/build-state.js +1 -2
  117. package/src/autonomy/progress-reporter.js +1 -1
  118. package/src/config/agent-customizer.js +11 -3
  119. package/src/config/claude-settings-generator.js +27 -7
  120. package/src/config/context-file-generator.js +41 -21
  121. package/src/config/framework-adapter.js +1 -0
  122. package/src/config/gemini-hooks-generator.js +19 -7
  123. package/src/config/mcp-configs.js +1 -0
  124. package/src/context/layers/l1-global.js +2 -1
  125. package/src/dashboard/data-reader.js +4 -3
  126. package/src/dashboard/layout.js +2 -1
  127. package/src/decision/analyzer.js +6 -30
  128. package/src/decision/engine.js +4 -28
  129. package/src/decision/registry-healer.js +3 -2
  130. package/src/decision/registry-updater.js +23 -14
  131. package/src/extensions/loader.js +2 -8
  132. package/src/gates/g1-planning-complete.js +2 -1
  133. package/src/gates/g2-qa-planning.js +2 -1
  134. package/src/gates/g3-implementation.js +2 -1
  135. package/src/gates/g4-qa-implementation.js +3 -2
  136. package/src/gates/g5-deploy-ready.js +2 -1
  137. package/src/health/engine.js +4 -3
  138. package/src/installer/core.js +431 -81
  139. package/src/installer/preflight.js +131 -0
  140. package/src/installer/provider-overlay.js +3 -3
  141. package/src/installer/scaffold-applier.js +358 -0
  142. package/src/installer/templates.js +46 -29
  143. package/src/installer/validator.js +17 -12
  144. package/src/intelligence/registry-manager.js +22 -29
  145. package/src/intelligence/timeline.js +11 -6
  146. package/src/license/commands.js +1 -1
  147. package/src/license/wait.js +102 -0
  148. package/src/memory/agent-memory.js +81 -0
  149. package/src/memory/dream.js +32 -1
  150. package/src/merger/replace-merger.js +28 -15
  151. package/src/orchestrator/agent-selector.js +2 -1
  152. package/src/orchestrator/cli.js +1880 -71
  153. package/src/orchestrator/doctor.js +270 -0
  154. package/src/orchestrator/handoff-engine.js +4 -3
  155. package/src/orchestrator/index.js +2 -0
  156. package/src/orchestrator/pipeline-manager.js +306 -15
  157. package/src/orchestrator/session-manager.js +339 -6
  158. package/src/tasks/handoff.js +3 -2
  159. package/src/telemetry/config.js +4 -3
  160. package/src/telemetry/schema.js +1 -0
  161. package/src/terminal/collector.js +3 -2
  162. package/src/terminal/index.js +1 -2
  163. package/src/terminal/isolation.js +52 -18
  164. package/src/terminal/prompt-builder.js +42 -25
  165. package/src/terminal/run-parallel.js +1 -1
  166. package/src/terminal/run-team.js +3 -3
  167. package/src/terminal/team-task-list.js +43 -4
  168. package/src/upgrade/backup.js +3 -2
  169. package/src/upgrade/checker.js +3 -2
  170. package/src/upgrade/migrator.js +65 -7
  171. package/src/upgrade/tracked-files-detector.js +86 -0
  172. package/src/upgrade/user-messages.js +94 -0
  173. package/src/utils/config-parser.js +2 -1
  174. package/src/utils/feature-flags.js +2 -1
  175. package/src/utils/flatten-entities.js +69 -0
  176. package/src/utils/framework-dir.js +16 -0
  177. package/src/utils/model-id.js +85 -0
  178. package/src/utils/provider-limits.js +84 -23
  179. package/src/utils/schema-validator.js +1 -1
  180. package/src/wizard/i18n.js +5 -4
  181. package/src/wizard/index.js +14 -0
  182. package/assets/logo - c/303/263pia.png +0 -0
  183. package/assets/logo.svg +0 -42
  184. package/assets/logo2.png +0 -0
  185. package/assets/social-preview.png +0 -0
  186. package/scripts/bundle-framework.js +0 -69
  187. package/scripts/changelog-generator.js +0 -222
  188. package/scripts/codebase-mapper.js +0 -728
  189. package/scripts/commit-message-generator.js +0 -167
  190. package/scripts/coverage-analyzer.js +0 -260
  191. package/scripts/dependency-analyzer.js +0 -280
  192. package/scripts/doctor/checks/agents.js +0 -77
  193. package/scripts/doctor/checks/constitution.js +0 -41
  194. package/scripts/doctor/checks/domain-alignment.js +0 -58
  195. package/scripts/doctor/checks/prism-layers.js +0 -84
  196. package/scripts/doctor/checks/registry.js +0 -55
  197. package/scripts/doctor/checks/schemas.js +0 -61
  198. package/scripts/doctor/fixes/reference-fix.js +0 -100
  199. package/scripts/doctor/fixes/registry-fix.js +0 -56
  200. package/scripts/doctor/index.js +0 -212
  201. package/scripts/framework-analyzer.js +0 -308
  202. package/scripts/generate-constitution-domain.js +0 -253
  203. package/scripts/generate-signing-key.js +0 -33
  204. package/scripts/health-check.js +0 -481
  205. package/scripts/ide-sync.js +0 -326
  206. package/scripts/performance-analyzer.js +0 -325
  207. package/scripts/plan-tracker.js +0 -278
  208. package/scripts/populate-entity-registry.js +0 -481
  209. package/scripts/pr-review.js +0 -317
  210. package/scripts/rollback-manager.js +0 -310
  211. package/scripts/semantic-lint.js +0 -328
  212. package/scripts/sign-manifest.js +0 -53
  213. package/scripts/stuck-detector.js +0 -343
  214. package/scripts/test-quality-assessment.js +0 -257
  215. package/scripts/validate-agents.js +0 -368
  216. package/scripts/validate-package.js +0 -505
  217. package/scripts/validate-tasks.js +0 -465
  218. package/src/autonomy/worktree-manager.js +0 -250
  219. package/src/intelligence/decision-engine.js +0 -256
  220. package/src/intelligence/document-sharder.js +0 -221
  221. package/src/intelligence/elicitation.js +0 -265
@@ -1,212 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * @fileoverview Doctor — Modular diagnostic system with auto-fix capability.
5
- *
6
- * Orchestrates individual check modules and fix modules to provide
7
- * comprehensive framework health validation and automatic repair.
8
- *
9
- * Exports:
10
- * runDoctor(frameworkDir, options) → DoctorReport
11
- * formatDoctorReport(report) → human-readable string
12
- *
13
- * DoctorReport:
14
- * { overall, checks, fixes, timestamp, summary }
15
- */
16
-
17
- import { existsSync } from 'fs';
18
- import { join } from 'path';
19
- import { fileURLToPath } from 'url';
20
-
21
- // Check modules
22
- import { checkRegistry } from './checks/registry.js';
23
- import { checkSchemas } from './checks/schemas.js';
24
- import { checkConstitution } from './checks/constitution.js';
25
- import { checkAgents } from './checks/agents.js';
26
- import { checkPrismLayers } from './checks/prism-layers.js';
27
- import { checkDomainAlignment } from './checks/domain-alignment.js';
28
-
29
- // Fix modules
30
- import { fixRegistryCount } from './fixes/registry-fix.js';
31
- import { fixBrokenReferences } from './fixes/reference-fix.js';
32
-
33
- /**
34
- * Map of fixId to fix function.
35
- */
36
- const FIX_REGISTRY = {
37
- 'registry-count': fixRegistryCount,
38
- 'broken-references': fixBrokenReferences,
39
- };
40
-
41
- /**
42
- * All available check functions.
43
- */
44
- const CHECK_REGISTRY = {
45
- registry: checkRegistry,
46
- schemas: checkSchemas,
47
- constitution: checkConstitution,
48
- agents: checkAgents,
49
- prismLayers: checkPrismLayers,
50
- domainAlignment: checkDomainAlignment,
51
- };
52
-
53
- /**
54
- * Run the doctor diagnostic suite.
55
- *
56
- * @param {string} frameworkDir - Path to the framework directory
57
- * @param {object} [options={}] - Configuration options
58
- * @param {boolean} [options.fix=false] - Run auto-fix for fixable issues
59
- * @param {string[]} [options.checks] - Specific checks to run (default: all)
60
- * @returns {object} DoctorReport
61
- */
62
- export function runDoctor(frameworkDir, options = {}) {
63
- const { fix = false, checks: checkFilter } = options;
64
-
65
- if (!existsSync(frameworkDir)) {
66
- return {
67
- overall: 'UNHEALTHY',
68
- checks: {
69
- frameworkDir: { pass: false, details: `Directory not found: ${frameworkDir}`, severity: 'critical', fixable: false, fixId: null },
70
- },
71
- fixes: [],
72
- timestamp: new Date().toISOString(),
73
- summary: { total: 1, passed: 0, failed: 1, criticalFailures: 1, warnings: 0, fixesApplied: 0 },
74
- };
75
- }
76
-
77
- // Run checks
78
- const checksToRun = checkFilter
79
- ? Object.entries(CHECK_REGISTRY).filter(([name]) => checkFilter.includes(name))
80
- : Object.entries(CHECK_REGISTRY);
81
-
82
- const checkResults = {};
83
- for (const [name, checkFn] of checksToRun) {
84
- checkResults[name] = checkFn(frameworkDir);
85
- }
86
-
87
- // Run fixes if requested
88
- const fixes = [];
89
- if (fix) {
90
- for (const [name, result] of Object.entries(checkResults)) {
91
- if (!result.pass && result.fixable && result.fixId) {
92
- const fixFn = FIX_REGISTRY[result.fixId];
93
- if (fixFn) {
94
- const fixResult = fixFn(frameworkDir);
95
- fixes.push({ check: name, fixId: result.fixId, ...fixResult });
96
-
97
- // Re-run the check if fix was applied
98
- if (fixResult.fixed) {
99
- const checkFn = CHECK_REGISTRY[name];
100
- if (checkFn) {
101
- checkResults[name] = checkFn(frameworkDir);
102
- }
103
- }
104
- }
105
- }
106
- }
107
- }
108
-
109
- // Determine overall health
110
- const criticalFailures = Object.values(checkResults).filter(c => !c.pass && c.severity === 'critical');
111
- const warnings = Object.values(checkResults).filter(c => !c.pass && c.severity === 'warning');
112
-
113
- let overall;
114
- if (criticalFailures.length > 0) {
115
- overall = 'UNHEALTHY';
116
- } else if (warnings.length > 0) {
117
- overall = 'DEGRADED';
118
- } else {
119
- overall = 'HEALTHY';
120
- }
121
-
122
- return {
123
- overall,
124
- checks: checkResults,
125
- fixes,
126
- timestamp: new Date().toISOString(),
127
- summary: {
128
- total: Object.keys(checkResults).length,
129
- passed: Object.values(checkResults).filter(c => c.pass).length,
130
- failed: Object.values(checkResults).filter(c => !c.pass).length,
131
- criticalFailures: criticalFailures.length,
132
- warnings: warnings.length,
133
- fixesApplied: fixes.filter(f => f.fixed).length,
134
- },
135
- };
136
- }
137
-
138
- /**
139
- * Format a DoctorReport into a human-readable string.
140
- *
141
- * @param {object} report - DoctorReport from runDoctor
142
- * @returns {string} Formatted report
143
- */
144
- export function formatDoctorReport(report) {
145
- const statusSymbol = {
146
- HEALTHY: '[OK]',
147
- DEGRADED: '[WARN]',
148
- UNHEALTHY: '[FAIL]',
149
- };
150
-
151
- const checkSymbol = (check) => check.pass ? '[PASS]' : '[FAIL]';
152
-
153
- const lines = [
154
- '=== Doctor Report ===',
155
- `Status: ${statusSymbol[report.overall] || '[ ? ]'} ${report.overall}`,
156
- `Time: ${report.timestamp}`,
157
- '',
158
- ];
159
-
160
- if (report.summary) {
161
- lines.push(`Summary: ${report.summary.passed}/${report.summary.total} checks passed`);
162
- if (report.summary.criticalFailures > 0) {
163
- lines.push(` ${report.summary.criticalFailures} critical failure(s)`);
164
- }
165
- if (report.summary.warnings > 0) {
166
- lines.push(` ${report.summary.warnings} warning(s)`);
167
- }
168
- if (report.summary.fixesApplied > 0) {
169
- lines.push(` ${report.summary.fixesApplied} fix(es) applied`);
170
- }
171
- lines.push('');
172
- }
173
-
174
- lines.push('Checks:');
175
- for (const [name, check] of Object.entries(report.checks)) {
176
- const symbol = checkSymbol(check);
177
- const severity = check.severity !== 'info' ? ` (${check.severity})` : '';
178
- const fixable = check.fixable ? ' [fixable]' : '';
179
- lines.push(` ${symbol} ${name}: ${check.details}${severity}${fixable}`);
180
- }
181
-
182
- if (report.fixes && report.fixes.length > 0) {
183
- lines.push('');
184
- lines.push('Fixes:');
185
- for (const fix of report.fixes) {
186
- const symbol = fix.fixed ? '[FIXED]' : '[SKIP]';
187
- lines.push(` ${symbol} ${fix.check}: ${fix.details}`);
188
- }
189
- }
190
-
191
- lines.push('');
192
- lines.push('=== End Report ===');
193
-
194
- return lines.join('\n');
195
- }
196
-
197
- // ---------------------------------------------------------------------------
198
- // CLI entrypoint
199
- // ---------------------------------------------------------------------------
200
-
201
- if (process.argv[1] === fileURLToPath(import.meta.url)) {
202
- const args = process.argv.slice(2);
203
- const fix = args.includes('--fix');
204
- const frameworkDir = args.find(a => !a.startsWith('--')) || join(process.cwd(), 'chati.dev');
205
-
206
- const report = runDoctor(frameworkDir, { fix });
207
- console.log(formatDoctorReport(report));
208
-
209
- if (report.overall === 'UNHEALTHY') {
210
- process.exit(1);
211
- }
212
- }
@@ -1,308 +0,0 @@
1
- /**
2
- * Framework Analyzer — Detects project technology stack through static analysis.
3
- *
4
- * Inspects package.json, configuration files, and file patterns to identify
5
- * frameworks, languages, package managers, ORMs, databases, and monorepo tools.
6
- *
7
- * @module scripts/framework-analyzer
8
- */
9
-
10
- import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';
11
- import { join } from 'node:path';
12
-
13
- /**
14
- * @typedef {Object} FrameworkReport
15
- * @property {string[]} frontendFrameworks
16
- * @property {string[]} backendFrameworks
17
- * @property {string[]} languages
18
- * @property {string} packageManager
19
- * @property {string[]} monorepoTools
20
- * @property {string[]} orms
21
- * @property {string[]} databases
22
- * @property {string[]} testingFrameworks
23
- * @property {string[]} buildTools
24
- * @property {Object} raw — raw detection results before merging
25
- */
26
-
27
- /**
28
- * Safely reads and parses a JSON file.
29
- * @param {string} filePath
30
- * @returns {Object|null}
31
- */
32
- function readJSON(filePath) {
33
- try {
34
- return JSON.parse(readFileSync(filePath, 'utf-8'));
35
- } catch {
36
- return null;
37
- }
38
- }
39
-
40
- /**
41
- * Checks if a file or directory exists.
42
- * @param {...string} segments
43
- * @returns {boolean}
44
- */
45
- function pathExists(...segments) {
46
- return existsSync(join(...segments));
47
- }
48
-
49
- /**
50
- * Detects technologies from package.json dependencies.
51
- *
52
- * @param {string} targetDir
53
- * @returns {Partial<FrameworkReport>}
54
- */
55
- export function detectByPackageJson(targetDir) {
56
- const pkg = readJSON(join(targetDir, 'package.json'));
57
- if (!pkg) return {};
58
-
59
- const allDeps = {
60
- ...pkg.dependencies,
61
- ...pkg.devDependencies,
62
- ...pkg.peerDependencies,
63
- };
64
- const depNames = new Set(Object.keys(allDeps));
65
-
66
- const frontendFrameworks = [];
67
- const backendFrameworks = [];
68
- const orms = [];
69
- const databases = [];
70
- const testingFrameworks = [];
71
- const buildTools = [];
72
- const monorepoTools = [];
73
-
74
- // Frontend
75
- if (depNames.has('next')) frontendFrameworks.push('Next.js');
76
- else if (depNames.has('react')) frontendFrameworks.push('React');
77
- if (depNames.has('nuxt') || depNames.has('nuxt3')) frontendFrameworks.push('Nuxt');
78
- else if (depNames.has('vue')) frontendFrameworks.push('Vue');
79
- if (depNames.has('@sveltejs/kit')) frontendFrameworks.push('SvelteKit');
80
- else if (depNames.has('svelte')) frontendFrameworks.push('Svelte');
81
- if (depNames.has('@angular/core')) frontendFrameworks.push('Angular');
82
-
83
- // Backend
84
- if (depNames.has('express')) backendFrameworks.push('Express');
85
- if (depNames.has('fastify')) backendFrameworks.push('Fastify');
86
- if (depNames.has('koa')) backendFrameworks.push('Koa');
87
- if (depNames.has('@nestjs/core')) backendFrameworks.push('NestJS');
88
- if (depNames.has('hono')) backendFrameworks.push('Hono');
89
- if (depNames.has('@hapi/hapi') || depNames.has('hapi')) backendFrameworks.push('Hapi');
90
-
91
- // ORM
92
- if (depNames.has('prisma') || depNames.has('@prisma/client')) orms.push('Prisma');
93
- if (depNames.has('drizzle-orm')) orms.push('Drizzle');
94
- if (depNames.has('typeorm')) orms.push('TypeORM');
95
- if (depNames.has('sequelize')) orms.push('Sequelize');
96
- if (depNames.has('mongoose')) orms.push('Mongoose');
97
- if (depNames.has('knex')) orms.push('Knex');
98
-
99
- // Database
100
- if (depNames.has('pg') || depNames.has('postgres') || depNames.has('@vercel/postgres')) databases.push('PostgreSQL');
101
- if (depNames.has('mysql2') || depNames.has('mysql')) databases.push('MySQL');
102
- if (depNames.has('mongodb') || depNames.has('mongoose')) databases.push('MongoDB');
103
- if (depNames.has('better-sqlite3') || depNames.has('sqlite3')) databases.push('SQLite');
104
- if (depNames.has('redis') || depNames.has('ioredis')) databases.push('Redis');
105
-
106
- // Testing
107
- if (depNames.has('jest')) testingFrameworks.push('Jest');
108
- if (depNames.has('vitest')) testingFrameworks.push('Vitest');
109
- if (depNames.has('mocha')) testingFrameworks.push('Mocha');
110
- if (depNames.has('@playwright/test') || depNames.has('playwright')) testingFrameworks.push('Playwright');
111
- if (depNames.has('cypress')) testingFrameworks.push('Cypress');
112
-
113
- // Build tools
114
- if (depNames.has('vite')) buildTools.push('Vite');
115
- if (depNames.has('webpack')) buildTools.push('Webpack');
116
- if (depNames.has('esbuild')) buildTools.push('esbuild');
117
- if (depNames.has('rollup')) buildTools.push('Rollup');
118
- if (depNames.has('tsup')) buildTools.push('tsup');
119
- if (depNames.has('turbo')) buildTools.push('Turborepo');
120
-
121
- // Monorepo
122
- if (depNames.has('turbo') || depNames.has('turborepo')) monorepoTools.push('Turborepo');
123
- if (depNames.has('lerna')) monorepoTools.push('Lerna');
124
- if (depNames.has('nx') || depNames.has('@nrwl/workspace')) monorepoTools.push('Nx');
125
-
126
- return { frontendFrameworks, backendFrameworks, orms, databases, testingFrameworks, buildTools, monorepoTools };
127
- }
128
-
129
- /**
130
- * Detects technologies from configuration files present in the project.
131
- *
132
- * @param {string} targetDir
133
- * @returns {Partial<FrameworkReport>}
134
- */
135
- export function detectByConfigFiles(targetDir) {
136
- const languages = [];
137
- const buildTools = [];
138
- const monorepoTools = [];
139
-
140
- // TypeScript
141
- if (pathExists(targetDir, 'tsconfig.json') || pathExists(targetDir, 'tsconfig.base.json')) {
142
- languages.push('TypeScript');
143
- }
144
-
145
- // Python
146
- if (pathExists(targetDir, 'pyproject.toml') || pathExists(targetDir, 'setup.py') || pathExists(targetDir, 'requirements.txt')) {
147
- languages.push('Python');
148
- }
149
-
150
- // Go
151
- if (pathExists(targetDir, 'go.mod')) {
152
- languages.push('Go');
153
- }
154
-
155
- // Rust
156
- if (pathExists(targetDir, 'Cargo.toml')) {
157
- languages.push('Rust');
158
- }
159
-
160
- // Build tools
161
- if (pathExists(targetDir, 'vite.config.js') || pathExists(targetDir, 'vite.config.ts')) {
162
- buildTools.push('Vite');
163
- }
164
- if (pathExists(targetDir, 'webpack.config.js') || pathExists(targetDir, 'webpack.config.ts')) {
165
- buildTools.push('Webpack');
166
- }
167
- if (pathExists(targetDir, 'rollup.config.js') || pathExists(targetDir, 'rollup.config.mjs')) {
168
- buildTools.push('Rollup');
169
- }
170
-
171
- // Monorepo
172
- if (pathExists(targetDir, 'turbo.json')) monorepoTools.push('Turborepo');
173
- if (pathExists(targetDir, 'lerna.json')) monorepoTools.push('Lerna');
174
- if (pathExists(targetDir, 'nx.json')) monorepoTools.push('Nx');
175
- if (pathExists(targetDir, 'pnpm-workspace.yaml')) monorepoTools.push('pnpm workspaces');
176
-
177
- // Package manager detection
178
- let packageManager = 'npm'; // default
179
- if (pathExists(targetDir, 'bun.lockb') || pathExists(targetDir, 'bun.lock')) {
180
- packageManager = 'bun';
181
- } else if (pathExists(targetDir, 'pnpm-lock.yaml')) {
182
- packageManager = 'pnpm';
183
- } else if (pathExists(targetDir, 'yarn.lock')) {
184
- packageManager = 'yarn';
185
- }
186
-
187
- return { languages, buildTools, monorepoTools, packageManager };
188
- }
189
-
190
- /**
191
- * Detects technologies from file patterns in the project directory.
192
- *
193
- * @param {string} targetDir
194
- * @returns {Partial<FrameworkReport>}
195
- */
196
- export function detectByFilePatterns(targetDir) {
197
- const languages = [];
198
-
199
- // Check top-level files and src/ for language clues
200
- const dirsToCheck = [targetDir];
201
- if (pathExists(targetDir, 'src')) dirsToCheck.push(join(targetDir, 'src'));
202
-
203
- const extensions = new Set();
204
- for (const dir of dirsToCheck) {
205
- let entries;
206
- try {
207
- entries = readdirSync(dir);
208
- } catch {
209
- continue;
210
- }
211
- for (const entry of entries) {
212
- try {
213
- const stat = statSync(join(dir, entry));
214
- if (stat.isFile()) {
215
- const ext = entry.slice(entry.lastIndexOf('.'));
216
- extensions.add(ext);
217
- }
218
- } catch {
219
- // skip
220
- }
221
- }
222
- }
223
-
224
- if (extensions.has('.ts') || extensions.has('.tsx')) {
225
- languages.push('TypeScript');
226
- }
227
- if (extensions.has('.js') || extensions.has('.jsx') || extensions.has('.mjs')) {
228
- languages.push('JavaScript');
229
- }
230
- if (extensions.has('.py')) {
231
- languages.push('Python');
232
- }
233
- if (extensions.has('.go')) {
234
- languages.push('Go');
235
- }
236
- if (extensions.has('.rs')) {
237
- languages.push('Rust');
238
- }
239
-
240
- return { languages };
241
- }
242
-
243
- /**
244
- * Merges multiple partial detection reports, deduplicating arrays.
245
- *
246
- * @param {...Partial<FrameworkReport>} reports
247
- * @returns {FrameworkReport}
248
- */
249
- export function mergeDetections(...reports) {
250
- const merged = {
251
- frontendFrameworks: [],
252
- backendFrameworks: [],
253
- languages: [],
254
- packageManager: 'npm',
255
- monorepoTools: [],
256
- orms: [],
257
- databases: [],
258
- testingFrameworks: [],
259
- buildTools: [],
260
- raw: {},
261
- };
262
-
263
- const arrayFields = [
264
- 'frontendFrameworks',
265
- 'backendFrameworks',
266
- 'languages',
267
- 'monorepoTools',
268
- 'orms',
269
- 'databases',
270
- 'testingFrameworks',
271
- 'buildTools',
272
- ];
273
-
274
- for (const report of reports) {
275
- if (!report) continue;
276
- for (const field of arrayFields) {
277
- if (Array.isArray(report[field])) {
278
- for (const item of report[field]) {
279
- if (!merged[field].includes(item)) {
280
- merged[field].push(item);
281
- }
282
- }
283
- }
284
- }
285
- if (report.packageManager) {
286
- merged.packageManager = report.packageManager;
287
- }
288
- }
289
-
290
- // Store raw detections for debugging
291
- merged.raw = { reports: reports.filter(Boolean) };
292
-
293
- return merged;
294
- }
295
-
296
- /**
297
- * Full framework analysis for a target directory.
298
- *
299
- * @param {string} targetDir
300
- * @returns {FrameworkReport}
301
- */
302
- export function analyzeFramework(targetDir) {
303
- const byPackage = detectByPackageJson(targetDir);
304
- const byConfig = detectByConfigFiles(targetDir);
305
- const byFiles = detectByFilePatterns(targetDir);
306
-
307
- return mergeDetections(byPackage, byConfig, byFiles);
308
- }