@cxi-lmai/ci-agent-platform 3.1.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -144,6 +144,13 @@ picked, not both. Claude-harness model usage is billed by Anthropic, while
144
144
  omp-harness model usage is billed by OpenRouter. GitLab only for now; GitHub
145
145
  Actions omp support is not shipped yet.
146
146
 
147
+ `omp` is a Bun program, so the GitLab template's `before_script` installs
148
+ `bun` next to it (`npm install -g bun`) — the default `node:22-bookworm` image
149
+ ships no Bun runtime, and without it every agent call fails while the job
150
+ still reports success. A custom `PIPE_CI_IMAGE` needs nothing beyond node +
151
+ npm for that install to work. If the harness binary cannot execute, the job
152
+ now fails immediately instead of going green with no review.
153
+
147
154
  ### What it costs
148
155
 
149
156
  Every pipeline job spends paid model usage, so the defaults are deliberately
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cxi-lmai/ci-agent-platform",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "description": "Autonomous dev pipeline on plain GitLab CI or GitHub Actions, driven by Claude Code. A labeled issue goes in, an open merge request comes out.",
5
5
  "keywords": [
6
6
  "claude",
@@ -31,8 +31,9 @@ variables:
31
31
  PIPE_SCRIPTS_DIR: ".claude-pipeline/scripts"
32
32
 
33
33
  # --- CI image (see ci-templates decision note) -----------------------------
34
- # Must provide: node + npm, git, curl. jq and claude-code are installed in
35
- # before_script when missing. The runner scripts talk to the GitLab API with
34
+ # Must provide: node + npm, git, curl. jq, claude-code, and (when
35
+ # PIPE_HARNESS=omp) bun + omp are installed in before_script when missing.
36
+ # The runner scripts talk to the GitLab API with
36
37
  # curl and jq directly, so no glab is needed in the image; glab is only used
37
38
  # interactively, by the install wizard.
38
39
  # Python caveat (E2E finding N-7): node:22-bookworm ships python3 but NOT
@@ -162,7 +163,7 @@ variables:
162
163
 
163
164
  # --- Hidden base job: shared config + runtime variable mapping ---------------
164
165
  # Maps GitLab's CI_ runtime variables onto the PIPE_ names the scripts read, and
165
- # installs claude-code if the image does not ship it.
166
+ # installs the selected harness (and its runtime) if the image does not ship it.
166
167
  .claude-base:
167
168
  image: $PIPE_CI_IMAGE
168
169
  variables:
@@ -193,6 +194,12 @@ variables:
193
194
  fi
194
195
  - |
195
196
  if [ "$PIPE_HARNESS" = "omp" ]; then
197
+ # omp is a Bun program (`#!/usr/bin/env bun`, engines.bun >= 1.3.14)
198
+ # and node:22-bookworm ships no bun, so the installed `omp` shim is
199
+ # unrunnable without it. The `bun` npm package postinstalls the real
200
+ # binary, so no curl|bash and no image change is needed. Deliberately
201
+ # no `|| true`: a missing harness runtime must fail the job loudly.
202
+ command -v bun >/dev/null 2>&1 || npm install -g bun
196
203
  command -v omp >/dev/null 2>&1 || npm install -g @oh-my-pi/pi-coding-agent
197
204
  else
198
205
  command -v claude >/dev/null 2>&1 || npm install -g @anthropic-ai/claude-code
@@ -246,12 +246,39 @@ pipe_scrub_agent_secrets() {
246
246
  done < <(compgen -e | while IFS= read -r v; do pipe_agent_secret_var "$v" && echo "$v"; done)
247
247
  }
248
248
 
249
+ # --- Harness preflight ------------------------------------------------------
250
+ # Every pipe_run_* invocation ends in `|| true`, so a harness binary that
251
+ # exists but cannot execute used to produce a green job with no review, no
252
+ # marker file and one line on stderr (issue #1: `omp` is a Bun program and the
253
+ # default node:22-bookworm image ships no bun, so `command -v omp` succeeded
254
+ # while every run failed with "/usr/bin/env: 'bun': No such file or
255
+ # directory"). Executing the binary once, before the tolerant invocation,
256
+ # converts any harness-runtime breakage into an immediate job failure.
257
+
258
+ pipe_require_harness() {
259
+ # $1 = harness binary name (claude|omp). Exits the job on failure: a
260
+ # non-runnable harness means no agent can run, so there is nothing left for
261
+ # the caller to recover from.
262
+ local bin="$1" out
263
+ if ! command -v "$bin" >/dev/null 2>&1; then
264
+ pipe_log "FATAL: harness binary '$bin' not found on PATH (PIPE_HARNESS=${PIPE_HARNESS:-claude}); install it in before_script"
265
+ exit 1
266
+ fi
267
+ if ! out=$("$bin" --version 2>&1); then
268
+ pipe_log "FATAL: harness binary '$bin' ($(command -v "$bin")) cannot execute: '$bin --version' failed"
269
+ printf '%s\n' "$out" >&2
270
+ pipe_log "omp requires bun on PATH (npm install -g bun); claude requires node"
271
+ exit 1
272
+ fi
273
+ }
274
+
249
275
  pipe_run_claude() {
250
276
  # $1 = agent label for metrics, $2 = skill invocation (e.g. "/review-mr"),
251
277
  # $3 = allowed tools (optional), $4 = model for the main loop (optional,
252
278
  # e.g. $PIPE_MODEL_REVIEW; subagents keep their frontmatter models),
253
279
  # stdin = extra prompt (optional, usually empty)
254
280
  local label="$1" skill="$2" tools="${3:-Agent,Read,Write,Edit,Glob,Grep,Bash}" model="${4:-}"
281
+ pipe_require_harness claude
255
282
  local stdin_file; stdin_file=$(mktemp)
256
283
  cat > "$stdin_file" || true
257
284
 
@@ -350,6 +377,7 @@ pipe_run_omp() {
350
377
  # frontmatter), stdin = extra prompt (optional, usually empty).
351
378
  local label="$1" skill="$2" tools="${3:-Agent,Read,Write,Edit,Glob,Grep,Bash}" model="${4:-}"
352
379
  local omp_tools; omp_tools=$(pipe_translate_tools_to_omp "$tools")
380
+ pipe_require_harness omp
353
381
  local stdin_file; stdin_file=$(mktemp)
354
382
  cat > "$stdin_file" || true
355
383