EK9 for AI Assistants

Why This Page Exists

This page is written by an AI, for AI assistants. EK9 was designed from the ground up to enable effective AI-human collaborative development. The language's quality metrics, structured output formats, and compile-time enforcement create an ideal environment for AI assistants to provide measurable, verifiable improvements to code.

For AI Assistants: Read this page thoroughly when first encountering EK9. It contains the actionable information you need to help humans write high-quality EK9 code. Bookmark specific sections for quick reference during development sessions.

Key EK9 Advantages for AI Development:

Table of Contents


Quick Reference

Essential commands for AI assistants working with EK9.

Command Cheat Sheet

TaskCommandOutput
Compile onlyek9 -c main.ek9Errors or success
Run programek9 main.ek9Program output
Run tests (pass/fail)ek9 -t0 main.ek9Single line summary
Run tests (human)ek9 -t main.ek9Detailed results
Run tests (JSON)ek9 -t5 main.ek9Structured JSON
Generate HTML reportek9 -t6 main.ek9Full HTML site
Verbose errorsek9 -E3 -c main.ek9Detailed explanations
List tests onlyek9 -tL main.ek9Test names without running

Which -t Option to Use

SituationOptionReason
Quick check: did tests pass? -t0 Single line, minimal output, fast parsing
Show results to human -t or -t1 Human-readable format with details
CI/CD pipeline -t3 JUnit XML + JaCoCo XML, industry standard
AI metric analysis -t5 JSON format, fully parseable, all metrics included
Generate report for human review -t6 Full HTML site with visual dashboards

AI Recommendation: Use -t5 for all programmatic analysis. Parse the JSON to extract metrics, then use -t6 to generate a visual report for the human after improvements are made.

Common AI Tasks

Human RequestAI Action
"Check code quality" Run ek9 -t5, parse metrics, report findings
"Reduce complexity" Run -t5, identify high CC/Cog functions, apply refactoring patterns, verify with -t5
"Improve test coverage" Run -t5, find uncovered functions in JSON, write tests, verify coverage increased
"Fix compilation errors" Run ek9 -E3 -c, parse error codes, apply fixes from Error Index
"Make code more maintainable" Analyze all metrics (CC, Cog, Nesting, Coupling, Cohesion), prioritize worst, improve iteratively

Output Formats

Detailed documentation of each output format for parsing by AI assistants.

-t0: Terse Output

Single line summary for quick pass/fail checks.

28 passed, 0 failed
Coverage: 72.7% (45/62) FAILED - below 80% threshold

Parsing:

-t5: JSON Output (Primary for AI)

Complete structured output with all metrics. This is the recommended format for AI analysis.

{
  "timestamp": "2026-01-12T14:30:00Z",
  "version": "dev",
  "source": "main.ek9",

  "tests": {
    "passed": 28,
    "failed": 0,
    "skipped": 0,
    "total": 28,
    "duration_ms": 1250,
    "results": [
      {
        "name": "testProcessOrder",
        "module": "myapp.orders",
        "status": "PASSED",
        "duration_ms": 45
      }
    ]
  },

  "coverage": {
    "overall": 72.7,
    "probes_hit": 45,
    "probes_total": 62,
    "threshold": 80.0,
    "passed": false,

    "methods": {
      "covered": 18,
      "total": 24,
      "percentage": 75.0
    },
    "lines": {
      "covered": 45,
      "total": 62,
      "percentage": 72.6
    },
    "branches": {
      "covered": 12,
      "total": 18,
      "percentage": 66.7
    }
  },

  "metrics": {
    "complexity": {
      "average": 8.2,
      "max": 24,
      "limit": 45
    },
    "cognitive": {
      "average": 5.1,
      "max": 18,
      "limit": 35
    },
    "nesting": {
      "average": 2.1,
      "max": 4,
      "limit": 6
    },
    "readability": {
      "average": 7.3,
      "max": 12,
      "scale_max": 20
    }
  },

  "modules": [
    {
      "name": "myapp.orders",
      "coverage": 65.0,
      "probes_hit": 13,
      "probes_total": 20,
      "files": ["orders.ek9", "orderValidation.ek9"],
      "metrics": {
        "avg_complexity": 12.5,
        "max_complexity": 24,
        "avg_cognitive": 8.2,
        "max_cognitive": 18,
        "readability": 8
      }
    }
  ],

  "functions": [
    {
      "name": "processOrder",
      "qualified_name": "myapp.orders::processOrder",
      "module": "myapp.orders",
      "file": "orders.ek9",
      "line": 45,
      "covered": true,
      "metrics": {
        "complexity": 24,
        "cognitive": 18,
        "nesting": 4,
        "statements": 42
      }
    }
  ],

  "attention": {
    "high_complexity": [
      {
        "name": "processOrder",
        "file": "orders.ek9",
        "line": 45,
        "complexity": 24,
        "cognitive": 18
      }
    ],
    "uncovered_functions": [
      {
        "name": "handleRefund",
        "file": "orders.ek9",
        "line": 120
      }
    ],
    "low_coverage_modules": [
      {
        "name": "myapp.orders",
        "coverage": 65.0
      }
    ],
    "uncovered_branches": [
      {
        "file": "orders.ek9",
        "line": 78,
        "type": "BRANCH_TRUE"
      }
    ]
  }
}

