Clarx

Output Format

The JSON structure returned by the Clarx engine and CLI.

Output Format

The engine returns a structured AnalysisResult object. The CLI --format json flag serializes this directly.


TypeScript types

type AnalysisResult = {
  version: string;           // standard version used: "0.1"
  confidence: 'high' | 'medium' | 'low';
  score: number;             // 0–100
  hardFailures: RuleId[];    // e.g. ["C1", "O1"]
  pillars: {
    discoverability: PillarScore;
    boundary_clarity: PillarScore;
    context_efficiency: PillarScore;
    operational_guidance: PillarScore;
    edit_safety: PillarScore;
  };
  rules: Record<RuleId, RuleResult>;
  meta: {
    analyzedAt: string;      // ISO timestamp
    root: string;            // absolute path analyzed
    filesScanned: number;
    manifestFound: boolean;
    importGraphResolved: boolean;
  };
};

type PillarScore = {
  score: number;             // 0–100
  weight: number;            // 0.20
  rules: Record<RuleId, RuleResult>;
};

type RuleResult = {
  id: RuleId;                // "C2"
  passed: boolean;
  severity: 'hard_failure' | 'warning' | 'recommendation';
  scoreImpact: number;
  message: string;           // human-readable finding
  locations?: Location[];    // files involved, if applicable
};

type Location = {
  path: string;              // relative to root
  line?: number;
  detail?: string;
};

Example output

{
  "version": "0.1",
  "confidence": "medium",
  "score": 72,
  "hardFailures": [],
  "pillars": {
    "discoverability": {
      "score": 85,
      "weight": 0.20,
      "rules": {
        "D1": { "id": "D1", "passed": true, "severity": "warning", "scoreImpact": 0, "message": "Root has 8 meaningful entries" },
        "D2": { "id": "D2", "passed": true, "severity": "warning", "scoreImpact": 0, "message": "All 3 workspaces have purpose statements" },
        "D3": { "id": "D3", "passed": true, "severity": "warning", "scoreImpact": 0, "message": "Source, test, and config directories are segregated" },
        "D4": { "id": "D4", "passed": false, "severity": "warning", "scoreImpact": 15, "message": "Utility dumping ground files found", "locations": [{ "path": "packages/shared/src/utils.ts" }] },
        "D5": { "id": "D5", "passed": true, "severity": "recommendation", "scoreImpact": 0, "message": "Max depth 4 before module boundary" }
      }
    },
    "context_efficiency": {
      "score": 60,
      "weight": 0.20,
      "rules": {
        "C1": { "id": "C1", "passed": true, "severity": "hard_failure", "scoreImpact": 0, "message": "No generated artifacts found in source tree" },
        "C2": { "id": "C2", "passed": false, "severity": "warning", "scoreImpact": 25, "message": "2 files exceed 400 lines", "locations": [
          { "path": "apps/api/src/routes/auth.ts", "detail": "847 lines" },
          { "path": "apps/web/src/pages/dashboard.tsx", "detail": "601 lines" }
        ]},
        "C3": { "id": "C3", "passed": true, "severity": "warning", "scoreImpact": 0, "message": "No file imports more than 15 distinct modules" },
        "C4": { "id": "C4", "passed": false, "severity": "recommendation", "scoreImpact": 20, "message": "High fan-in files not declared in manifest", "locations": [
          { "path": "packages/ui/src/tokens.ts", "detail": "23 dependents" }
        ]},
        "C5": { "id": "C5", "passed": true, "severity": "recommendation", "scoreImpact": 0, "message": "Max import depth 6" }
      }
    }
  },
  "meta": {
    "analyzedAt": "2026-04-30T14:23:00.000Z",
    "root": "/Users/dev/my-app",
    "filesScanned": 312,
    "manifestFound": false,
    "importGraphResolved": true
  }
}

Using the output

import { analyze } from '@clarxai/engine';

const result = await analyze({ root: process.cwd() });

// Gate on overall score
if (result.score < 70) {
  console.error(`Score ${result.score} is below threshold 70`);
  process.exit(1);
}

// Gate on hard failures
if (result.hardFailures.length > 0) {
  console.error(`Hard failures: ${result.hardFailures.join(', ')}`);
  process.exit(2);
}

// Find all failing warnings
const failingWarnings = Object.values(result.rules).filter(
  r => !r.passed && r.severity === 'warning'
);