ilo 26.5.0

ilo - the token-minimal programming language AI agents write
Documentation
name: Rust

on:
  push:
    branches: [ "main", "next" ]
  pull_request:
    branches: [ "main", "next" ]

env:
  CARGO_TERM_COLOR: always
  # Interpreter tests exercise deep recursion (e.g. fib(10)), which can blow
  # the 8 MiB default thread stack on Linux debug builds. 16 MiB is enough.
  RUST_MIN_STACK: 16777216

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
    - name: Check formatting
      run: cargo fmt --all -- --check
    - name: Clippy
      run: cargo clippy --workspace --all-targets -- -D warnings
    - name: Set up Python
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
      with:
        python-version: '3.12'
    - name: Install skills-ref (agentskills.io reference validator)
      run: pip install git+https://github.com/agentskills/agentskills.git#subdirectory=skills-ref
    - name: Validate Agent Skills spec conformance
      run: skills-ref validate skills/ilo/
    - name: Enforce modular-skill token budget (cl100k_base approx)
      # Aggressive per-module caps set in ILO-382 (measured baseline + ~50-token
      # headroom). See scripts/check-skill-tokens.ilo for per-module overrides.
      # Aggregate across all modules ≤ 12,500. Uses the built-in `tokcount`
      # bytes/3.4 approximation (within ~5% for natural-language skill files);
      # ILO-47 tracks upgrading to the full tiktoken-rs BPE tokeniser.
      run: cargo run --quiet -- run scripts/check-skill-tokens.ilo
    - name: Shellcheck install.sh
      run: shellcheck -s sh scripts/install/install.sh
    - name: Verify install.sh sha256 verification (offline regression test)
      # Stubs curl and exercises happy / tamper / missing-asset paths so a
      # refactor can't silently drop the supply-chain integrity check.
      run: bash scripts/install/test-install-sh.sh

  skill-validate:
    # Validate skills/ilo/SKILL.md against the agentskills.io reference
    # validator. This catches regressions in cross-host compatibility
    # (Claude Code, Claude Desktop, Codex, etc.) before the Rust tests run.
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
    - name: Install skills-ref
      run: npm install -g skills-ref
    - name: Validate skill
      run: skills-ref validate skills/ilo/
    - name: Print resolved properties (for debug)
      run: skills-ref read-properties skills/ilo/

  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
    - name: Install cargo-nextest
      uses: taiki-e/install-action@65851e10cd6c377f11a60e600abc07cb08643468 # v2
      with:
        tool: nextest
    - name: Build
      run: cargo build --verbose
    - name: Verify ai.txt is in sync with SPEC.md
      # build.rs regenerates ai.txt from SPEC.md. If a contributor edited SPEC.md without
      # committing the regenerated ai.txt, the diff is non-empty and CI fails.
      run: git diff --exit-code ai.txt
    - name: Run tests (JUnit XML output)
      run: cargo nextest run --profile ci
    - name: Upload test results to Codecov
      if: ${{ !cancelled() }}
      uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6
      with:
        files: target/nextest/ci/junit.xml
        report_type: test_results
        token: ${{ secrets.CODECOV_TOKEN }}

  cross-platform:
    # Smoke-test that ilo builds on every supported native target.
    # This catches linker / cfg regressions before they reach release builds.
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-musl
            os: ubuntu-latest
            cross: true
          - target: aarch64-unknown-linux-musl
            os: ubuntu-latest
            cross: true
          - target: x86_64-apple-darwin
            os: macos-latest
          - target: aarch64-apple-darwin
            os: macos-latest
          - target: x86_64-pc-windows-msvc
            os: windows-latest

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5

      - name: Install Rust
        uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
        with:
          targets: ${{ matrix.target }}

      - name: Install cross
        if: matrix.cross
        run: cargo install cross --git https://github.com/cross-rs/cross

      - name: Build (cross)
        if: matrix.cross
        run: cross build --target ${{ matrix.target }} --no-default-features
        shell: bash

      - name: Build (native)
        if: '!matrix.cross'
        run: cargo build --target ${{ matrix.target }} --no-default-features
        shell: bash

  wasm-smoke:
    # Verify wasm32-wasip1 builds cleanly — no runtime smoke yet (wasmtime
    # install adds ~2 min; tracked as part of ILO-16 follow-ups).
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5

      - name: Install Rust
        uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
        with:
          targets: wasm32-wasip1

      - name: Build WASM
        run: cargo build --target wasm32-wasip1 --no-default-features

  coverage:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
    - name: Install cargo-llvm-cov
      uses: taiki-e/install-action@65851e10cd6c377f11a60e600abc07cb08643468 # v2
      with:
        tool: cargo-llvm-cov
    - name: Build libilo.a (needed by AOT tests)
      run: cargo build
    - name: Generate coverage
      run: cargo llvm-cov --workspace --lcov --output-path lcov.info
    - name: Upload to Codecov
      uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6
      with:
        files: lcov.info
        fail_ci_if_error: false
      env:
        CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}