@aiready/doc-drift 0.9.0 → 0.9.3

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/doc-drift@0.8.0 build /Users/pengcao/projects/aiready/packages/doc-drift
3
+ > @aiready/doc-drift@0.9.2 build /Users/pengcao/projects/aiready/packages/doc-drift
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
@@ -10,7 +10,7 @@
10
10
  CJS Build start
11
11
  ESM Build start
12
12
 
13
- [4:11:45 PM]  WARN  ▲ [WARNING] The condition "types" here will never be used as it comes after both "import" and "require" [package.json]
13
+  WARN  ▲ [WARNING] The condition "types" here will never be used as it comes after both "import" and "require" [package.json] 7:57:09 pm
14
14
 
15
15
  package.json:33:6:
16
16
   33 │ "types": "./dist/index.d.ts"
@@ -31,7 +31,7 @@
31
31
 
32
32
 
33
33
 
34
- [4:11:45 PM]  WARN  ▲ [WARNING] The condition "types" here will never be used as it comes after both "import" and "require" [package.json]
34
+  WARN  ▲ [WARNING] The condition "types" here will never be used as it comes after both "import" and "require" [package.json] 7:57:09 pm
35
35
 
36
36
  package.json:33:6:
37
37
   33 │ "types": "./dist/index.d.ts"
@@ -51,16 +51,16 @@
51
51
 
52
52
 
53
53
 
54
- CJS dist/cli.js 7.52 KB
55
- CJS dist/index.js 5.50 KB
56
- CJS ⚡️ Build success in 46ms
54
+ CJS dist/index.js 5.57 KB
55
+ CJS dist/cli.js 7.60 KB
56
+ CJS ⚡️ Build success in 38ms
57
57
  ESM dist/cli.mjs 1.39 KB
58
58
  ESM dist/index.mjs 88.00 B
59
- ESM dist/chunk-FMK4O4O7.mjs 4.79 KB
60
- ESM ⚡️ Build success in 47ms
59
+ ESM dist/chunk-CGSYYULO.mjs 4.85 KB
60
+ ESM ⚡️ Build success in 38ms
61
61
  DTS Build start
62
- DTS ⚡️ Build success in 3358ms
62
+ DTS ⚡️ Build success in 2875ms
63
63
  DTS dist/cli.d.ts 108.00 B
64
- DTS dist/index.d.ts 950.00 B
64
+ DTS dist/index.d.ts 968.00 B
65
65
  DTS dist/cli.d.mts 108.00 B
66
- DTS dist/index.d.mts 950.00 B
66
+ DTS dist/index.d.mts 968.00 B
@@ -1,16 +1,16 @@
1
1
 
2
2
  
3
- > @aiready/doc-drift@0.8.0 test /Users/pengcao/projects/aiready/packages/doc-drift
3
+ > @aiready/doc-drift@0.9.2 test /Users/pengcao/projects/aiready/packages/doc-drift
4
4
  > vitest run
5
5
 
