@aiready/core 0.23.4 → 0.23.6

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 (109) hide show
  1. package/dist/{chunk-NGHT7JOG.mjs → chunk-Q55AMEFV.mjs} +63 -0
  2. package/dist/{client-D-cn9ydj.d.mts → client-CKcjnPXt.d.mts} +79 -1
  3. package/dist/{client-D-cn9ydj.d.ts → client-CKcjnPXt.d.ts} +79 -1
  4. package/dist/client.d.mts +1 -1
  5. package/dist/client.d.ts +1 -1
  6. package/dist/client.js +66 -0
  7. package/dist/client.mjs +9 -1
  8. package/dist/index.d.mts +10 -2
  9. package/dist/index.d.ts +10 -2
  10. package/dist/index.js +159 -21
  11. package/dist/index.mjs +102 -22
  12. package/package.json +1 -1
  13. package/dist/__tests__/parser-factory.test.d.ts +0 -5
  14. package/dist/__tests__/parser-factory.test.d.ts.map +0 -1
  15. package/dist/__tests__/parser-factory.test.js +0 -70
  16. package/dist/__tests__/parser-factory.test.js.map +0 -1
  17. package/dist/__tests__/python-parser.test.d.ts +0 -5
  18. package/dist/__tests__/python-parser.test.d.ts.map +0 -1
  19. package/dist/__tests__/python-parser.test.js +0 -194
  20. package/dist/__tests__/python-parser.test.js.map +0 -1
  21. package/dist/__tests__/scoring.test.d.ts +0 -2
  22. package/dist/__tests__/scoring.test.d.ts.map +0 -1
  23. package/dist/__tests__/scoring.test.js +0 -197
  24. package/dist/__tests__/scoring.test.js.map +0 -1
  25. package/dist/chunk-3YI4IS3D.mjs +0 -601
  26. package/dist/chunk-5HIXDC3X.mjs +0 -716
  27. package/dist/chunk-5V3L53AE.mjs +0 -805
  28. package/dist/chunk-CKVKHN3G.mjs +0 -660
  29. package/dist/chunk-COHIBX3Q.mjs +0 -635
  30. package/dist/chunk-CWRCDSKZ.mjs +0 -417
  31. package/dist/chunk-D3D3NCRR.mjs +0 -556
  32. package/dist/chunk-HCFYP7UD.mjs +0 -805
  33. package/dist/chunk-HFLFBA6F.mjs +0 -417
  34. package/dist/chunk-HKSARRCD.mjs +0 -365
  35. package/dist/chunk-JJ5JL5FX.mjs +0 -417
  36. package/dist/chunk-KDSTXVLQ.mjs +0 -724
  37. package/dist/chunk-KI7XORTN.mjs +0 -417
  38. package/dist/chunk-LTMHFNFK.mjs +0 -690
  39. package/dist/chunk-LTNXTXRI.mjs +0 -659
  40. package/dist/chunk-M22BXHBR.mjs +0 -805
  41. package/dist/chunk-MH3A3LX6.mjs +0 -615
  42. package/dist/chunk-OQ6IGDXG.mjs +0 -553
  43. package/dist/chunk-QAFB3HXQ.mjs +0 -590
  44. package/dist/chunk-QQBKXHLU.mjs +0 -678
  45. package/dist/chunk-RDHYGES7.mjs +0 -678
  46. package/dist/chunk-SWTDBVYJ.mjs +0 -660
  47. package/dist/chunk-UIWL5JQB.mjs +0 -417
  48. package/dist/chunk-UQGI67WR.mjs +0 -417
  49. package/dist/chunk-UTZOO4XO.mjs +0 -553
  50. package/dist/chunk-X4F46I5L.mjs +0 -635
  51. package/dist/chunk-XKK7YHPX.mjs +0 -619
  52. package/dist/chunk-YCA4FTEK.mjs +0 -600
  53. package/dist/chunk-ZSZRRTJM.mjs +0 -719
  54. package/dist/client-BgmiMoil.d.mts +0 -1344
  55. package/dist/client-BgmiMoil.d.ts +0 -1344
  56. package/dist/client-BxGrPuuN.d.mts +0 -1191
  57. package/dist/client-BxGrPuuN.d.ts +0 -1191
  58. package/dist/client-D9seCH4K.d.mts +0 -1334
  59. package/dist/client-D9seCH4K.d.ts +0 -1334
  60. package/dist/client-DIXIh7rw.d.mts +0 -1193
  61. package/dist/client-DIXIh7rw.d.ts +0 -1193
  62. package/dist/client-DVHXWOHw.d.mts +0 -1245
  63. package/dist/client-DVHXWOHw.d.ts +0 -1245
  64. package/dist/index.d.ts.map +0 -1
  65. package/dist/index.js.map +0 -1
  66. package/dist/parsers/parser-factory.d.ts +0 -69
  67. package/dist/parsers/parser-factory.d.ts.map +0 -1
  68. package/dist/parsers/parser-factory.js +0 -116
  69. package/dist/parsers/parser-factory.js.map +0 -1
  70. package/dist/parsers/python-parser.d.ts +0 -47
  71. package/dist/parsers/python-parser.d.ts.map +0 -1
  72. package/dist/parsers/python-parser.js +0 -243
  73. package/dist/parsers/python-parser.js.map +0 -1
  74. package/dist/parsers/typescript-parser.d.ts +0 -22
  75. package/dist/parsers/typescript-parser.d.ts.map +0 -1
  76. package/dist/parsers/typescript-parser.js +0 -242
  77. package/dist/parsers/typescript-parser.js.map +0 -1
  78. package/dist/scoring.d.ts +0 -120
  79. package/dist/scoring.d.ts.map +0 -1
  80. package/dist/scoring.js +0 -197
  81. package/dist/scoring.js.map +0 -1
  82. package/dist/types/language.d.ts +0 -172
  83. package/dist/types/language.d.ts.map +0 -1
  84. package/dist/types/language.js +0 -45
  85. package/dist/types/language.js.map +0 -1
  86. package/dist/types.d.ts +0 -122
  87. package/dist/types.d.ts.map +0 -1
  88. package/dist/types.js +0 -2
  89. package/dist/types.js.map +0 -1
  90. package/dist/utils/ast-parser.d.ts +0 -59
  91. package/dist/utils/ast-parser.d.ts.map +0 -1
  92. package/dist/utils/ast-parser.js +0 -213
  93. package/dist/utils/ast-parser.js.map +0 -1
  94. package/dist/utils/cli-helpers.d.ts +0 -54
  95. package/dist/utils/cli-helpers.d.ts.map +0 -1
  96. package/dist/utils/cli-helpers.js +0 -78
  97. package/dist/utils/cli-helpers.js.map +0 -1
  98. package/dist/utils/config.d.ts +0 -9
  99. package/dist/utils/config.d.ts.map +0 -1
  100. package/dist/utils/config.js +0 -80
  101. package/dist/utils/config.js.map +0 -1
  102. package/dist/utils/file-scanner.d.ts +0 -16
  103. package/dist/utils/file-scanner.d.ts.map +0 -1
  104. package/dist/utils/file-scanner.js +0 -104
  105. package/dist/utils/file-scanner.js.map +0 -1
  106. package/dist/utils/metrics.d.ts +0 -6
  107. package/dist/utils/metrics.d.ts.map +0 -1
  108. package/dist/utils/metrics.js +0 -8
  109. package/dist/utils/metrics.js.map +0 -1
