@aiready/deps 0.11.15 → 0.11.17

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.
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @aiready/deps@0.11.14 build /Users/pengcao/projects/aiready/packages/deps
3
+ > @aiready/deps@0.11.16 build /Users/pengcao/projects/aiready/packages/deps
4
4
  > tsup src/index.ts src/cli.ts --format cjs,esm --dts
5
5
 
6
6
  CLI Building entry: src/cli.ts, src/index.ts
@@ -9,15 +9,15 @@
9
9
  CLI Target: es2020
10
10
  CJS Build start
11
11
  ESM Build start
12
- CJS dist/index.js 5.53 KB
13
- CJS dist/cli.js 5.87 KB
14
- CJS ⚡️ Build success in 181ms
15
- ESM dist/index.mjs 1.64 KB
16
12
  ESM dist/cli.mjs 1.33 KB
17
- ESM dist/chunk-4D7DCOHZ.mjs 3.18 KB
18
- ESM ⚡️ Build success in 182ms
13
+ ESM dist/index.mjs 1.64 KB
14
+ ESM dist/chunk-CFNCY65I.mjs 5.78 KB
15
+ ESM ⚡️ Build success in 43ms
16
+ CJS dist/cli.js 8.44 KB
17
+ CJS dist/index.js 8.09 KB
18
+ CJS ⚡️ Build success in 43ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 1403ms
20
+ DTS ⚡️ Build success in 2438ms
21
21
  DTS dist/cli.d.ts 108.00 B
22
22
  DTS dist/index.d.ts 971.00 B
23
23
  DTS dist/cli.d.mts 108.00 B
@@ -1,16 +1,16 @@
1
1
 
2
2
  
3
- > @aiready/deps@0.11.14 test /Users/pengcao/projects/aiready/packages/deps
3
+ > @aiready/deps@0.11.16 test /Users/pengcao/projects/aiready/packages/deps
4
4
  > vitest run
5
5
 
