@aiready/doc-drift 0.13.11 → 0.13.13
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/.turbo/turbo-build.log +23 -24
- package/.turbo/turbo-test.log +17 -18
- package/dist/chunk-DEXSCXHS.mjs +142 -0
- package/dist/cli.js +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/src/analyzer.ts +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
DTS Build
|
|
20
|
-
DTS
|
|
21
|
-
DTS dist/
|
|
22
|
-
DTS dist/
|
|
23
|
-
DTS dist/
|
|
24
|
-
DTS dist/index.d.mts 2.83 KB
|
|
1
|
+
|
|
2
|
+
> @aiready/doc-drift@0.13.13 build /Users/pengcao/projects/aiready/packages/doc-drift
|
|
3
|
+
> tsup src/index.ts src/cli.ts --format cjs,esm --dts
|
|
4
|
+
|
|
5
|
+
CLI Building entry: src/cli.ts, src/index.ts
|
|
6
|
+
CLI Using tsconfig: tsconfig.json
|
|
7
|
+
CLI tsup v8.5.1
|
|
8
|
+
CLI Target: es2020
|
|
9
|
+
CJS Build start
|
|
10
|
+
ESM Build start
|
|
11
|
+
CJS dist/cli.js 7.10 KB
|
|
12
|
+
CJS dist/index.js 7.70 KB
|
|
13
|
+
CJS ⚡️ Build success in 370ms
|
|
14
|
+
ESM dist/chunk-DEXSCXHS.mjs 4.39 KB
|
|
15
|
+
ESM dist/cli.mjs 1.39 KB
|
|
16
|
+
ESM dist/index.mjs 2.59 KB
|
|
17
|
+
ESM ⚡️ Build success in 371ms
|
|
18
|
+
DTS Build start
|
|
19
|
+
DTS ⚡️ Build success in 10196ms
|
|
20
|
+
DTS dist/cli.d.ts 108.00 B
|
|
21
|
+
DTS dist/index.d.ts 2.83 KB
|
|
22
|
+
DTS dist/cli.d.mts 108.00 B
|
|
23
|
+
DTS dist/index.d.mts 2.83 KB
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
[
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
[32m✓[39m src/__tests__/scoring.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
10
|
-
[32m✓[39m src/__tests__/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
[2m Test Files [22m [1m[32m3 passed[39m[22m[90m (3)[39m
|
|
14
|
-
[2m Tests [22m [1m[32m5 passed[39m[22m[90m (5)[39m
|
|
15
|
-
[2m Start at [22m
|
|
16
|
-
[2m Duration [22m
|
|
17
|
-
|
|
18
|
-
[?25h
|
|
1
|
+
|
|
2
|
+
> @aiready/doc-drift@0.13.12 test /Users/pengcao/projects/aiready/packages/doc-drift
|
|
3
|
+
> vitest run
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
[1m[46m RUN [49m[22m [36mv4.0.18 [39m[90m/Users/pengcao/projects/aiready/packages/doc-drift[39m
|
|
7
|
+
|
|
8
|
+
[32m✓[39m src/__tests__/provider.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 2[2mms[22m[39m
|
|
9
|
+
[32m✓[39m src/__tests__/scoring.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
10
|
+
[32m✓[39m src/__tests__/analyzer.test.ts [2m([22m[2m1 test[22m[2m)[22m[33m 583[2mms[22m[39m
|
|
11
|
+
[33m[2m✓[22m[39m detects missing param documentation and uncommented complexity [33m 576[2mms[22m[39m
|
|
12
|
+
|
|
13
|
+
[2m Test Files [22m [1m[32m3 passed[39m[22m[90m (3)[39m
|
|
14
|
+
[2m Tests [22m [1m[32m5 passed[39m[22m[90m (5)[39m
|
|
15
|
+
[2m Start at [22m 10:44:29
|
|
16
|
+
[2m Duration [22m 3.24s[2m (transform 1.08s, setup 0ms, import 6.97s, tests 590ms, environment 0ms)[22m
|
|
17
|
+
|
|
@@ -0,0 +1,142 @@
|
|
|
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 {
|
|
10
|
+
scanFiles,
|
|
11
|
+
calculateDocDrift,
|
|
12
|
+
getFileCommitTimestamps,
|
|
13
|
+
getLineRangeLastModifiedCached,
|
|
14
|
+
Severity,
|
|
15
|
+
IssueType,
|
|
16
|
+
emitProgress,
|
|
17
|
+
getParser
|
|
18
|
+
} from "@aiready/core";
|
|
19
|
+
import { readFileSync } from "fs";
|
|
20
|
+
async function analyzeDocDrift(options) {
|
|
21
|
+
const files = await scanFiles(options);
|
|
22
|
+
const issues = [];
|
|
23
|
+
let uncommentedExports = 0;
|
|
24
|
+
let totalExports = 0;
|
|
25
|
+
let outdatedComments = 0;
|
|
26
|
+
let undocumentedComplexity = 0;
|
|
27
|
+
let actualDrift = 0;
|
|
28
|
+
let processed = 0;
|
|
29
|
+
for (const file of files) {
|
|
30
|
+
processed++;
|
|
31
|
+
emitProgress(
|
|
32
|
+
processed,
|
|
33
|
+
files.length,
|
|
34
|
+
"doc-drift",
|
|
35
|
+
"analyzing files",
|
|
36
|
+
options.onProgress
|
|
37
|
+
);
|
|
38
|
+
const parser = getParser(file);
|
|
39
|
+
if (!parser) continue;
|
|
40
|
+
let code;
|
|
41
|
+
try {
|
|
42
|
+
code = readFileSync(file, "utf-8");
|
|
43
|
+
} catch {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await parser.initialize();
|
|
48
|
+
const parseResult = parser.parse(code, file);
|
|
49
|
+
let fileLineStamps;
|
|
50
|
+
for (const exp of parseResult.exports) {
|
|
51
|
+
if (exp.type === "function" || exp.type === "class") {
|
|
52
|
+
totalExports++;
|
|
53
|
+
if (!exp.documentation) {
|
|
54
|
+
uncommentedExports++;
|
|
55
|
+
if (exp.loc) {
|
|
56
|
+
const lines = exp.loc.end.line - exp.loc.start.line;
|
|
57
|
+
if (lines > 20) undocumentedComplexity++;
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
const doc = exp.documentation;
|
|
61
|
+
const docContent = doc.content;
|
|
62
|
+
if (exp.type === "function" && exp.parameters) {
|
|
63
|
+
const params = exp.parameters;
|
|
64
|
+
const missingParams = params.filter((p) => {
|
|
65
|
+
const regex = new RegExp(`\\b${p}\\b`);
|
|
66
|
+
return !regex.test(docContent);
|
|
67
|
+
});
|
|
68
|
+
if (missingParams.length > 0) {
|
|
69
|
+
outdatedComments++;
|
|
70
|
+
issues.push({
|
|
71
|
+
type: IssueType.DocDrift,
|
|
72
|
+
severity: Severity.Major,
|
|
73
|
+
message: `Documentation mismatch: function parameters (${missingParams.join(", ")}) are not mentioned in the docs.`,
|
|
74
|
+
location: { file, line: exp.loc?.start.line || 1 }
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (exp.loc && doc.loc) {
|
|
79
|
+
if (!fileLineStamps) {
|
|
80
|
+
fileLineStamps = getFileCommitTimestamps(file);
|
|
81
|
+
}
|
|
82
|
+
const bodyModified = getLineRangeLastModifiedCached(
|
|
83
|
+
fileLineStamps,
|
|
84
|
+
exp.loc.start.line,
|
|
85
|
+
exp.loc.end.line
|
|
86
|
+
);
|
|
87
|
+
const docModified = getLineRangeLastModifiedCached(
|
|
88
|
+
fileLineStamps,
|
|
89
|
+
doc.loc.start.line,
|
|
90
|
+
doc.loc.end.line
|
|
91
|
+
);
|
|
92
|
+
if (bodyModified > 0 && docModified > 0) {
|
|
93
|
+
const DRIFT_THRESHOLD_SECONDS = 24 * 60 * 60;
|
|
94
|
+
if (bodyModified - docModified > DRIFT_THRESHOLD_SECONDS) {
|
|
95
|
+
actualDrift++;
|
|
96
|
+
issues.push({
|
|
97
|
+
type: IssueType.DocDrift,
|
|
98
|
+
severity: Severity.Major,
|
|
99
|
+
message: `Documentation drift: logic was modified on ${new Date(bodyModified * 1e3).toLocaleDateString()} but documentation was last updated on ${new Date(docModified * 1e3).toLocaleDateString()}.`,
|
|
100
|
+
location: { file, line: doc.loc.start.line }
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.warn(`Doc-drift: Failed to parse ${file}: ${error}`);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const riskResult = calculateDocDrift({
|
|
114
|
+
uncommentedExports,
|
|
115
|
+
totalExports,
|
|
116
|
+
outdatedComments,
|
|
117
|
+
undocumentedComplexity,
|
|
118
|
+
actualDrift
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
summary: {
|
|
122
|
+
filesAnalyzed: files.length,
|
|
123
|
+
functionsAnalyzed: totalExports,
|
|
124
|
+
score: riskResult.score,
|
|
125
|
+
rating: riskResult.rating
|
|
126
|
+
},
|
|
127
|
+
issues,
|
|
128
|
+
rawData: {
|
|
129
|
+
uncommentedExports,
|
|
130
|
+
totalExports,
|
|
131
|
+
outdatedComments,
|
|
132
|
+
undocumentedComplexity,
|
|
133
|
+
actualDrift
|
|
134
|
+
},
|
|
135
|
+
recommendations: riskResult.recommendations
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export {
|
|
140
|
+
__require,
|
|
141
|
+
analyzeDocDrift
|
|
142
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -83,7 +83,7 @@ async function analyzeDocDrift(options) {
|
|
|
83
83
|
if (exp.type === "function" && exp.parameters) {
|
|
84
84
|
const params = exp.parameters;
|
|
85
85
|
const missingParams = params.filter((p) => {
|
|
86
|
-
const regex = new RegExp(`\\b${p}\\b
|
|
86
|
+
const regex = new RegExp(`\\b${p}\\b`);
|
|
87
87
|
return !regex.test(docContent);
|
|
88
88
|
});
|
|
89
89
|
if (missingParams.length > 0) {
|
package/dist/cli.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -78,7 +78,7 @@ async function analyzeDocDrift(options) {
|
|
|
78
78
|
if (exp.type === "function" && exp.parameters) {
|
|
79
79
|
const params = exp.parameters;
|
|
80
80
|
const missingParams = params.filter((p) => {
|
|
81
|
-
const regex = new RegExp(`\\b${p}\\b
|
|
81
|
+
const regex = new RegExp(`\\b${p}\\b`);
|
|
82
82
|
return !regex.test(docContent);
|
|
83
83
|
});
|
|
84
84
|
if (missingParams.length > 0) {
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/doc-drift",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.13",
|
|
4
4
|
"description": "AI-Readiness: Documentation Drift Detection",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"commander": "^14.0.0",
|
|
11
11
|
"glob": "^13.0.0",
|
|
12
12
|
"picocolors": "^1.0.0",
|
|
13
|
-
"@aiready/core": "0.23.
|
|
13
|
+
"@aiready/core": "0.23.14"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@types/node": "^24.0.0",
|
package/src/analyzer.ts
CHANGED
|
@@ -87,7 +87,7 @@ export async function analyzeDocDrift(
|
|
|
87
87
|
const params = exp.parameters;
|
|
88
88
|
// Check if params mentioned in doc (standard @param or simple mention)
|
|
89
89
|
const missingParams = params.filter((p) => {
|
|
90
|
-
const regex = new RegExp(`\\b${p}\\b
|
|
90
|
+
const regex = new RegExp(`\\b${p}\\b`);
|
|
91
91
|
return !regex.test(docContent);
|
|
92
92
|
});
|
|
93
93
|
|