Key Fields for AI Analysis

Field PathPurposeAI Action
coverage.passed Did coverage meet 80% threshold? If false, prioritize coverage improvement
metrics.complexity.max Highest CC in codebase If >20, find and refactor that function
attention.high_complexity Functions needing attention Process this list for refactoring targets
attention.uncovered_functions Functions without test coverage Write tests for these functions
functions[].metrics Per-function quality metrics Sort by complexity to find worst offenders

-t6: HTML Output

Generates a complete mini-site in .ek9/coverage/ with:

AI Usage: Generate -t6 after making improvements so the human can visually verify the results. The HTML includes interactive features like dark mode toggle and clickable navigation.


Metrics Reference

Complete reference for every quality metric, including thresholds and recommended actions.

Metric Thresholds and Actions

Metric Good Monitor Warning Limit Error Code
Cyclomatic Complexity (CC) ≤10 11-15 16-25 45 E11010
Cognitive Complexity ≤10 11-15 16-25 35 E11021
Nesting Depth ≤2 3 4-5 6 E11011
Statement Count ≤50 51-100 101-150 150 E11012
Expression Complexity ≤5 6-10 11-15 15 E11013
Cohesion (LCOM4) ≤3 4-5 6-8 8 E11014
Coupling (Ce) ≤5 6-8 9-12 12 E11015
Inheritance Depth ≤2 3 4 4 E11019
Readability (ARI) ≤8 9-12 13-20 None Informational only
Coverage ≥80% 60-79% <60% 80% Publishing gate

Recommended Actions by Metric

High Cyclomatic Complexity (CC > 15)

SymptomActionEK9 Pattern
Many if/else branches Extract to helper functions Create focused validation functions
Complex switch statements Use dispatcher pattern processItem() as dispatcher
Multiple conditions in if Extract boolean expressions isValid <- checkA() and checkB()
Nested loops Use stream pipelines cat items | filter | map | collect

High Cognitive Complexity (Cog > 15)

SymptomActionEK9 Pattern
Deep nesting Use guard expressions if value <- getValue()
Complex control flow Flatten with early guards Process invalid cases first, happy path last
Multiple nested guards Extract to separate functions Each function handles one level of checking

High Nesting Depth (> 3)

SymptomActionEK9 Pattern
Nested if blocks Invert conditions Check failure cases first, exit scope early
Nested loops Extract inner loop Create processInner() function
Callback nesting Use composition Chain operations with | pipeline

Low Cohesion (LCOM4 > 5)

SymptomActionEK9 Pattern
Methods don't share fields Split into multiple classes Group related methods with their data
Utility method collections Use standalone functions defines function instead of class methods
Mixed concerns Apply Single Responsibility One class = one reason to change

