@eduardbar/drift 1.4.0 → 1.5.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 (66) hide show
  1. package/.github/actions/drift-review/README.md +4 -2
  2. package/.github/actions/drift-review/action.yml +22 -5
  3. package/.github/actions/drift-scan/README.md +3 -3
  4. package/.github/actions/drift-scan/action.yml +1 -1
  5. package/.github/workflows/publish-vscode.yml +1 -3
  6. package/.github/workflows/publish.yml +8 -0
  7. package/.github/workflows/quality.yml +15 -0
  8. package/.github/workflows/reusable-quality-checks.yml +95 -0
  9. package/.github/workflows/review-pr.yml +0 -1
  10. package/AGENTS.md +2 -2
  11. package/CHANGELOG.md +14 -1
  12. package/README.md +30 -3
  13. package/benchmarks/fixtures/critical/drift.config.ts +21 -0
  14. package/benchmarks/fixtures/critical/src/app/user-service.ts +30 -0
  15. package/benchmarks/fixtures/critical/src/domain/entities.ts +19 -0
  16. package/benchmarks/fixtures/critical/src/domain/policies.ts +22 -0
  17. package/benchmarks/fixtures/critical/src/index.ts +10 -0
  18. package/benchmarks/fixtures/critical/src/infra/memory-user-repo.ts +14 -0
  19. package/benchmarks/perf-budget.v1.json +27 -0
  20. package/dist/benchmark.js +12 -0
  21. package/dist/cli.js +2 -2
  22. package/dist/doctor.d.ts +21 -0
  23. package/dist/doctor.js +10 -3
  24. package/dist/guard-baseline.d.ts +12 -0
  25. package/dist/guard-baseline.js +57 -0
  26. package/dist/guard-metrics.d.ts +6 -0
  27. package/dist/guard-metrics.js +39 -0
  28. package/dist/guard-types.d.ts +2 -1
  29. package/dist/guard.d.ts +3 -1
  30. package/dist/guard.js +9 -70
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.js +1 -1
  33. package/dist/init.js +1 -1
  34. package/dist/output-metadata.d.ts +2 -0
  35. package/dist/output-metadata.js +2 -0
  36. package/dist/trust.d.ts +2 -1
  37. package/dist/trust.js +1 -1
  38. package/dist/types.d.ts +1 -1
  39. package/docs/AGENTS.md +1 -1
  40. package/package.json +10 -4
  41. package/schemas/drift-doctor.v1.json +57 -0
  42. package/schemas/drift-guard.v1.json +298 -0
  43. package/scripts/check-docs-drift.mjs +154 -0
  44. package/scripts/check-performance-budget.mjs +360 -0
  45. package/scripts/check-runtime-policy.mjs +66 -0
  46. package/src/benchmark.ts +17 -0
  47. package/src/cli.ts +2 -2
  48. package/src/doctor.ts +15 -3
  49. package/src/guard-baseline.ts +74 -0
  50. package/src/guard-metrics.ts +52 -0
  51. package/src/guard-types.ts +3 -1
  52. package/src/guard.ts +14 -90
  53. package/src/index.ts +1 -0
  54. package/src/init.ts +1 -1
  55. package/src/output-metadata.ts +2 -0
  56. package/src/trust.ts +1 -1
  57. package/src/types.ts +1 -0
  58. package/tests/ci-quality-matrix.test.ts +37 -0
  59. package/tests/ci-smoke-gate.test.ts +26 -0
  60. package/tests/ci-version-alignment.test.ts +93 -0
  61. package/tests/docs-drift-check.test.ts +115 -0
  62. package/tests/new-features.test.ts +2 -2
  63. package/tests/perf-budget-check.test.ts +146 -0
  64. package/tests/phase1-init-doctor-guard.test.ts +104 -2
  65. package/tests/runtime-policy-alignment.test.ts +46 -0
  66. package/vitest.config.ts +2 -0
