@aiready/core 0.23.15 → 0.23.20

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
@@ -91,6 +91,7 @@ __export(index_exports, {
91
91
  calculateConceptCohesion: () => calculateConceptCohesion,
92
92
  calculateDebtInterest: () => calculateDebtInterest,
93
93
  calculateDependencyHealth: () => calculateDependencyHealth,
94
+ calculateDetailedTokenROI: () => calculateDetailedTokenROI,
94
95
  calculateDocDrift: () => calculateDocDrift,
95
96
  calculateExtendedFutureProofScore: () => calculateExtendedFutureProofScore,
96
97
  calculateFutureProofScore: () => calculateFutureProofScore,
@@ -119,7 +120,12 @@ __export(index_exports, {
119
120
  formatHours: () => formatHours,
120
121
  formatScore: () => formatScore,
121
122
  formatToolScore: () => formatToolScore,
123
+ generateCompleteReport: () => generateCompleteReport,
122
124
  generateHTML: () => generateHTML,
125
+ generateReportFooter: () => generateReportFooter,
126
+ generateReportHead: () => generateReportHead,
127
+ generateStatCards: () => generateStatCards,
128
+ generateTable: () => generateTable,
123
129
  generateValueChain: () => generateValueChain,
124
130
  getElapsedTime: () => getElapsedTime,
125
131
  getFileCommitTimestamps: () => getFileCommitTimestamps,
@@ -128,9 +134,12 @@ __export(index_exports, {
128
134
  getLineRangeLastModifiedCached: () => getLineRangeLastModifiedCached,
129
135
  getModelPreset: () => getModelPreset,
130
136
  getParser: () => getParser,
137
+ getPriorityIcon: () => getPriorityIcon,
131
138
  getProjectSizeTier: () => getProjectSizeTier,
132
139
  getRating: () => getRating,
133
140
  getRatingDisplay: () => getRatingDisplay,
141
+ getRatingEmoji: () => getRatingEmoji,
142
+ getRatingLabel: () => getRatingLabel,
134
143
  getRatingSlug: () => getRatingSlug,
135
144
  getRatingWithContext: () => getRatingWithContext,
136
145
  getRecommendedThreshold: () => getRecommendedThreshold,
@@ -143,6 +152,7 @@ __export(index_exports, {
143
152
  getSeverityLevel: () => getSeverityLevel,
144
153
  getSeverityValue: () => getSeverityValue,
145
154
  getSupportedLanguages: () => getSupportedLanguages,
155
+ getToolEmoji: () => getToolEmoji,
146
156
  getToolWeight: () => getToolWeight,
147
157
  getWasmPath: () => getWasmPath,
148
158
  groupIssuesByFile: () => groupIssuesByFile,
@@ -172,12 +182,71 @@ __export(index_exports, {
172
182
  setupParser: () => setupParser,
173
183
  severityToAnnotationLevel: () => severityToAnnotationLevel,
174
184
  validateSpokeOutput: () => validateSpokeOutput,
175
- validateWithSchema: () => validateWithSchema
185
+ validateWithSchema: () => validateWithSchema,
186
+ wrapInCard: () => wrapInCard
176
187
  });
177
188
  module.exports = __toCommonJS(index_exports);
178
189
 
179
- // src/types/schema.ts
190
+ // src/types/business.ts
180
191
  var import_zod = require("zod");
192
+ var LeadSource = /* @__PURE__ */ ((LeadSource2) => {
193
+ LeadSource2["ClawMoreHero"] = "clawmore-hero";
194
+ LeadSource2["ClawMoreWaitlist"] = "clawmore-waitlist";
195
+ LeadSource2["ClawMoreBeta"] = "clawmore-beta";
196
+ LeadSource2["AiReadyPlatform"] = "aiready-platform";
197
+ return LeadSource2;
198
+ })(LeadSource || {});
199
+ var LeadSourceSchema = import_zod.z.nativeEnum(LeadSource);
200
+ var LeadSchema = import_zod.z.object({
201
+ id: import_zod.z.string(),
202
+ email: import_zod.z.string().email(),
203
+ name: import_zod.z.string().min(1),
204
+ interest: import_zod.z.string().default("General"),
205
+ notes: import_zod.z.string().optional(),
206
+ timestamp: import_zod.z.string().datetime(),
207
+ source: LeadSourceSchema,
208
+ status: import_zod.z.enum(["new", "contacted", "qualified", "converted", "archived"]).default("new")
209
+ });
210
+ var LeadSubmissionSchema = LeadSchema.omit({
211
+ id: true,
212
+ timestamp: true,
213
+ status: true
214
+ });
215
+ var ManagedAccountSchema = import_zod.z.object({
216
+ id: import_zod.z.string(),
217
+ // Internal UUID
218
+ accountId: import_zod.z.string(),
219
+ // AWS Account ID
220
+ userId: import_zod.z.string(),
221
+ // Owner (caopengau@gmail.com)
222
+ stripeSubscriptionId: import_zod.z.string(),
223
+ // AI Token Management
224
+ tokenStrategy: import_zod.z.enum(["managed", "byok"]).default("managed"),
225
+ byokConfig: import_zod.z.object({
226
+ openaiKey: import_zod.z.string().optional(),
227
+ anthropicKey: import_zod.z.string().optional(),
228
+ openrouterKey: import_zod.z.string().optional()
229
+ }).optional(),
230
+ // Financials (in cents)
231
+ baseFeeCents: import_zod.z.number().default(2900),
232
+ includedComputeCents: import_zod.z.number().default(1500),
233
+ // $15.00 AWS included
234
+ includedTokenCents: import_zod.z.number().default(500),
235
+ // $5.00 Managed Tokens included
236
+ // Pre-paid Balance (credits)
237
+ prepaidTokenBalanceCents: import_zod.z.number().default(0),
238
+ // Users buy these in $10 packs
239
+ currentMonthlyTokenSpendCents: import_zod.z.number().default(0),
240
+ // Governance
241
+ status: import_zod.z.enum(["provisioning", "active", "warning", "quarantined", "suspended"]).default("provisioning"),
242
+ lastCostSyncAt: import_zod.z.string().datetime().optional(),
243
+ region: import_zod.z.string().default("ap-southeast-2"),
244
+ // Alerting thresholds (percentage of includedComputeCents)
245
+ alertThresholds: import_zod.z.array(import_zod.z.number()).default([50, 80, 100, 150])
246
+ });
247
+
248
+ // src/types/enums.ts
249
+ var import_zod2 = require("zod");
181
250
  var Severity = /* @__PURE__ */ ((Severity2) => {
182
251
  Severity2["Critical"] = "critical";
183
252
  Severity2["Major"] = "major";
@@ -185,7 +254,7 @@ var Severity = /* @__PURE__ */ ((Severity2) => {
185
254
  Severity2["Info"] = "info";
186
255
  return Severity2;
187
256
  })(Severity || {});
188
- var SeveritySchema = import_zod.z.nativeEnum(Severity);
257
+ var SeveritySchema = import_zod2.z.nativeEnum(Severity);
189
258
  var ToolName = /* @__PURE__ */ ((ToolName3) => {
190
259
  ToolName3["PatternDetect"] = "pattern-detect";
191
260
  ToolName3["ContextAnalyzer"] = "context-analyzer";
@@ -202,7 +271,7 @@ var ToolName = /* @__PURE__ */ ((ToolName3) => {
202
271
  ToolName3["SemanticDistance"] = "semantic-distance";
203
272
  return ToolName3;
204
273
  })(ToolName || {});
205
- var ToolNameSchema = import_zod.z.nativeEnum(ToolName);
274
+ var ToolNameSchema = import_zod2.z.nativeEnum(ToolName);
206
275
  var FRIENDLY_TOOL_NAMES = {
207
276
  ["pattern-detect" /* PatternDetect */]: "Semantic Duplicates",
208
277
  ["context-analyzer" /* ContextAnalyzer */]: "Context Fragmentation",
@@ -239,14 +308,14 @@ var IssueType = /* @__PURE__ */ ((IssueType2) => {
239
308
  IssueType2["ChangeAmplification"] = "change-amplification";
240
309
  return IssueType2;
241
310
  })(IssueType || {});
242
- var IssueTypeSchema = import_zod.z.nativeEnum(IssueType);
311
+ var IssueTypeSchema = import_zod2.z.nativeEnum(IssueType);
243
312
  var AnalysisStatus = /* @__PURE__ */ ((AnalysisStatus2) => {
244
313
  AnalysisStatus2["Processing"] = "processing";
245
314
  AnalysisStatus2["Completed"] = "completed";
246
315
  AnalysisStatus2["Failed"] = "failed";
247
316
  return AnalysisStatus2;
248
317
  })(AnalysisStatus || {});
249
- var AnalysisStatusSchema = import_zod.z.nativeEnum(AnalysisStatus);
318
+ var AnalysisStatusSchema = import_zod2.z.nativeEnum(AnalysisStatus);
250
319
  var ModelTier = /* @__PURE__ */ ((ModelTier2) => {
251
320
  ModelTier2["Compact"] = "compact";
252
321
  ModelTier2["Standard"] = "standard";
@@ -254,192 +323,149 @@ var ModelTier = /* @__PURE__ */ ((ModelTier2) => {
254
323
  ModelTier2["Frontier"] = "frontier";
255
324
  return ModelTier2;
256
325
  })(ModelTier || {});
257
- var ModelTierSchema = import_zod.z.nativeEnum(ModelTier);
258
- var LocationSchema = import_zod.z.object({
259
- file: import_zod.z.string(),
260
- line: import_zod.z.number(),
261
- column: import_zod.z.number().optional(),
262
- endLine: import_zod.z.number().optional(),
263
- endColumn: import_zod.z.number().optional()
326
+ var ModelTierSchema = import_zod2.z.nativeEnum(ModelTier);
327
+
328
+ // src/types/common.ts
329
+ var import_zod3 = require("zod");
330
+ var LocationSchema = import_zod3.z.object({
331
+ file: import_zod3.z.string(),
332
+ line: import_zod3.z.number(),
333
+ column: import_zod3.z.number().optional(),
334
+ endLine: import_zod3.z.number().optional(),
335
+ endColumn: import_zod3.z.number().optional()
264
336
  });
265
- var IssueSchema = import_zod.z.object({
337
+
338
+ // src/types/schemas/issue.ts
339
+ var import_zod4 = require("zod");
340
+ var IssueSchema = import_zod4.z.object({
266
341
  type: IssueTypeSchema,
267
342
  severity: SeveritySchema,
268
- message: import_zod.z.string(),
343
+ message: import_zod4.z.string(),
269
344
  location: LocationSchema,
270
- suggestion: import_zod.z.string().optional()
345
+ suggestion: import_zod4.z.string().optional()
271
346
  });
272
- var MetricsSchema = import_zod.z.object({
273
- tokenCost: import_zod.z.number().optional(),
274
- complexityScore: import_zod.z.number().optional(),
275
- consistencyScore: import_zod.z.number().optional(),
276
- docFreshnessScore: import_zod.z.number().optional(),
347
+
348
+ // src/types/schemas/metrics.ts
349
+ var import_zod5 = require("zod");
350
+ var MetricsSchema = import_zod5.z.object({
351
+ tokenCost: import_zod5.z.number().optional(),
352
+ complexityScore: import_zod5.z.number().optional(),
353
+ consistencyScore: import_zod5.z.number().optional(),
354
+ docFreshnessScore: import_zod5.z.number().optional(),
277
355
  // AI agent readiness metrics (v0.12+)
278
- aiSignalClarityScore: import_zod.z.number().optional(),
279
- agentGroundingScore: import_zod.z.number().optional(),
280
- testabilityScore: import_zod.z.number().optional(),
281
- docDriftScore: import_zod.z.number().optional(),
282
- dependencyHealthScore: import_zod.z.number().optional(),
356
+ aiSignalClarityScore: import_zod5.z.number().optional(),
357
+ agentGroundingScore: import_zod5.z.number().optional(),
358
+ testabilityScore: import_zod5.z.number().optional(),
359
+ docDriftScore: import_zod5.z.number().optional(),
360
+ dependencyHealthScore: import_zod5.z.number().optional(),
283
361
  modelContextTier: ModelTierSchema.optional(),
284
362
  // Business value metrics
285
- estimatedMonthlyCost: import_zod.z.number().optional(),
286
- estimatedDeveloperHours: import_zod.z.number().optional(),
287
- comprehensionDifficultyIndex: import_zod.z.number().optional(),
363
+ estimatedMonthlyCost: import_zod5.z.number().optional(),
364
+ estimatedDeveloperHours: import_zod5.z.number().optional(),
365
+ comprehensionDifficultyIndex: import_zod5.z.number().optional(),
288
366
  // Extended metrics for specific spokes
289
- totalSymbols: import_zod.z.number().optional(),
290
- totalExports: import_zod.z.number().optional()
367
+ totalSymbols: import_zod5.z.number().optional(),
368
+ totalExports: import_zod5.z.number().optional()
291
369
  });
292
- var AnalysisResultSchema = import_zod.z.object({
293
- fileName: import_zod.z.string(),
294
- issues: import_zod.z.array(IssueSchema),
370
+
371
+ // src/types/schemas/report.ts
372
+ var import_zod6 = require("zod");
373
+ var AnalysisResultSchema = import_zod6.z.object({
374
+ fileName: import_zod6.z.string(),
375
+ issues: import_zod6.z.array(IssueSchema),
295
376
  metrics: MetricsSchema
296
377
  });
297
- var SpokeSummarySchema = import_zod.z.object({
298
- totalFiles: import_zod.z.number().optional(),
299
- totalIssues: import_zod.z.number().optional(),
300
- criticalIssues: import_zod.z.number().optional(),
301
- majorIssues: import_zod.z.number().optional(),
302
- score: import_zod.z.number().optional()
303
- }).catchall(import_zod.z.any());
304
- var SpokeOutputSchema = import_zod.z.object({
305
- results: import_zod.z.array(AnalysisResultSchema),
378
+ var SpokeSummarySchema = import_zod6.z.object({
379
+ totalFiles: import_zod6.z.number().optional(),
380
+ totalIssues: import_zod6.z.number().optional(),
381
+ criticalIssues: import_zod6.z.number().optional(),
382
+ majorIssues: import_zod6.z.number().optional(),
383
+ score: import_zod6.z.number().optional()
384
+ }).catchall(import_zod6.z.any());
385
+ var SpokeOutputSchema = import_zod6.z.object({
386
+ results: import_zod6.z.array(AnalysisResultSchema),
306
387
  summary: SpokeSummarySchema,
307
- metadata: import_zod.z.object({
308
- toolName: import_zod.z.string(),
309
- version: import_zod.z.string().optional(),
310
- timestamp: import_zod.z.string().optional(),
311
- config: import_zod.z.any().optional()
312
- }).catchall(import_zod.z.any()).optional()
388
+ metadata: import_zod6.z.object({
389
+ toolName: import_zod6.z.string(),
390
+ version: import_zod6.z.string().optional(),
391
+ timestamp: import_zod6.z.string().optional(),
392
+ config: import_zod6.z.any().optional()
393
+ }).catchall(import_zod6.z.any()).optional()
313
394
  });
314
- var UnifiedReportSchema = import_zod.z.object({
315
- summary: import_zod.z.object({
316
- totalFiles: import_zod.z.number(),
317
- totalIssues: import_zod.z.number(),
318
- criticalIssues: import_zod.z.number(),
319
- majorIssues: import_zod.z.number(),
320
- businessImpact: import_zod.z.object({
321
- estimatedMonthlyWaste: import_zod.z.number().optional(),
322
- potentialSavings: import_zod.z.number().optional(),
323
- productivityHours: import_zod.z.number().optional()
395
+ var UnifiedReportSchema = import_zod6.z.object({
396
+ summary: import_zod6.z.object({
397
+ totalFiles: import_zod6.z.number(),
398
+ totalIssues: import_zod6.z.number(),
399
+ criticalIssues: import_zod6.z.number(),
400
+ majorIssues: import_zod6.z.number(),
401
+ businessImpact: import_zod6.z.object({
402
+ estimatedMonthlyWaste: import_zod6.z.number().optional(),
403
+ potentialSavings: import_zod6.z.number().optional(),
404
+ productivityHours: import_zod6.z.number().optional()
324
405
  }).optional()
325
406
  }),
326
- results: import_zod.z.array(AnalysisResultSchema),
327
- scoring: import_zod.z.object({
328
- overall: import_zod.z.number(),
329
- rating: import_zod.z.string(),
330
- timestamp: import_zod.z.string(),
331
- breakdown: import_zod.z.array(
332
- import_zod.z.object({
333
- toolName: import_zod.z.union([ToolNameSchema, import_zod.z.string()]),
334
- score: import_zod.z.number()
335
- }).catchall(import_zod.z.any())
407
+ results: import_zod6.z.array(AnalysisResultSchema),
408
+ scoring: import_zod6.z.object({
409
+ overall: import_zod6.z.number(),
410
+ rating: import_zod6.z.string(),
411
+ timestamp: import_zod6.z.string(),
412
+ breakdown: import_zod6.z.array(
413
+ import_zod6.z.object({
414
+ toolName: import_zod6.z.union([ToolNameSchema, import_zod6.z.string()]),
415
+ score: import_zod6.z.number()
416
+ }).catchall(import_zod6.z.any())
336
417
  )
337
418
  }).optional()
338
- }).catchall(import_zod.z.any());
339
- var AIReadyConfigSchema = import_zod.z.object({
419
+ }).catchall(import_zod6.z.any());
420
+
421
+ // src/types/schemas/config.ts
422
+ var import_zod7 = require("zod");
423
+ var AIReadyConfigSchema = import_zod7.z.object({
340
424
  /** Target score threshold (0-100) */
341
- threshold: import_zod.z.number().optional(),
425
+ threshold: import_zod7.z.number().optional(),
342
426
  /** Files or directories to include in scan */
343
- include: import_zod.z.array(import_zod.z.string()).optional(),
427
+ include: import_zod7.z.array(import_zod7.z.string()).optional(),
344
428
  /** Files or directories to exclude from scan */
345
- exclude: import_zod.z.array(import_zod.z.string()).optional(),
429
+ exclude: import_zod7.z.array(import_zod7.z.string()).optional(),
346
430
  /** Scan-specific configuration */
347
- scan: import_zod.z.object({
348
- include: import_zod.z.array(import_zod.z.string()).optional(),
349
- exclude: import_zod.z.array(import_zod.z.string()).optional(),
350
- parallel: import_zod.z.boolean().optional(),
351
- deep: import_zod.z.boolean().optional(),
352
- tools: import_zod.z.array(import_zod.z.string()).optional()
431
+ scan: import_zod7.z.object({
432
+ include: import_zod7.z.array(import_zod7.z.string()).optional(),
433
+ exclude: import_zod7.z.array(import_zod7.z.string()).optional(),
434
+ parallel: import_zod7.z.boolean().optional(),
435
+ deep: import_zod7.z.boolean().optional(),
436
+ tools: import_zod7.z.array(import_zod7.z.string()).optional()
353
437
  }).optional(),
354
438
  /** Output-specific configuration */
355
- output: import_zod.z.object({
439
+ output: import_zod7.z.object({
356
440
  /** Output format (json, console, html) */
357
- format: import_zod.z.enum(["json", "console", "html"]).optional(),
441
+ format: import_zod7.z.enum(["json", "console", "html"]).optional(),
358
442
  /** Output file path */
359
- path: import_zod.z.string().optional(),
443
+ path: import_zod7.z.string().optional(),
360
444
  /** Output directory */
361
- saveTo: import_zod.z.string().optional(),
445
+ saveTo: import_zod7.z.string().optional(),
362
446
  /** Whether to show score breakdown in console */
363
- showBreakdown: import_zod.z.boolean().optional(),
447
+ showBreakdown: import_zod7.z.boolean().optional(),
364
448
  /** Baseline report to compare against */
365
- compareBaseline: import_zod.z.string().optional()
449
+ compareBaseline: import_zod7.z.string().optional()
366
450
  }).optional(),
367
451
  /** Tool-specific configuration overrides (Strictly ToolName -> Config) */
368
- tools: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional(),
452
+ tools: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.any()).optional(),
369
453
  /** Scoring profile and weights */
370
- scoring: import_zod.z.object({
454
+ scoring: import_zod7.z.object({
371
455
  /** Name of the scoring profile (e.g. "strict", "balanced") */
372
- profile: import_zod.z.string().optional(),
456
+ profile: import_zod7.z.string().optional(),
373
457
  /** Custom weights for tools and metrics */
374
- weights: import_zod.z.record(import_zod.z.string(), import_zod.z.number()).optional()
458
+ weights: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.number()).optional()
375
459
  }).optional(),
376
460
  /** Visualizer settings (interactive graph) */
377
- visualizer: import_zod.z.object({
378
- groupingDirs: import_zod.z.array(import_zod.z.string()).optional(),
379
- graph: import_zod.z.object({
380
- maxNodes: import_zod.z.number().optional(),
381
- maxEdges: import_zod.z.number().optional()
461
+ visualizer: import_zod7.z.object({
462
+ groupingDirs: import_zod7.z.array(import_zod7.z.string()).optional(),
463
+ graph: import_zod7.z.object({
464
+ maxNodes: import_zod7.z.number().optional(),
465
+ maxEdges: import_zod7.z.number().optional()
382
466
  }).optional()
383
467
  }).optional()
384
- }).catchall(import_zod.z.any());
385
-
386
- // src/types/business.ts
387
- var import_zod2 = require("zod");
388
- var LeadSource = /* @__PURE__ */ ((LeadSource2) => {
389
- LeadSource2["ClawMoreHero"] = "clawmore-hero";
390
- LeadSource2["ClawMoreWaitlist"] = "clawmore-waitlist";
391
- LeadSource2["ClawMoreBeta"] = "clawmore-beta";
392
- LeadSource2["AiReadyPlatform"] = "aiready-platform";
393
- return LeadSource2;
394
- })(LeadSource || {});
395
- var LeadSourceSchema = import_zod2.z.nativeEnum(LeadSource);
396
- var LeadSchema = import_zod2.z.object({
397
- id: import_zod2.z.string(),
398
- email: import_zod2.z.string().email(),
399
- name: import_zod2.z.string().min(1),
400
- interest: import_zod2.z.string().default("General"),
401
- notes: import_zod2.z.string().optional(),
402
- timestamp: import_zod2.z.string().datetime(),
403
- source: LeadSourceSchema,
404
- status: import_zod2.z.enum(["new", "contacted", "qualified", "converted", "archived"]).default("new")
405
- });
406
- var LeadSubmissionSchema = LeadSchema.omit({
407
- id: true,
408
- timestamp: true,
409
- status: true
410
- });
411
- var ManagedAccountSchema = import_zod2.z.object({
412
- id: import_zod2.z.string(),
413
- // Internal UUID
414
- accountId: import_zod2.z.string(),
415
- // AWS Account ID
416
- userId: import_zod2.z.string(),
417
- // Owner (caopengau@gmail.com)
418
- stripeSubscriptionId: import_zod2.z.string(),
419
- // AI Token Management
420
- tokenStrategy: import_zod2.z.enum(["managed", "byok"]).default("managed"),
421
- byokConfig: import_zod2.z.object({
422
- openaiKey: import_zod2.z.string().optional(),
423
- anthropicKey: import_zod2.z.string().optional(),
424
- openrouterKey: import_zod2.z.string().optional()
425
- }).optional(),
426
- // Financials (in cents)
427
- baseFeeCents: import_zod2.z.number().default(2900),
428
- includedComputeCents: import_zod2.z.number().default(1500),
429
- // $15.00 AWS included
430
- includedTokenCents: import_zod2.z.number().default(500),
431
- // $5.00 Managed Tokens included
432
- // Pre-paid Balance (credits)
433
- prepaidTokenBalanceCents: import_zod2.z.number().default(0),
434
- // Users buy these in $10 packs
435
- currentMonthlyTokenSpendCents: import_zod2.z.number().default(0),
436
- // Governance
437
- status: import_zod2.z.enum(["provisioning", "active", "warning", "quarantined", "suspended"]).default("provisioning"),
438
- lastCostSyncAt: import_zod2.z.string().datetime().optional(),
439
- region: import_zod2.z.string().default("ap-southeast-2"),
440
- // Alerting thresholds (percentage of includedComputeCents)
441
- alertThresholds: import_zod2.z.array(import_zod2.z.number()).default([50, 80, 100, 150])
442
- });
468
+ }).catchall(import_zod7.z.any());
443
469
 
444
470
  // src/types.ts
445
471
  var GLOBAL_INFRA_OPTIONS = [
@@ -3553,13 +3579,84 @@ function generateHTML(graph) {
3553
3579
  </html>`;
3554
3580
  }
3555
3581
 
3556
- // src/scoring.ts
3557
- var RecommendationPriority = /* @__PURE__ */ ((RecommendationPriority2) => {
3558
- RecommendationPriority2["High"] = "high";
3559
- RecommendationPriority2["Medium"] = "medium";
3560
- RecommendationPriority2["Low"] = "low";
3561
- return RecommendationPriority2;
3562
- })(RecommendationPriority || {});
3582
+ // src/utils/html-report-builder.ts
3583
+ function generateReportHead(title) {
3584
+ return `<!DOCTYPE html>
3585
+ <html lang="en">
3586
+ <head>
3587
+ <meta charset="UTF-8">
3588
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
3589
+ <title>${title}</title>
3590
+ <style>
3591
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 2rem; background-color: #f9f9f9; }
3592
+ h1, h2, h3 { color: #1a1a1a; border-bottom: 2px solid #eaeaea; padding-bottom: 0.5rem; }
3593
+ .card { background: white; padding: 1.5rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); margin-bottom: 2rem; border: 1px solid #eaeaea; }
3594
+ .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
3595
+ .stat-card { background: #fff; padding: 1rem; border-radius: 6px; text-align: center; border: 1px solid #eaeaea; }
3596
+ .stat-value { font-size: 1.8rem; font-weight: bold; color: #2563eb; }
3597
+ .stat-label { font-size: 0.875rem; color: #666; text-transform: uppercase; }
3598
+ table { width: 100%; border-collapse: collapse; margin-top: 1rem; background: white; border-radius: 4px; overflow: hidden; }
3599
+ th, td { text-align: left; padding: 0.875rem 1rem; border-bottom: 1px solid #eaeaea; }
3600
+ th { background-color: #f8fafc; font-weight: 600; color: #475569; }
3601
+ tr:last-child td { border-bottom: none; }
3602
+ .critical { color: #dc2626; font-weight: bold; }
3603
+ .major { color: #ea580c; font-weight: bold; }
3604
+ .minor { color: #2563eb; }
3605
+ code { background: #f1f5f9; padding: 0.2rem 0.4rem; border-radius: 4px; font-size: 0.875rem; color: #334155; }
3606
+ .footer { margin-top: 4rem; text-align: center; color: #94a3b8; font-size: 0.875rem; }
3607
+ </style>
3608
+ </head>`;
3609
+ }
3610
+ function generateStatCards(cards) {
3611
+ const cardsHtml = cards.map(
3612
+ (card) => `
3613
+ <div class="stat-card">
3614
+ <div class="stat-value"${card.color ? ` style="color: ${card.color}"` : ""}>${card.value}</div>
3615
+ <div class="stat-label">${card.label}</div>
3616
+ </div>`
3617
+ ).join("");
3618
+ return `<div class="stats">${cardsHtml}</div>`;
3619
+ }
3620
+ function generateTable(config) {
3621
+ const headersHtml = config.headers.map((h) => `<th>${h}</th>`).join("");
3622
+ const rowsHtml = config.rows.map((row) => `<tr>${row.map((cell) => `<td>${cell}</td>`).join("")}</tr>`).join("");
3623
+ return `<table>
3624
+ <thead><tr>${headersHtml}</tr></thead>
3625
+ <tbody>${rowsHtml}</tbody>
3626
+ </table>`;
3627
+ }
3628
+ function generateReportFooter(options) {
3629
+ const versionText = options.version ? ` v${options.version}` : "";
3630
+ const links = [];
3631
+ if (options.packageUrl) {
3632
+ links.push(`<a href="${options.packageUrl}">Star us on GitHub</a>`);
3633
+ }
3634
+ if (options.bugUrl) {
3635
+ links.push(`<a href="${options.bugUrl}">Report it here</a>`);
3636
+ }
3637
+ const linksHtml = links.length ? links.map((l) => `<p>Like AIReady? ${l}</p>`).join("\n ") : "";
3638
+ return `<div class="footer">
3639
+ <p>Generated by <strong>@aiready/${options.packageName}</strong>${versionText}</p>
3640
+ ${linksHtml}
3641
+ </div>`;
3642
+ }
3643
+ function wrapInCard(content, title) {
3644
+ const titleHtml = title ? `<h2>${title}</h2>` : "";
3645
+ return `<div class="card">
3646
+ ${titleHtml}
3647
+ ${content}
3648
+ </div>`;
3649
+ }
3650
+ function generateCompleteReport(options, bodyContent) {
3651
+ return `${generateReportHead(options.title)}
3652
+ <body>
3653
+ ${bodyContent}
3654
+ ${generateReportFooter(options)}
3655
+ </body>
3656
+ </html>`;
3657
+ }
3658
+
3659
+ // src/utils/rating-helpers.ts
3563
3660
  var ReadinessRating = /* @__PURE__ */ ((ReadinessRating2) => {
3564
3661
  ReadinessRating2["Excellent"] = "Excellent";
3565
3662
  ReadinessRating2["Good"] = "Good";
@@ -3568,6 +3665,59 @@ var ReadinessRating = /* @__PURE__ */ ((ReadinessRating2) => {
3568
3665
  ReadinessRating2["Critical"] = "Critical";
3569
3666
  return ReadinessRating2;
3570
3667
  })(ReadinessRating || {});
3668
+ function getRatingLabel(score) {
3669
+ if (score >= 90) return "Excellent";
3670
+ if (score >= 75) return "Good";
3671
+ if (score >= 60) return "Fair";
3672
+ if (score >= 40) return "Needs Work";
3673
+ return "Critical";
3674
+ }
3675
+ function getRatingSlug(score) {
3676
+ if (score >= 90) return "excellent";
3677
+ if (score >= 75) return "good";
3678
+ if (score >= 60) return "fair";
3679
+ if (score >= 40) return "needs-work";
3680
+ return "critical";
3681
+ }
3682
+ function getRatingEmoji(score) {
3683
+ if (score >= 90) return "\u2705";
3684
+ if (score >= 75) return "\u{1F44D}";
3685
+ if (score >= 60) return "\u{1F44C}";
3686
+ if (score >= 40) return "\u{1F528}";
3687
+ return "\u{1F6A8}";
3688
+ }
3689
+ function getToolEmoji(score) {
3690
+ return getRatingEmoji(score);
3691
+ }
3692
+ function getPriorityIcon(priority) {
3693
+ switch (priority) {
3694
+ case "critical":
3695
+ return "\u{1F534}";
3696
+ case "high":
3697
+ return "\u{1F7E0}";
3698
+ case "medium":
3699
+ return "\u{1F7E1}";
3700
+ case "low":
3701
+ return "\u{1F535}";
3702
+ default:
3703
+ return "\u26AA";
3704
+ }
3705
+ }
3706
+ function getRating(score) {
3707
+ if (score >= 90) return "Excellent" /* Excellent */;
3708
+ if (score >= 75) return "Good" /* Good */;
3709
+ if (score >= 60) return "Fair" /* Fair */;
3710
+ if (score >= 40) return "Needs Work" /* NeedsWork */;
3711
+ return "Critical" /* Critical */;
3712
+ }
3713
+
3714
+ // src/scoring.ts
3715
+ var RecommendationPriority = /* @__PURE__ */ ((RecommendationPriority2) => {
3716
+ RecommendationPriority2["High"] = "high";
3717
+ RecommendationPriority2["Medium"] = "medium";
3718
+ RecommendationPriority2["Low"] = "low";
3719
+ return RecommendationPriority2;
3720
+ })(RecommendationPriority || {});
3571
3721
  var DEFAULT_TOOL_WEIGHTS = {
3572
3722
  ["pattern-detect" /* PatternDetect */]: 22,
3573
3723
  ["context-analyzer" /* ContextAnalyzer */]: 19,
@@ -3746,20 +3896,6 @@ function calculateOverallScore(toolOutputs, config, cliWeights) {
3746
3896
  }
3747
3897
  };
3748
3898
  }
3749
- function getRating(score) {
3750
- if (score >= 90) return "Excellent" /* Excellent */;
3751
- if (score >= 75) return "Good" /* Good */;
3752
- if (score >= 60) return "Fair" /* Fair */;
3753
- if (score >= 40) return "Needs Work" /* NeedsWork */;
3754
- return "Critical" /* Critical */;
3755
- }
3756
- function getRatingSlug(score) {
3757
- if (score >= 90) return "excellent";
3758
- if (score >= 75) return "good";
3759
- if (score >= 60) return "fair";
3760
- if (score >= 40) return "needs-work";
3761
- return "critical";
3762
- }
3763
3899
  function getRatingWithContext(score, fileCount, modelTier = "standard") {
3764
3900
  const threshold = getRecommendedThreshold(fileCount, modelTier);
3765
3901
  const normalized = score - threshold + 70;
@@ -3882,20 +4018,52 @@ var DEFAULT_COST_CONFIG = {
3882
4018
  developerCount: 5,
3883
4019
  daysPerMonth: 30
3884
4020
  };
3885
- function calculateMonthlyCost(tokenWaste, config = {}) {
3886
- const multiplier = tokenWaste > 5e4 ? 5 : tokenWaste > 1e4 ? 3.5 : 2.5;
4021
+ function calculateMonthlyCost(tokenWaste, config = {}, options) {
4022
+ const baseMultiplier = tokenWaste > 5e4 ? 5 : tokenWaste > 1e4 ? 3.5 : 2.5;
4023
+ const contextMultiplier = options?.avgContextBudget ? options.avgContextBudget / Math.max(1, tokenWaste) : baseMultiplier;
4024
+ const fragRatio = options?.fragmentationScore ?? 0.3;
4025
+ const dupRatio = 1 - fragRatio;
3887
4026
  const budget = calculateTokenBudget({
3888
- totalContextTokens: tokenWaste * multiplier,
4027
+ totalContextTokens: tokenWaste * contextMultiplier,
3889
4028
  wastedTokens: {
3890
- duplication: tokenWaste * 0.7,
3891
- fragmentation: tokenWaste * 0.3,
4029
+ duplication: tokenWaste * dupRatio * (options?.potentialSavings ? 1.2 : 1),
4030
+ fragmentation: tokenWaste * fragRatio,
3892
4031
  chattiness: 0.1 * tokenWaste
3893
- // Added baseline chattiness
3894
4032
  }
3895
4033
  });
3896
- const preset = getModelPreset("gpt-5.4-mini");
4034
+ const preset = getModelPreset("claude-3.5-sonnet");
3897
4035
  return estimateCostFromBudget(budget, preset, config);
3898
4036
  }
4037
+ function calculateDetailedTokenROI(params) {
4038
+ const {
4039
+ totalTokens,
4040
+ avgContextBudget,
4041
+ potentialSavings,
4042
+ fragmentationScore,
4043
+ developerCount,
4044
+ queriesPerDevPerDay = 60
4045
+ } = params;
4046
+ const budget = calculateTokenBudget({
4047
+ totalContextTokens: avgContextBudget,
4048
+ wastedTokens: {
4049
+ duplication: potentialSavings * 0.8,
4050
+ // 80% of potential savings are duplication-based
4051
+ fragmentation: totalTokens * fragmentationScore * 0.5,
4052
+ // fragmentation impact
4053
+ chattiness: totalTokens * 0.1
4054
+ }
4055
+ });
4056
+ const model = getModelPreset("claude-3.5-sonnet");
4057
+ const cost = estimateCostFromBudget(budget, model, {
4058
+ developerCount,
4059
+ queriesPerDevPerDay
4060
+ });
4061
+ return {
4062
+ monthlySavings: Math.round(cost.total),
4063
+ contextTaxPerDev: Math.round(cost.total / (developerCount || 1) * 100) / 100,
4064
+ efficiencyGain: Math.round(budget.efficiencyRatio * 100) / 100
4065
+ };
4066
+ }
3899
4067
  function calculateTokenBudget(params) {
3900
4068
  const { totalContextTokens, wastedTokens } = params;
3901
4069
  const estimatedResponseTokens = params.estimatedResponseTokens ?? totalContextTokens * 0.2;
@@ -5423,6 +5591,7 @@ function emitIssuesAsAnnotations(issues) {
5423
5591
  calculateConceptCohesion,
5424
5592
  calculateDebtInterest,
5425
5593
  calculateDependencyHealth,
5594
+ calculateDetailedTokenROI,
5426
5595
  calculateDocDrift,
5427
5596
  calculateExtendedFutureProofScore,
5428
5597
  calculateFutureProofScore,
@@ -5451,7 +5620,12 @@ function emitIssuesAsAnnotations(issues) {
5451
5620
  formatHours,
5452
5621
  formatScore,
5453
5622
  formatToolScore,
5623
+ generateCompleteReport,
5454
5624
  generateHTML,
5625
+ generateReportFooter,
5626
+ generateReportHead,
5627
+ generateStatCards,
5628
+ generateTable,
5455
5629
  generateValueChain,
5456
5630
  getElapsedTime,
5457
5631
  getFileCommitTimestamps,
@@ -5460,9 +5634,12 @@ function emitIssuesAsAnnotations(issues) {
5460
5634
  getLineRangeLastModifiedCached,
5461
5635
  getModelPreset,
5462
5636
  getParser,
5637
+ getPriorityIcon,
5463
5638
  getProjectSizeTier,
5464
5639
  getRating,
5465
5640
  getRatingDisplay,
5641
+ getRatingEmoji,
5642
+ getRatingLabel,
5466
5643
  getRatingSlug,
5467
5644
  getRatingWithContext,
5468
5645
  getRecommendedThreshold,
@@ -5475,6 +5652,7 @@ function emitIssuesAsAnnotations(issues) {
5475
5652
  getSeverityLevel,
5476
5653
  getSeverityValue,
5477
5654
  getSupportedLanguages,
5655
+ getToolEmoji,
5478
5656
  getToolWeight,
5479
5657
  getWasmPath,
5480
5658
  groupIssuesByFile,
@@ -5504,5 +5682,6 @@ function emitIssuesAsAnnotations(issues) {
5504
5682
  setupParser,
5505
5683
  severityToAnnotationLevel,
5506
5684
  validateSpokeOutput,
5507
- validateWithSchema
5685
+ validateWithSchema,
5686
+ wrapInCard
5508
5687
  });