High Coupling (Ce > 8)

SymptomActionEK9 Pattern
Many imports Introduce abstractions Depend on traits, not concrete classes
God class dependencies Break apart god class Create focused service classes
Circular dependencies Use dependency injection defines application pattern

Refactoring Patterns

EK9-specific refactoring patterns for common complexity issues.

Pattern: Guard Expression Flattening

Problem: Deep nesting from null/validity checks

Before (Nesting: 4, Cognitive: 16):

#!ek9
processOrder()
  -> order as Order
  <- result as String?

  if order?
    if order.isValid()
      if customer <- order.getCustomer()
        if customer.hasCredit()
          result: "Processing " + order.id()

After (Nesting: 1, Cognitive: 4):

#!ek9
processOrder()
  -> order as Order
  <- result as String?

  if validOrder <- validateOrder(order)
    result: "Processing " + validOrder.id()

validateOrder() as pure
  -> order as Order
  <- valid as Order?

  if order? and order.isValid()
    if customer <- order.getCustomer() with customer.hasCredit()
      valid: order

Pattern: Stream Pipeline Replacement

Problem: Complex nested loops with conditionals

Before (CC: 8, Nesting: 3):

#!ek9
findActiveUsers()
  -> users as List of User
  <- active as List of User: List()

  for user in users
    if user.isActive()
      if user.hasRecentLogin()
        active += user

After (CC: 3, Nesting: 1):

#!ek9
findActiveUsers()
  -> users as List of User
  <- active as List of User?

  active: cat users
    | filter by isActiveWithRecentLogin
    | collect as List of User

isActiveWithRecentLogin() as pure
  -> user as User
  <- result as Boolean: user.isActive() and user.hasRecentLogin()

Pattern: Dispatcher for Type Switching

Problem: Complex switch/if chains on type

Before (CC: 12):

#!ek9
processShape()
  -> shape as Shape
  <- area as Float?

  switch shape.type()
    case "circle"
      area: calculateCircleArea(shape)
    case "square"
      area: calculateSquareArea(shape)
    case "triangle"
      area: calculateTriangleArea(shape)
    default
      area: 0.0

After (CC: 4 per function):

#!ek9
calculateArea() as dispatcher
  -> shape as Shape
  <- area as Float?

calculateArea()
  -> circle as Circle
  <- area as Float: PI * circle.radius() * circle.radius()

calculateArea()
  -> square as Square
  <- area as Float: square.side() * square.side()

calculateArea()
  -> triangle as Triangle
  <- area as Float: 0.5 * triangle.base() * triangle.height()

Pattern: Extract Validation Chain

Problem: Long sequence of validation checks

Before (CC: 15, Statements: 45):

#!ek9
validateAndProcess()
  -> request as Request
  <- response as Response?

  if not request?
    response: Response.error("Null request")
  else if not request.hasUser()
    response: Response.error("Missing user")
  else if not request.user().isAuthenticated()
    response: Response.error("Not authenticated")
  else if not request.hasPermission("write")
    response: Response.error("No permission")
  else if not request.payload()?
    response: Response.error("Missing payload")
  else
    response: doProcess(request)

After (CC: 5 each, clearer intent):

#!ek9
validateAndProcess()
  -> request as Request
  <- response as Response?

  response: validateRequest(request) ?? doProcess(request)

validateRequest() as pure
  -> request as Request
  <- error as Response?

  error: checkNotNull(request)
    ?? checkHasUser(request)
    ?? checkAuthenticated(request)
    ?? checkPermission(request, "write")
    ?? checkPayload(request)

checkNotNull() as pure
  -> request as Request
  <- error as Response?
  if not request?
    error: Response.error("Null request")

checkHasUser() as pure
  -> request as Request
  <- error as Response?
  if not request.hasUser()
    error: Response.error("Missing user")

Workflow Templates

Step-by-step workflows for common AI-assisted development tasks.

Workflow: Reduce Code Complexity