package/dist/doctor.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { existsSync, readdirSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import kleur from 'kleur';
4
+ import { OUTPUT_SCHEMA, withOutputMetadata } from './output-metadata.js';
4
5
  const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx']);
5
6
  const IGNORED_DIRECTORIES = new Set(['node_modules', '.git', 'dist', '.next', 'coverage']);
6
7
  const DECIMAL_RADIX = 10;
7
- const MIN_SUPPORTED_NODE_MAJOR = 18;
8
+ const MIN_SUPPORTED_NODE_MAJOR = 20;
8
9
  const LOW_MEMORY_SOURCE_FILE_THRESHOLD = 500;
9
10
  const DRIFT_CONFIG_CANDIDATES = [
10
11
  'drift.config.ts',
@@ -92,7 +93,7 @@ function printConsoleReport(report) {
92
93
  process.stdout.write(`${kleur.bold().white('drift doctor')} ${kleur.gray('- environment diagnostics')}\n\n`);
93
94
  const nodeStatus = report.node.supported
94
95
  ? `${icons.check} ${kleur.green('Node runtime supported')}`
95
- : `${icons.warn} ${kleur.yellow('Node runtime below recommended minimum (>=18)')}`;
96
+ : `${icons.warn} ${kleur.yellow('Node runtime below supported minimum (>=20)')}`;
96
97
  process.stdout.write(`${nodeStatus} ${kleur.gray(`(${report.node.version})`)}\n`);
97
98
  if (report.project.packageJsonFound) {
98
99
  process.stdout.write(`${icons.check} package.json found\n`);
@@ -120,10 +121,16 @@ function printConsoleReport(report) {
120
121
  }
121
122
  process.stdout.write('\n');
122
123
  }
124
+ export function formatDoctorJsonObject(report) {
125
+ return withOutputMetadata(report, OUTPUT_SCHEMA.doctor);
126
+ }
127
+ export function formatDoctorJson(report) {
128
+ return JSON.stringify(formatDoctorJsonObject(report), null, 2);
129
+ }
123
130
  export async function runDoctor(projectPath, options) {
124
131
  const report = buildDoctorReport(projectPath);
125
132
  if (options?.json) {
126
- process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
133
+ process.stdout.write(`${formatDoctorJson(report)}\n`);
127
134
  }
128
135
  else {
129
136
  printConsoleReport(report);
@@ -0,0 +1,12 @@
1
+ import type { GuardBaseline, IssueSeverity } from './guard-types.js';
2
+ export interface NormalizedBaseline {
3
+ score?: number;
4
+ totalIssues?: number;
5
+ bySeverity: Partial<Record<IssueSeverity, number>>;
6
+ }
7
+ export declare function normalizeBaseline(baseline: GuardBaseline): NormalizedBaseline;
8
+ export declare function readBaselineFromFile(projectPath: string, baselinePath?: string): {
9
+ baseline: NormalizedBaseline;
10
+ path: string;
11
+ } | undefined;
12
+ //# sourceMappingURL=guard-baseline.d.ts.map
@@ -0,0 +1,57 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ function parseNumber(value) {
4
+ return typeof value === 'number' && !Number.isNaN(value) ? value : undefined;
5
+ }
6
+ function firstDefinedNumber(values) {
7
+ for (const value of values) {
8
+ const parsed = parseNumber(value);
9
+ if (parsed !== undefined) {
10
+ return parsed;
11
+ }
12
+ }
13
+ return undefined;
14
+ }
15
+ function normalizeSeverity(baseline, severity) {
16
+ const summaryBySeverity = baseline.summary?.[`${severity}s`];
17
+ return firstDefinedNumber([
18
+ baseline.bySeverity?.[severity],
19
+ severity === 'error' ? baseline.errors : undefined,
20
+ severity === 'warning' ? baseline.warnings : undefined,
21
+ severity === 'info' ? baseline.infos : undefined,
22
+ summaryBySeverity,
23
+ ]);
24
+ }
25
+ function hasAnchor(baseline) {
26
+ if (baseline.score !== undefined || baseline.totalIssues !== undefined) {
27
+ return true;
28
+ }
29
+ const severities = ['error', 'warning', 'info'];
30
+ return severities.some((severity) => baseline.bySeverity[severity] !== undefined);
31
+ }
32
+ export function normalizeBaseline(baseline) {
33
+ const normalized = {
34
+ score: parseNumber(baseline.score),
35
+ totalIssues: parseNumber(baseline.totalIssues),
36
+ bySeverity: {
37
+ error: normalizeSeverity(baseline, 'error'),
38
+ warning: normalizeSeverity(baseline, 'warning'),
39
+ info: normalizeSeverity(baseline, 'info'),
40
+ },
41
+ };
42
+ if (!hasAnchor(normalized)) {
43
+ throw new Error('Invalid guard baseline: expected score, totalIssues, or severity counters (error/warning/info).');
44
+ }
45
+ return normalized;
46
+ }
47
+ export function readBaselineFromFile(projectPath, baselinePath) {
48
+ const resolvedBaselinePath = resolve(projectPath, baselinePath ?? 'drift-baseline.json');
49
+ if (!existsSync(resolvedBaselinePath))
50
+ return undefined;
51
+ const raw = JSON.parse(readFileSync(resolvedBaselinePath, 'utf8'));
52
+ return {
53
+ baseline: normalizeBaseline(raw),
54
+ path: resolvedBaselinePath,
55
+ };
56
+ }
57
+ //# sourceMappingURL=guard-baseline.js.map
@@ -0,0 +1,6 @@
1
+ import type { DriftDiff, DriftReport } from './types.js';
2
+ import type { GuardMetrics } from './guard-types.js';
3
+ import type { NormalizedBaseline } from './guard-baseline.js';
4
+ export declare function buildMetricsFromDiff(diff: DriftDiff): GuardMetrics;
5
+ export declare function buildMetricsFromBaseline(current: DriftReport, baseline: NormalizedBaseline): GuardMetrics;
6
+ //# sourceMappingURL=guard-metrics.d.ts.map
@@ -0,0 +1,39 @@
1
+ function createSeverityDelta() {
2
+ return {
3
+ error: 0,
4
+ warning: 0,
5
+ info: 0,
6
+ };
7
+ }
8
+ function applySeverityDelta(delta, issues, direction) {
9
+ for (const issue of issues) {
10
+ delta[issue.severity] += direction;
11
+ }
12
+ }
13
+ function countSeverityDeltaFromDiff(diff) {
14
+ const severityDelta = createSeverityDelta();
15
+ for (const file of diff.files) {
16
+ applySeverityDelta(severityDelta, file.newIssues, 1);
17
+ applySeverityDelta(severityDelta, file.resolvedIssues, -1);
18
+ }
19
+ return severityDelta;
20
+ }
21
+ export function buildMetricsFromDiff(diff) {
22
+ return {
23
+ scoreDelta: diff.totalDelta,
24
+ totalIssuesDelta: diff.newIssuesCount - diff.resolvedIssuesCount,
25
+ severityDelta: countSeverityDeltaFromDiff(diff),
26
+ };
27
+ }
28
+ export function buildMetricsFromBaseline(current, baseline) {
29
+ return {
30
+ scoreDelta: current.totalScore - (baseline.score ?? current.totalScore),
31
+ totalIssuesDelta: current.totalIssues - (baseline.totalIssues ?? current.totalIssues),
32
+ severityDelta: {
33
+ error: current.summary.errors - (baseline.bySeverity.error ?? current.summary.errors),
34
+ warning: current.summary.warnings - (baseline.bySeverity.warning ?? current.summary.warnings),
35
+ info: current.summary.infos - (baseline.bySeverity.info ?? current.summary.infos),
36
+ },
37
+ };
38
+ }
39
+ //# sourceMappingURL=guard-metrics.js.map
@@ -1,4 +1,4 @@
1
- import type { DriftAnalysisOptions, DriftDiff, DriftIssue, DriftReport } from './types.js';
1
+ import type { DriftAnalysisOptions, DriftDiff, DriftIssue, DriftOutputMetadata, DriftReport } from './types.js';
2
2
  export type IssueSeverity = DriftIssue['severity'];
3
3
  export interface GuardBaseline {
4
4
  score?: number;
@@ -54,4 +54,5 @@ export interface GuardResult {
54
54
  current: DriftReport;
55
55
  diff?: DriftDiff;
56
56
  }
57
+ export type GuardResultJson = GuardResult & DriftOutputMetadata;
57
58
  //# sourceMappingURL=guard-types.d.ts.map
package/dist/guard.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { GuardEvaluation, GuardMetrics, GuardOptions, GuardResult, GuardThresholds } from './guard-types.js';
1
+ import type { GuardEvaluation, GuardMetrics, GuardOptions, GuardResult, GuardResultJson, GuardThresholds } from './guard-types.js';
2
2
  interface GuardEvalInput {
3
3
  metrics: GuardMetrics;
4
4
  budget?: number;
@@ -9,6 +9,8 @@ interface GuardEvalInput {
9
9
  };
10
10
  }
11
11
  export declare function evaluateGuard(input: GuardEvalInput): GuardEvaluation;
12
+ export declare function formatGuardJsonObject(result: GuardResult): GuardResultJson;
13
+ export declare function formatGuardJson(result: GuardResult): string;
12
14
  export declare function runGuard(targetPath: string, options?: GuardOptions): Promise<GuardResult>;
13
15
  export {};
14
16
  //# sourceMappingURL=guard.d.ts.map
package/dist/guard.js CHANGED
@@ -1,45 +1,12 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
1
  import { relative, resolve } from 'node:path';
3
2
  import { analyzeProject } from './analyzer.js';
4
3
  import { loadConfig } from './config.js';
5
4
  import { computeDiff } from './diff.js';
6
5
  import { cleanupTempDir, extractFilesAtRef } from './git.js';
6
+ import { normalizeBaseline, readBaselineFromFile } from './guard-baseline.js';
7
+ import { buildMetricsFromBaseline, buildMetricsFromDiff } from './guard-metrics.js';
8
+ import { OUTPUT_SCHEMA, withOutputMetadata } from './output-metadata.js';
7
9
  import { buildReport } from './reporter.js';
8
- function parseNumber(value) {
9
- return typeof value === 'number' && !Number.isNaN(value) ? value : undefined;
10
- }
11
- function normalizeBaseline(baseline) {
12
- const bySeverityFromRoot = baseline.bySeverity;
13
- const bySeverity = {
14
- error: parseNumber(bySeverityFromRoot?.error) ?? parseNumber(baseline.errors) ?? parseNumber(baseline.summary?.errors),
15
- warning: parseNumber(bySeverityFromRoot?.warning) ?? parseNumber(baseline.warnings) ?? parseNumber(baseline.summary?.warnings),
16
- info: parseNumber(bySeverityFromRoot?.info) ?? parseNumber(baseline.infos) ?? parseNumber(baseline.summary?.infos),
17
- };
18
- const normalized = {
19
- score: parseNumber(baseline.score),
20
- totalIssues: parseNumber(baseline.totalIssues),
21
- bySeverity,
22
- };
23
- const hasAnyAnchor = normalized.score !== undefined ||
24
- normalized.totalIssues !== undefined ||
25
- normalized.bySeverity.error !== undefined ||
26
- normalized.bySeverity.warning !== undefined ||
27
- normalized.bySeverity.info !== undefined;
28
- if (!hasAnyAnchor) {
29
- throw new Error('Invalid guard baseline: expected score, totalIssues, or severity counters (error/warning/info).');
30
- }
31
- return normalized;
32
- }
33
- function readBaselineFromFile(projectPath, baselinePath) {
34
- const resolvedBaselinePath = resolve(projectPath, baselinePath ?? 'drift-baseline.json');
35
- if (!existsSync(resolvedBaselinePath))
36
- return undefined;
37
- const raw = JSON.parse(readFileSync(resolvedBaselinePath, 'utf8'));
38
- return {
39
- baseline: normalizeBaseline(raw),
40
- path: resolvedBaselinePath,
41
- };
42
- }
43
10
  function remapBaseReportPaths(baseReport, tempDir, projectPath) {
44
11
  return {
45
12
  ...baseReport,
@@ -49,40 +16,6 @@ function remapBaseReportPaths(baseReport, tempDir, projectPath) {
49
16
  })),
50
17
  };
51
18
  }
52
- function countSeverityDeltaFromDiff(diff) {
53
- const severityDelta = {
54
- error: 0,
55
- warning: 0,
56
- info: 0,
57
- };
58
- for (const file of diff.files) {
59
- for (const issue of file.newIssues) {
60
- severityDelta[issue.severity] += 1;
61
- }
62
- for (const issue of file.resolvedIssues) {
63
- severityDelta[issue.severity] -= 1;
64
- }
65
- }
66
- return severityDelta;
67
- }
68
- function buildMetricsFromDiff(diff) {
69
- return {
70
- scoreDelta: diff.totalDelta,
71
- totalIssuesDelta: diff.newIssuesCount - diff.resolvedIssuesCount,
72
- severityDelta: countSeverityDeltaFromDiff(diff),
73
- };
74
- }
75
- function buildMetricsFromBaseline(current, baseline) {
76
- return {
77
- scoreDelta: current.totalScore - (baseline.score ?? current.totalScore),
78
- totalIssuesDelta: current.totalIssues - (baseline.totalIssues ?? current.totalIssues),
79
- severityDelta: {
80
- error: current.summary.errors - (baseline.bySeverity.error ?? current.summary.errors),
81
- warning: current.summary.warnings - (baseline.bySeverity.warning ?? current.summary.warnings),
82
- info: current.summary.infos - (baseline.bySeverity.info ?? current.summary.infos),
83
- },
84
- };
85
- }
86
19
  function addCheck(checks, input) {
87
20
  checks.push({
88
21
  id: input.id,
@@ -138,6 +71,12 @@ export function evaluateGuard(input) {
138
71
  checks,
139
72
  };
140
73
  }
74
+ export function formatGuardJsonObject(result) {
75
+ return withOutputMetadata(result, OUTPUT_SCHEMA.guard);
76
+ }
77
+ export function formatGuardJson(result) {
78
+ return JSON.stringify(formatGuardJsonObject(result), null, 2);
79
+ }
141
80
  export async function runGuard(targetPath, options = {}) {
142
81
  const runtimeState = await initializeGuardRuntime(targetPath, options);
143
82
  const { projectPath, config, currentReport } = runtimeState;
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export type { GuardBaseline, GuardThresholds, GuardOptions, GuardMetrics, GuardC
6
6
  export { generateReview, formatReviewMarkdown } from './review.js';
7
7
  export { runDoctor } from './doctor.js';
8
8
  export type { DoctorOptions } from './doctor.js';
9
- export { buildTrustReport, formatTrustConsole, formatTrustMarkdown, formatTrustJson, resolveTrustGatePolicy, evaluateTrustGate, shouldFailByMaxRisk, shouldFailTrustGate, normalizeMergeRiskLevel, MERGE_RISK_ORDER, } from './trust.js';
9
+ export { buildTrustReport, formatTrustConsole, formatTrustMarkdown, formatTrustJsonObject, formatTrustJson, resolveTrustGatePolicy, evaluateTrustGate, shouldFailByMaxRisk, shouldFailTrustGate, normalizeMergeRiskLevel, MERGE_RISK_ORDER, } from './trust.js';
10
10
  export type { TrustGateOptions, TrustGatePolicyResolutionOptions, TrustGatePolicyResolutionStep, TrustGateEvaluation, } from './trust.js';
11
11
  export { computeTrustKpis, computeTrustKpisFromReports, formatTrustKpiConsole, formatTrustKpiJson, } from './trust-kpi.js';
12
12
  export { toSarif, diffToSarif } from './sarif.js';
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ export { computeDiff } from './diff.js';
4
4
  export { runGuard, evaluateGuard } from './guard.js';
5
5
  export { generateReview, formatReviewMarkdown } from './review.js';
6
6
  export { runDoctor } from './doctor.js';
7
- export { buildTrustReport, formatTrustConsole, formatTrustMarkdown, formatTrustJson, resolveTrustGatePolicy, evaluateTrustGate, shouldFailByMaxRisk, shouldFailTrustGate, normalizeMergeRiskLevel, MERGE_RISK_ORDER, } from './trust.js';
7
+ export { buildTrustReport, formatTrustConsole, formatTrustMarkdown, formatTrustJsonObject, formatTrustJson, resolveTrustGatePolicy, evaluateTrustGate, shouldFailByMaxRisk, shouldFailTrustGate, normalizeMergeRiskLevel, MERGE_RISK_ORDER, } from './trust.js';
8
8
  export { computeTrustKpis, computeTrustKpisFromReports, formatTrustKpiConsole, formatTrustKpiJson, } from './trust-kpi.js';
9
9
  export { toSarif, diffToSarif } from './sarif.js';
10
10
  export { generateArchitectureMap, generateArchitectureSvg } from './map.js';
package/dist/init.js CHANGED
@@ -130,7 +130,7 @@ jobs:
130
130
 
131
131
  - uses: actions/setup-node@v4
132
132
  with:
133
- node-version: 18
133
+ node-version: 20
134
134
 
135
135
  - name: Install drift
136
136
  run: npm install -g @eduardbar/drift
@@ -2,6 +2,8 @@ export declare const OUTPUT_SCHEMA: {
2
2
  readonly report: "schemas/drift-report.v1.json";
3
3
  readonly trust: "schemas/drift-trust.v1.json";
4
4
  readonly ai: "schemas/drift-ai-output.v1.json";
5
+ readonly doctor: "schemas/drift-doctor.v1.json";
6
+ readonly guard: "schemas/drift-guard.v1.json";
5
7
  };
6
8
  type OutputMetadata = {
7
9
  $schema: string;
@@ -6,6 +6,8 @@ export const OUTPUT_SCHEMA = {
6
6
  report: 'schemas/drift-report.v1.json',
7
7
  trust: 'schemas/drift-trust.v1.json',
8
8
  ai: 'schemas/drift-ai-output.v1.json',
9
+ doctor: 'schemas/drift-doctor.v1.json',
10
+ guard: 'schemas/drift-guard.v1.json',
9
11
  };
10
12
  export function withOutputMetadata(payload, schema) {
11
13
  return {
package/dist/trust.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DriftDiff, DriftReport, DriftTrustReport, MergeRiskLevel } from './types.js';
1
+ import type { DriftDiff, DriftReport, DriftTrustReport, DriftTrustReportJson, MergeRiskLevel } from './types.js';
2
2
  import type { SnapshotEntry } from './snapshot.js';
3
3
  import type { TrustGateOptions } from './trust-policy.js';
4
4
  export { MERGE_RISK_ORDER, detectBranchName, explainTrustGatePolicy, formatTrustGatePolicyExplanation, normalizeMergeRiskLevel, resolveTrustGatePolicy, } from './trust-policy.js';
@@ -29,6 +29,7 @@ export interface TrustGateEvaluation {
29
29
  export declare function buildTrustReport(report: DriftReport, options?: BuildTrustOptions): DriftTrustReport;
30
30
  export declare function formatTrustConsole(trust: DriftTrustReport): string;
31
31
  export declare function formatTrustMarkdown(trust: DriftTrustReport): string;
32
+ export declare function formatTrustJsonObject(trust: DriftTrustReport): DriftTrustReportJson;
32
33
  export declare function formatTrustJson(trust: DriftTrustReport): string;
33
34
  export declare function renderTrustOutput(trust: DriftTrustReport, options?: TrustRenderOptions): string;
34
35
  export declare function shouldFailByMaxRisk(actual: MergeRiskLevel, allowedMaxRisk: MergeRiskLevel): boolean;
package/dist/trust.js CHANGED
@@ -109,7 +109,7 @@ export function formatTrustMarkdown(trust) {
109
109
  }
110
110
  return sections.join('\n');
111
111
  }
112
- function formatTrustJsonObject(trust) {
112
+ export function formatTrustJsonObject(trust) {
113
113
  return withOutputMetadata(trust, OUTPUT_SCHEMA.trust);
114
114
  }
115
115
  export function formatTrustJson(trust) {
package/dist/types.d.ts CHANGED
@@ -4,6 +4,6 @@ export type { LayerDefinition, ModuleBoundary, DriftPerformanceConfig, DriftAnal
4
4
  export type { DriftConfig } from './types/app.js';
5
5
  export type { PluginRuleContext, DriftPluginRule, DriftPlugin, LoadedPlugin, PluginLoadError, PluginLoadWarning, } from './types/plugin.js';
6
6
  export type { FileDiff, DriftDiff, HistoricalAnalysis, TrendDataPoint, BlameAttribution, DriftTrendReport, DriftBlameReport, } from './types/diff.js';
7
- export type { GuardBaseline, GuardThresholds, GuardOptions, GuardMetrics, GuardCheck, GuardEvaluation, GuardResult, } from './guard-types.js';
7
+ export type { GuardBaseline, GuardThresholds, GuardOptions, GuardMetrics, GuardCheck, GuardEvaluation, GuardResult, GuardResultJson, } from './guard-types.js';
8
8
  export type { SarifLevel, DriftSarifRule, DriftSarifResult, DriftSarifRun, DriftSarifLog, } from './sarif.js';
9
9
  //# sourceMappingURL=types.d.ts.map
package/docs/AGENTS.md CHANGED
@@ -10,7 +10,7 @@ Esta guia define como colaborar en `drift` para mantener calidad tecnica, consis
10
10
 
11
11
  ### Stack real
12
12
 
13
- - Runtime: Node.js 18+
13
+ - Runtime: Node.js 20.x and 22.x (LTS)
14
14
  - Lenguaje: TypeScript (`type: module`)
15
15
  - Analisis AST: `ts-morph`
16
16
  - CLI: `commander`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eduardbar/drift",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "AI Code Audit CLI for merge trust in AI-assisted PRs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,7 +16,10 @@
16
16
  "test:watch": "vitest",
17
17
  "test:coverage": "vitest run --coverage",
18
18
  "benchmark": "node --import tsx src/benchmark.ts",
19
- "smoke:repo": "node ./scripts/smoke-repo.mjs"
19
+ "smoke:repo": "node ./scripts/smoke-repo.mjs",
20
+ "check:runtime-policy": "node ./scripts/check-runtime-policy.mjs",
21
+ "check:docs-drift": "node ./scripts/check-docs-drift.mjs",
22
+ "check:perf-budget": "node ./scripts/check-performance-budget.mjs"
20
23
  },
21
24
  "keywords": [
22
25
  "vibe-coding",
@@ -28,6 +31,9 @@
28
31
  ],
29
32
  "author": "eduardbar",
30
33
  "license": "MIT",
34
+ "engines": {
35
+ "node": "^20.0.0 || ^22.0.0"
36
+ },
31
37
  "homepage": "https://github.com/eduardbar/drift#readme",
32
38
  "repository": {
33
39
  "type": "git",
@@ -43,9 +49,9 @@
43
49
  },
44
50
  "devDependencies": {
45
51
  "@types/node": "^25.3.0",
46
- "@vitest/coverage-v8": "^4.0.18",
52
+ "@vitest/coverage-v8": "^4.1.2",
47
53
  "tsx": "^4.21.0",
48
54
  "typescript": "^5.9.3",
49
- "vitest": "^4.0.18"
55
+ "vitest": "^4.1.2"
50
56
  }
51
57
  }
@@ -0,0 +1,57 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "schemas/drift-doctor.v1.json",
4
+ "title": "drift doctor v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "$schema",
9
+ "toolVersion",
10
+ "targetPath",
11
+ "node",
12
+ "project"
13
+ ],
14
+ "properties": {
15
+ "$schema": {
16
+ "const": "schemas/drift-doctor.v1.json"
17
+ },
18
+ "toolVersion": {
19
+ "type": "string"
20
+ },
21
+ "targetPath": {
22
+ "type": "string"
23
+ },
24
+ "node": {
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": ["version", "major", "supported"],
28
+ "properties": {
29
+ "version": { "type": "string" },
30
+ "major": { "type": "number" },
31
+ "supported": { "type": "boolean" }
32
+ }
33
+ },
34
+ "project": {
35
+ "type": "object",
36
+ "additionalProperties": false,
37
+ "required": [
38
+ "packageJsonFound",
39
+ "esm",
40
+ "tsconfigFound",
41
+ "sourceFilesCount",
42
+ "lowMemorySuggested",
43
+ "driftConfigFile"
44
+ ],
45
+ "properties": {
46
+ "packageJsonFound": { "type": "boolean" },
47
+ "esm": { "type": "boolean" },
48
+ "tsconfigFound": { "type": "boolean" },
49
+ "sourceFilesCount": { "type": "number" },
50
+ "lowMemorySuggested": { "type": "boolean" },
51
+ "driftConfigFile": {
52
+ "type": ["string", "null"]
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }