diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33992a96..c4c1fc39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,8 +82,14 @@ jobs: - name: lint — validated constructors are scoped run: python3 scripts/lint/check-validated-constructors.py + - name: lint — olympus migration is complete + consistent + # Enforces the Olympus rename/version migration invariants so a future + # workflow edit can't silently revert to agent_ops_ref or leave the 5 + # wrapper pins out of sync (the class that left pr-review.yml ahead). + run: bash scripts/lint/check-olympus-migration.sh + # NOTE: the generic internal-infra LEAKAGE gate now runs in the separate - # guard.yml workflow (delegated to agent-ops guard.yml@v0.2.0). The in-tree + # guard.yml workflow (delegated to olympus guard.yml@v0.4.0). The in-tree # scripts/lint/check-leakage.sh is retained only for the pcap-corpus gate + # the self-test below; heron-specific lints stay here. @@ -170,7 +176,7 @@ jobs: run: python3 scripts/staging/tests/test_longevity_check.py # NOTE: the agent-bot tests (triage reply composition + mara debounce) - # moved to agent-ops with the agent loop; they run in agent-ops's own CI + # moved to olympus with the agent loop; they run in olympus's own CI # against the canonical scripts/agent-bot/* now that heron delegates those # surfaces. heron no longer carries the in-tree scripts or their tests. diff --git a/.github/workflows/guard.yml b/.github/workflows/guard.yml index 33d25143..a35e8582 100644 --- a/.github/workflows/guard.yml +++ b/.github/workflows/guard.yml @@ -1,18 +1,18 @@ name: guard # Hygiene gate — DELEGATES the generic, LLM-free leakage check to the shared -# agent-ops mechanism (Netis/agent-ops). agent-ops's check-leakage.sh was +# olympus mechanism (Netis/olympus). olympus's check-leakage.sh was # extracted FROM this repo; the reusable workflow runs it on GitHub-hosted # ubuntu against THIS repo's tracked files + THIS repo's # scripts/lint/leakage-allowlist.txt, so the gate is single-sourced and any -# future hardening in agent-ops applies here automatically. +# future hardening in olympus applies here automatically. # # Scope note (intentional): only the LEAKAGE gate is delegated. # - secret-EXISTENCE / secret-VALUE checks stay in ci.yml — they validate # THIS repo's specific secrets (AGENT_GH_TOKEN / LITELLM_*) with the values -# passed in as env, which is inherently consumer-specific. (agent-ops +# passed in as env, which is inherently consumer-specific. (olympus # guard.yml's run_secret_checks also mis-invokes check-secret-values.sh — -# tracked as an agent-ops follow-up — so we pass run_secret_checks: false.) +# tracked as an olympus follow-up — so we pass run_secret_checks: false.) # - heron-specific lints (pcap-corpus, validated-constructors, # test-check-leakage self-test) stay in ci.yml — not part of the framework. # @@ -31,8 +31,8 @@ permissions: jobs: guard: - uses: Netis/olympus/.github/workflows/guard.yml@v0.2.0 + uses: Netis/olympus/.github/workflows/guard.yml@v0.4.0 with: - agent_ops_ref: v0.2.0 + olympus_ref: v0.4.0 run_secret_checks: false secrets: inherit diff --git a/.github/workflows/issue-implement.yml b/.github/workflows/issue-implement.yml index 56ddab93..6b92f34b 100644 --- a/.github/workflows/issue-implement.yml +++ b/.github/workflows/issue-implement.yml @@ -1,14 +1,14 @@ name: issue-implement -# Dev agent **wiwi** — now DELEGATES to the shared agent-ops mechanism -# (Netis/agent-ops). This repo's implement policy — the default branch wiwi +# Dev agent **wiwi** — now DELEGATES to the shared olympus mechanism +# (Netis/olympus). This repo's implement policy — the default branch wiwi # branches off, the build+test command it must make green, the scope ceiling, # the `auto-agent` label on the DRAFT PR, and the agent name — all live in -# `.agent-ops.json`. The agent code + reusable workflow live in agent-ops, +# `.olympus.json`. The agent code + reusable workflow live in olympus, # pinned to a tag. Upgrading the mechanism = bumping the @ref below (and -# `agent_ops_ref`) in lockstep. +# `olympus_ref`) in lockstep. # -# This is heron dogfooding the framework it spun out: agent-ops was extracted +# This is heron dogfooding the framework it spun out: olympus was extracted # FROM heron's in-tree scripts/agent-bot/run_wiwi.sh, which has since been # removed now that this delegation is proven (same staged approach as # issue-triage.yml). @@ -21,7 +21,7 @@ name: issue-implement # # Behavioral note (intentional): the in-tree workflow used # `concurrency: cancel-in-progress: true` (re-labelling cancelled an in-flight -# wiwi). agent-ops's implement.yml fixes concurrency to cancel-in-progress: +# wiwi). olympus's implement.yml fixes concurrency to cancel-in-progress: # false — safer, since it never kills wiwi mid-push/half-PR. To retry a stuck # run, cancel it explicitly via `gh run cancel` rather than re-labelling. @@ -37,8 +37,8 @@ permissions: jobs: implement: if: ${{ github.event.label.name == 'agent:try' }} - uses: Netis/olympus/.github/workflows/implement.yml@v0.2.0 + uses: Netis/olympus/.github/workflows/implement.yml@v0.4.0 with: - agent_ops_ref: v0.2.0 + olympus_ref: v0.4.0 runner_labels: '["self-hosted","heron"]' secrets: inherit # LITELLM_BASE_URL / API_KEY / NO_PROXY + AGENT_GH_TOKEN + AUTO_MERGE_TEAM diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml index d2819cfe..baef8c69 100644 --- a/.github/workflows/issue-triage.yml +++ b/.github/workflows/issue-triage.yml @@ -1,12 +1,12 @@ name: issue-triage -# Triage now DELEGATES to the shared agent-ops mechanism (Netis/agent-ops). +# Triage now DELEGATES to the shared olympus mechanism (Netis/olympus). # This repo's triage policy — gates, labels, reply language, agent names — -# lives in `.agent-ops.json`; the agent code + reusable workflow live in -# agent-ops, pinned to a tag. Upgrading the mechanism = bumping the @ref below -# (and `agent_ops_ref`) in lockstep. +# lives in `.olympus.json`; the agent code + reusable workflow live in +# olympus, pinned to a tag. Upgrading the mechanism = bumping the @ref below +# (and `olympus_ref`) in lockstep. # -# This is heron dogfooding the framework it spun out: agent-ops was extracted +# This is heron dogfooding the framework it spun out: olympus was extracted # FROM heron's in-tree scripts/agent-bot/run_triage.sh, which has since been # removed now that this delegation is proven in production. # @@ -24,8 +24,8 @@ permissions: jobs: triage: - uses: Netis/olympus/.github/workflows/triage.yml@v0.2.0 + uses: Netis/olympus/.github/workflows/triage.yml@v0.4.0 with: - agent_ops_ref: v0.2.0 + olympus_ref: v0.4.0 runner_labels: '["self-hosted","heron"]' secrets: inherit # LITELLM_BASE_URL / API_KEY / NO_PROXY + AGENT_GH_TOKEN diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index e0959e94..d6c5f74f 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -1,13 +1,13 @@ name: pr-review -# Headless code-review agent (vivi) — now DELEGATES to the shared agent-ops -# mechanism (Netis/agent-ops). The review bot's identity, the auto-agent label, +# Headless code-review agent (vivi) — now DELEGATES to the shared olympus +# mechanism (Netis/olympus). The review bot's identity, the auto-agent label, # the default branch, and the build command all live in this repo's -# `.agent-ops.json`; the reviewer code + reusable workflow live in agent-ops, +# `.olympus.json`; the reviewer code + reusable workflow live in olympus, # pinned to a tag. Upgrading the mechanism = bumping the @ref below (and -# `agent_ops_ref`) in lockstep. +# `olympus_ref`) in lockstep. # -# heron dogfooding the framework it spun out: agent-ops's review.yml was +# heron dogfooding the framework it spun out: olympus's review.yml was # extracted FROM this repo's in-tree scripts/pr-review/* + scripts/agent-bot/ # {auto_merge,revise_dispatch}.sh, which have since been removed # now that this delegation is proven (same staged approach as @@ -17,7 +17,7 @@ name: pr-review # after `ci` succeeds on a same-repo PR, reviews the diff, posts a structured # review, then for auto-agent PRs either admin-merges (APPROVE + allowlisted # author) or dispatches the pr-revise workflow (CHANGES_REQUESTED). Manual -# re-review via workflow_dispatch is preserved (needs agent-ops ≥ v0.2.0, which +# re-review via workflow_dispatch is preserved (needs olympus ≥ v0.2.0, which # added the pr_number input). on: @@ -39,9 +39,9 @@ permissions: jobs: review: - uses: Netis/olympus/.github/workflows/review.yml@v0.3.1 + uses: Netis/olympus/.github/workflows/review.yml@v0.4.0 with: - agent_ops_ref: v0.3.1 + olympus_ref: v0.4.0 runner_labels: '["self-hosted","heron"]' # Empty on the workflow_run path (resolved from the run event); the PR # number typed on a manual workflow_dispatch re-review. diff --git a/.github/workflows/pr-revise.yml b/.github/workflows/pr-revise.yml index f6e9d6ff..15a5fbdd 100644 --- a/.github/workflows/pr-revise.yml +++ b/.github/workflows/pr-revise.yml @@ -1,14 +1,14 @@ name: pr-revise -# wiwi REVISION pass — now DELEGATES to the shared agent-ops mechanism -# (Netis/agent-ops). Dispatched by the review workflow's revise_dispatch step +# wiwi REVISION pass — now DELEGATES to the shared olympus mechanism +# (Netis/olympus). Dispatched by the review workflow's revise_dispatch step # (`gh workflow run pr-revise.yml -f pr_number=N`) when vivi REQUEST_CHANGES a # wiwi PR (label `auto-agent`) and the round cap isn't hit. The workflow NAME # must stay `pr-revise.yml` because revise_dispatch targets it by filename. # -# It checks out the PR head, runs agent-ops's run_revise.sh to address the +# It checks out the PR head, runs olympus's run_revise.sh to address the # blocking feedback, and pushes back — which re-triggers ci → pr-review, so -# vivi re-reviews. The round cap lives in revise_dispatch.sh (agent-ops side). +# vivi re-reviews. The round cap lives in revise_dispatch.sh (olympus side). # # Dispatch-only: the trigger is a PAT-authenticated `gh workflow run` (a review # posted by GITHUB_TOKEN can't start a workflow run — GitHub anti-recursion). @@ -30,9 +30,9 @@ permissions: jobs: revise: - uses: Netis/olympus/.github/workflows/revise.yml@v0.2.0 + uses: Netis/olympus/.github/workflows/revise.yml@v0.4.0 with: pr_number: ${{ inputs.pr_number }} - agent_ops_ref: v0.2.0 + olympus_ref: v0.4.0 runner_labels: '["self-hosted","heron"]' secrets: inherit # LITELLM_* + AGENT_GH_TOKEN diff --git a/.gitignore b/.gitignore index 735c272e..8025e88a 100644 --- a/.gitignore +++ b/.gitignore @@ -54,4 +54,10 @@ __pycache__/ .superpowers .worktrees/ +# Transient clone of the internal Olympus agent repo, created by the agent-loop +# runner. Never commit it — a checked-in gitlink breaks public clones (no +# .gitmodules) and its .git/config holds a runner credential. +/_agentops/ +/_agentops + /logs/ diff --git a/.agent-ops.json b/.olympus.json similarity index 89% rename from .agent-ops.json rename to .olympus.json index 37afecaa..94ec2bd0 100644 --- a/.agent-ops.json +++ b/.olympus.json @@ -1,5 +1,5 @@ { - "$schema": "https://raw.githubusercontent.com/Netis/agent-ops/main/schema/agent-ops.schema.json", + "$schema": "https://raw.githubusercontent.com/Netis/olympus/main/schema/olympus.schema.json", "project": { "name": "heron", "default_branch": "main" diff --git a/scripts/lint/check-olympus-migration.sh b/scripts/lint/check-olympus-migration.sh new file mode 100755 index 00000000..0b9035cd --- /dev/null +++ b/scripts/lint/check-olympus-migration.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# Validate that the Olympus migration is complete and internally consistent. +# +# The expected Olympus version is NOT hardcoded here — it is derived from the +# first wrapper's `olympus_ref:` and treated as the source of truth, so a future +# version bump needs no edit to this script. A bump is enforced by asserting +# every wrapper agrees on that version (the class of bug that left pr-review.yml +# ahead of the other four). +# +# Checks: +# 1. .olympus.json exists, .agent-ops.json does not +# 2. .olympus.json $schema points to Netis/olympus +# 3. All 5 wrapper workflows use olympus_ref (not agent_ops_ref) +# 4. All 5 wrappers agree on one olympus_ref version, and each wrapper's +# `uses: Netis/olympus/...@vX.Y.Z` pin matches its own olympus_ref +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +cd "$REPO_ROOT" + +fail=0 +fail_one() { echo " FAIL: $1"; fail=$((fail + 1)); } +pass_one() { echo " PASS: $1"; } + +WRAPPERS=( + ".github/workflows/guard.yml" + ".github/workflows/issue-implement.yml" + ".github/workflows/issue-triage.yml" + ".github/workflows/pr-revise.yml" + ".github/workflows/pr-review.yml" +) + +echo "=== Olympus migration check ===" +echo "" + +# 1. Policy file +echo "--- Policy file ---" +if [ -f .olympus.json ]; then + pass_one ".olympus.json exists" +else + fail_one ".olympus.json missing" +fi + +if [ ! -f .agent-ops.json ]; then + pass_one ".agent-ops.json removed" +else + fail_one ".agent-ops.json still present" +fi + +if grep -q 'Netis/olympus/main/schema/olympus.schema.json' .olympus.json 2>/dev/null; then + pass_one '$schema points to olympus.schema.json' +else + fail_one '$schema does not point to olympus.schema.json' +fi + +# 2. Workflow wrappers +echo "" +echo "--- Workflow wrappers ---" + +# Extract the `olympus_ref:` version (e.g. v0.4.0) from a wrapper, or "" if none. +ref_version() { + grep -oE 'olympus_ref:[[:space:]]*v[0-9]+\.[0-9]+\.[0-9]+' "$1" \ + | head -1 | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' +} + +EXPECTED="$(ref_version "${WRAPPERS[0]}")" +if [ -n "$EXPECTED" ]; then + pass_one "expected olympus version derived from $(basename "${WRAPPERS[0]}"): $EXPECTED" +else + fail_one "could not derive olympus_ref version from $(basename "${WRAPPERS[0]}")" +fi + +for wf in "${WRAPPERS[@]}"; do + base="$(basename "$wf")" + if ! grep -q 'agent_ops_ref' "$wf"; then + pass_one "$base: no agent_ops_ref" + else + fail_one "$base: still uses agent_ops_ref" + fi + + wf_ref="$(ref_version "$wf")" + if [ -n "$wf_ref" ] && [ "$wf_ref" = "$EXPECTED" ]; then + pass_one "$base: olympus_ref $wf_ref (agrees)" + else + fail_one "$base: olympus_ref '${wf_ref:-}' != expected '$EXPECTED'" + fi + + # The `uses:` pin must match this wrapper's own olympus_ref version. + if [ -n "$wf_ref" ] && grep -E 'uses:.*Netis/olympus' "$wf" | grep -qF "@$wf_ref"; then + pass_one "$base: uses-pin matches @$wf_ref" + else + fail_one "$base: uses-pin does not match olympus_ref '${wf_ref:-}'" + fi +done + +echo "" +echo "========================================" +echo "Checks failed: $fail" +echo "========================================" + +if [ "$fail" -gt 0 ]; then + exit 1 +fi +echo "Olympus ${EXPECTED} migration validated."