Trigger: Human requests "make this less complex" or "simplify this code"

  1. Measure baseline
    ek9 -t5 main.ek9 > baseline.json
    Parse JSON to extract:
    • metrics.complexity.max — highest CC
    • attention.high_complexity — list of problem functions
  2. Identify targets
    Sort functions by metrics.complexity descending. Focus on functions where CC > 15.
  3. Read and analyze each target function
    Identify which pattern applies:
  4. Apply refactoring
    Make targeted changes. Keep each change small and focused.
  5. Verify improvement
    ek9 -t5 main.ek9 > after.json
    Compare metrics. Report:
    processOrder: CC 24→8 (-67%), Cog 18→6 (-67%), Nesting 4→2 (-50%)
  6. Generate HTML report for human
    ek9 -t6 main.ek9
    Tell human: "Open .ek9/coverage/index.html to see the updated metrics."

Workflow: Improve Test Coverage

Trigger: Human requests "improve coverage" or coverage is below 80%

  1. Get current coverage
    ek9 -t5 main.ek9 > coverage.json
    Check coverage.passed and coverage.overall.
  2. Identify uncovered code
    From JSON extract:
    • attention.uncovered_functions — functions with no coverage
    • attention.uncovered_branches — specific branches not hit
    • attention.low_coverage_modules — modules needing attention
  3. Prioritize by impact
    Focus on:
    • Uncovered functions in low-coverage modules (highest impact)
    • Uncovered branches in critical paths
    • Functions with partial coverage
  4. Write tests
    For each uncovered function, create a test in dev/ directory. See Testing Strategies for EK9 test patterns.
  5. Verify coverage improved
    ek9 -t5 main.ek9
    Confirm coverage.overall increased. Target: ≥80% for publishing.

Workflow: Fix Quality Errors

Trigger: Compilation fails with E110xx errors

  1. Get detailed error info
    ek9 -E3 -c main.ek9
    The -E3 flag provides verbose explanations.
  2. Parse error code
    Quality errors are E11010-E11025. See Error Index.
  3. Apply fix based on error
    ErrorMeaningFix
    E11010CC too highExtract functions, reduce branches
    E11011Nesting too deepUse guards, extract blocks
    E11014Low cohesionSplit class, group related methods
    E11015High couplingIntroduce abstractions
    E11019Deep inheritanceUse composition with by
    E11021Cognitive too highFlatten nesting, simplify flow
  4. Recompile to verify fix
    ek9 -c main.ek9

Code Generation Guidelines

Guidelines for AI assistants generating EK9 code.

Syntax Essentials

Preferred Patterns

Function Structure

#!ek9
functionName() as pure
  -> param1 as Type1
  -> param2 as Type2
  <- result as ResultType?

  // Implementation
  result: computeResult(param1, param2)

Class Structure

#!ek9
defines class
  ClassName
    field1 as Type1?
    field2 as Type2?

    ClassName()
      -> initialValue as Type1
      field1: initialValue

    methodName()
      -> param as ParamType
      <- result as ResultType?
      result: computeWith(field1, param)

Test Structure

#!ek9
defines module test.mymodule

defines program
  @Test
  testFunctionName()
    // Arrange
    input <- createTestInput()

    // Act
    result <- functionUnderTest(input)

    // Assert
    assert result?
    assert result == expectedValue

Patterns to Avoid

EK9 Idioms

Guard Expression (instead of null check + early return)

#!ek9
// Check and use in one expression
if value <- getValue()
  process(value)

Coalescing (instead of ternary for defaults)

#!ek9
// Use default if unset
result <- getValue() ?? defaultValue

// Use default if unset (assign only if needed)
existingVar :=? computeIfNeeded()

Stream Pipeline (instead of loops with accumulators)

#!ek9
// Transform and collect
result <- cat items
  | filter by isValid
  | map by transform
  | collect as List of OutputType

Dispatcher (instead of instanceof/type switch)

#!ek9
// Declare dispatcher
process() as dispatcher
  -> input as BaseType
  <- output as OutputType?