package/dist/index.js CHANGED
@@ -49,8 +49,13 @@ __export(index_exports, {
49
49
  JavaParser: () => JavaParser,
50
50
  LANGUAGE_EXTENSIONS: () => LANGUAGE_EXTENSIONS,
51
51
  Language: () => Language,
52
+ LeadSchema: () => LeadSchema,
53
+ LeadSource: () => LeadSource,
54
+ LeadSourceSchema: () => LeadSourceSchema,
55
+ LeadSubmissionSchema: () => LeadSubmissionSchema,
52
56
  LocationSchema: () => LocationSchema,
53
57
  MODEL_PRICING_PRESETS: () => MODEL_PRICING_PRESETS,
58
+ ManagedAccountSchema: () => ManagedAccountSchema,
54
59
  MetricsSchema: () => MetricsSchema,
55
60
  ModelTier: () => ModelTier,
56
61
  ModelTierSchema: () => ModelTierSchema,
@@ -330,6 +335,64 @@ var UnifiedReportSchema = import_zod.z.object({
330
335
  }).optional()
331
336
  }).catchall(import_zod.z.any());
332
337
 
338
+ // src/types/business.ts
339
+ var import_zod2 = require("zod");
340
+ var LeadSource = /* @__PURE__ */ ((LeadSource2) => {
341
+ LeadSource2["ClawMoreHero"] = "clawmore-hero";
342
+ LeadSource2["ClawMoreWaitlist"] = "clawmore-waitlist";
343
+ LeadSource2["ClawMoreBeta"] = "clawmore-beta";
344
+ LeadSource2["AiReadyPlatform"] = "aiready-platform";
345
+ return LeadSource2;
346
+ })(LeadSource || {});
347
+ var LeadSourceSchema = import_zod2.z.nativeEnum(LeadSource);
348
+ var LeadSchema = import_zod2.z.object({
349
+ id: import_zod2.z.string(),
350
+ email: import_zod2.z.string().email(),
351
+ name: import_zod2.z.string().min(1),
352
+ interest: import_zod2.z.string().default("General"),
353
+ notes: import_zod2.z.string().optional(),
354
+ timestamp: import_zod2.z.string().datetime(),
355
+ source: LeadSourceSchema,
356
+ status: import_zod2.z.enum(["new", "contacted", "qualified", "converted", "archived"]).default("new")
357
+ });
358
+ var LeadSubmissionSchema = LeadSchema.omit({
359
+ id: true,
360
+ timestamp: true,
361
+ status: true
362
+ });
363
+ var ManagedAccountSchema = import_zod2.z.object({
364
+ id: import_zod2.z.string(),
365
+ // Internal UUID
366
+ accountId: import_zod2.z.string(),
367
+ // AWS Account ID
368
+ userId: import_zod2.z.string(),
369
+ // Owner (caopengau@gmail.com)
370
+ stripeSubscriptionId: import_zod2.z.string(),
371
+ // AI Token Management
372
+ tokenStrategy: import_zod2.z.enum(["managed", "byok"]).default("managed"),
373
+ byokConfig: import_zod2.z.object({
374
+ openaiKey: import_zod2.z.string().optional(),
375
+ anthropicKey: import_zod2.z.string().optional(),
376
+ openrouterKey: import_zod2.z.string().optional()
377
+ }).optional(),
378
+ // Financials (in cents)
379
+ baseFeeCents: import_zod2.z.number().default(2900),
380
+ includedComputeCents: import_zod2.z.number().default(1500),
381
+ // $15.00 AWS included
382
+ includedTokenCents: import_zod2.z.number().default(500),
383
+ // $5.00 Managed Tokens included
384
+ // Pre-paid Balance (credits)
385
+ prepaidTokenBalanceCents: import_zod2.z.number().default(0),
386
+ // Users buy these in $10 packs
387
+ currentMonthlyTokenSpendCents: import_zod2.z.number().default(0),
388
+ // Governance
389
+ status: import_zod2.z.enum(["provisioning", "active", "warning", "quarantined", "suspended"]).default("provisioning"),
390
+ lastCostSyncAt: import_zod2.z.string().datetime().optional(),
391
+ region: import_zod2.z.string().default("ap-southeast-2"),
392
+ // Alerting thresholds (percentage of includedComputeCents)
393
+ alertThresholds: import_zod2.z.array(import_zod2.z.number()).default([50, 80, 100, 150])
394
+ });
395
+
333
396
  // src/types.ts
