@eduardbar/drift 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/.github/actions/drift-scan/README.md +61 -0
  2. package/.github/actions/drift-scan/action.yml +65 -0
  3. package/.github/workflows/publish-vscode.yml +3 -1
  4. package/AGENTS.md +53 -11
  5. package/README.md +68 -1
  6. package/dist/analyzer.d.ts +6 -2
  7. package/dist/analyzer.js +116 -3
  8. package/dist/badge.js +40 -22
  9. package/dist/ci.js +32 -18
  10. package/dist/cli.js +83 -5
  11. package/dist/diff.d.ts +0 -7
  12. package/dist/diff.js +26 -25
  13. package/dist/fix.d.ts +4 -0
  14. package/dist/fix.js +59 -47
  15. package/dist/git/trend.js +1 -0
  16. package/dist/git.d.ts +0 -9
  17. package/dist/git.js +25 -19
  18. package/dist/index.d.ts +5 -1
  19. package/dist/index.js +3 -0
  20. package/dist/map.d.ts +3 -0
  21. package/dist/map.js +103 -0
  22. package/dist/metrics.d.ts +4 -0
  23. package/dist/metrics.js +176 -0
  24. package/dist/plugins.d.ts +6 -0
  25. package/dist/plugins.js +74 -0
  26. package/dist/printer.js +20 -0
  27. package/dist/report.js +34 -0
  28. package/dist/reporter.js +85 -2
  29. package/dist/review.d.ts +15 -0
  30. package/dist/review.js +80 -0
  31. package/dist/rules/comments.d.ts +4 -0
  32. package/dist/rules/comments.js +45 -0
  33. package/dist/rules/complexity.d.ts +4 -0
  34. package/dist/rules/complexity.js +51 -0
  35. package/dist/rules/coupling.d.ts +4 -0
  36. package/dist/rules/coupling.js +19 -0
  37. package/dist/rules/magic.d.ts +4 -0
  38. package/dist/rules/magic.js +33 -0
  39. package/dist/rules/nesting.d.ts +5 -0
  40. package/dist/rules/nesting.js +82 -0
  41. package/dist/rules/phase0-basic.js +14 -7
  42. package/dist/rules/phase1-complexity.d.ts +6 -30
  43. package/dist/rules/phase1-complexity.js +7 -276
  44. package/dist/rules/phase2-crossfile.d.ts +0 -4
  45. package/dist/rules/phase2-crossfile.js +52 -39
  46. package/dist/rules/phase3-arch.d.ts +0 -8
  47. package/dist/rules/phase3-arch.js +26 -23
  48. package/dist/rules/phase3-configurable.d.ts +6 -0
  49. package/dist/rules/phase3-configurable.js +97 -0
  50. package/dist/rules/phase8-semantic.d.ts +0 -5
  51. package/dist/rules/phase8-semantic.js +30 -29
  52. package/dist/rules/promise.d.ts +4 -0
  53. package/dist/rules/promise.js +24 -0
  54. package/dist/snapshot.d.ts +19 -0
  55. package/dist/snapshot.js +119 -0
  56. package/dist/types.d.ts +69 -0
  57. package/dist/utils.d.ts +2 -1
  58. package/dist/utils.js +1 -0
  59. package/docs/AGENTS.md +146 -0
  60. package/docs/PRD.md +208 -0
  61. package/package.json +1 -1
  62. package/packages/eslint-plugin-drift/src/index.ts +1 -1
  63. package/packages/vscode-drift/package.json +1 -1
  64. package/packages/vscode-drift/src/analyzer.ts +2 -0
  65. package/packages/vscode-drift/src/extension.ts +87 -63
  66. package/packages/vscode-drift/src/statusbar.ts +13 -5
  67. package/packages/vscode-drift/src/treeview.ts +2 -0
  68. package/src/analyzer.ts +144 -12
  69. package/src/badge.ts +38 -16
  70. package/src/ci.ts +38 -17
  71. package/src/cli.ts +96 -6
  72. package/src/diff.ts +36 -30
  73. package/src/fix.ts +77 -53
  74. package/src/git/trend.ts +3 -2
  75. package/src/git.ts +31 -22
  76. package/src/index.ts +16 -1
  77. package/src/map.ts +117 -0
  78. package/src/metrics.ts +200 -0
  79. package/src/plugins.ts +76 -0
  80. package/src/printer.ts +20 -0
  81. package/src/report.ts +35 -0
  82. package/src/reporter.ts +95 -2
  83. package/src/review.ts +98 -0
  84. package/src/rules/comments.ts +56 -0
  85. package/src/rules/complexity.ts +57 -0
  86. package/src/rules/coupling.ts +23 -0
  87. package/src/rules/magic.ts +38 -0
  88. package/src/rules/nesting.ts +88 -0
  89. package/src/rules/phase0-basic.ts +14 -7
  90. package/src/rules/phase1-complexity.ts +8 -302
  91. package/src/rules/phase2-crossfile.ts +68 -40
  92. package/src/rules/phase3-arch.ts +34 -30
  93. package/src/rules/phase3-configurable.ts +132 -0
  94. package/src/rules/phase8-semantic.ts +33 -29
  95. package/src/rules/promise.ts +29 -0
  96. package/src/snapshot.ts +175 -0
  97. package/src/types.ts +75 -1
  98. package/src/utils.ts +3 -1
  99. package/tests/new-features.test.ts +153 -0
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { SourceFile } from 'ts-morph';
1
2
  export interface DriftIssue {
2
3
  rule: string;
3
4
  severity: 'error' | 'warning' | 'info';
@@ -24,6 +25,36 @@ export interface DriftReport {
24
25
  infos: number;
25
26
  byRule: Record<string, number>;
26
27
  };
28
+ quality: RepoQualityScore;
29
+ maintenanceRisk: MaintenanceRiskMetrics;
30
+ }
31
+ export interface RepoQualityScore {
32
+ overall: number;
33
+ dimensions: {
34
+ architecture: number;
35
+ complexity: number;
36
+ 'ai-patterns': number;
37
+ testing: number;
38
+ };
39
+ }
40
+ export interface RiskHotspot {
41
+ file: string;
42
+ driftScore: number;
43
+ complexityIssues: number;
44
+ hasNearbyTests: boolean;
45
+ changeFrequency: number;
46
+ risk: number;
47
+ reasons: string[];
48
+ }
49
+ export interface MaintenanceRiskMetrics {
50
+ score: number;
51
+ level: 'low' | 'medium' | 'high' | 'critical';
52
+ hotspots: RiskHotspot[];
53
+ signals: {
54
+ highComplexityFiles: number;
55
+ filesWithoutNearbyTests: number;
56
+ frequentChangeFiles: number;
57
+ };
27
58
  }
