Skip to content

Releases: Victor-Casado/if-ai

v1.2.0 — Every limit is a budget you can change

Choose a tag to compare

@Victor-Casado Victor-Casado released this 20 Sep 22:27
Immutable release. Only release title and notes can be modified.
72eb1ba

Five new inputs, a README rewritten around getting you running, and a rule applied throughout: a limit this Action invented is yours to change, and a limit the provider owns is not ours to impose at all.

- uses: Victor-Casado/if-ai@v1.2.0
  with:
    condition: This change does not remove or weaken existing tests.
    min-confidence: '0.90'
    mode: diff
    api-key: ${{ secrets.OPENROUTER_API_KEY }}

Nothing to migrate from v1.1.0. Every new input defaults to the value that was previously fixed.

New: budgets you can set

Input Default What it bounds
max-files 200 Paid calls, which matters most in per-file mode
timeout-seconds 30 One evaluation, covering every attempt
retries 1 Retries after a rate limit or server fault. 0 guarantees a single paid call
max-request-bytes 2000000 Transport guard
max-file-bytes 2000000 Memory used to buffer one file's patch

Change lists and commit metadata have their own ceiling, so lowering max-file-bytes to bound one patch does not make the file list unreadable.

Removed: limits the provider owns

The request size cap. The old 28,000-byte limit was never measured against anything. A probe against both providers found each accepting a 102 KB request and rejecting a 203 KB one, so the cap was turning away roughly three quarters of what they would take. Requests are now sent and the rejection is reported.

The condition's 4,000-byte limit, for the same reason: the provider sizes the whole request.

The model identifier allowlist. ^[a-zA-Z0-9/~._-]{1,100}$ guessed at provider naming and rejected 96 of OpenRouter's 447 live models, which use suffixes such as :free and :batch. Only names that are empty or carry whitespace or control characters are refused now.

Errors that name the real cause

  • HTTP 400 explains that the provider rejected the request and that content larger than the model's context is the usual reason. OpenRouter reports this with a structured detail.error_type, so that case is named directly. TypeSafe returns a bare 400 and gets the general wording. Only the structured field classifies a response: an error body can echo the content that was sent.
  • An oversized pull request no longer reports a broken checkout. A file whose patch exceeds the budget says so and points at paths.
  • A stalled error body that outlasts the deadline reports a timeout rather than a status code.

Provider response bodies are still never logged or repeated in an error.

README

Rewritten around a reader who wants it working, not convinced. Three numbered steps and a complete, pasteable workflow now come first: the workflow moved from line 87 to line 22. The pricing evidence and evaluation table moved below the point where you could already have it running.

Verification

105 tests, typecheck, Prettier, and the bundle build pass on Linux and Windows. CI verifies that the committed dist/index.cjs matches source.

The live smoke test ran against Jev through OpenRouter on this commit and passed in all three modes, including a per-file run that correctly identified the failing file.

Known limits

A passing check is advisory. Confidence is calibrated model certainty rather than measured accuracy, and pull request content can attempt to influence the verdict. OpenRouter's Decisions API is alpha and may change.

Installing

Use @v1.2.0, or pin the full commit SHA 72eb1ba4ebaed5ed58dc5b3c8a4a2b0ecadcb554 for an immutable install. Pinning is worth it here: this step receives your API key.

v1.1.0 — Scope a rule to the files it concerns

Choose a tag to compare

@Victor-Casado Victor-Casado released this 20 Sep 02:08
Immutable release. Only release title and notes can be modified.
6e5a7d7

Adds the paths input, so a rule only sees the files it is about.