334
397
  var GLOBAL_INFRA_OPTIONS = [
335
398
  "rootDir",
@@ -789,7 +852,14 @@ function resolveOutputPath(userPath, defaultFilename, workingDir = process.cwd()
789
852
  if (userPath) {
790
853
  outputPath = userPath;
791
854
  } else {
792
- const aireadyDir = (0, import_path2.join)(workingDir, ".aiready");
855
+ let baseDir = workingDir;
856
+ try {
857
+ if ((0, import_fs2.statSync)(workingDir).isFile()) {
858
+ baseDir = (0, import_path2.dirname)(workingDir);
859
+ }
860
+ } catch (e) {
861
+ }
862
+ const aireadyDir = (0, import_path2.join)(baseDir, ".aiready");
793
863
  outputPath = (0, import_path2.join)(aireadyDir, defaultFilename);
794
864
  }
795
865
  const parentDir = (0, import_path2.dirname)(outputPath);
@@ -1055,7 +1125,7 @@ var TypeScriptParser = class {
1055
1125
  hasSideEffects: false
1056
1126
  };
1057
1127
  const start = node.range?.[0] ?? 0;
1058
- const preceding = code.slice(Math.max(0, start - 200), start);
1128
+ const preceding = code.slice(Math.max(0, start - 1e3), start);
1059
1129
  const jsdocMatches = Array.from(
1060
1130
  preceding.matchAll(/\/\*\*([\s\S]*?)\*\//g)
1061
1131
  );
@@ -1064,9 +1134,24 @@ var TypeScriptParser = class {
1064
1134
  const matchEndIndex = (lastMatch.index || 0) + lastMatch[0].length;
1065
1135
  const between = preceding.slice(matchEndIndex);
1066
1136
  if (/^\s*$/.test(between)) {
1137
+ const precedingStartOffset = Math.max(0, start - 1e3);
1138
+ const absoluteStartOffset = precedingStartOffset + (lastMatch.index || 0);
1139
+ const absoluteEndOffset = precedingStartOffset + matchEndIndex;
1140
+ const codeBeforeStart = code.slice(0, absoluteStartOffset);
1141
+ const startLines = codeBeforeStart.split("\n");
1142
+ const startLine = startLines.length;
1143
+ const startColumn = startLines[startLines.length - 1].length;
1144
+ const codeBeforeEnd = code.slice(0, absoluteEndOffset);
1145
+ const endLines = codeBeforeEnd.split("\n");
1146
+ const endLine = endLines.length;
1147
+ const endColumn = endLines[endLines.length - 1].length;
1067
1148
  metadata.documentation = {
1068
1149
  content: lastMatch[1].replace(/^\s*\*+/gm, "").trim(),
1069
- type: "jsdoc"
1150
+ type: "jsdoc",
1151
+ loc: {
1152
+ start: { line: startLine, column: startColumn },
1153
+ end: { line: endLine, column: endColumn }
1154
+ }
1070
1155
  };
1071
1156
  }
1072
1157
  }
@@ -1375,37 +1460,60 @@ function analyzeNodeMetadata(node, code, options) {
1375
1460
  let prev = node.previousSibling || null;
1376
1461
  while (prev && /comment/i.test(prev.type)) {
1377
1462
  const text = prev.text || "";
1463
+ const loc = {
1464
+ start: {
1465
+ line: prev.startPosition.row + 1,
1466
+ column: prev.startPosition.column
1467
+ },
1468
+ end: {
1469
+ line: prev.endPosition.row + 1,
1470
+ column: prev.endPosition.column
1471
+ }
1472
+ };
1378
1473
  if (text.trim().startsWith("/**") || text.trim().startsWith("/*")) {
1379
1474
  metadata.documentation = {
1380
1475
  content: text.replace(/^[/*]+|[/*]+$/g, "").trim(),
1381
- type: "comment"
1476
+ type: "comment",
1477
+ loc
1382
1478
  };
1383
1479
  break;
1384
1480
  }
1385
1481
  if (text.trim().startsWith("///")) {
1386
1482
  metadata.documentation = {
1387
1483
  content: text.replace(/^\/\/\//, "").trim(),
1388
- type: "xml-doc"
1484
+ type: "xml-doc",
1485
+ loc
1389
1486
  };
1390
1487
  break;
1391
1488
  }
1392
1489
  if (text.trim().startsWith("//")) {
1393
1490
  metadata.documentation = {
1394
1491
  content: text.replace(/^\/\//, "").trim(),
1395
- type: "comment"
1492
+ type: "comment",
1493
+ loc
1396
1494
  };
1397
1495
  break;
1398
1496
  }
1399
1497
  prev = prev.previousSibling;
1400
1498
  }
1401
- if (node.type === "function_definition") {
1499
+ if (node.type === "function_definition" || node.type === "class_definition") {
1402
1500
  const body2 = node.childForFieldName ? node.childForFieldName("body") : node.children.find((c) => c.type === "block");
1403
1501
  if (body2 && body2.children.length > 0) {
1404
1502
  const firstStmt = body2.children[0];
1405
1503
  if (firstStmt.type === "expression_statement" && firstStmt.firstChild?.type === "string") {
1406
1504
  metadata.documentation = {
1407
1505
  content: firstStmt.firstChild.text.replace(/['"`]/g, "").trim(),
1408
- type: "docstring"
1506
+ type: "docstring",
1507
+ loc: {
1508
+ start: {
1509
+ line: firstStmt.startPosition.row + 1,
1510
+ column: firstStmt.startPosition.column
1511
+ },
1512
+ end: {
1513
+ line: firstStmt.endPosition.row + 1,
1514
+ column: firstStmt.endPosition.column
1515
+ }
1516
+ }
1409
1517
  };
1410
1518
  }
1411
1519
  }
@@ -4549,23 +4657,47 @@ function calculateDocDrift(params) {
4549
4657
  uncommentedExports,
4550
4658
  totalExports,
4551
4659
  outdatedComments,
4552
- undocumentedComplexity
4660
+ undocumentedComplexity,
4661
+ actualDrift
4553
4662
  } = params;
4554
4663
  const uncommentedRatio = totalExports > 0 ? uncommentedExports / totalExports : 0;
4555
- const outdatedScore = Math.min(100, outdatedComments * 15);
4556
- const uncommentedScore = Math.min(100, uncommentedRatio * 100);
4557
- const complexityScore = Math.min(100, undocumentedComplexity * 10);
4558
- const score = Math.round(
4559
- outdatedScore * 0.6 + uncommentedScore * 0.2 + complexityScore * 0.2
4664
+ const outdatedRatio = totalExports > 0 ? outdatedComments / totalExports : 0;
4665
+ const complexityRatio = totalExports > 0 ? undocumentedComplexity / totalExports : 0;
4666
+ const driftRatio = totalExports > 0 ? actualDrift / totalExports : 0;
4667
+ const DRIFT_THRESHOLD = 0.2;
4668
+ const OUTDATED_THRESHOLD = 0.4;
4669
+ const COMPLEXITY_THRESHOLD = 0.2;
4670
+ const UNCOMMENTED_THRESHOLD = 0.8;
4671
+ const driftRisk = Math.min(100, driftRatio / DRIFT_THRESHOLD * 100);
4672
+ const outdatedRisk = Math.min(
4673
+ 100,
4674
+ outdatedRatio / OUTDATED_THRESHOLD * 100
4675
+ );
4676
+ const complexityRisk = Math.min(
4677
+ 100,
4678
+ complexityRatio / COMPLEXITY_THRESHOLD * 100
4560
4679
  );
4561
- const finalScore = Math.min(100, Math.max(0, score));
4680
+ const uncommentedRisk = Math.min(
4681
+ 100,
4682
+ uncommentedRatio / UNCOMMENTED_THRESHOLD * 100
4683
+ );
4684
+ const risk = Math.round(
4685
+ driftRisk * 0.4 + complexityRisk * 0.3 + outdatedRisk * 0.2 + uncommentedRisk * 0.1
4686
+ );
4687
+ const finalRisk = Math.min(100, Math.max(0, risk));
4688
+ const score = totalExports > 0 ? 100 - finalRisk : 100;
4562
4689
  let rating;
4563
- if (finalScore < 10) rating = "minimal";
4564
- else if (finalScore < 30) rating = "low";
4565
- else if (finalScore < 60) rating = "moderate";
4566
- else if (finalScore < 85) rating = "high";
4690
+ if (score >= 90)
4691
+ rating = "minimal";
4692
+ else if (score >= 75) rating = "low";
4693
+ else if (score >= 60) rating = "moderate";
4694
+ else if (score >= 40) rating = "high";
4567
4695
  else rating = "severe";
4568
4696
  const recommendations = [];
4697
+ if (actualDrift > 0)
4698
+ recommendations.push(
4699
+ `Review ${actualDrift} functions where code was changed after documentation was last updated.`
4700
+ );
4569
4701
  if (outdatedComments > 0)
4570
4702
  recommendations.push(
4571
4703
  `Update or remove ${outdatedComments} outdated comments that contradict the code.`
@@ -4579,12 +4711,13 @@ function calculateDocDrift(params) {
4579
4711
  `Explain the business logic for ${undocumentedComplexity} highly complex functions.`
4580
4712
  );
4581
4713
  return {
4582
- score: finalScore,
4714
+ score,
4583
4715
  rating,
4584
4716
  dimensions: {
4585
4717
  uncommentedExports,
4586
4718
  outdatedComments,
4587
- undocumentedComplexity
4719
+ undocumentedComplexity,
4720
+ actualDrift
4588
4721
  },
4589
4722
  recommendations
4590
4723
  };
@@ -5018,8 +5151,13 @@ function emitIssuesAsAnnotations(issues) {
5018
5151
  JavaParser,
5019
5152
  LANGUAGE_EXTENSIONS,
5020
5153
  Language,
5154
+ LeadSchema,
5155
+ LeadSource,
5156
+ LeadSourceSchema,
5157
+ LeadSubmissionSchema,
5021
5158
  LocationSchema,
5022
5159
  MODEL_PRICING_PRESETS,
5160
+ ManagedAccountSchema,
5023
5161
  MetricsSchema,
5024
5162
  ModelTier,
5025
5163
  ModelTierSchema,
package/dist/index.mjs CHANGED
@@ -13,7 +13,12 @@ import {
13
13
  IssueTypeSchema,
14
14
  LANGUAGE_EXTENSIONS,
15
15
  Language,
16
+ LeadSchema,
17
+ LeadSource,
18
+ LeadSourceSchema,
19
+ LeadSubmissionSchema,
16
20
  LocationSchema,
21
+ ManagedAccountSchema,
17
22
  MetricsSchema,
18
23
  ModelTier,
19
24
  ModelTierSchema,
@@ -44,7 +49,7 @@ import {
44
49
  getToolWeight,
45
50
  normalizeToolName,
46
51
  parseWeightString
47
- } from "./chunk-NGHT7JOG.mjs";
52
+ } from "./chunk-Q55AMEFV.mjs";
48
53
 
49
54
  // src/types/contract.ts
50
55
  function validateSpokeOutput(toolName, output) {
@@ -454,7 +459,14 @@ function resolveOutputPath(userPath, defaultFilename, workingDir = process.cwd()
454
459
  if (userPath) {
455
460
  outputPath = userPath;
456
461
  } else {
457
- const aireadyDir = join2(workingDir, ".aiready");
462
+ let baseDir = workingDir;
463
+ try {
464
+ if (statSync(workingDir).isFile()) {
465
+ baseDir = dirname2(workingDir);
466
+ }
467
+ } catch (e) {
468
+ }
469
+ const aireadyDir = join2(baseDir, ".aiready");
458
470
  outputPath = join2(aireadyDir, defaultFilename);
459
471
  }
460
472
  const parentDir = dirname2(outputPath);
@@ -720,7 +732,7 @@ var TypeScriptParser = class {
720
732
  hasSideEffects: false
721
733
  };
722
734
  const start = node.range?.[0] ?? 0;
723
- const preceding = code.slice(Math.max(0, start - 200), start);
735
+ const preceding = code.slice(Math.max(0, start - 1e3), start);
724
736
  const jsdocMatches = Array.from(
725
737
  preceding.matchAll(/\/\*\*([\s\S]*?)\*\//g)
726
738
  );
@@ -729,9 +741,24 @@ var TypeScriptParser = class {
729
741
  const matchEndIndex = (lastMatch.index || 0) + lastMatch[0].length;
730
742
  const between = preceding.slice(matchEndIndex);
731
743
  if (/^\s*$/.test(between)) {
744
+ const precedingStartOffset = Math.max(0, start - 1e3);
745
+ const absoluteStartOffset = precedingStartOffset + (lastMatch.index || 0);
746
+ const absoluteEndOffset = precedingStartOffset + matchEndIndex;
747
+ const codeBeforeStart = code.slice(0, absoluteStartOffset);
748
+ const startLines = codeBeforeStart.split("\n");
749
+ const startLine = startLines.length;
750
+ const startColumn = startLines[startLines.length - 1].length;
751
+ const codeBeforeEnd = code.slice(0, absoluteEndOffset);
752
+ const endLines = codeBeforeEnd.split("\n");
753
+ const endLine = endLines.length;
754
+ const endColumn = endLines[endLines.length - 1].length;
732
755
  metadata.documentation = {
733
756
  content: lastMatch[1].replace(/^\s*\*+/gm, "").trim(),
734
- type: "jsdoc"
757
+ type: "jsdoc",
758
+ loc: {
759
+ start: { line: startLine, column: startColumn },
760
+ end: { line: endLine, column: endColumn }
761
+ }
735
762
  };
736
763
  }
737
764
  }
@@ -1040,37 +1067,60 @@ function analyzeNodeMetadata(node, code, options) {
1040
1067
  let prev = node.previousSibling || null;
1041
1068
  while (prev && /comment/i.test(prev.type)) {
1042
1069
  const text = prev.text || "";
1070
+ const loc = {
1071
+ start: {
1072
+ line: prev.startPosition.row + 1,
1073
+ column: prev.startPosition.column
1074
+ },
1075
+ end: {
1076
+ line: prev.endPosition.row + 1,
1077
+ column: prev.endPosition.column
1078
+ }
1079
+ };
1043
1080
  if (text.trim().startsWith("/**") || text.trim().startsWith("/*")) {
1044
1081
  metadata.documentation = {
1045
1082
  content: text.replace(/^[/*]+|[/*]+$/g, "").trim(),
1046
- type: "comment"
1083
+ type: "comment",
1084
+ loc
1047
1085
  };
1048
1086
  break;
1049
1087
  }
1050
1088
  if (text.trim().startsWith("///")) {
1051
1089
  metadata.documentation = {
1052
1090
  content: text.replace(/^\/\/\//, "").trim(),
1053
- type: "xml-doc"
1091
+ type: "xml-doc",
1092
+ loc
1054
1093
  };
1055
1094
  break;
1056
1095
  }
1057
1096
  if (text.trim().startsWith("//")) {
1058
1097
  metadata.documentation = {
1059
1098
  content: text.replace(/^\/\//, "").trim(),
1060
- type: "comment"
1099
+ type: "comment",
1100
+ loc
1061
1101
  };
1062
1102
  break;
1063
1103
  }
1064
1104
  prev = prev.previousSibling;
1065
1105
  }
1066
- if (node.type === "function_definition") {
1106
+ if (node.type === "function_definition" || node.type === "class_definition") {
1067
1107
  const body2 = node.childForFieldName ? node.childForFieldName("body") : node.children.find((c) => c.type === "block");
1068
1108
  if (body2 && body2.children.length > 0) {
1069
1109
  const firstStmt = body2.children[0];
1070
1110
  if (firstStmt.type === "expression_statement" && firstStmt.firstChild?.type === "string") {
1071
1111
  metadata.documentation = {
1072
1112
  content: firstStmt.firstChild.text.replace(/['"`]/g, "").trim(),
1073
- type: "docstring"
1113
+ type: "docstring",
1114
+ loc: {
1115
+ start: {
1116
+ line: firstStmt.startPosition.row + 1,
1117
+ column: firstStmt.startPosition.column
1118
+ },
1119
+ end: {
1120
+ line: firstStmt.endPosition.row + 1,
1121
+ column: firstStmt.endPosition.column
1122
+ }
1123
+ }
1074
1124
  };
1075
1125
  }
1076
1126
  }
@@ -3782,23 +3832,47 @@ function calculateDocDrift(params) {
3782
3832
  uncommentedExports,
3783
3833
  totalExports,
3784
3834
  outdatedComments,
3785
- undocumentedComplexity
3835
+ undocumentedComplexity,
3836
+ actualDrift
3786
3837
  } = params;
3787
3838
  const uncommentedRatio = totalExports > 0 ? uncommentedExports / totalExports : 0;
3788
- const outdatedScore = Math.min(100, outdatedComments * 15);
3789
- const uncommentedScore = Math.min(100, uncommentedRatio * 100);
3790
- const complexityScore = Math.min(100, undocumentedComplexity * 10);
3791
- const score = Math.round(
3792
- outdatedScore * 0.6 + uncommentedScore * 0.2 + complexityScore * 0.2
3839
+ const outdatedRatio = totalExports > 0 ? outdatedComments / totalExports : 0;
3840
+ const complexityRatio = totalExports > 0 ? undocumentedComplexity / totalExports : 0;
3841
+ const driftRatio = totalExports > 0 ? actualDrift / totalExports : 0;
3842
+ const DRIFT_THRESHOLD = 0.2;
3843
+ const OUTDATED_THRESHOLD = 0.4;
3844
+ const COMPLEXITY_THRESHOLD = 0.2;
3845
+ const UNCOMMENTED_THRESHOLD = 0.8;
3846
+ const driftRisk = Math.min(100, driftRatio / DRIFT_THRESHOLD * 100);
3847
+ const outdatedRisk = Math.min(
3848
+ 100,
3849
+ outdatedRatio / OUTDATED_THRESHOLD * 100
3850
+ );
3851
+ const complexityRisk = Math.min(
3852
+ 100,
3853
+ complexityRatio / COMPLEXITY_THRESHOLD * 100
3854
+ );
3855
+ const uncommentedRisk = Math.min(
3856
+ 100,
3857
+ uncommentedRatio / UNCOMMENTED_THRESHOLD * 100
3858
+ );
3859
+ const risk = Math.round(
3860
+ driftRisk * 0.4 + complexityRisk * 0.3 + outdatedRisk * 0.2 + uncommentedRisk * 0.1
3793
3861
  );
3794
- const finalScore = Math.min(100, Math.max(0, score));
3862
+ const finalRisk = Math.min(100, Math.max(0, risk));
3863
+ const score = totalExports > 0 ? 100 - finalRisk : 100;
3795
3864
  let rating;
3796
- if (finalScore < 10) rating = "minimal";
3797
- else if (finalScore < 30) rating = "low";
3798
- else if (finalScore < 60) rating = "moderate";
3799
- else if (finalScore < 85) rating = "high";
3865
+ if (score >= 90)
3866
+ rating = "minimal";
3867
+ else if (score >= 75) rating = "low";
3868
+ else if (score >= 60) rating = "moderate";
3869
+ else if (score >= 40) rating = "high";
3800
3870
  else rating = "severe";
3801
3871
  const recommendations = [];
3872
+ if (actualDrift > 0)
3873
+ recommendations.push(
3874
+ `Review ${actualDrift} functions where code was changed after documentation was last updated.`
3875
+ );
3802
3876
  if (outdatedComments > 0)
3803
3877
  recommendations.push(
3804
3878
  `Update or remove ${outdatedComments} outdated comments that contradict the code.`
@@ -3812,12 +3886,13 @@ function calculateDocDrift(params) {
3812
3886
  `Explain the business logic for ${undocumentedComplexity} highly complex functions.`
3813
3887
  );
3814
3888
  return {
3815
- score: finalScore,
3889
+ score,
3816
3890
  rating,
3817
3891
  dimensions: {
3818
3892
  uncommentedExports,
3819
3893
  outdatedComments,
3820
- undocumentedComplexity
3894
+ undocumentedComplexity,
3895
+ actualDrift
3821
3896
  },
3822
3897
  recommendations
3823
3898
  };
@@ -4250,8 +4325,13 @@ export {
4250
4325
  JavaParser,
4251
4326
  LANGUAGE_EXTENSIONS,
4252
4327
  Language,
4328
+ LeadSchema,
4329
+ LeadSource,
4330
+ LeadSourceSchema,
4331
+ LeadSubmissionSchema,
4253
4332
  LocationSchema,
4254
4333
  MODEL_PRICING_PRESETS,
4334
+ ManagedAccountSchema,
4255
4335
  MetricsSchema,
4256
4336
  ModelTier,
4257
4337
  ModelTierSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/core",
3
- "version": "0.23.4",
3
+ "version": "0.23.6",
4
4
  "description": "Shared utilities for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -1,5 +0,0 @@
1
- /**
2
- * Test multi-language parser factory
3
- */
4
- export {};
5
- //# sourceMappingURL=parser-factory.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"parser-factory.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/parser-factory.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -1,70 +0,0 @@
1
- /**
2
- * Test multi-language parser factory
3
- */
4
- import { describe, it, expect } from 'vitest';
5
- import {
6
- ParserFactory,
7
- Language,
8
- getParser,
9
- isFileSupported,
10
- getSupportedLanguages,
11
- } from '../parsers/parser-factory';
12
- describe('ParserFactory', () => {
13
- it('should return TypeScript parser for .ts files', () => {
14
- const parser = getParser('test.ts');
15
- expect(parser).toBeDefined();
16
- expect(parser?.language).toBe(Language.TypeScript);
17
- });
18
- it('should return TypeScript parser for .tsx files', () => {
19
- const parser = getParser('component.tsx');
20
- expect(parser).toBeDefined();
21
- expect(parser?.language).toBe(Language.TypeScript);
22
- });
23
- it('should return JavaScript parser for .js files', () => {
24
- const parser = getParser('script.js');
25
- expect(parser).toBeDefined();
26
- expect(parser?.language).toBe(Language.TypeScript); // TS parser handles JS too
27
- });
28
- it('should return Python parser for .py files', () => {
29
- const parser = getParser('script.py');
30
- expect(parser).toBeDefined();
31
- expect(parser?.language).toBe(Language.Python);
32
- });
33
- it('should return null for unsupported files', () => {
34
- const parser = getParser('README.md');
35
- expect(parser).toBeNull();
36
- });
37
- it('should correctly identify supported files', () => {
38
- expect(isFileSupported('test.ts')).toBe(true);
39
- expect(isFileSupported('test.py')).toBe(true);
40
- expect(isFileSupported('test.java')).toBe(false); // Not yet implemented
41
- expect(isFileSupported('README.md')).toBe(false);
42
- });
43
- it('should list all supported languages', () => {
44
- const languages = getSupportedLanguages();
45
- expect(languages).toContain(Language.TypeScript);
46
- expect(languages).toContain(Language.Python);
47
- expect(languages.length).toBeGreaterThanOrEqual(2);
48
- });
49
- it('should be case-insensitive for extensions', () => {
50
- expect(getParser('Test.TS')).toBeDefined();
51
- expect(getParser('Test.PY')).toBeDefined();
52
- });
53
- });
54
- describe('Language Detection', () => {
55
- it('should detect language from file path', () => {
56
- const factory = ParserFactory.getInstance();
57
- expect(factory.getLanguageForFile('src/index.ts')).toBe(
58
- Language.TypeScript
59
- );
60
- expect(factory.getLanguageForFile('src/component.tsx')).toBe(
61
- Language.TypeScript
62
- );
63
- expect(factory.getLanguageForFile('src/script.js')).toBe(
64
- Language.JavaScript
65
- );
66
- expect(factory.getLanguageForFile('src/main.py')).toBe(Language.Python);
67
- expect(factory.getLanguageForFile('README.md')).toBeNull();
68
- });
69
- });
70
- //# sourceMappingURL=parser-factory.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"parser-factory.test.js","sourceRoot":"","sources":["../../src/__tests__/parser-factory.test.ts"],"names":[],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Test Python parser
3
- */
4
- export {};
5
- //# sourceMappingURL=python-parser.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"python-parser.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/python-parser.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}