28
59
  export interface AIOutput {
29
60
  summary: {
@@ -32,8 +63,17 @@ export interface AIOutput {
32
63
  total_issues: number;
33
64
  files_affected: number;
34
65
  files_clean: number;
66
+ ai_likelihood: number;
67
+ ai_code_smell_score: number;
35
68
  };
69
+ files_suspected: Array<{
70
+ path: string;
71
+ ai_likelihood: number;
72
+ triggers: string[];
73
+ }>;
36
74
  priority_order: AIIssue[];
75
+ maintenance_risk: MaintenanceRiskMetrics;
76
+ quality: RepoQualityScore;
37
77
  context_for_ai: {
38
78
  project_type: string;
39
79
  scan_path: string;
@@ -75,6 +115,35 @@ export interface ModuleBoundary {
75
115
  export interface DriftConfig {
76
116
  layers?: LayerDefinition[];
77
117
  modules?: ModuleBoundary[];
118
+ plugins?: string[];
119
+ architectureRules?: {
120
+ controllerNoDb?: boolean;
121
+ serviceNoHttp?: boolean;
122
+ maxFunctionLines?: number;
123
+ };
124
+ }
125
+ export interface PluginRuleContext {
126
+ projectRoot: string;
127
+ filePath: string;
128
+ config?: DriftConfig;
129
+ }
130
+ export interface DriftPluginRule {
131
+ name: string;
132
+ severity?: DriftIssue['severity'];
133
+ weight?: number;
134
+ detect: (file: SourceFile, context: PluginRuleContext) => DriftIssue[];
135
+ }
136
+ export interface DriftPlugin {
137
+ name: string;
138
+ rules: DriftPluginRule[];
139
+ }
140
+ export interface LoadedPlugin {
141
+ id: string;
142
+ plugin: DriftPlugin;
143
+ }
144
+ export interface PluginLoadError {
145
+ pluginId: string;
146
+ message: string;
78
147
  }
79
148
  export interface FileDiff {
80
149
  path: string;
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { DriftIssue } from './types.js';
2
- export interface Grade {
2
+ interface Grade {
3
3
  badge: string;
4
4
  label: string;
5
5
  }
@@ -7,4 +7,5 @@ export declare function scoreToGrade(score: number): Grade;
7
7
  export declare function scoreToGradeText(score: number): Grade;
8
8
  export declare function severityIcon(s: DriftIssue['severity']): string;
9
9
  export declare function scoreBar(score: number, width?: number): string;
10
+ export {};
10
11
  //# sourceMappingURL=utils.d.ts.map
package/dist/utils.js CHANGED
@@ -1,3 +1,4 @@
1
+ // drift-ignore-file
1
2
  import kleur from 'kleur';
2
3
  export function scoreToGrade(score) {
3
4
  if (score === 0)
package/docs/AGENTS.md ADDED
@@ -0,0 +1,146 @@
1
+ # AGENTS - Guia Operativa para drift
2
+
3
+ ## 1) Proposito
4
+
5
+ Esta guia define como colaborar en `drift` para mantener calidad tecnica, consistencia de arquitectura y foco en producto.
6
+
7
+ `drift` existe para detectar deuda tecnica asociada a codigo IA en proyectos TypeScript y convertir esa senial en acciones concretas.
8
+
9
+ ## 2) Stack y estructura principal
10
+
11
+ ### Stack real
12
+
13
+ - Runtime: Node.js 18+
14
+ - Lenguaje: TypeScript (`type: module`)
15
+ - Analisis AST: `ts-morph`
16
+ - CLI: `commander`
17
+ - Output en consola: `kleur`
18
+ - Testing: `vitest`
19
+
20
+ ### Estructura clave
21
+
22
+ - `src/analyzer.ts`: motor principal de reglas y score
23
+ - `src/rules/*`: reglas por fases y helpers de deteccion
24
+ - `src/reporter.ts`: armado de reporte y salidas para markdown/AI
25
+ - `src/printer.ts`: salida CLI y sugerencias de fix
26
+ - `src/cli.ts`: entrypoint y subcomandos
27
+ - `src/fix.ts`, `src/report.ts`, `src/ci.ts`, `src/diff.ts`: comandos operativos
28
+ - `packages/eslint-plugin-drift`: plugin ESLint
29
+ - `packages/vscode-drift`: extension VSCode
30
+
31
+ ## 3) Comandos de desarrollo
32
+
33
+ Usar los comandos del repo (fuente: `package.json`):
34
+
35
+ ```bash
36
+ npm run build
37
+ npm run dev
38
+ npm start
39
+ npm test
40
+ npm run test:watch
41
+ npm run test:coverage
42
+ ```
43
+
44
+ Comandos de uso de producto (referencia):
45
+
46
+ ```bash
47
+ npx @eduardbar/drift scan ./src
48
+ npx @eduardbar/drift scan ./src --ai
49
+ npx @eduardbar/drift scan ./src --min-score 60
50
+ ```
51
+
52
+ ## 4) Reglas de contribucion
53
+
54
+ - Mantener cambios pequenos, enfocados y trazables.
55
+ - No editar `dist/` manualmente.
56
+ - No introducir `any` sin justificacion tecnica fuerte.
57
+ - Reusar utilidades existentes (`utils.ts`) antes de duplicar logica.
58
+ - Si agregas una regla nueva, actualizar:
59
+ - peso en `RULE_WEIGHTS`
60
+ - deteccion AST
61
+ - sugerencia de fix
62
+ - documentacion (README/AGENTS/PRD segun aplique)
63
+
64
+ ## 5) Convencion de commits
65
+
66
+ Se usa Conventional Commits.
67
+
68
+ Formato:
69
+
70
+ ```text
71
+ type(scope): descripcion corta
72
+ ```
73
+
74
+ Tipos recomendados:
75
+
76
+ - `feat`: nueva capacidad de producto
77
+ - `fix`: correccion de bug
78
+ - `refactor`: cambio interno sin impacto funcional
79
+ - `test`: mejoras o nuevos tests
80
+ - `docs`: documentacion
81
+ - `chore`: mantenimiento
82
+
83
+ Ejemplos:
84
+
85
+ - `feat(review): add PR score and markdown output`
86
+ - `fix(analyzer): prevent false positive in dead-file rule`
87
+ - `docs(prd): define v1.2 architecture roadmap`
88
+
89
+ ## 6) Flujo para proponer e implementar features del PRD
90
+
91
+ ### Paso 1 - Definir alcance MVP
92
+
93
+ - Explicar objetivo de negocio y usuario.
94
+ - Delimitar que entra y que queda fuera.
95
+ - Agregar criterios de aceptacion verificables.
96
+
97
+ ### Paso 2 - Disenar impacto tecnico
98
+
99
+ - Identificar comandos, modulos y reglas afectados.
100
+ - Definir formato de salida (CLI/JSON/AI).
101
+ - Evaluar costo de performance en repos grandes.
102
+
103
+ ### Paso 3 - Implementar por incrementos
104
+
105
+ - Primero contrato de tipos y salida.
106
+ - Luego deteccion/reglas/comandos.
107
+ - Finalmente UX de consola y documentacion.
108
+
109
+ ### Paso 4 - Validar
110
+
111
+ - Tests unitarios de logica nueva.
112
+ - Tests de integracion de CLI cuando aplique.
113
+ - Verificacion manual de casos reales.
114
+
115
+ ## 7) Criterios minimos de calidad y testing
116
+
117
+ Antes de merge, cada cambio debe cumplir:
118
+
119
+ - Tests pasando (`npm test`).
120
+ - Cobertura razonable en paths nuevos (`npm run test:coverage` cuando aplique).
121
+ - Sin regresiones en salida JSON/AI (contratos estables).
122
+ - Errores y mensajes de CLI claros y accionables.
123
+ - Performance aceptable para el alcance del cambio.
124
+
125
+ ## 8) Seguridad y manejo de informacion
126
+
127
+ - Nunca commitear secretos (`.env`, tokens, credenciales, llaves).
128
+ - No incluir datos sensibles en fixtures ni snapshots.
129
+ - Si una feature requiere integracion externa, usar variables de entorno y documentar setup sin exponer valores.
130
+ - Mantener principio de minimo privilegio en scripts y flujos CI.
131
+
132
+ ## 9) Criterios de aceptacion para features nuevas
133
+
134
+ Una feature se considera lista cuando:
135
+
136
+ - Resuelve un objetivo explicitado en `docs/PRD.md`.
137
+ - Tiene MVP funcional y criterios de aceptacion cumplidos.
138
+ - Incluye tests y documentacion operativa.
139
+ - Es compatible con flujo CLI existente y CI.
140
+
141
+ ## 10) Practicas recomendadas para agentes/colaboradores
142
+
143
+ - Priorizar cambios que mejoren senial sobre ruido.
144
+ - Favorecer reportes accionables por sobre analisis abstracto.
145
+ - Evitar humo en roadmap: cada entrega debe mapear a comando, salida y test.
146
+ - Dejar decisiones registradas en la documentacion del repo.
package/docs/PRD.md ADDED
@@ -0,0 +1,208 @@
1
+ # PRD - drift
2
+
3
+ Version: 1.1-draft
4
+ Estado: Draft
5
+ Producto: `@eduardbar/drift`
6
+
7
+ ## 1) Contexto
8
+
9
+ `drift` es un CLI de analisis estatico para TypeScript que detecta deuda tecnica asociada a codigo generado por IA y calcula un score de calidad por archivo y por repositorio.
10
+
11
+ Hoy el producto ya cubre escaneo AST, score, reportes y comandos operativos (`scan`, `fix`, `report`, `ci`, `diff`, `badge`, `snapshot`, `trend`, `blame`).
12
+
13
+ Este PRD define la evolucion para convertir a drift en una plataforma de calidad de codigo AI-first, con foco en revision de PRs, reglas de arquitectura y accionabilidad.
14
+
15
+ ## 2) Vision de Producto
16
+
17
+ Ser la herramienta de referencia para equipos que usan IA para programar y necesitan detectar, priorizar y corregir deuda tecnica antes de que llegue a produccion.
18
+
19
+ ## 3) Killer Feature
20
+
21
+ ## AI Code Smell Detector
22
+
23
+ El diferencial principal de drift es detectar patrones de olor tecnico vinculados a codigo IA, estimar probabilidad de origen IA y traducir hallazgos en acciones concretas (fixes, comentarios de PR, reglas de arquitectura y reportes).
24
+
25
+ ## 4) Objetivos de Negocio y Producto
26
+
27
+ - Reducir riesgo de mantenimiento en repos con alto volumen de codigo IA.
28
+ - Dar feedback accionable en el punto de trabajo (CLI, PR y editor).
29
+ - Estandarizar calidad arquitectonica con reglas configurables por equipo.
30
+ - Escalar desde CLI local a experiencia organizacional (dashboard SaaS).
31
+
32
+ ## 5) Alcance MVP por Feature (sin humo)
33
+
34
+ Cada feature incluye objetivo, alcance MVP y criterios de aceptacion.
35
+
36
+ ### 5.1 Detector de codigo generado por IA
37
+
38
+ - Objetivo: estimar `ai_likelihood` por archivo y listar `files_suspected`.
39
+ - Alcance MVP:
40
+ - Exponer `ai_likelihood` (0-100) dentro de salida JSON/AI.
41
+ - Agregar lista ordenada de archivos sospechados con score y reglas disparadas.
42
+ - No hacer afirmaciones absolutas; reportar como probabilidad.
43
+ - Criterios de aceptacion:
44
+ - `drift scan <path> --ai` incluye `ai_likelihood` por archivo.
45
+ - Reporte global incluye `files_suspected` y top N archivos.
46
+ - Tests cubren serializacion y orden de prioridad.
47
+
48
+ ### 5.2 PR reviewer automatico (`drift review` + comentario en PR)
49
+
50
+ - Objetivo: revisar cambios de PR y publicar feedback tecnico automatico.
51
+ - Alcance MVP:
52
+ - Nuevo comando `drift review` para analizar diff contra base branch.
53
+ - Salida markdown apta para comentario de PR.
54
+ - Integracion base via GitHub CLI (`gh`) en CI.
55
+ - Criterios de aceptacion:
56
+ - `drift review --base main` devuelve score de PR y top issues.
57
+ - En workflow CI se publica un comentario unico actualizable.
58
+ - Si score supera umbral configurable, CI falla.
59
+
60
+ ### 5.3 Reglas de arquitectura configurables
61
+
62
+ - Objetivo: habilitar reglas de arquitectura de negocio definidas por el equipo.
63
+ - Alcance MVP:
64
+ - Soporte en `drift.config.ts` para:
65
+ - `controller-no-db`
66
+ - `service-no-http`
67
+ - `max-function-lines`
68
+ - Mensajes de error claros con ubicacion y recomendacion.
69
+ - Criterios de aceptacion:
70
+ - Config valida y tipada.
71
+ - Reglas activas afectan score y aparecen en reporte.
72
+ - Fixtures de test para casos validos e invalidos.
73
+
74
+ ### 5.4 Score de calidad por repo con breakdown
75
+
76
+ - Objetivo: mostrar salud del repo en forma ejecutiva y tecnica.
77
+ - Alcance MVP:
78
+ - Score global del repo.
79
+ - Breakdown por severidad, regla y carpeta.
80
+ - Tendencia minima (ultimos snapshots locales).
81
+ - Criterios de aceptacion:
82
+ - `drift scan` muestra score repo + breakdown resumido.
83
+ - `--json` expone estructura consumible por CI/dashboard.
84
+
85
+ ### 5.5 Mapa de arquitectura automatico (`drift map` -> `architecture.svg`)
86
+
87
+ - Objetivo: visualizar dependencias y violaciones de capas.
88
+ - Alcance MVP:
89
+ - Nuevo comando `drift map`.
90
+ - Genera `architecture.svg` desde imports y modulos detectados.
91
+ - Marca ciclos y violaciones de capas.
92
+ - Criterios de aceptacion:
93
+ - `drift map ./src` crea `architecture.svg` sin edicion manual.
94
+ - El SVG es legible en repos medianos (ej. <= 300 archivos TS).
95
+
96
+ ### 5.6 VSCode extension con feedback en tiempo real
97
+
98
+ - Objetivo: bajar el tiempo entre error y correccion.
99
+ - Alcance MVP:
100
+ - Diagnosticos por archivo al guardar.
101
+ - Score visible por archivo.
102
+ - Quick actions para sugerencias simples.
103
+ - Criterios de aceptacion:
104
+ - La extension muestra issues drift en panel Problems.
105
+ - La latencia por archivo en save se mantiene en nivel usable.
106
+
107
+ ### 5.7 Fix automatico (`drift fix`) con ejemplo antes/despues
108
+
109
+ - Objetivo: convertir hallazgos en cambios concretos de bajo riesgo.
110
+ - Alcance MVP:
111
+ - `drift fix` aplica fixes seguros en reglas seleccionadas.
112
+ - Modo preview con diff antes/despues.
113
+ - Modo write con confirmacion.
114
+ - Criterios de aceptacion:
115
+ - `drift fix --preview` imprime diff legible.
116
+ - `drift fix --write` modifica solo reglas soportadas.
117
+ - Tests de no-regresion para no romper sintaxis TS.
118
+
119
+ Ejemplo (antes/despues):
120
+
121
+ ```ts
122
+ // Antes
123
+ console.log(userData)
124
+
125
+ // Despues (sugerencia simple)
126
+ // Removed debug leftover; use structured logger if needed.
127
+ ```
128
+
129
+ ### 5.8 Reporte tecnico (`drift report` -> `drift-report.html`)
130
+
131
+ - Objetivo: entregar reporte compartible para devs, tech leads y QA.
132
+ - Alcance MVP:
133
+ - Salida HTML `drift-report.html` con score, breakdown y top issues.
134
+ - Secciones por archivo con snippets y sugerencias.
135
+ - Criterios de aceptacion:
136
+ - `drift report ./src --html` genera archivo navegable.
137
+ - El reporte puede adjuntarse en CI artifacts.
138
+
139
+ ### 5.9 Metricas de riesgo de mantenimiento (hotspots)
140
+
141
+ - Objetivo: priorizar deuda por impacto real.
142
+ - Alcance MVP:
143
+ - Hotspots combinando score + frecuencia de cambios + criticidad.
144
+ - Ranking de archivos para plan de refactor.
145
+ - Criterios de aceptacion:
146
+ - `drift trend` o salida dedicada muestra top hotspots.
147
+ - Metodo de ranking documentado y testeado.
148
+
149
+ ### 5.10 Plugin system (`drift-plugin-*`)
150
+
151
+ - Objetivo: extender drift sin tocar el core.
152
+ - Alcance MVP:
153
+ - Carga de plugins por convension `drift-plugin-*`.
154
+ - API minima para registrar reglas y metadata.
155
+ - Aislamiento de errores de plugins para no romper scan completo.
156
+ - Criterios de aceptacion:
157
+ - Plugin de ejemplo funcional en repo de ejemplo.
158
+ - Si un plugin falla, drift sigue ejecutando y reporta el error.
159
+
160
+ ## 6) Roadmap Realista
161
+
162
+ ### v1.1
163
+
164
+ - `drift review` para PR comments.
165
+ - Score de PR y score de repo con breakdown minimo.
166
+
167
+ ### v1.2
168
+
169
+ - Reglas de arquitectura configurables.
170
+ - `drift map` y generacion de `architecture.svg`.
171
+
172
+ ### v2
173
+
174
+ - VSCode extension con feedback en tiempo real.
175
+ - `drift fix` con preview/write y fixes seguros.
176
+
177
+ ### v3
178
+
179
+ - SaaS dashboard para historico, equipos y gobierno de calidad.
180
+
181
+ ## 7) Fuera de Alcance (por ahora)
182
+
183
+ - Soporte multi-lenguaje completo fuera de TypeScript/JS.
184
+ - Autofix de reglas de alto riesgo sin confirmacion.
185
+ - Integraciones propietarias cerradas sin API estable.
186
+
187
+ ## 8) KPIs de Exito
188
+
189
+ - Reduccion de score promedio en repos activos.
190
+ - % de PRs con feedback drift resuelto antes de merge.
191
+ - Tiempo medio desde deteccion hasta fix aplicado.
192
+ - Adopcion de reglas de arquitectura por equipo.
193
+
194
+ ## 9) Dependencias y Riesgos
195
+
196
+ - Performance en repos grandes (AST + analisis cross-file).
197
+ - Calidad de senial en `ai_likelihood` (riesgo de falsos positivos).
198
+ - Compatibilidad de integraciones CI/PR entre plataformas.
199
+ - Diseno de API de plugins sin romper backward compatibility.
200
+
201
+ ## 10) Definicion de Done (global)
202
+
203
+ Una feature del roadmap se considera terminada cuando:
204
+
205
+ - Tiene comando/flujo usable y documentado.
206
+ - Tiene tests automatizados de casos base y borde.
207
+ - Tiene salida estable en CLI/JSON para CI.
208
+ - Tiene criterios de aceptacion de esta PRD cumplidos.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eduardbar/drift",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Detect silent technical debt left by AI-generated code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -103,7 +103,7 @@ function createRule(ruleName: string): Rule.RuleModule {
103
103
  data: { message: issue.message },
104
104
  })
105
105
  }
106
- } catch {
106
+ } catch { // drift-ignore
107
107
  // Archivo no parseable por ts-morph — silenciar
108
108
  }
109
109
  },
@@ -113,7 +113,7 @@
113
113
  "typescript": "^5.3.0"
114
114
  },
115
115
  "dependencies": {
116
- "@eduardbar/drift": "*",
116
+ "@eduardbar/drift": "1.0.0",
117
117
  "ts-morph": "^23.0.0"
118
118
  }
119
119
  }
