@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.
- package/.github/actions/drift-scan/README.md +61 -0
- package/.github/actions/drift-scan/action.yml +65 -0
- package/.github/workflows/publish-vscode.yml +3 -1
- package/AGENTS.md +53 -11
- package/README.md +68 -1
- package/dist/analyzer.d.ts +6 -2
- package/dist/analyzer.js +116 -3
- package/dist/badge.js +40 -22
- package/dist/ci.js +32 -18
- package/dist/cli.js +83 -5
- package/dist/diff.d.ts +0 -7
- package/dist/diff.js +26 -25
- package/dist/fix.d.ts +4 -0
- package/dist/fix.js +59 -47
- package/dist/git/trend.js +1 -0
- package/dist/git.d.ts +0 -9
- package/dist/git.js +25 -19
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -0
- package/dist/map.d.ts +3 -0
- package/dist/map.js +103 -0
- package/dist/metrics.d.ts +4 -0
- package/dist/metrics.js +176 -0
- package/dist/plugins.d.ts +6 -0
- package/dist/plugins.js +74 -0
- package/dist/printer.js +20 -0
- package/dist/report.js +34 -0
- package/dist/reporter.js +85 -2
- package/dist/review.d.ts +15 -0
- package/dist/review.js +80 -0
- package/dist/rules/comments.d.ts +4 -0
- package/dist/rules/comments.js +45 -0
- package/dist/rules/complexity.d.ts +4 -0
- package/dist/rules/complexity.js +51 -0
- package/dist/rules/coupling.d.ts +4 -0
- package/dist/rules/coupling.js +19 -0
- package/dist/rules/magic.d.ts +4 -0
- package/dist/rules/magic.js +33 -0
- package/dist/rules/nesting.d.ts +5 -0
- package/dist/rules/nesting.js +82 -0
- package/dist/rules/phase0-basic.js +14 -7
- package/dist/rules/phase1-complexity.d.ts +6 -30
- package/dist/rules/phase1-complexity.js +7 -276
- package/dist/rules/phase2-crossfile.d.ts +0 -4
- package/dist/rules/phase2-crossfile.js +52 -39
- package/dist/rules/phase3-arch.d.ts +0 -8
- package/dist/rules/phase3-arch.js +26 -23
- package/dist/rules/phase3-configurable.d.ts +6 -0
- package/dist/rules/phase3-configurable.js +97 -0
- package/dist/rules/phase8-semantic.d.ts +0 -5
- package/dist/rules/phase8-semantic.js +30 -29
- package/dist/rules/promise.d.ts +4 -0
- package/dist/rules/promise.js +24 -0
- package/dist/snapshot.d.ts +19 -0
- package/dist/snapshot.js +119 -0
- package/dist/types.d.ts +69 -0
- package/dist/utils.d.ts +2 -1
- package/dist/utils.js +1 -0
- package/docs/AGENTS.md +146 -0
- package/docs/PRD.md +208 -0
- package/package.json +1 -1
- package/packages/eslint-plugin-drift/src/index.ts +1 -1
- package/packages/vscode-drift/package.json +1 -1
- package/packages/vscode-drift/src/analyzer.ts +2 -0
- package/packages/vscode-drift/src/extension.ts +87 -63
- package/packages/vscode-drift/src/statusbar.ts +13 -5
- package/packages/vscode-drift/src/treeview.ts +2 -0
- package/src/analyzer.ts +144 -12
- package/src/badge.ts +38 -16
- package/src/ci.ts +38 -17
- package/src/cli.ts +96 -6
- package/src/diff.ts +36 -30
- package/src/fix.ts +77 -53
- package/src/git/trend.ts +3 -2
- package/src/git.ts +31 -22
- package/src/index.ts +16 -1
- package/src/map.ts +117 -0
- package/src/metrics.ts +200 -0
- package/src/plugins.ts +76 -0
- package/src/printer.ts +20 -0
- package/src/report.ts +35 -0
- package/src/reporter.ts +95 -2
- package/src/review.ts +98 -0
- package/src/rules/comments.ts +56 -0
- package/src/rules/complexity.ts +57 -0
- package/src/rules/coupling.ts +23 -0
- package/src/rules/magic.ts +38 -0
- package/src/rules/nesting.ts +88 -0
- package/src/rules/phase0-basic.ts +14 -7
- package/src/rules/phase1-complexity.ts +8 -302
- package/src/rules/phase2-crossfile.ts +68 -40
- package/src/rules/phase3-arch.ts +34 -30
- package/src/rules/phase3-configurable.ts +132 -0
- package/src/rules/phase8-semantic.ts +33 -29
- package/src/rules/promise.ts +29 -0
- package/src/snapshot.ts +175 -0
- package/src/types.ts +75 -1
- package/src/utils.ts +3 -1
- 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
|
-
|
|
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
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,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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
})
|
|
102
|
+
const scanCmd = vscode.commands.registerCommand(
|
|
103
|
+
'drift.scanWorkspace',
|
|
104
|
+
() => scanWorkspace(diagnostics, treeProvider, reportCache, statusBar)
|
|
105
|
+
)
|
|
78
106
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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) => {
|