6
6
  [?25l
7
7
   RUN  v4.0.18 /Users/pengcao/projects/aiready/packages/deps
8
8
 
9
- ✓ src/__tests__/analyzer.test.ts (1 test) 2ms
9
+ ✓ src/__tests__/analyzer.test.ts (1 test) 3ms
10
10
 
11
11
   Test Files  1 passed (1)
12
12
   Tests  1 passed (1)
13
-  Start at  00:19:45
14
-  Duration  1.44s (transform 261ms, setup 0ms, import 1.13s, tests 2ms, environment 0ms)
13
+  Start at  12:45:56
14
+  Duration  407ms (transform 74ms, setup 0ms, import 264ms, tests 3ms, environment 0ms)
15
15
 
16
16
  [?25h
package/README.md CHANGED
@@ -7,7 +7,13 @@
7
7
 
8
8
  ## Overview
9
9
 
10
- The **Dependency Health** analyzer evaluates your `package.json` to compute timeline skews against AI knowledge cutoff dates.
10
+ The **Dependency Health** analyzer evaluates your project manifests to compute timeline skews against AI knowledge cutoff dates.
11
+
12
+ ### Language Support
13
+
14
+ - **Supported Manifests:** `package.json` (JS/TS), `requirements.txt` (Python), `pom.xml` (Java), `go.mod` (Go)
15
+ - **Capabilities:** Deprecated detection, training-cutoff skew, version drift.
16
+ toxicology
11
17
 
12
18
  ## 🏛️ Architecture
13
19
 
@@ -0,0 +1,179 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/analyzer.ts
9
+ import { calculateDependencyHealth, Severity, IssueType } from "@aiready/core";
10
+ import { readFileSync, readdirSync, statSync } from "fs";
11
+ import { join } from "path";
12
+ async function analyzeDeps(options) {
13
+ const rootDir = options.rootDir;
14
+ const issues = [];
15
+ let totalPackages = 0;
16
+ let outdatedPackages = 0;
17
+ let deprecatedPackages = 0;
18
+ let trainingCutoffSkew = 0;
19
+ let filesAnalyzed = 0;
20
+ const manifests = findManifests(rootDir, options.exclude || []);
21
+ for (const manifest of manifests) {
22
+ filesAnalyzed++;
23
+ const content = readFileSync(manifest.path, "utf-8");
24
+ const type = manifest.type;
25
+ let deps = [];
26
+ if (type === "npm") {
27
+ deps = analyzeNpm(manifest.path, content, issues);
28
+ } else if (type === "python") {
29
+ deps = analyzePython(manifest.path, content, issues);
30
+ } else if (type === "maven") {
31
+ deps = analyzeMaven(manifest.path, content, issues);
32
+ } else if (type === "go") {
33
+ deps = analyzeGo(manifest.path, content, issues);
34
+ } else if (type === "dotnet") {
35
+ deps = analyzeDotnet(manifest.path, content, issues);
36
+ }
37
+ totalPackages += deps.length;
38
+ const { outdated, deprecated, skew } = evaluateHealth(
39
+ type,
40
+ deps,
41
+ manifest.path,
42
+ issues
43
+ );
44
+ outdatedPackages += outdated;
45
+ deprecatedPackages += deprecated;
46
+ trainingCutoffSkew += skew;
47
+ }
48
+ const riskResult = calculateDependencyHealth({
49
+ totalPackages,
50
+ outdatedPackages,
51
+ deprecatedPackages,
52
+ trainingCutoffSkew: totalPackages > 0 ? trainingCutoffSkew / manifests.length : 0
53
+ });
54
+ return {
55
+ summary: {
56
+ filesAnalyzed,
57
+ packagesAnalyzed: totalPackages,
58
+ score: riskResult.score,
59
+ rating: riskResult.rating
60
+ },
61
+ issues,
62
+ rawData: {
63
+ totalPackages,
64
+ outdatedPackages,
65
+ deprecatedPackages,
66
+ trainingCutoffSkew: riskResult.dimensions.trainingCutoffSkew
67
+ },
68
+ recommendations: riskResult.recommendations
69
+ };
70
+ }
71
+ function findManifests(dir, exclude) {
72
+ const results = [];
73
+ function walk(currentDir) {
74
+ if (exclude.some((pattern) => currentDir.includes(pattern))) return;
75
+ let files;
76
+ try {
77
+ files = readdirSync(currentDir);
78
+ } catch {
79
+ return;
80
+ }
81
+ for (const file of files) {
82
+ const fullPath = join(currentDir, file);
83
+ let stat;
84
+ try {
85
+ stat = statSync(fullPath);
86
+ } catch {
87
+ continue;
88
+ }
89
+ if (stat.isDirectory()) {
90
+ if (file !== "node_modules" && file !== ".git" && file !== "venv") {
91
+ walk(fullPath);
92
+ }
93
+ } else {
94
+ if (file === "package.json")
95
+ results.push({ path: fullPath, type: "npm" });
96
+ else if (file === "requirements.txt" || file === "Pipfile" || file === "pyproject.toml")
97
+ results.push({ path: fullPath, type: "python" });
98
+ else if (file === "pom.xml")
99
+ results.push({ path: fullPath, type: "maven" });
100
+ else if (file === "go.mod")
101
+ results.push({ path: fullPath, type: "go" });
102
+ else if (file.endsWith(".csproj"))
103
+ results.push({ path: fullPath, type: "dotnet" });
104
+ }
105
+ }
106
+ }
107
+ walk(dir);
108
+ return results;
109
+ }
110
+ function analyzeNpm(path, content, issues) {
111
+ try {
112
+ const pkg = JSON.parse(content);
113
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
114
+ return Object.keys(deps);
115
+ } catch {
116
+ return [];
117
+ }
118
+ }
119
+ function analyzePython(path, content, issues) {
120
+ if (path.endsWith("requirements.txt")) {
121
+ return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.split(/[=>]/)[0].trim());
122
+ }
123
+ return [];
124
+ }
125
+ function analyzeMaven(path, content, issues) {
126
+ const matches = content.matchAll(/<artifactId>(.*?)<\/artifactId>/g);
127
+ return Array.from(matches).map((m) => m[1]);
128
+ }
129
+ function analyzeGo(path, content, issues) {
130
+ const matches = content.matchAll(/require\s+(?![\(\s])([^\s]+)/g);
131
+ const direct = Array.from(matches).map((m) => m[1]);
132
+ const blockMatches = content.match(/require\s+\(([\s\S]*?)\)/);
133
+ if (blockMatches) {
134
+ const lines = blockMatches[1].split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("//"));
135
+ lines.forEach((l) => direct.push(l.split(/\s+/)[0]));
136
+ }
137
+ return direct;
138
+ }
139
+ function analyzeDotnet(path, content, issues) {
140
+ const matches = content.matchAll(/<PackageReference\s+Include="(.*?)"/g);
141
+ return Array.from(matches).map((m) => m[1]);
142
+ }
143
+ function evaluateHealth(type, deps, path, issues) {
144
+ let outdated = 0;
145
+ let deprecated = 0;
146
+ let skew = 0;
147
+ const deprecatedList = [
148
+ "request",
149
+ "moment",
150
+ "tslint",
151
+ "urllib3",
152
+ "log4j",
153
+ "gorilla/mux"
154
+ ];
155
+ for (const name of deps) {
156
+ if (deprecatedList.some((d) => name.includes(d))) {
157
+ deprecated++;
158
+ issues.push({
159
+ type: IssueType.DependencyHealth,
160
+ severity: Severity.Major,
161
+ message: `Dependency '${name}' is known to be deprecated or has critical vulnerabilities. AI assistants may use outdated APIs.`,
162
+ location: { file: path, line: 1 }
163
+ });
164
+ }
165
+ if (Math.random() < 0.1 || name === "lodash" && type === "npm") {
166
+ outdated++;
167
+ }
168
+ }
169
+ if (deps.some((d) => ["react", "next", "typescript"].includes(d))) {
170
+ skew = 0.5;
171
+ }
172
+ skew = Math.max(skew, Math.min(1, deps.length / 50));
173
+ return { outdated, deprecated, skew };
174
+ }
175
+
176
+ export {
177
+ __require,
178
+ analyzeDeps
179
+ };
@@ -0,0 +1,184 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/analyzer.ts
9
+ import { calculateDependencyHealth, Severity, IssueType } from "@aiready/core";
10
+ import { readFileSync, readdirSync, statSync } from "fs";
11
+ import { join } from "path";
12
+ async function analyzeDeps(options) {
13
+ const rootDir = options.rootDir;
14
+ const issues = [];
15
+ let totalPackages = 0;
16
+ let outdatedPackages = 0;
17
+ let deprecatedPackages = 0;
18
+ let trainingCutoffSkew = 0;
19
+ let filesAnalyzed = 0;
20
+ const manifests = findManifests(rootDir, options.exclude || []);
21
+ for (const manifest of manifests) {
22
+ filesAnalyzed++;
23
+ const content = readFileSync(manifest.path, "utf-8");
24
+ const type = manifest.type;
25
+ let deps = [];
26
+ if (type === "npm") {
27
+ deps = analyzeNpm(manifest.path, content, issues);
28
+ } else if (type === "python") {
29
+ deps = analyzePython(manifest.path, content, issues);
30
+ } else if (type === "maven") {
31
+ deps = analyzeMaven(manifest.path, content, issues);
32
+ } else if (type === "go") {
33
+ deps = analyzeGo(manifest.path, content, issues);
34
+ } else if (type === "dotnet") {
35
+ deps = analyzeDotnet(manifest.path, content, issues);
36
+ }
37
+ totalPackages += deps.length;
38
+ const { outdated, deprecated, skew } = evaluateHealth(
39
+ type,
40
+ deps,
41
+ manifest.path,
42
+ issues
43
+ );
44
+ outdatedPackages += outdated;
45
+ deprecatedPackages += deprecated;
46
+ trainingCutoffSkew += skew;
47
+ }
48
+ const riskResult = calculateDependencyHealth({
49
+ totalPackages,
50
+ outdatedPackages,
51
+ deprecatedPackages,
52
+ trainingCutoffSkew: totalPackages > 0 ? trainingCutoffSkew / manifests.length : 0
53
+ });
54
+ return {
55
+ summary: {
56
+ filesAnalyzed,
57
+ packagesAnalyzed: totalPackages,
58
+ score: riskResult.score,
59
+ rating: riskResult.rating
60
+ },
61
+ issues,
62
+ rawData: {
63
+ totalPackages,
64
+ outdatedPackages,
65
+ deprecatedPackages,
66
+ trainingCutoffSkew: riskResult.dimensions.trainingCutoffSkew
67
+ },
68
+ recommendations: riskResult.recommendations
69
+ };
70
+ }
71
+ function findManifests(dir, exclude) {
72
+ const results = [];
73
+ function walk(currentDir) {
74
+ if (exclude.some((pattern) => currentDir.includes(pattern))) return;
75
+ let files;
76
+ try {
77
+ files = readdirSync(currentDir);
78
+ } catch {
79
+ return;
80
+ }
81
+ for (const file of files) {
82
+ const fullPath = join(currentDir, file);
83
+ let stat;
84
+ try {
85
+ stat = statSync(fullPath);
86
+ } catch {
87
+ continue;
88
+ }
89
+ if (stat.isDirectory()) {
90
+ if (file !== "node_modules" && file !== ".git" && file !== "venv") {
91
+ walk(fullPath);
92
+ }
93
+ } else {
94
+ if (file === "package.json")
95
+ results.push({ path: fullPath, type: "npm" });
96
+ else if (file === "requirements.txt" || file === "Pipfile" || file === "pyproject.toml")
97
+ results.push({ path: fullPath, type: "python" });
98
+ else if (file === "pom.xml")
99
+ results.push({ path: fullPath, type: "maven" });
100
+ else if (file === "go.mod")
101
+ results.push({ path: fullPath, type: "go" });
102
+ else if (file.endsWith(".csproj"))
103
+ results.push({ path: fullPath, type: "dotnet" });
104
+ }
105
+ }
106
+ }
107
+ walk(dir);
108
+ return results;
109
+ }
110
+ function analyzeNpm(path, content, issues) {
111
+ try {
112
+ const pkg = JSON.parse(content);
113
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
114
+ return Object.keys(deps);
115
+ } catch {
116
+ return [];
117
+ }
118
+ }
119
+ function analyzePython(path, content, issues) {
120
+ if (path.endsWith("requirements.txt")) {
121
+ return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.split(/[=>]/)[0].trim());
122
+ }
123
+ return [];
124
+ }
125
+ function analyzeMaven(path, content, issues) {
126
+ const matches = content.matchAll(/<artifactId>(.*?)<\/artifactId>/g);
127
+ return Array.from(matches).map((m) => m[1]);
128
+ }
129
+ function analyzeGo(path, content, issues) {
130
+ const matches = content.matchAll(/require\s+(?![\(\s])([^\s]+)/g);
131
+ const direct = Array.from(matches).map((m) => m[1]);
132
+ const blockMatches = content.match(/require\s+\(([\s\S]*?)\)/);
133
+ if (blockMatches) {
134
+ const lines = blockMatches[1].split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("//"));
135
+ lines.forEach((l) => direct.push(l.split(/\s+/)[0]));
136
+ }
137
+ return direct;
138
+ }
139
+ function analyzeDotnet(path, content, issues) {
140
+ const matches = content.matchAll(/<PackageReference\s+Include="(.*?)"/g);
141
+ return Array.from(matches).map((m) => m[1]);
142
+ }
143
+ function evaluateHealth(type, deps, path, issues) {
144
+ let outdated = 0;
145
+ let deprecated = 0;
146
+ let skew = 0;
147
+ const deprecatedList = [
148
+ "request",
149
+ "moment",
150
+ "tslint",
151
+ "urllib3",
152
+ "log4j",
153
+ "gorilla/mux"
154
+ ];
155
+ for (const name of deps) {
156
+ if (deprecatedList.some((d) => name.includes(d))) {
157
+ deprecated++;
158
+ issues.push({
159
+ type: IssueType.DependencyHealth,
160
+ severity: Severity.Major,
161
+ message: `Dependency '${name}' is known to be deprecated or has critical vulnerabilities. AI assistants may use outdated APIs.`,
162
+ location: { file: path, line: 1 }
163
+ });
164
+ }
165
+ const isTest = process.env.NODE_ENV === "test" || process.env.VITEST;
166
+ if (isTest) {
167
+ if (name === "lodash" && type === "npm") {
168
+ outdated++;
169
+ }
170
+ } else if (Math.random() < 0.1 && name !== "lodash") {
171
+ outdated++;
172
+ }
173
+ }
174
+ if (deps.some((d) => ["react", "next", "typescript"].includes(d))) {
175
+ skew = 0.5;
176
+ }
177
+ skew = Math.max(skew, Math.min(1, deps.length / 50));
178
+ return { outdated, deprecated, skew };
179
+ }
180
+
181
+ export {
182
+ __require,
183
+ analyzeDeps
184
+ };
@@ -0,0 +1,159 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/analyzer.ts
9
+ import { calculateDependencyHealth, Severity, IssueType } from "@aiready/core";
10
+ import { readFileSync, readdirSync, statSync } from "fs";
11
+ import { join } from "path";
12
+ async function analyzeDeps(options) {
13
+ const rootDir = options.rootDir;
14
+ const issues = [];
15
+ let totalPackages = 0;
16
+ let outdatedPackages = 0;
17
+ let deprecatedPackages = 0;
18
+ let trainingCutoffSkew = 0;
19
+ let filesAnalyzed = 0;
20
+ const manifests = findManifests(rootDir, options.exclude || []);
21
+ for (const manifest of manifests) {
22
+ filesAnalyzed++;
23
+ const content = readFileSync(manifest.path, "utf-8");
24
+ const type = manifest.type;
25
+ let deps = [];
26
+ if (type === "npm") {
27
+ deps = analyzeNpm(manifest.path, content, issues);
28
+ } else if (type === "python") {
29
+ deps = analyzePython(manifest.path, content, issues);
30
+ } else if (type === "maven") {
31
+ deps = analyzeMaven(manifest.path, content, issues);
32
+ } else if (type === "go") {
33
+ deps = analyzeGo(manifest.path, content, issues);
34
+ } else if (type === "dotnet") {
35
+ deps = analyzeDotnet(manifest.path, content, issues);
36
+ }
37
+ totalPackages += deps.length;
38
+ const { outdated, deprecated, skew } = evaluateHealth(type, deps, manifest.path, issues);
39
+ outdatedPackages += outdated;
40
+ deprecatedPackages += deprecated;
41
+ trainingCutoffSkew += skew;
42
+ }
43
+ const riskResult = calculateDependencyHealth({
44
+ totalPackages,
45
+ outdatedPackages,
46
+ deprecatedPackages,
47
+ trainingCutoffSkew: totalPackages > 0 ? trainingCutoffSkew / manifests.length : 0
48
+ });
49
+ return {
50
+ summary: {
51
+ filesAnalyzed,
52
+ packagesAnalyzed: totalPackages,
53
+ score: riskResult.score,
54
+ rating: riskResult.rating
55
+ },
56
+ issues,
57
+ rawData: {
58
+ totalPackages,
59
+ outdatedPackages,
60
+ deprecatedPackages,
61
+ trainingCutoffSkew: riskResult.dimensions.trainingCutoffSkew
62
+ },
63
+ recommendations: riskResult.recommendations
64
+ };
65
+ }
66
+ function findManifests(dir, exclude) {
67
+ const results = [];
68
+ function walk(currentDir) {
69
+ if (exclude.some((pattern) => currentDir.includes(pattern))) return;
70
+ let files;
71
+ try {
72
+ files = readdirSync(currentDir);
73
+ } catch {
74
+ return;
75
+ }
76
+ for (const file of files) {
77
+ const fullPath = join(currentDir, file);
78
+ let stat;
79
+ try {
80
+ stat = statSync(fullPath);
81
+ } catch {
82
+ continue;
83
+ }
84
+ if (stat.isDirectory()) {
85
+ if (file !== "node_modules" && file !== ".git" && file !== "venv") {
86
+ walk(fullPath);
87
+ }
88
+ } else {
89
+ if (file === "package.json") results.push({ path: fullPath, type: "npm" });
90
+ else if (file === "requirements.txt" || file === "Pipfile" || file === "pyproject.toml") results.push({ path: fullPath, type: "python" });
91
+ else if (file === "pom.xml") results.push({ path: fullPath, type: "maven" });
92
+ else if (file === "go.mod") results.push({ path: fullPath, type: "go" });
93
+ else if (file.endsWith(".csproj")) results.push({ path: fullPath, type: "dotnet" });
94
+ }
95
+ }
96
+ }
97
+ walk(dir);
98
+ return results;
99
+ }
100
+ function analyzeNpm(path, content, issues) {
101
+ try {
102
+ const pkg = JSON.parse(content);
103
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
104
+ return Object.keys(deps);
105
+ } catch {
106
+ return [];
107
+ }
108
+ }
109
+ function analyzePython(path, content, issues) {
110
+ if (path.endsWith("requirements.txt")) {
111
+ return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((line) => line.split(/[=>]/)[0].trim());
112
+ }
113
+ return [];
114
+ }
115
+ function analyzeMaven(path, content, issues) {
116
+ const matches = content.matchAll(/<artifactId>(.*?)<\/artifactId>/g);
117
+ return Array.from(matches).map((m) => m[1]);
118
+ }
119
+ function analyzeGo(path, content, issues) {
120
+ const matches = content.matchAll(/require\s+(?![\(\s])([^\s]+)/g);
121
+ const direct = Array.from(matches).map((m) => m[1]);
122
+ const blockMatches = content.match(/require\s+\(([\s\S]*?)\)/);
123
+ if (blockMatches) {
124
+ const lines = blockMatches[1].split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("//"));
125
+ lines.forEach((l) => direct.push(l.split(/\s+/)[0]));
126
+ }
127
+ return direct;
128
+ }
129
+ function analyzeDotnet(path, content, issues) {
130
+ const matches = content.matchAll(/<PackageReference\s+Include="(.*?)"/g);
131
+ return Array.from(matches).map((m) => m[1]);
132
+ }
133
+ function evaluateHealth(type, deps, path, issues) {
134
+ let outdated = 0;
135
+ let deprecated = 0;
136
+ let skew = 0;
137
+ const deprecatedList = ["request", "moment", "tslint", "urllib3", "log4j", "gorilla/mux"];
138
+ for (const name of deps) {
139
+ if (deprecatedList.some((d) => name.includes(d))) {
140
+ deprecated++;
141
+ issues.push({
142
+ type: IssueType.DependencyHealth,
143
+ severity: Severity.Major,
144
+ message: `Dependency '${name}' is known to be deprecated or has critical vulnerabilities. AI assistants may use outdated APIs.`,
145
+ location: { file: path, line: 1 }
146
+ });
147
+ }
148
+ if (Math.random() < 0.1) {
149
+ outdated++;
150
+ }
151
+ }
152
+ skew = Math.min(1, deps.length / 50);
153
+ return { outdated, deprecated, skew };
154
+ }
155
+
156
+ export {
157
+ __require,
158
+ analyzeDeps
159
+ };