@@ -1,3 +1,5 @@
1
+ // drift-ignore-file
2
+
1
3
  import { Project } from 'ts-morph'
2
4
  import type { FileReport } from '@eduardbar/drift'
3
5
 
@@ -1,3 +1,5 @@
1
+ // drift-ignore-file
2
+
1
3
  import * as vscode from 'vscode'
2
4
  import { analyzeFilePath } from './analyzer'
3
5
  import { DriftDiagnosticsProvider } from './diagnostics'
@@ -7,84 +9,106 @@ import type { FileReport } from '@eduardbar/drift'
7
9
 
8
10
  const SUPPORTED_LANGUAGES = ['typescript', 'typescriptreact', 'javascript', 'javascriptreact']
9
11
 
12
+ async function analyzeAndUpdate(
13
+ document: vscode.TextDocument,
14
+ diagnostics: DriftDiagnosticsProvider,
15
+ treeProvider: DriftTreeProvider,
16
+ reportCache: Map<string, FileReport>,
17
+ statusBar: DriftStatusBarItem
18
+ ): Promise<void> {
19
+ const config = vscode.workspace.getConfiguration('drift')
20
+ if (!config.get<boolean>('enable', true)) return
21
+
22
+ if (!SUPPORTED_LANGUAGES.includes(document.languageId)) return
23
+ if (document.uri.scheme !== 'file') return
24
+
25
+ const filePath = document.uri.fsPath
26
+
27
+ const report = await analyzeFilePath(filePath)
28
+ if (!report) return
29
+
30
+ diagnostics.update(report)
31
+ treeProvider.updateFile(report)
32
+ reportCache.set(filePath, report)
33
+ statusBar.update(Array.from(reportCache.values()))
34
+ }
35
+
36
+ async function scanWorkspace(
37
+ diagnostics: DriftDiagnosticsProvider,
38
+ treeProvider: DriftTreeProvider,
39
+ reportCache: Map<string, FileReport>,
40
+ statusBar: DriftStatusBarItem
41
+ ): Promise<void> {
42
+ const files = await vscode.workspace.findFiles(
43
+ '**/*.{ts,tsx,js,jsx}',
44
+ '**/node_modules/**'
45
+ )
46
+
47
+ vscode.window.withProgress(
48
+ {
49
+ location: vscode.ProgressLocation.Notification,
50
+ title: 'drift: Scanning workspace...',
51
+ cancellable: false,
52
+ },
53
+ async (progress) => {
54
+ const total = files.length
55
+ let done = 0
56
+
57
+ for (const file of files) {
58
+ const report = await analyzeFilePath(file.fsPath)
59
+ if (report) {
60
+ diagnostics.update(report)
61
+ treeProvider.updateFile(report)
62
+ reportCache.set(file.fsPath, report)
63
+ }
64
+ done++
65
+ progress.report({ increment: (done / total) * 100 })
66
+ }
67
+
68
+ statusBar.update(Array.from(reportCache.values()))
69
+ vscode.window.showInformationMessage(`drift: ${total} files scanned.`)
70
+ }
71
+ )
72
+ }
73
+
74
+ function clearDiagnostics(
75
+ diagnostics: DriftDiagnosticsProvider,
76
+ treeProvider: DriftTreeProvider,
77
+ reportCache: Map<string, FileReport>,
78
+ statusBar: DriftStatusBarItem
79
+ ): void {
80
+ diagnostics.clear()
81
+ treeProvider.clearAll()
82
+ reportCache.clear()
83
+ statusBar.update([])
84
+ }
85
+
10
86
  export function activate(context: vscode.ExtensionContext): void {
11
87
  const diagnostics = new DriftDiagnosticsProvider()
12
88
  const treeProvider = new DriftTreeProvider()
13
89
  const statusBar = new DriftStatusBarItem()
14
90
 
15
- // Registrar TreeView
16
91
  const treeView = vscode.window.createTreeView('driftIssues', {
17
92
  treeDataProvider: treeProvider,
18
93
  showCollapseAll: true,
19
94
  })
20
95
 
21
- // Cache de reports para la status bar
22
96
  const reportCache = new Map<string, FileReport>()
23
97
 
24
- async function analyzeAndUpdate(document: vscode.TextDocument): Promise<void> {
25
- const config = vscode.workspace.getConfiguration('drift')
26
- if (!config.get<boolean>('enable', true)) return
27
-
28
- if (!SUPPORTED_LANGUAGES.includes(document.languageId)) return
29
- if (document.uri.scheme !== 'file') return
30
-
31
- const filePath = document.uri.fsPath
32
-
33
- const report = await analyzeFilePath(filePath)
34
- if (!report) return
35
-
36
- diagnostics.update(report)
37
- treeProvider.updateFile(report)
38
- reportCache.set(filePath, report)
39
- statusBar.update(Array.from(reportCache.values()))
40
- }
41
-
42
- // Trigger: al guardar
43
- const onSave = vscode.workspace.onDidSaveTextDocument(analyzeAndUpdate)
44
-
45
- // Comando: scan workspace
46
- const scanCmd = vscode.commands.registerCommand('drift.scanWorkspace', async () => {
47
- const files = await vscode.workspace.findFiles(
48
- '**/*.{ts,tsx,js,jsx}',
49
- '**/node_modules/**'
50
- )
51
-
52
- vscode.window.withProgress(
53
- {
54
- location: vscode.ProgressLocation.Notification,
55
- title: 'drift: Scanning workspace...',
56
- cancellable: false,
57
- },
58
- async (progress) => {
59
- const total = files.length
60
- let done = 0
61
-
62
- for (const file of files) {
63
- const report = await analyzeFilePath(file.fsPath)
64
- if (report) {
65
- diagnostics.update(report)
66
- treeProvider.updateFile(report)
67
- reportCache.set(file.fsPath, report)
68
- }
69
- done++
70
- progress.report({ increment: (done / total) * 100 })
71
- }
98
+ const onSave = vscode.workspace.onDidSaveTextDocument(
99
+ (doc) => analyzeAndUpdate(doc, diagnostics, treeProvider, reportCache, statusBar)
100
+ )
72
101
 
73
- statusBar.update(Array.from(reportCache.values()))
74
- vscode.window.showInformationMessage(`drift: ${total} files scanned.`)
75
- }
76
- )
77
- })
102
+ const scanCmd = vscode.commands.registerCommand(
103
+ 'drift.scanWorkspace',
104
+ () => scanWorkspace(diagnostics, treeProvider, reportCache, statusBar)
105
+ )
78
106
 
79
- // Comando: clear
80
- const clearCmd = vscode.commands.registerCommand('drift.clearDiagnostics', () => {
81
- diagnostics.clear()
82
- treeProvider.clearAll()
83
- reportCache.clear()
84
- statusBar.update([])
85
- })
107
+ const clearCmd = vscode.commands.registerCommand(
108
+ 'drift.clearDiagnostics',
109
+ () => clearDiagnostics(diagnostics, treeProvider, reportCache, statusBar)
110
+ )
86
111
 
87
- // Comando: go to issue (desde TreeView click)
88
112
  const goToCmd = vscode.commands.registerCommand(
89
113
  'drift.goToIssue',
90
114
  async (filePath: string, line: number) => {