← All projects
AI automation · merge request review

uBixKelpie

Beta v0.1.0-beta.1 PHP 8.5+ · built on uBixCore · GitLab CI

uBixKelpie is uBixSys's AI automation product. The first beta reviews your merge requests: it reads the diff, opens one inline thread per finding, and keeps a summary note up to date.

Issue fixing and code monitoring are the intent and are not built. This page says what the beta does and what it does not.

Status
Beta · interfaces may change
Release
v0.1.0-beta.1
Review runs on
OpenCode · OpenRouter · GitLab CI
Built on
uBixCore, as a Composer dependency
Language
PHP 8.5+
License
BSD-3-Clause
Synopsis
.gitlab-ci.yml
include:
  - project: ubixsys/ubixkelpie
    ref: v0.1.0-beta.1          # a tag, to pin; or dev
    file: ci/ai-review/ai-review.yml

variables:
  AI_REVIEW_REF: v0.1.0-beta.1   # the same ref: the scripts are fetched at it
  AI_REVIEW_MODE: advisory
Description

uBixKelpie is a uBixCore application. The beta has two working parts. The first is ai-review-mr, a reusable GitLab CI job that reviews a merge request with OpenCode and OpenRouter and posts the findings as discussion threads. The second is a GitLab webhook receiver in the KelpieApi app that re-runs a merge request's sign-off job when someone approves it.

The review complements uBixCore's code:review rather than repeating it. code:review is the deterministic gate: lint, static types, tests, conventions. The AI review is judgement, and advisory first: logic bugs, security, edge cases, design smells and missing tests for changed behaviour. It is told not to report what a linter or code:review would catch.

It treats a repository's own standards as context: CLAUDE.md, AGENTS.md, CONTRIBUTING.md, docs/standards/**/*.md and an optional .ai-review.md. These are read from the target branch, so a merge request cannot rewrite the rules it is judged by.

The review container gets the repository mounted read-only and only the read, grep and glob tools: no shell, no edit, no web. The GitLab token is not in OpenCode's environment. The diff, title and standards are treated as untrusted data.

Two secrets, then it runs

Two masked, unprotected group variables: OPENROUTER_API_KEY, and AI_REVIEW_GITLAB_TOKEN (a group access token, Reporter role, api scope, which posts the threads and fetches the scripts). With either missing the job exits 75, posts an UNREVIEWED note when it can, and is allowed to fail. It never turns a pipeline red for being unconfigured. It needs a runner tagged shell with Docker.

Examples
advisory or blocking
variables:
  AI_REVIEW_MODE: blocking     # default advisory: threads posted, the job never fails
  AI_REVIEW_MAX_ROUNDS: "3"    # one round is one pushed commit
  AI_REVIEW_MODEL: openrouter/anthropic/claude-haiku-5.5

blocking exits 1 only when a blocker or major finding with high confidence stands.

dismiss a finding
# resolve the thread with a reply that starts with the word:
Dismissed: this path is only reached from the admin CLI

A dismissed finding is skipped from then on. Its identity is the file plus the issue slug, not the line, so it survives edits. Resolving without that word means "fixed": if the same finding comes back, it opens a new thread. Add the review:extra label to allow more rounds.

try it locally
$ ci/ai-review/test/run-tests.sh          # dry-run tests, no network or model
$ ci/ai-review/review.sh --dry-run --repo . --diff my.diff

--dry-run prints the validated JSON and every comment it would post, and never calls GitLab.

What is not built

Picking up Git issues and fixing them, and running servers that monitor code, are the product's aim. Neither is in v0.1.0-beta.1. The uBixKelpie README still describes the repository as a foundation, with the review and the merge request workflow added on top. There is no database and no chat channel yet.

Capabilities
One inline thread per finding Built
Findings are posted as discussion threads on the changed line. If GitLab refuses the position, a plain thread is posted and the reason is in the job log.
Deduplication Built
A finding already open or dismissed is matched by its id or by file and title, so a reworded finding does not duplicate. A finding on a line an open thread already covers goes into the summary instead of a second thread. The discussions are read again just before posting, so a thread another job posted meanwhile is not posted twice.
"Already open" and "no longer reported" Built
The summary counts threads still open, and lists a thread as no longer reported when the lines it points at changed since it was posted. Listed threads are never resolved automatically, and agents never resolve them.
A visible note when nothing is found Built
A clean review or a skipped one is not silent: a plain note says the review ran with no findings, the model, the commit and the files covered. Later runs replace it.
Advisory or blocking Built
Advisory by default, so a pilot can measure noise before anything can block a merge. Blocking mode fails the job on a standing high-confidence blocker or major finding.
Cost guards Built
Skips drafts, docs-only changes and empty diffs; leaves out lockfiles, vendor/ and generated files; stops with a note over the size cap (3000 lines or 150 KiB by default) or past the round cap.
Approval gate Built
POST /gitlab/webhook on KelpieApi re-runs the merge request's require-approval job on an Approve or a 👍 emoji. A wrong or missing secret is refused with 401. Requires uBixCore ^0.46.1.
KelpieApi Built
Health and version endpoints, CORS and JSON errors, deployed through a dev → staging → main pipeline.
Fixes Git issues Not built
Picks up an issue and works on a fix. Planned.
Monitors code on servers Not built
Runs servers that watch code and report what they find. Planned.

The default model tier is the one the beta documents; a cheaper "contributor" tier trains on the prompts it receives, including the code under review, so it is not for private code.