From b3d7a507812e75f8005c52e91bcc5850c1a4d4a1 Mon Sep 17 00:00:00 2001 From: Ralf Anton Beier Date: Wed, 20 May 2026 20:35:49 +0200 Subject: [PATCH] fix(ci): mythos-auto aggregate uses curl, not gh; register p3_stream.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fifth mythos-auto plumbing fix. The `aggregate` job composed the sticky PR comment and applied the `mythos-pass-done` label with `gh api` / `gh pr edit`. The GitHub CLI is not installed on the `light` runner, so the step exited 127: /var/lib/runners/runner8/_work/.../d339fc7e.sh: line 53: gh: command not found On PR #173 the Mythos scan ran end-to-end and returned NO_FINDINGS for both touched Tier-5 files, but this `gh`-absent aggregate bug meant the label never auto-applied and the label-only `Mythos delta-pass gate` failed downstream. Fix: - Sticky-comment upsert and label apply rewritten with `curl` against the GitHub REST API. `curl` and `jq` are universally present on the runners; `gh` is not. - The markdown body is JSON-encoded via `jq -Rs '{body: .}'` — the whole file as one raw string — so newlines, quotes, emoji, backticks, and the model-authored hypothesis text are all escaped and cannot break out of the JSON request body. - `curl -fsS` fails loudly on an HTTP error rather than silently posting nothing. - The label step gains `REPO` in its env (the labels endpoint needs the repo path); the labels POST adds without clobbering existing labels. Also registers `meld-core/src/p3_stream.rs` (introduced in #173) in the Tier-5 path lists of both mythos-gate.yml and mythos-auto.yml. This was deferred from #173: claude-code-action self-validates that the workflow invoking it has content identical to `main`, so a PR cannot both modify `mythos-auto.yml` and be scanned by it. This PR touches only the two workflow files — no Tier-5 source — so its own auto-runner detect job finds nothing to scan and skips cleanly, sidestepping the self-validation collision. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/mythos-auto.yml | 44 ++++++++++++++++++++++++------- .github/workflows/mythos-gate.yml | 1 + CHANGELOG.md | 19 +++++++++++++ 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/.github/workflows/mythos-auto.yml b/.github/workflows/mythos-auto.yml index 423e388..f6c295c 100644 --- a/.github/workflows/mythos-auto.yml +++ b/.github/workflows/mythos-auto.yml @@ -101,6 +101,7 @@ jobs: "meld-core/src/rewriter.rs" "meld-core/src/component_wrap.rs" "meld-core/src/p3_async.rs" + "meld-core/src/p3_stream.rs" "meld-core/src/adapter/" "meld-core/src/resource_graph.rs" "meld-core/src/segments.rs" @@ -317,18 +318,35 @@ jobs: printf '%s' "$body" > /tmp/mythos-body.md echo "verdict=$verdict" >> "$GITHUB_OUTPUT" - # Sticky-comment upsert: find by marker, PATCH if found - # else POST. Marker is the literal HTML comment string. + # Sticky-comment upsert via the GitHub REST API with `curl`. + # `gh` (GitHub CLI) is NOT installed on the `light` runner — + # the prior `gh api` form exited 127. `curl` and `jq` are + # universally present. Marker is the literal HTML comment. + # + # `jq -Rs '{body: .}'` reads the whole markdown file as one + # raw string and JSON-encodes it — newlines, quotes, emoji, + # backticks are all escaped, so nothing in the model-authored + # hypothesis text can break out of the JSON request body. marker='' - existing=$(gh api "repos/${REPO}/issues/${PR_NUMBER}/comments" \ - --paginate --jq ".[] | select(.body | contains(\"${marker}\")) | .id" | head -n1) + api="https://api.github.com" + auth="Authorization: Bearer ${GH_TOKEN}" + accept="Accept: application/vnd.github+json" + jq -Rs '{body: .}' < /tmp/mythos-body.md > /tmp/mythos-body.json + + existing=$(curl -fsS -H "$auth" -H "$accept" \ + "${api}/repos/${REPO}/issues/${PR_NUMBER}/comments?per_page=100" \ + | jq -r --arg m "$marker" \ + 'map(select(.body | contains($m))) | .[0].id // empty') + if [ -n "$existing" ]; then - gh api -X PATCH "repos/${REPO}/issues/comments/${existing}" \ - -f body="@/tmp/mythos-body.md" >/dev/null + curl -fsS -X PATCH -H "$auth" -H "$accept" \ + "${api}/repos/${REPO}/issues/comments/${existing}" \ + -d @/tmp/mythos-body.json >/dev/null echo "updated comment $existing" else - gh api -X POST "repos/${REPO}/issues/${PR_NUMBER}/comments" \ - -f body="@/tmp/mythos-body.md" >/dev/null + curl -fsS -X POST -H "$auth" -H "$accept" \ + "${api}/repos/${REPO}/issues/${PR_NUMBER}/comments" \ + -d @/tmp/mythos-body.json >/dev/null echo "posted new comment" fi @@ -337,8 +355,16 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} + REPO: ${{ github.repository }} run: | - gh pr edit "$PR_NUMBER" --add-label mythos-pass-done + # `curl` rather than `gh pr edit` — `gh` is absent on the + # light runner. The labels endpoint adds without clobbering + # existing labels. + curl -fsS -X POST \ + -H "Authorization: Bearer ${GH_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/${REPO}/issues/${PR_NUMBER}/labels" \ + -d '{"labels":["mythos-pass-done"]}' >/dev/null - name: Fail job on FINDING verdict if: steps.compose.outputs.verdict == 'FAIL' diff --git a/.github/workflows/mythos-gate.yml b/.github/workflows/mythos-gate.yml index 385c708..d182b5f 100644 --- a/.github/workflows/mythos-gate.yml +++ b/.github/workflows/mythos-gate.yml @@ -60,6 +60,7 @@ jobs: "meld-core/src/rewriter.rs" "meld-core/src/component_wrap.rs" "meld-core/src/p3_async.rs" + "meld-core/src/p3_stream.rs" "meld-core/src/adapter/" "meld-core/src/resource_graph.rs" "meld-core/src/segments.rs" diff --git a/CHANGELOG.md b/CHANGELOG.md index 3418cec..9e3d217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Fixed + +- **mythos-auto aggregate job: `gh` → `curl`** + (`.github/workflows/mythos-auto.yml`). The `aggregate` job composed + the sticky PR comment and applied the `mythos-pass-done` label via + `gh api` / `gh pr edit`, but the GitHub CLI is not installed on the + `light` runner — the step exited 127 (`gh: command not found`), + blocking the label even when the Mythos scan returned NO_FINDINGS. + Rewrites both the comment upsert and the label apply with `curl` + against the REST API (`curl` + `jq` are universally present). The + markdown body is JSON-encoded with `jq -Rs '{body: .}'` so nothing + in the model-authored hypothesis text can break the request. Also + registers `meld-core/src/p3_stream.rs` in the Mythos Tier-5 path + lists (`mythos-gate.yml`, `mythos-auto.yml`) — deferred from #173, + which could not modify `mythos-auto.yml` and still be scanned by + it (claude-code-action self-validates the invoking workflow against + `main`). This PR touches only the workflow files, so its own + auto-runner detect job finds no Tier-5 source and skips the scan. + ### Added - **Cross-component `stream` pairing detection** (issue #141,