6
6
  [?25l
7
7
   RUN  v4.0.18 /Users/pengcao/projects/aiready/packages/doc-drift
8
8
 
9
- ✓ src/__tests__/analyzer.test.ts (1 test) 35ms
9
+ ✓ src/__tests__/analyzer.test.ts (1 test) 273ms
10
10
 
11
11
   Test Files  1 passed (1)
12
12
   Tests  1 passed (1)
13
-  Start at  16:12:21
14
-  Duration  2.13s (transform 133ms, setup 0ms, import 1.12s, tests 35ms, environment 0ms)
13
+  Start at  20:00:26
14
+  Duration  2.33s (transform 304ms, setup 0ms, import 1.34s, tests 273ms, environment 0ms)
15
15
 
16
16
  [?25h
@@ -0,0 +1,145 @@
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
+ } from "@aiready/core";
17
+ import { readFileSync } from "fs";
18
+ import { parse } from "@typescript-eslint/typescript-estree";
19
+ async function analyzeDocDrift(options) {
20
+ const files = await scanFiles(options);
21
+ const issues = [];
22
+ const staleMonths = options.staleMonths ?? 6;
23
+ const staleSeconds = staleMonths * 30 * 24 * 60 * 60;
24
+ let uncommentedExports = 0;
25
+ let totalExports = 0;
26
+ let outdatedComments = 0;
27
+ let undocumentedComplexity = 0;
28
+ const now = Math.floor(Date.now() / 1e3);
29
+ let processed = 0;
30
+ for (const file of files) {
31
+ processed++;
32
+ options.onProgress?.(processed, files.length, `doc-drift: analyzing files`);
33
+ let code;
34
+ try {
35
+ code = readFileSync(file, "utf-8");
36
+ } catch {
37
+ continue;
38
+ }
39
+ let ast;
40
+ try {
41
+ ast = parse(code, {
42
+ jsx: file.endsWith(".tsx") || file.endsWith(".jsx"),
43
+ loc: true,
44
+ comment: true
45
+ });
46
+ } catch {
47
+ continue;
48
+ }
49
+ const comments = ast.comments || [];
50
+ let fileLineStamps;
51
+ for (const node of ast.body) {
52
+ if (node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration") {
53
+ const decl = node.declaration;
54
+ if (!decl) continue;
55
+ if (decl.type === "FunctionDeclaration" || decl.type === "ClassDeclaration" || decl.type === "VariableDeclaration") {
56
+ totalExports++;
57
+ const nodeLine = node.loc.start.line;
58
+ const jsdocs = comments.filter(
59
+ (c) => c.type === "Block" && c.value.startsWith("*") && c.loc.end.line === nodeLine - 1
60
+ );
61
+ if (jsdocs.length === 0) {
62
+ uncommentedExports++;
63
+ if (decl.type === "FunctionDeclaration" && decl.body?.loc) {
64
+ const lines = decl.body.loc.end.line - decl.body.loc.start.line;
65
+ if (lines > 20) undocumentedComplexity++;
66
+ }
67
+ } else {
68
+ const jsdoc = jsdocs[0];
69
+ const jsdocText = jsdoc.value;
70
+ if (decl.type === "FunctionDeclaration") {
71
+ const params = decl.params.map((p) => p.name || p.left && p.left.name).filter(Boolean);
72
+ const paramTags = Array.from(
73
+ jsdocText.matchAll(/@param\s+(?:\{[^}]+\}\s+)?([a-zA-Z0-9_]+)/g)
74
+ ).map((m) => m[1]);
75
+ const missingParams = params.filter(
76
+ (p) => !paramTags.includes(p)
77
+ );
78
+ if (missingParams.length > 0) {
79
+ outdatedComments++;
80
+ issues.push({
81
+ type: IssueType.DocDrift,
82
+ severity: Severity.Major,
83
+ message: `JSDoc @param mismatch: function has parameters (${missingParams.join(", ")}) not documented in JSDoc.`,
84
+ location: { file, line: nodeLine }
85
+ });
86
+ continue;
87
+ }
88
+ }
89
+ if (!fileLineStamps) {
90
+ fileLineStamps = getFileCommitTimestamps(file);
91
+ }
92
+ const commentModified = getLineRangeLastModifiedCached(
93
+ fileLineStamps,
94
+ jsdoc.loc.start.line,
95
+ jsdoc.loc.end.line
96
+ );
97
+ const bodyModified = getLineRangeLastModifiedCached(
98
+ fileLineStamps,
99
+ decl.loc.start.line,
100
+ decl.loc.end.line
101
+ );
102
+ if (commentModified > 0 && bodyModified > 0) {
103
+ if (now - commentModified > staleSeconds && bodyModified - commentModified > staleSeconds / 2) {
104
+ outdatedComments++;
105
+ issues.push({
106
+ type: IssueType.DocDrift,
107
+ severity: Severity.Minor,
108
+ message: `JSDoc is significantly older than the function body implementation. Code may have drifted.`,
109
+ location: { file, line: jsdoc.loc.start.line }
110
+ });
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ const riskResult = calculateDocDrift({
119
+ uncommentedExports,
120
+ totalExports,
121
+ outdatedComments,
122
+ undocumentedComplexity
123
+ });
124
+ return {
125
+ summary: {
126
+ filesAnalyzed: files.length,
127
+ functionsAnalyzed: totalExports,
128
+ score: riskResult.score,
129
+ rating: riskResult.rating
130
+ },
131
+ issues,
132
+ rawData: {
133
+ uncommentedExports,
134
+ totalExports,
135
+ outdatedComments,
136
+ undocumentedComplexity
137
+ },
138
+ recommendations: riskResult.recommendations
139
+ };
140
+ }
141
+
142
+ export {
143
+ __require,
144
+ analyzeDocDrift
145
+ };
package/dist/cli.js CHANGED
@@ -101,8 +101,8 @@ async function analyzeDocDrift(options) {
101
101
  if (missingParams.length > 0) {
102
102
  outdatedComments++;
103
103
  issues.push({
104
- type: "doc-drift",
105
- severity: "major",
104
+ type: import_core.IssueType.DocDrift,
105
+ severity: import_core.Severity.Major,
106
106
  message: `JSDoc @param mismatch: function has parameters (${missingParams.join(", ")}) not documented in JSDoc.`,
107
107
  location: { file, line: nodeLine }
108
108
  });
@@ -126,8 +126,8 @@ async function analyzeDocDrift(options) {
126
126
  if (now - commentModified > staleSeconds && bodyModified - commentModified > staleSeconds / 2) {
127
127
  outdatedComments++;
128
128
  issues.push({
129
- type: "doc-drift",
130
- severity: "minor",
129
+ type: import_core.IssueType.DocDrift,
130
+ severity: import_core.Severity.Minor,
131
131
  message: `JSDoc is significantly older than the function body implementation. Code may have drifted.`,
132
132
  location: { file, line: jsdoc.loc.start.line }
133
133
  });
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  __require,
3
3
  analyzeDocDrift
4
- } from "./chunk-FMK4O4O7.mjs";
4
+ } from "./chunk-CGSYYULO.mjs";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Issue, ScanOptions } from '@aiready/core';
1
+ import { Issue, IssueType, ScanOptions } from '@aiready/core';
2
2
 
3
3
  interface DocDriftOptions extends ScanOptions {
4
4
  /** Maximum commit distance to check for drift */
@@ -7,7 +7,7 @@ interface DocDriftOptions extends ScanOptions {
7
7
  staleMonths?: number;
8
8
  }
9
9
  interface DocDriftIssue extends Issue {
10
- type: 'doc-drift';
10
+ type: IssueType.DocDrift;
11
11
  }
12
12
  interface DocDriftReport {
13
13
  summary: {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Issue, ScanOptions } from '@aiready/core';
1
+ import { Issue, IssueType, ScanOptions } from '@aiready/core';
2
2
 
3
3
  interface DocDriftOptions extends ScanOptions {
4
4
  /** Maximum commit distance to check for drift */
@@ -7,7 +7,7 @@ interface DocDriftOptions extends ScanOptions {
7
7
  staleMonths?: number;
8
8
  }
9
9
  interface DocDriftIssue extends Issue {
10
- type: 'doc-drift';
10
+ type: IssueType.DocDrift;
11
11
  }
12
12
  interface DocDriftReport {
13
13
  summary: {
package/dist/index.js CHANGED
@@ -90,8 +90,8 @@ async function analyzeDocDrift(options) {
90
90
  if (missingParams.length > 0) {
91
91
  outdatedComments++;
92
92
  issues.push({
93
- type: "doc-drift",
94
- severity: "major",
93
+ type: import_core.IssueType.DocDrift,
94
+ severity: import_core.Severity.Major,
95
95
  message: `JSDoc @param mismatch: function has parameters (${missingParams.join(", ")}) not documented in JSDoc.`,
96
96
  location: { file, line: nodeLine }
97
97
  });
@@ -115,8 +115,8 @@ async function analyzeDocDrift(options) {
115
115
  if (now - commentModified > staleSeconds && bodyModified - commentModified > staleSeconds / 2) {
116
116
  outdatedComments++;
117
117
  issues.push({
118
- type: "doc-drift",
119
- severity: "minor",
118
+ type: import_core.IssueType.DocDrift,
119
+ severity: import_core.Severity.Minor,
120
120
  message: `JSDoc is significantly older than the function body implementation. Code may have drifted.`,
121
121
  location: { file, line: jsdoc.loc.start.line }
122
122
  });
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  analyzeDocDrift
3
- } from "./chunk-FMK4O4O7.mjs";
3
+ } from "./chunk-CGSYYULO.mjs";
4
4
  export {
5
5
  analyzeDocDrift
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/doc-drift",
3
- "version": "0.9.0",
3
+ "version": "0.9.3",
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.19.0"
13
+ "@aiready/core": "0.19.3"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/node": "^24.0.0",
package/src/analyzer.ts CHANGED
@@ -3,6 +3,8 @@ import {
3
3
  calculateDocDrift,
4
4
  getFileCommitTimestamps,
5
5
  getLineRangeLastModifiedCached,
6
+ Severity,
7
+ IssueType,
6
8
  } from '@aiready/core';
7
9
  import type { DocDriftOptions, DocDriftReport, DocDriftIssue } from './types';
8
10
  import { readFileSync } from 'fs';
@@ -103,8 +105,8 @@ export async function analyzeDocDrift(
103
105
  if (missingParams.length > 0) {
104
106
  outdatedComments++;
105
107
  issues.push({
106
- type: 'doc-drift',
107
- severity: 'major',
108
+ type: IssueType.DocDrift,
109
+ severity: Severity.Major,
108
110
  message: `JSDoc @param mismatch: function has parameters (${missingParams.join(', ')}) not documented in JSDoc.`,
109
111
  location: { file, line: nodeLine },
110
112
  });
@@ -135,8 +137,8 @@ export async function analyzeDocDrift(
135
137
  ) {
136
138
  outdatedComments++;
137
139
  issues.push({
138
- type: 'doc-drift',
139
- severity: 'minor',
140
+ type: IssueType.DocDrift,
141
+ severity: Severity.Minor,
140
142
  message: `JSDoc is significantly older than the function body implementation. Code may have drifted.`,
141
143
  location: { file, line: jsdoc.loc.start.line },
142
144
  });
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ScanOptions, Issue } from '@aiready/core';
1
+ import type { ScanOptions, Issue, IssueType } from '@aiready/core';
2
2
 
3
3
  export interface DocDriftOptions extends ScanOptions {
4
4
  /** Maximum commit distance to check for drift */
@@ -8,7 +8,7 @@ export interface DocDriftOptions extends ScanOptions {
8
8
  }
9
9
 
10
10
  export interface DocDriftIssue extends Issue {
11
- type: 'doc-drift';
11
+ type: IssueType.DocDrift;
12
12
  }
13
13
 
14
14
  export interface DocDriftReport {