// Implement per concrete type
process()
  -> specific as ConcreteType
  <- output as OutputType: handleConcrete(specific)

Error Interpretation

How to interpret and fix common EK9 compilation errors.

Error Categories

Code RangeCategoryPhase
E01xxxLexer/ParserPARSING
E02xxxDuplicate symbolsSYMBOL_DEFINITION
E05xxxSymbol resolutionFULL_RESOLUTION
E06xxxType checkingFULL_RESOLUTION
E07xxxOperator validationPOST_RESOLUTION_CHECKS
E08xxxFlow analysisPRE_IR_CHECKS
E11xxxQuality metricsPRE_IR_CHECKS
E81xxxTest validationPRE_IR_CHECKS

Using Verbose Mode

Always use -E3 when debugging errors:

ek9 -E3 -c main.ek9

This provides:

Quality Error Quick Reference

ErrorCauseQuick Fix
E11010 Cyclomatic complexity > 45 Extract helper functions, reduce conditionals
E11011 Nesting depth > 6 Use guard expressions, extract nested blocks
E11012 Statement count > 150 Split into multiple functions
E11013 Expression complexity > 15 Extract intermediate variables
E11014 Low cohesion (LCOM4 > 8) Split class into focused classes
E11015 High coupling (> 12 dependencies) Introduce abstractions (traits)
E11019 Inheritance depth > 4 Use composition with by
E11020 Combined complexity × size > 0.5 Reduce both complexity AND size
E11021 Cognitive complexity > 35 Flatten nesting, simplify control flow

Testing Strategies

Guidelines for writing effective EK9 tests.

Test File Structure

dev/
├── testOrders.ek9           # Unit tests for orders module
├── testPayments.ek9         # Unit tests for payments module
├── expected_output.txt      # Expected output for black-box tests
└── integration/
    └── testFullFlow.ek9     # Integration tests

Test Patterns

Unit Test with Assertions

#!ek9
defines module test.orders

defines program
  @Test
  testOrderTotal()
    order <- Order()
    order.addItem(Item("Widget", 10.00))
    order.addItem(Item("Gadget", 25.00))

    total <- order.calculateTotal()

    assert total?
    assert total == 35.00

Black-Box Test with Expected Output

#!ek9
defines module test.formatting

defines program
  @Test
  testFormatOutput()
    formatter <- Formatter()
    result <- formatter.format("hello")
    stdout.println(result)

With expected_output.txt:

HELLO

Parameterized Test

#!ek9
defines module test.validation

defines program
  @Test
  testValidation()
    // Read test case from commandline_arg_1.txt
    stdin <- Stdin()
    input <- stdin.readLine()

    result <- validate(input)

    stdout.println(result)

With commandline_arg_1.txt and expected_case_1.txt pairs.

Coverage-Driven Testing

  1. Run ek9 -t5 to get coverage data
  2. Check attention.uncovered_functions
  3. For each uncovered function:
    • Analyze function signature and behavior
    • Identify edge cases (null, empty, boundary values)
    • Write tests covering happy path and edge cases
  4. Check attention.uncovered_branches
  5. For each uncovered branch:
    • Identify the condition (BRANCH_TRUE or BRANCH_FALSE)
    • Create test input that exercises that branch
  6. Re-run ek9 -t5 to verify improved coverage

Summary for AI Assistants

Key takeaways for effective AI-assisted EK9 development:

  1. Use -t5 for analysis — JSON is your primary data source
  2. Metrics drive action — Use thresholds to identify and prioritize work
  3. Verify improvements — Always re-run metrics after changes
  4. Use -E3 for errors — Verbose mode explains problems clearly
  5. Report measurably — Show before/after metrics to humans
  6. Generate -t6 for humans — HTML reports for visual review

The AI-Human Partnership: EK9's quality system is designed to make AI assistants maximally effective. You measure, identify issues, apply patterns, and verify. The human reviews results and guides priorities. Together, you produce code that is measurably better than either could produce alone.

Quick Links