@aiready/cli 0.9.45 → 0.9.47

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/src/index.ts CHANGED
@@ -2,11 +2,19 @@ import { analyzePatterns } from '@aiready/pattern-detect';
2
2
  import { analyzeContext } from '@aiready/context-analyzer';
3
3
  import { analyzeConsistency } from '@aiready/consistency';
4
4
  import type { AnalysisResult, ScanOptions } from '@aiready/core';
5
+ import {
6
+ calculateOverallScore,
7
+ type ToolScoringOutput,
8
+ type ScoringResult,
9
+ calculateTokenBudget,
10
+ } from '@aiready/core';
11
+ export type { ToolScoringOutput, ScoringResult };
5
12
  import type { ContextAnalysisResult } from '@aiready/context-analyzer';
6
13
  import type { DuplicatePattern } from '@aiready/pattern-detect';
7
- import type { ConsistencyReport } from '@aiready/consistency';
8
-
9
- import type { ConsistencyOptions } from '@aiready/consistency';
14
+ import type {
15
+ ConsistencyReport,
16
+ ConsistencyOptions,
17
+ } from '@aiready/consistency';
10
18
 
11
19
  export interface UnifiedAnalysisOptions extends ScanOptions {
12
20
  tools?: (
@@ -45,6 +53,7 @@ export interface UnifiedAnalysisResult {
45
53
  toolsRun: string[];
46
54
  executionTime: number;
47
55
  };
56
+ scoring?: ScoringResult;
48
57
  }
49
58
 
50
59
  // Severity ordering (higher number = more severe)
@@ -268,6 +277,184 @@ export async function analyzeUnified(
268
277
  return result;
269
278
  }
270
279
 
280
+ export async function scoreUnified(
281
+ results: UnifiedAnalysisResult,
282
+ options: UnifiedAnalysisOptions
283
+ ): Promise<ScoringResult> {
284
+ const toolScores: Map<string, ToolScoringOutput> = new Map();
285
+
286
+ // Patterns score
287
+ if (results.duplicates) {
288
+ const { calculatePatternScore } = await import('@aiready/pattern-detect');
289
+ try {
290
+ const patternScore = calculatePatternScore(
291
+ results.duplicates,
292
+ results.patterns?.length || 0
293
+ );
294
+
295
+ // Calculate token budget for patterns (waste = duplication)
296
+ const wastedTokens = results.duplicates.reduce(
297
+ (sum: number, d: any) => sum + (d.tokenCost || 0),
298
+ 0
299
+ );
300
+ patternScore.tokenBudget = calculateTokenBudget({
301
+ totalContextTokens: wastedTokens * 2, // Estimated context
302
+ wastedTokens: {
303
+ duplication: wastedTokens,
304
+ fragmentation: 0,
305
+ chattiness: 0,
306
+ },
307
+ });
308
+
309
+ toolScores.set('pattern-detect', patternScore);
310
+ } catch (err) {
311
+ void err;
312
+ }
313
+ }
314
+
315
+ // Context score
316
+ if (results.context) {
317
+ const { generateSummary: genContextSummary, calculateContextScore } =
318
+ await import('@aiready/context-analyzer');
319
+ try {
320
+ const ctxSummary = genContextSummary(results.context);
321
+ const contextScore = calculateContextScore(ctxSummary);
322
+
323
+ // Calculate token budget for context (waste = fragmentation + depth overhead)
324
+ contextScore.tokenBudget = calculateTokenBudget({
325
+ totalContextTokens: ctxSummary.totalTokens,
326
+ wastedTokens: {
327
+ duplication: 0,
328
+ fragmentation: ctxSummary.totalPotentialSavings || 0,
329
+ chattiness: 0,
330
+ },
331
+ });
332
+
333
+ toolScores.set('context-analyzer', contextScore);
334
+ } catch (err) {
335
+ void err;
336
+ }
337
+ }
338
+
339
+ // Consistency score
340
+ if (results.consistency) {
341
+ const { calculateConsistencyScore } = await import('@aiready/consistency');
342
+ try {
343
+ const issues =
344
+ results.consistency.results?.flatMap((r: any) => r.issues) || [];
345
+ const totalFiles = results.consistency.summary?.filesAnalyzed || 0;
346
+ const consistencyScore = calculateConsistencyScore(issues, totalFiles);
347
+ toolScores.set('consistency', consistencyScore);
348
+ } catch (err) {
349
+ void err;
350
+ }
351
+ }
352
+
353
+ // AI signal clarity score
354
+ if (results.aiSignalClarity) {
355
+ const { calculateAiSignalClarityScore } =
356
+ await import('@aiready/ai-signal-clarity');
357
+ try {
358
+ const hrScore = calculateAiSignalClarityScore(results.aiSignalClarity);
359
+ toolScores.set('ai-signal-clarity', hrScore);
360
+ } catch (err) {
361
+ void err;
362
+ }
363
+ }
364
+
365
+ // Agent grounding score
366
+ if (results.grounding) {
367
+ const { calculateGroundingScore } =
368
+ await import('@aiready/agent-grounding');
369
+ try {
370
+ const agScore = calculateGroundingScore(results.grounding);
371
+ toolScores.set('agent-grounding', agScore);
372
+ } catch (err) {
373
+ void err;
374
+ }
375
+ }
376
+
377
+ // Testability score
378
+ if (results.testability) {
379
+ const { calculateTestabilityScore } = await import('@aiready/testability');
380
+ try {
381
+ const tbScore = calculateTestabilityScore(results.testability);
382
+ toolScores.set('testability', tbScore);
383
+ } catch (err) {
384
+ void err;
385
+ }
386
+ }
387
+
388
+ // Documentation Drift score
389
+ if (results.docDrift) {
390
+ toolScores.set('doc-drift', {
391
+ toolName: 'doc-drift',
392
+ score: results.docDrift.summary.score,
393
+ rawMetrics: results.docDrift.rawData,
394
+ factors: [],
395
+ recommendations: (results.docDrift.recommendations || []).map(
396
+ (action: string) => ({
397
+ action,
398
+ estimatedImpact: 5,
399
+ priority: 'medium',
400
+ })
401
+ ),
402
+ });
403
+ }
404
+
405
+ // Dependency Health score
406
+ if (results.deps) {
407
+ toolScores.set('dependency-health', {
408
+ toolName: 'dependency-health',
409
+ score: results.deps.summary.score,
410
+ rawMetrics: results.deps.rawData,
411
+ factors: [],
412
+ recommendations: (results.deps.recommendations || []).map(
413
+ (action: string) => ({
414
+ action,
415
+ estimatedImpact: 5,
416
+ priority: 'medium',
417
+ })
418
+ ),
419
+ });
420
+ }
421
+
422
+ // Change Amplification score
423
+ if (results.changeAmplification) {
424
+ toolScores.set('change-amplification', {
425
+ toolName: 'change-amplification',
426
+ score: results.changeAmplification.summary.score,
427
+ rawMetrics: results.changeAmplification.rawData,
428
+ factors: [],
429
+ recommendations: (results.changeAmplification.recommendations || []).map(
430
+ (action: string) => ({
431
+ action,
432
+ estimatedImpact: 5,
433
+ priority: 'medium',
434
+ })
435
+ ),
436
+ });
437
+ }
438
+
439
+ // Handle case where toolScores is empty
440
+ if (toolScores.size === 0) {
441
+ return {
442
+ overall: 0,
443
+ rating: 'Critical',
444
+ timestamp: new Date().toISOString(),
445
+ toolsUsed: [],
446
+ breakdown: [],
447
+ calculation: {
448
+ formula: '0 / 0 = 0',
449
+ weights: {},
450
+ normalized: '0 / 0 = 0',
451
+ },
452
+ } as ScoringResult;
453
+ }
454
+
455
+ return calculateOverallScore(toolScores, options, undefined);
456
+ }
457
+
271
458
  export function generateUnifiedSummary(result: UnifiedAnalysisResult): string {
272
459
  const { summary } = result;
273
460
  let output = `🚀 AIReady Analysis Complete\n\n`;