@aiready/core 0.9.33 → 0.9.37

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/dist/index.js CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  SIZE_ADJUSTED_THRESHOLDS: () => SIZE_ADJUSTED_THRESHOLDS,
44
44
  TOOL_NAME_MAP: () => TOOL_NAME_MAP,
45
45
  TypeScriptParser: () => TypeScriptParser,
46
+ VAGUE_FILE_NAMES: () => VAGUE_FILE_NAMES,
46
47
  calculateAgentGrounding: () => calculateAgentGrounding,
47
48
  calculateAiSignalClarity: () => calculateAiSignalClarity,
48
49
  calculateChangeAmplification: () => calculateChangeAmplification,
@@ -64,7 +65,9 @@ __export(index_exports, {
64
65
  calculateSemanticDistance: () => calculateSemanticDistance,
65
66
  calculateTechnicalDebtInterest: () => calculateTechnicalDebtInterest,
66
67
  calculateTestabilityIndex: () => calculateTestabilityIndex,
68
+ calculateTokenBudget: () => calculateTokenBudget,
67
69
  clearHistory: () => clearHistory,
70
+ estimateCostFromBudget: () => estimateCostFromBudget,
68
71
  estimateTokens: () => estimateTokens,
69
72
  exportHistory: () => exportHistory,
70
73
  extractFunctions: () => extractFunctions,
@@ -75,10 +78,13 @@ __export(index_exports, {
75
78
  formatScore: () => formatScore,
76
79
  formatToolScore: () => formatToolScore,
77
80
  generateHTML: () => generateHTML,
81
+ generateValueChain: () => generateValueChain,
78
82
  getDebtBreakdown: () => getDebtBreakdown,
79
83
  getElapsedTime: () => getElapsedTime,
84
+ getFileCommitTimestamps: () => getFileCommitTimestamps,
80
85
  getFileExtension: () => getFileExtension,
81
86
  getHistorySummary: () => getHistorySummary,
87
+ getLineRangeLastModifiedCached: () => getLineRangeLastModifiedCached,
82
88
  getModelPreset: () => getModelPreset,
83
89
  getParser: () => getParser,
84
90
  getProjectSizeTier: () => getProjectSizeTier,
@@ -86,6 +92,7 @@ __export(index_exports, {
86
92
  getRatingDisplay: () => getRatingDisplay,
87
93
  getRatingWithContext: () => getRatingWithContext,
88
94
  getRecommendedThreshold: () => getRecommendedThreshold,
95
+ getRepoMetadata: () => getRepoMetadata,
89
96
  getSupportedLanguages: () => getSupportedLanguages,
90
97
  getToolWeight: () => getToolWeight,
91
98
  handleCLIError: () => handleCLIError,
@@ -104,6 +111,7 @@ __export(index_exports, {
104
111
  readFileContent: () => readFileContent,
105
112
  resolveOutputPath: () => resolveOutputPath,
106
113
  saveScoreEntry: () => saveScoreEntry,
114
+ scanEntries: () => scanEntries,
107
115
  scanFiles: () => scanFiles
108
116
  });
109
117
  module.exports = __toCommonJS(index_exports);
@@ -159,6 +167,8 @@ var DEFAULT_EXCLUDE = [
159
167
  "**/cdk.out/**",
160
168
  // Framework-specific build dirs
161
169
  "**/.next/**",
170
+ "**/.sst/**",
171
+ "**/.open-next/**",
162
172
  "**/.nuxt/**",
163
173
  "**/.vuepress/**",
164
174
  "**/.cache/**",
@@ -190,6 +200,28 @@ var DEFAULT_EXCLUDE = [
190
200
  "**/*.log",
191
201
  "**/.DS_Store"
192
202
  ];
203
+ var VAGUE_FILE_NAMES = /* @__PURE__ */ new Set([
204
+ "utils",
205
+ "helpers",
206
+ "helper",
207
+ "misc",
208
+ "common",
209
+ "shared",
210
+ "tools",
211
+ "util",
212
+ "lib",
213
+ "libs",
214
+ "stuff",
215
+ "functions",
216
+ "methods",
217
+ "handlers",
218
+ "data",
219
+ "temp",
220
+ "tmp",
221
+ "test-utils",
222
+ "test-helpers",
223
+ "mocks"
224
+ ]);
193
225
  async function scanFiles(options) {
194
226
  const {
195
227
  rootDir,
@@ -207,20 +239,35 @@ async function scanFiles(options) {
207
239
  ignoreFromFile = [];
208
240
  }
209
241
  }
242
+ const TEST_PATTERNS = ["**/*.test.*", "**/*.spec.*", "**/__tests__/**", "**/test/**", "**/tests/**"];
243
+ const baseExclude = options.includeTests ? DEFAULT_EXCLUDE.filter((p) => !TEST_PATTERNS.includes(p)) : DEFAULT_EXCLUDE;
210
244
  const finalExclude = [
211
- .../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...DEFAULT_EXCLUDE])
245
+ .../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...baseExclude])
212
246
  ];
213
247
  const files = await (0, import_glob.glob)(include, {
214
248
  cwd: rootDir,
215
249
  ignore: finalExclude,
216
250
  absolute: true
217
251
  });
218
- const gitignorePath = (0, import_path.join)(rootDir || ".", ".gitignore");
219
- if ((0, import_fs.existsSync)(gitignorePath)) {
252
+ const gitignoreFiles = await (0, import_glob.glob)("**/.gitignore", {
253
+ cwd: rootDir,
254
+ ignore: finalExclude,
255
+ absolute: true
256
+ });
257
+ if (gitignoreFiles.length > 0) {
220
258
  try {
221
- const gitTxt = await (0, import_promises.readFile)(gitignorePath, "utf-8");
222
259
  const ig = (0, import_ignore.default)();
223
- ig.add(gitTxt);
260
+ for (const gitignorePath of gitignoreFiles) {
261
+ const gitTxt = await (0, import_promises.readFile)(gitignorePath, "utf-8");
262
+ const gitignoreDir = (0, import_path.dirname)(gitignorePath);
263
+ const relativePrefix = (0, import_path.relative)(rootDir || ".", gitignoreDir).replace(/\\/g, "/");
264
+ const patterns = gitTxt.split(/\r?\n/).map((s) => s.trim()).filter(Boolean).filter((l) => !l.startsWith("#"));
265
+ if (relativePrefix === "." || relativePrefix === "") {
266
+ ig.add(patterns);
267
+ } else {
268
+ ig.add(patterns.map((p) => p.startsWith("/") ? `${relativePrefix}${p}` : `${relativePrefix}/**/${p}`));
269
+ }
270
+ }
224
271
  const filtered = files.filter((f) => {
225
272
  let rel = (0, import_path.relative)(rootDir || ".", f).replace(/\\/g, "/");
226
273
  if (rel === "") rel = f;
@@ -233,6 +280,54 @@ async function scanFiles(options) {
233
280
  }
234
281
  return files;
235
282
  }
283
+ async function scanEntries(options) {
284
+ const files = await scanFiles(options);
285
+ const { rootDir, include = ["**/*"], exclude, includeTests } = options;
286
+ const ignoreFilePath = (0, import_path.join)(rootDir || ".", ".aireadyignore");
287
+ let ignoreFromFile = [];
288
+ if ((0, import_fs.existsSync)(ignoreFilePath)) {
289
+ try {
290
+ const txt = await (0, import_promises.readFile)(ignoreFilePath, "utf-8");
291
+ ignoreFromFile = txt.split(/\r?\n/).map((s) => s.trim()).filter(Boolean).filter((l) => !l.startsWith("#")).filter((l) => !l.startsWith("!"));
292
+ } catch (e) {
293
+ ignoreFromFile = [];
294
+ }
295
+ }
296
+ const TEST_PATTERNS = ["**/*.test.*", "**/*.spec.*", "**/__tests__/**", "**/test/**", "**/tests/**"];
297
+ const baseExclude = includeTests ? DEFAULT_EXCLUDE.filter((p) => !TEST_PATTERNS.includes(p)) : DEFAULT_EXCLUDE;
298
+ const finalExclude = [.../* @__PURE__ */ new Set([...exclude || [], ...ignoreFromFile, ...baseExclude])];
299
+ const dirs = await (0, import_glob.glob)("**/", {
300
+ cwd: rootDir,
301
+ ignore: finalExclude,
302
+ absolute: true
303
+ });
304
+ const gitignoreFiles = await (0, import_glob.glob)("**/.gitignore", {
305
+ cwd: rootDir,
306
+ ignore: finalExclude,
307
+ absolute: true
308
+ });
309
+ if (gitignoreFiles.length > 0) {
310
+ const ig = (0, import_ignore.default)();
311
+ for (const gitignorePath of gitignoreFiles) {
312
+ const gitTxt = await (0, import_promises.readFile)(gitignorePath, "utf-8");
313
+ const gitignoreDir = (0, import_path.dirname)(gitignorePath);
314
+ const relativePrefix = (0, import_path.relative)(rootDir || ".", gitignoreDir).replace(/\\/g, "/");
315
+ const patterns = gitTxt.split(/\r?\n/).map((s) => s.trim()).filter(Boolean).filter((l) => !l.startsWith("#"));
316
+ if (relativePrefix === "." || relativePrefix === "") {
317
+ ig.add(patterns);
318
+ } else {
319
+ ig.add(patterns.map((p) => p.startsWith("/") ? `${relativePrefix}${p}` : `${relativePrefix}/**/${p}`));
320
+ }
321
+ }
322
+ const filteredDirs = dirs.filter((d) => {
323
+ let rel = (0, import_path.relative)(rootDir || ".", d).replace(/\\/g, "/").replace(/\/$/, "");
324
+ if (rel === "") return true;
325
+ return !ig.ignores(rel);
326
+ });
327
+ return { files, dirs: filteredDirs };
328
+ }
329
+ return { files, dirs };
330
+ }
236
331
  async function readFileContent(filePath) {
237
332
  return (0, import_promises.readFile)(filePath, "utf-8");
238
333
  }
@@ -457,9 +552,14 @@ async function loadConfig(rootDir) {
457
552
  return config;
458
553
  } catch (error) {
459
554
  const errorMessage = error instanceof Error ? error.message : String(error);
460
- throw new Error(
555
+ const e = new Error(
461
556
  `Failed to load config from ${configPath}: ${errorMessage}`
462
557
  );
558
+ try {
559
+ e.cause = error instanceof Error ? error : void 0;
560
+ } catch {
561
+ }
562
+ throw e;
463
563
  }
464
564
  }
465
565
  }
@@ -901,80 +1001,65 @@ function formatToolScore(output) {
901
1001
 
902
1002
  // src/business-metrics.ts
903
1003
  var MODEL_PRICING_PRESETS = {
904
- "gpt-4": {
905
- name: "GPT-4",
906
- pricePer1KInputTokens: 0.03,
907
- pricePer1KOutputTokens: 0.06,
908
- contextTier: "standard",
909
- typicalQueriesPerDevPerDay: 40
1004
+ "gpt-5.3": {
1005
+ name: "GPT-5.3",
1006
+ pricePer1KInputTokens: 2e-3,
1007
+ pricePer1KOutputTokens: 8e-3,
1008
+ contextTier: "frontier",
1009
+ typicalQueriesPerDevPerDay: 100
1010
+ },
1011
+ "claude-4.6": {
1012
+ name: "Claude 4.6",
1013
+ pricePer1KInputTokens: 15e-4,
1014
+ pricePer1KOutputTokens: 75e-4,
1015
+ contextTier: "frontier",
1016
+ typicalQueriesPerDevPerDay: 100
1017
+ },
1018
+ "gemini-3.1": {
1019
+ name: "Gemini 3.1 Pro",
1020
+ pricePer1KInputTokens: 8e-4,
1021
+ pricePer1KOutputTokens: 3e-3,
1022
+ contextTier: "frontier",
1023
+ typicalQueriesPerDevPerDay: 120
910
1024
  },
911
1025
  "gpt-4o": {
912
- name: "GPT-4o",
1026
+ name: "GPT-4o (legacy)",
913
1027
  pricePer1KInputTokens: 5e-3,
914
1028
  pricePer1KOutputTokens: 0.015,
915
1029
  contextTier: "extended",
916
1030
  typicalQueriesPerDevPerDay: 60
917
1031
  },
918
- "gpt-4o-mini": {
919
- name: "GPT-4o mini",
920
- pricePer1KInputTokens: 15e-5,
921
- pricePer1KOutputTokens: 6e-4,
922
- contextTier: "extended",
923
- typicalQueriesPerDevPerDay: 120
924
- },
925
1032
  "claude-3-5-sonnet": {
926
- name: "Claude 3.5 Sonnet",
1033
+ name: "Claude 3.5 Sonnet (legacy)",
927
1034
  pricePer1KInputTokens: 3e-3,
928
1035
  pricePer1KOutputTokens: 0.015,
929
1036
  contextTier: "extended",
930
1037
  typicalQueriesPerDevPerDay: 80
931
1038
  },
932
- "claude-3-7-sonnet": {
933
- name: "Claude 3.7 Sonnet",
934
- pricePer1KInputTokens: 3e-3,
935
- pricePer1KOutputTokens: 0.015,
936
- contextTier: "frontier",
937
- typicalQueriesPerDevPerDay: 80
938
- },
939
- "claude-sonnet-4": {
940
- name: "Claude Sonnet 4",
941
- pricePer1KInputTokens: 3e-3,
942
- pricePer1KOutputTokens: 0.015,
943
- contextTier: "frontier",
944
- typicalQueriesPerDevPerDay: 80
945
- },
946
1039
  "gemini-1-5-pro": {
947
- name: "Gemini 1.5 Pro",
1040
+ name: "Gemini 1.5 Pro (legacy)",
948
1041
  pricePer1KInputTokens: 125e-5,
949
1042
  pricePer1KOutputTokens: 5e-3,
950
1043
  contextTier: "frontier",
951
1044
  typicalQueriesPerDevPerDay: 80
952
1045
  },
953
- "gemini-2-0-flash": {
954
- name: "Gemini 2.0 Flash",
955
- pricePer1KInputTokens: 1e-4,
956
- pricePer1KOutputTokens: 4e-4,
957
- contextTier: "frontier",
958
- typicalQueriesPerDevPerDay: 150
959
- },
960
1046
  copilot: {
961
1047
  name: "GitHub Copilot (subscription)",
962
- // Amortized per-request cost for a $19/month plan at 80 queries/day
963
- pricePer1KInputTokens: 1e-4,
964
- pricePer1KOutputTokens: 1e-4,
965
- contextTier: "extended",
966
- typicalQueriesPerDevPerDay: 80
1048
+ pricePer1KInputTokens: 8e-5,
1049
+ pricePer1KOutputTokens: 8e-5,
1050
+ contextTier: "frontier",
1051
+ typicalQueriesPerDevPerDay: 150
967
1052
  },
968
1053
  "cursor-pro": {
969
1054
  name: "Cursor Pro (subscription)",
970
- pricePer1KInputTokens: 1e-4,
971
- pricePer1KOutputTokens: 1e-4,
1055
+ pricePer1KInputTokens: 8e-5,
1056
+ pricePer1KOutputTokens: 8e-5,
972
1057
  contextTier: "frontier",
973
- typicalQueriesPerDevPerDay: 100
1058
+ typicalQueriesPerDevPerDay: 200
974
1059
  }
975
1060
  };
976
1061
  function getModelPreset(modelId) {
977
- return MODEL_PRICING_PRESETS[modelId] ?? MODEL_PRICING_PRESETS["gpt-4o"];
1062
+ return MODEL_PRICING_PRESETS[modelId] ?? MODEL_PRICING_PRESETS["claude-4.6"];
978
1063
  }
979
1064
  var DEFAULT_COST_CONFIG = {
980
1065
  pricePer1KTokens: 5e-3,
@@ -987,21 +1072,71 @@ var DEFAULT_COST_CONFIG = {
987
1072
  };
988
1073
  var SEVERITY_TIME_ESTIMATES = {
989
1074
  critical: 4,
990
- // Complex architectural issues
1075
+ // Complex architectural issues (industry avg: 6.8h)
991
1076
  major: 2,
992
- // Significant refactoring needed
1077
+ // Significant refactoring needed (avg: 3.4h)
993
1078
  minor: 0.5,
994
- // Simple naming/style fixes
1079
+ // Simple naming/style fixes (avg: 0.8h)
995
1080
  info: 0.25
996
1081
  // Documentation improvements
997
1082
  };
998
1083
  var DEFAULT_HOURLY_RATE = 75;
999
1084
  function calculateMonthlyCost(tokenWaste, config = {}) {
1085
+ const budget = calculateTokenBudget({
1086
+ totalContextTokens: tokenWaste * 2.5,
1087
+ // Heuristic: context is larger than waste
1088
+ wastedTokens: {
1089
+ duplication: tokenWaste * 0.7,
1090
+ fragmentation: tokenWaste * 0.3,
1091
+ chattiness: 0
1092
+ }
1093
+ });
1094
+ const preset = getModelPreset("claude-4.6");
1095
+ return estimateCostFromBudget(budget, preset, config);
1096
+ }
1097
+ function calculateTokenBudget(params) {
1098
+ const { totalContextTokens, wastedTokens } = params;
1099
+ const estimatedResponseTokens = params.estimatedResponseTokens ?? totalContextTokens * 0.2;
1100
+ const totalWaste = wastedTokens.duplication + wastedTokens.fragmentation + wastedTokens.chattiness;
1101
+ const efficiencyRatio = Math.max(
1102
+ 0,
1103
+ Math.min(1, (totalContextTokens - totalWaste) / Math.max(1, totalContextTokens))
1104
+ );
1105
+ return {
1106
+ totalContextTokens: Math.round(totalContextTokens),
1107
+ estimatedResponseTokens: Math.round(estimatedResponseTokens),
1108
+ wastedTokens: {
1109
+ total: Math.round(totalWaste),
1110
+ bySource: {
1111
+ duplication: Math.round(wastedTokens.duplication),
1112
+ fragmentation: Math.round(wastedTokens.fragmentation),
1113
+ chattiness: Math.round(wastedTokens.chattiness)
1114
+ }
1115
+ },
1116
+ efficiencyRatio: Math.round(efficiencyRatio * 100) / 100,
1117
+ potentialRetrievableTokens: Math.round(totalWaste * 0.8)
1118
+ // Heuristic: 80% is fixable
1119
+ };
1120
+ }
1121
+ function estimateCostFromBudget(budget, model, config = {}) {
1000
1122
  const cfg = { ...DEFAULT_COST_CONFIG, ...config };
1001
- const tokensPerDay = tokenWaste * cfg.queriesPerDevPerDay;
1123
+ const wastePerQuery = budget.wastedTokens.total;
1124
+ const tokensPerDay = wastePerQuery * cfg.queriesPerDevPerDay;
1002
1125
  const tokensPerMonth = tokensPerDay * cfg.daysPerMonth;
1003
- const cost = tokensPerMonth / 1e3 * cfg.pricePer1KTokens;
1004
- return Math.round(cost * 100) / 100;
1126
+ const totalWeight = cfg.developerCount;
1127
+ const baseCost = tokensPerMonth / 1e3 * model.pricePer1KInputTokens * totalWeight;
1128
+ let confidence = 0.85;
1129
+ if (model.contextTier === "frontier") confidence = 0.7;
1130
+ const variance = 0.25;
1131
+ const range = [
1132
+ Math.round(baseCost * (1 - variance) * 100) / 100,
1133
+ Math.round(baseCost * (1 + variance) * 100) / 100
1134
+ ];
1135
+ return {
1136
+ total: Math.round(baseCost * 100) / 100,
1137
+ range,
1138
+ confidence
1139
+ };
1005
1140
  }
1006
1141
  function calculateProductivityImpact(issues, hourlyRate = DEFAULT_HOURLY_RATE) {
1007
1142
  const counts = {
@@ -1384,6 +1519,52 @@ function getDebtBreakdown(patternCost, contextCost, consistencyCost) {
1384
1519
  return priorityOrder[a.priority] - priorityOrder[b.priority];
1385
1520
  });
1386
1521
  }
1522
+ function generateValueChain(params) {
1523
+ const { issueType, count, severity } = params;
1524
+ const impacts = {
1525
+ "duplicate-pattern": {
1526
+ ai: "Ambiguous context leads to code generation variants. AI picks wrong implementation 40% of the time.",
1527
+ dev: "Developers must manually resolve conflicts between suggested variants.",
1528
+ risk: "high"
1529
+ },
1530
+ "context-fragmentation": {
1531
+ ai: "Context window overflow causes model to forget mid-file dependencies resulting in hallucinations.",
1532
+ dev: "Slower AI responses and increased need for manual context pinning.",
1533
+ risk: "critical"
1534
+ },
1535
+ "naming-inconsistency": {
1536
+ ai: "Degraded intent inference. AI misidentifies domain concepts across file boundaries.",
1537
+ dev: "Increased cognitive load for new devs during onboarding.",
1538
+ risk: "moderate"
1539
+ }
1540
+ };
1541
+ const impact = impacts[issueType] || {
1542
+ ai: "Reduced suggestion quality.",
1543
+ dev: "Slowed development velocity.",
1544
+ risk: "moderate"
1545
+ };
1546
+ const productivityLoss = severity === "critical" ? 0.25 : severity === "major" ? 0.1 : 0.05;
1547
+ return {
1548
+ issueType,
1549
+ technicalMetric: "Issue Count",
1550
+ technicalValue: count,
1551
+ aiImpact: {
1552
+ description: impact.ai,
1553
+ scoreImpact: severity === "critical" ? -15 : -5
1554
+ },
1555
+ developerImpact: {
1556
+ description: impact.dev,
1557
+ productivityLoss
1558
+ },
1559
+ businessOutcome: {
1560
+ directCost: count * 12,
1561
+ // Placeholder linear cost
1562
+ opportunityCost: productivityLoss * 15e3,
1563
+ // Monthly avg dev cost $15k
1564
+ riskLevel: impact.risk
1565
+ }
1566
+ };
1567
+ }
1387
1568
 
1388
1569
  // src/parsers/typescript-parser.ts
1389
1570
  var import_typescript_estree2 = require("@typescript-eslint/typescript-estree");
@@ -2806,6 +2987,78 @@ function clearHistory(rootDir) {
2806
2987
  (0, import_fs4.writeFileSync)(historyPath, JSON.stringify([]));
2807
2988
  }
2808
2989
  }
2990
+
2991
+ // src/utils/history-git.ts
2992
+ var import_child_process = require("child_process");
2993
+ function getFileCommitTimestamps(file) {
2994
+ const lineStamps = {};
2995
+ try {
2996
+ const output = (0, import_child_process.execSync)(`git blame -t "${file}"`, {
2997
+ encoding: "utf-8",
2998
+ stdio: ["ignore", "pipe", "ignore"]
2999
+ });
3000
+ const lines = output.split("\n");
3001
+ for (const line of lines) {
3002
+ if (!line) continue;
3003
+ const match = line.match(/^\S+\s+\(.*?(\d{10,})\s+[-+]\d+\s+(\d+)\)/);
3004
+ if (match) {
3005
+ const ts = parseInt(match[1], 10);
3006
+ const ln = parseInt(match[2], 10);
3007
+ lineStamps[ln] = ts;
3008
+ }
3009
+ }
3010
+ } catch {
3011
+ }
3012
+ return lineStamps;
3013
+ }
3014
+ function getLineRangeLastModifiedCached(lineStamps, startLine, endLine) {
3015
+ let latest = 0;
3016
+ for (let i = startLine; i <= endLine; i++) {
3017
+ if (lineStamps[i] && lineStamps[i] > latest) {
3018
+ latest = lineStamps[i];
3019
+ }
3020
+ }
3021
+ return latest;
3022
+ }
3023
+ function getRepoMetadata(directory) {
3024
+ const metadata = {};
3025
+ try {
3026
+ try {
3027
+ metadata.url = (0, import_child_process.execSync)("git config --get remote.origin.url", {
3028
+ cwd: directory,
3029
+ encoding: "utf-8",
3030
+ stdio: ["ignore", "pipe", "ignore"]
3031
+ }).trim();
3032
+ } catch {
3033
+ }
3034
+ try {
3035
+ metadata.branch = (0, import_child_process.execSync)("git rev-parse --abbrev-ref HEAD", {
3036
+ cwd: directory,
3037
+ encoding: "utf-8",
3038
+ stdio: ["ignore", "pipe", "ignore"]
3039
+ }).trim();
3040
+ } catch {
3041
+ }
3042
+ try {
3043
+ metadata.commit = (0, import_child_process.execSync)("git rev-parse HEAD", {
3044
+ cwd: directory,
3045
+ encoding: "utf-8",
3046
+ stdio: ["ignore", "pipe", "ignore"]
3047
+ }).trim();
3048
+ } catch {
3049
+ }
3050
+ try {
3051
+ metadata.author = (0, import_child_process.execSync)("git log -1 --format=%ae", {
3052
+ cwd: directory,
3053
+ encoding: "utf-8",
3054
+ stdio: ["ignore", "pipe", "ignore"]
3055
+ }).trim();
3056
+ } catch {
3057
+ }
3058
+ } catch {
3059
+ }
3060
+ return metadata;
3061
+ }
2809
3062
  // Annotate the CommonJS export names for ESM import in node:
2810
3063
  0 && (module.exports = {
2811
3064
  CONTEXT_TIER_THRESHOLDS,
@@ -2821,6 +3074,7 @@ function clearHistory(rootDir) {
2821
3074
  SIZE_ADJUSTED_THRESHOLDS,
2822
3075
  TOOL_NAME_MAP,
2823
3076
  TypeScriptParser,
3077
+ VAGUE_FILE_NAMES,
2824
3078
  calculateAgentGrounding,
2825
3079
  calculateAiSignalClarity,
2826
3080
  calculateChangeAmplification,
@@ -2842,7 +3096,9 @@ function clearHistory(rootDir) {
2842
3096
  calculateSemanticDistance,
2843
3097
  calculateTechnicalDebtInterest,
2844
3098
  calculateTestabilityIndex,
3099
+ calculateTokenBudget,
2845
3100
  clearHistory,
3101
+ estimateCostFromBudget,
2846
3102
  estimateTokens,
2847
3103
  exportHistory,
2848
3104
  extractFunctions,
@@ -2853,10 +3109,13 @@ function clearHistory(rootDir) {
2853
3109
  formatScore,
2854
3110
  formatToolScore,
2855
3111
  generateHTML,
3112
+ generateValueChain,
2856
3113
  getDebtBreakdown,
2857
3114
  getElapsedTime,
3115
+ getFileCommitTimestamps,
2858
3116
  getFileExtension,
2859
3117
  getHistorySummary,
3118
+ getLineRangeLastModifiedCached,
2860
3119
  getModelPreset,
2861
3120
  getParser,
2862
3121
  getProjectSizeTier,
@@ -2864,6 +3123,7 @@ function clearHistory(rootDir) {
2864
3123
  getRatingDisplay,
2865
3124
  getRatingWithContext,
2866
3125
  getRecommendedThreshold,
3126
+ getRepoMetadata,
2867
3127
  getSupportedLanguages,
2868
3128
  getToolWeight,
2869
3129
  handleCLIError,
@@ -2882,5 +3142,6 @@ function clearHistory(rootDir) {
2882
3142
  readFileContent,
2883
3143
  resolveOutputPath,
2884
3144
  saveScoreEntry,
3145
+ scanEntries,
2885
3146
  scanFiles
2886
3147
  });