- uses: Victor-Casado/if-ai@v1.1.0
  with:
    condition: No existing test is deleted or weakened by this change.
    min-confidence: '0.90'
    mode: diff
    paths: |
      src/**
      test/**
    api-key: ${{ secrets.OPENROUTER_API_KEY }}

New: paths

paths takes Git pathspecs, one per line, filtering changed files before anything is evaluated. Globs and :(exclude) both work. Up to 50 entries, 200 UTF-8 bytes each. Ignored in pr-body mode.

Why it exists. A rule about source code was being asked to reason about diffs containing no source code, and answering with low confidence because there was nothing to go on. Scoping the rule removes the question rather than tuning the threshold around it.

A filter matching nothing is a pass, not a failure. A rule scoped to src/** does not apply to a documentation-only pull request. That run reports a new status: 'skipped', calls no API, and costs nothing. A pull request with no changed files at all still errors; a filter is not allowed to disguise one as the other.

In per-file mode this is the cost control. One paid call per matching file instead of one per changed file. Filtering also happens before the 200-file limit, so a large pull request scoped to a few files is evaluated rather than rejected.

Also in this release

A guard on an event belongs in the workflow trigger, not in a job's if. GitHub evaluates the most recent check run for each name on a commit, and a job skipped by its if reports the skipped conclusion, which counts as satisfying a required status check. A job that runs on one event and skips on another for the same commit therefore replaces its own earlier verdict, including a failure. The README quickstart no longer triggers on edited while running mode: diff, which also removes a paid call that could not change the answer.

A required if-ai check does not cover fork PRs under the same-repository pattern: they are skipped, and a skipped check passes. That follows from the documented behavior, but the branch protection consequence is now written down in the README and the reference.

Verification

88 tests, typecheck, Prettier, and the bundle build pass on Linux and Windows. CI verifies that the committed dist/index.cjs matches source.

New coverage: pathspec scoping in diff and per-file against real Git repositories, :(exclude) magic, a filter matching nothing returning no subjects while an empty comparison still errors with and without a filter, and input parsing for trimming, blank lines, the entry cap, and the byte cap.

The live smoke test ran against Jev through OpenRouter on this commit and passed in all three modes, including a per-file run that correctly identified the failing file.

Known limits

A passing check is advisory. Confidence is calibrated model certainty rather than measured accuracy, and pull request content can attempt to influence the verdict. Requests cap at 28,000 UTF-8 bytes and 200 changed paths, with a 30-second deadline covering one retry on a rate limit or server fault. OpenRouter's Decisions API is alpha and may change.

Installing

Use @v1.1.0, or pin the full commit SHA 6e5a7d70f91c2ee24078638d62532e035a58a718 for an immutable install.

Nothing to migrate from v1.0.1. paths is optional and defaults to evaluating every changed file.

v1.0.1 — Retry transient failures

Choose a tag to compare

@Victor-Casado Victor-Casado released this 19 Sep 20:32
Immutable release. Only release title and notes can be modified.
31612ab

The first release carrying the retry work. v1.0.0 tagged the same commit as v0.3.2, so this is the first tag that includes it.

- uses: Victor-Casado/if-ai@v1.0.1
  with:
    condition: This change does not remove or weaken existing tests.
    min-confidence: '0.90'
    mode: diff
    api-key: ${{ secrets.OPENROUTER_API_KEY }}

Changes

A rate limit or a server fault is now retried once. Previously a single HTTP 429 or 5xx failed the whole check, and the error told the reader to rerun later, which meant a maintainer manually re-running a job on someone else's pull request. per-file mode was the most exposed, since it issues four concurrent requests per batch.

  • The existing 30-second deadline covers every attempt rather than each attempt, so the documented bound is unchanged. A retry spends the remaining budget instead of extending it.
  • Retry-After is honored, as seconds or as an HTTP date, up to 10 seconds. A provider asking for longer than that, or longer than the deadline has left, reports the real status rather than stalling and asking again into the same rate limit.
  • 401, 402, 403, and 422 describe the request itself and are not retried. Timeouts and transport failures are not retried either, since they describe the runner or the network rather than a provider state that clears on its own.
  • Retries are logged rather than silent.

A retried request is a second paid call.

The repository also now runs if-ai on its own pull requests; see .github/workflows/if-ai.yml.

Verification

85 tests, typecheck, Prettier, and the bundle build pass on Linux and Windows. CI verifies that the committed dist/index.cjs matches source.

New coverage: retry then succeed, retry then fail with the original status reported, permanent statuses not retried, the retry notice reaching the caller, the deadline guard, and Retry-After parsing for absent, blank, unparseable, numeric, negative, and HTTP-date values.

The live smoke test ran against Jev through OpenRouter on 7595fbb and passed in all three modes, including a per-file run that correctly identified the failing file. That covers the restructured request path on the happy path; it does not exercise a retry, since the provider returned no 429 or 5xx. The retry path is covered by unit tests only.

Known limits

Unchanged otherwise. A passing check is advisory, confidence is calibrated model certainty rather than measured accuracy, and PR content can attempt to influence the verdict. Requests cap at 28,000 UTF-8 bytes and 200 changed paths. OpenRouter's Decisions API is alpha and may change.

Installing

Use @v1.0.1, or pin the full commit SHA 31612abb71ad1351b2fe77caa8b11365300922e1 for an immutable install.

Public Launch

Choose a tag to compare

@Victor-Casado Victor-Casado released this 19 Sep 19:51
Immutable release. Only release title and notes can be modified.
5bfe6ed
Rename the Marketplace listing to 'if-ai PR Check' for v0.3.2 (#9)

Marketplace names must be unique across every action, user, and
organization. The GitHub user if-ai already exists, so the bare name is
rejected at publish time. Only the action.yml name field changes; the
repository name and every uses: path stay the same.

Record the reason in docs/maintaining.md and bump to 0.3.2.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

v0.3.2 — Marketplace listing name

Choose a tag to compare

@Victor-Casado Victor-Casado released this 19 Sep 19:49
Immutable release. Only release title and notes can be modified.
5bfe6ed

Prepares the action for a GitHub Marketplace listing. No behavior change from v0.3.1, and dist/index.cjs is byte-identical to it.

- uses: Victor-Casado/if-ai@v0.3.2
  with:
    condition: This change does not remove or weaken existing tests.
    min-confidence: '0.90'
    mode: diff
    api-key: ${{ secrets.OPENROUTER_API_KEY }}

Changes

  • The name in action.yml is now if-ai PR Check. Marketplace names must be unique across every action, user, and organization, and the GitHub user if-ai already exists, so the bare name is rejected at publish time.
  • docs/maintaining.md records that constraint.
  • Version references updated across package.json, the lockfile, the README, and the four examples.

The repository name and the uses: path are unchanged. Victor-Casado/if-ai still resolves, and no workflow needs editing beyond the version tag. Only the Marketplace listing title differs.

Verification

75 offline tests, TypeScript, Prettier, and the bundle build pass on Linux and Windows. CI verifies that the committed bundle matches source. No live smoke test was run, since evaluation behavior is unchanged; the v0.3.0 run against Jev through OpenRouter still covers it.

Known limits

Unchanged from v0.3.0. A passing check is advisory, confidence is calibrated model certainty rather than measured accuracy, and PR content can attempt to influence the verdict. Requests cap at 28,000 UTF-8 bytes and 200 changed paths, with a 30-second deadline and no retries. OpenRouter's Decisions API is alpha and may change.

Installing

Use @v0.3.2, or pin the full commit SHA 5bfe6ed245586fa96ecd313c8178ce305586497c for an immutable install.

v0.3.1 — README failure example

Choose a tag to compare

@Victor-Casado Victor-Casado released this 19 Sep 19:44
Immutable release. Only release title and notes can be modified.
86ee83f

Documentation only. No behavior change from v0.3.0, and dist/index.cjs is byte-identical to it.

- uses: Victor-Casado/if-ai@v0.3.1
  with:
    condition: This change does not remove or weaken existing tests.
    min-confidence: '0.90'
    mode: diff
    api-key: ${{ secrets.OPENROUTER_API_KEY }}

Changes

  • Simplified the README's failure example: the job summary is shown directly rather than quoted, without the Details column, and now covers condition-false, low-confidence, and passed in one table.
  • Version references updated across package.json, the lockfile, the README, and the four examples.

Verification

75 offline tests, TypeScript, Prettier, and the bundle build pass on Linux and Windows. CI verifies that the committed bundle matches source. No live smoke test was run for this release, since evaluation behavior is unchanged; the v0.3.0 run against Jev through OpenRouter still covers it.

Known limits

Unchanged from v0.3.0. A passing check is advisory, confidence is calibrated model certainty rather than measured accuracy, and PR content can attempt to influence the verdict. Requests cap at 28,000 UTF-8 bytes and 200 changed paths, with a 30-second deadline and no retries. OpenRouter's Decisions API is alpha and may change.

Installing

Use @v0.3.1, or pin the full commit SHA 86ee83f047ccca1e59f62d9b5155d85490599848 for an immutable install.

v0.3.0 — OpenRouter by default

Choose a tag to compare

@Victor-Casado Victor-Casado released this 19 Sep 19:34
Immutable release. Only release title and notes can be modified.
1d30387

Install it as a workflow step:

- uses: Victor-Casado/if-ai@v0.3.0
  with:
    condition: This change does not remove or weaken existing tests.
    min-confidence: '0.90'
    mode: diff
    api-key: ${{ secrets.OPENROUTER_API_KEY }}

Changes

  • OpenRouter is now the default provider. provider defaults to openrouter and runs typesafe/jev-1.13 through OpenRouter's alpha Decisions API. Pass an OPENROUTER_API_KEY secret as api-key. Direct TypeSafe access stays available with provider: typesafe and a TYPESAFE_API_KEY. if-ai never guesses the provider from a key and never falls back to the other one.
  • Rewritten README. Leads with the workflow you paste in, the price, and TypeSafe's published Jev workflow-eval figures, with an explicit note that those evals are TypeSafe's own, score agreement with averaged GPT-6 Astra and Fable 5.1 judgments rather than ground truth, and do not cover pull request review.
  • New input and output reference. Every input, output, mode, and limit, moved out of the README.
  • Examples pinned to actions/checkout v7.0.1.
  • @types/node held on major 24 to match the Action's Node 24 runtime.

Verification

75 offline tests, TypeScript, Prettier, and the bundle build pass on Linux and Windows. CI verifies that the committed dist/index.cjs matches source.

The live smoke test ran against Jev through OpenRouter on this commit and passed in all three modes, including a per-file run that correctly identified the failing file. That checks routing, request shape, and response handling. It does not measure model accuracy.

Known limits

A passing check is advisory. Confidence is calibrated model certainty, not measured accuracy, and PR content can attempt to influence the verdict.

Requests cap at 28,000 UTF-8 bytes and 200 changed paths, with a 30-second deadline and no retries. Binary files, LFS pointers, submodules, and non-UTF-8 patches fail explicitly rather than being truncated. Diff modes need a full-history checkout. OpenRouter's Decisions API is alpha and may change.

Upgrading

Nothing to migrate for new installs. Use @v0.3.0, or pin the full commit SHA 1d303877be14e49a41ff6a1d96c57e61bab2c1d4 for an immutable install.

v0.2.0 — OpenRouter support

Choose a tag to compare

@Victor-Casado Victor-Casado released this 19 Sep 19:06
Immutable release. Only release title and notes can be modified.
90ba79a

Run Jev with an OpenRouter key by setting provider: openrouter and passing the key through api-key. TypeSafe remains the default.

uses: Victor-Casado/if-ai@v0.2.0
with:
  condition: This change does not remove or weaken existing tests.
  min-confidence: '0.90'
  provider: openrouter
  api-key: ${{ secrets.OPENROUTER_API_KEY }}

The OpenRouter default model is typesafe/jev-1.13. Requests use its alpha Decisions API and Jev's native confidence. This does not add support for arbitrary chat models. Existing modes, thresholds, and outputs are unchanged.

Both providers share request limits, response validation, deadlines, and sanitized errors. HTTP 402 errors now point to credits and spending limits. Documentation explains provider setup and data processing.

Validation: 74 offline tests on Linux and Windows, TypeScript and formatting checks, reproducible bundle verification, CodeQL, and live smoke tests for TypeSafe and OpenRouter. Each live run covers all three modes plus an expected per-file failure. These synthetic checks verify integration, not model accuracy.

v0.1.1

Choose a tag to compare

@Victor-Casado Victor-Casado released this 19 Sep 18:54
Immutable release. Only release title and notes can be modified.
6503119

Fixes

  • Keep per-file patches separate when a file becomes a directory or a directory becomes a file. Previously, a parent path could include child changes and duplicate them in the combined diff.
  • Require a reviewed environment in the public fork and PR-body examples before making paid Jev calls. Configure the environment reviewers and secret before using those examples.

Contributor and repository updates

  • Replace obsolete planning documents with focused usage, contribution, security, and maintenance guidance.
  • Simplify response validation and test setup; enforce consistent formatting.
  • Add bug and feature forms, a PR template, CODEOWNERS, and weekly dependency updates.
  • Protect main with required PRs, CI, and CodeQL; protect release tags and enable immutable releases.

Validated with 48 offline tests on Linux and Windows, type and formatting checks, a reproducible bundle, and live Jev smoke tests across all three modes. The live tests include an expected per-file failure and use synthetic PR events. They do not measure model accuracy.

Use Victor-Casado/if-ai@v0.1.1, or pin this release's full commit SHA. Existing inputs and outputs are unchanged.

if-ai v0.1.0

Choose a tag to compare

@Victor-Casado Victor-Casado released this 19 Sep 07:02
Immutable release. Only release title and notes can be modified.

if-ai v0.1.0

Write pull request checks in plain English using Jev. Supply a condition and a minimum confidence; the check passes only when both are satisfied.

- uses: Victor-Casado/if-ai@v0.1.0
  with:
    condition: This change does not remove or weaken existing tests.
    min-confidence: '0.90'
    mode: diff
    api-key: ${{ secrets.TYPESAFE_API_KEY }}

Diff modes require a full-history checkout. See the README for a complete workflow.

Included

  • PR body, complete text diff, and per-file parallel evaluation.
  • One check with file-specific failures. Every file must pass in per-file mode.
  • Required condition and confidence threshold. False answers and low confidence fail the check.
  • Boolean, confidence, status, failed-file, and detailed result outputs, plus a job summary.
  • Bounded requests, response validation, and explicit failures for unsupported or oversized input. No silent truncation.
  • Four workflow examples, including fork PR handling, an MIT license, and a bundled Node 24 Action.

Validation

Offline tests run on Linux and Windows. Live Jev tests exercised all three modes and an intentionally failing per-file fixture. The live harness uses synthetic PR events and actual Git commits; these checks verify integration behavior, not model accuracy. Validation details.

Initial limits

Text only, up to 200 changed paths, and a 28,000-byte request limit per evaluation. Binary files, LFS pointers, submodules, and missing content fail explicitly. Renames are evaluated as a deletion and an addition. Per-file evaluations have no cross-file context.

The selected content goes directly to TypeSafe using your API key. Confidence is model certainty, not a correctness guarantee. This is an independent project, not affiliated with TypeSafe or GitHub.