Skip to content

ARES wire-up — turn a consumer repo's CI into ARES dashboard rows

What this is. A single prompt that walks Claude Code through wiring one repo’s CI/CD observability signal to ARES (cicd.devarno.cloud). Paste verbatim into a fresh Claude Code session opened at the consumer repo’s root (not petrova-codes).

The mission is gated: the agent halts at every <gate/> for explicit operator authorisation. Do not skip gates. Do not echo secrets.

Verb form: petrova act ares-wire (a thin wrapper that opens an editor pre-loaded with this prompt — wrapper not yet built; for now, paste).


You are a single-repo ARES-wiring agent, executing this brief against the codebase your working directory is rooted in. Your work is scoped to ONE repository — do NOT reach across repos unless this brief explicitly directs you to.

After your work lands, the host repo’s CI workflow completions appear on ARES History, Recent Executions, DORA metrics, Allure Reports (if test-producing), Ecosystem grid, and — if airlock-handoff-gated — the Auth E2E Verification matrix. Production-grade. Reversible in one click. No credential ever reaches your transcript.

  • Do NOT modify ARES internals. You consume the ARES ingest contract; you do not extend it.
  • Do NOT invent new ingest shapes. ARES accepts workflow_run.completed via HMAC-signed org webhook + a bearer-authed /api/v1/ingest/auth-e2e endpoint. Use these.
  • Do NOT push to main without explicit per-step operator authorization. All code lands via PR.
  • Never echo or print a secret value. Pipe secrets from source to sink in a single shell expression. With gh api, use -f config[secret]="$VAR" so the value is masked in argv.
  • Never commit a secret. CI secrets go to GitHub Actions secrets or <<ARES_RAILWAY_SERVICE>> env vars via the respective CLI.
  • If the sandbox denies a read or write, stop and ask the operator. Do not work around with creative re-routing.
  • Every action that mutates shared production state (org webhooks, Railway env vars, DB rows in shared Postgres) pauses for explicit operator confirmation, even in auto-mode.
  • Service-account keys you mint are the repo’s ONLY credential to external services. Rotate at ≤90 days via --rotate + --revoke-others. Document the rotation procedure inline.

Phase 0 — Petrova-aware preflight (NEW vs original brief)

Section titled “Phase 0 — Petrova-aware preflight (NEW vs original brief)”

Before anything else, run:

Terminal window
SLUG="$(yq '.slug' .petrova/contract.yaml)"
petrova doctor --slug="$SLUG"

If ares.current_status == "ok" AND the contract block reads status: wired, the mission is a no-op. Surface this to the operator and exit.

If the slug is not in petrova-codes’s registry.yaml, halt and ask the operator whether to onboard the repo first (via core/prompts/05-petrova-onboard.md).

If integrations_applicability.ares for this repo (in petrova-codes:registry.yaml) is not required, halt and ask the operator whether the registry should be updated first.


  • Endpoint: POST https://cicd.devarno.cloud/api/v1/ingest/github-workflow
  • Auth: HMAC-SHA256 in X-Hub-Signature-256, verified against GITHUB_WEBHOOK_SECRET on <<ARES_RAILWAY_SERVICE>> (Railway <<ARES_RAILWAY_PROJECT>>).
  • Body shape: standard GitHub workflow_run event payload. Only action == "completed" is processed. Only runs on branches {main, master, production} enter DORA aggregates; others are stored but excluded from metrics. Dedup key: gh-run-{workflow_run.id}.
  • Storage: table test_executions; key fields: id, test_suite, service_name, status, started_at, completed_at, duration_seconds, branch, commit_sha.

Auth-E2E ingest (optional, taskset 6 only)

Section titled “Auth-E2E ingest (optional, taskset 6 only)”
  • Endpoint: POST https://cicd.devarno.cloud/api/v1/ingest/auth-e2e
  • Auth: X-API-Key: $STATIC_API_KEY (shared secret; request from operator).
  • Body shape: { runId, commit, timestamp, environment, results:[{ archetype, status, durationMs, failureReason, testName, traceUrl? }] }. Matrix app-column matched by case-insensitive substring on testName.
  • File: <<ARES_REPO_PATH>>/atlas/ecosystem/repo-domains.yaml.
  • Add: repos[your-org][your-repo]: { domain: <one of 15>, is_major: true|false, description: "..." }.
  • Registry: <<ARES_REPO_PATH>>/dashboard/src/lib/api/allure.ts.
  • Entry: { id: "<slug>-cross-repo", name: "<Name> Cross-Repo", path: "/ares/cross-repo/<org>-<repo>", repository: "<org>/<repo>", type: "cross-repo" }. Populated automatically by the nightly cross-repo workflow; no generation work on your side.

Run, emit results in a compact table:

Terminal window
gh --version && railway --version && jq --version
gh auth status 2>&1 | grep -i scope # need: admin:org_hook, repo, workflow
railway status # need: linked Project + Environment + service
ls .github/workflows/ | head # need: ≥1 workflow on push/main
gh api repos/$OWNER/$REPO/actions/secrets --jq '.secrets[].name' # do not leak values
gh api orgs/$ORG 2>/dev/null | jq -r .type || gh api users/$ORG | jq -r .type

If gh auth status is missing admin:org_hook, the fix is operator-side: gh auth refresh -s admin:org_hook (interactive device flow).


Each taskset halts on explicit GO TASKSET N. Work only the gated taskset. Do NOT speculatively stage the next.

Deliverable: docs/findings/<YYYYMMDD-HHMM>-ares-wire-audit.md summarising the host repo’s CI surface (workflows + triggers), secrets catalog, any existing Hubble or ARES wiring, branch protection, whether the repo is airlock-handoff-gated, whether it emits KAHN-style orchestrator events.

Resolve:

  • Is the host repo’s owner an Organization or a User? (Determines webhook scope option.)
  • Is the host repo’s default branch one of {main, master, production}? (If not, DORA aggregation won’t pick up completions — flag it.)
  • Does the repo already have a notify-hubble job in CI that refers to a cross-org reusable workflow? (If yes, inline the logic — see precedent.)
  • Does the repo ship Allure results in any workflow? (Determines whether the Reports-page tile is worth adding.)
  • Is the repo a handoff consumer on airlock? (Determines whether the Verification-matrix column is worth adding.)

Exit: audit file committed on its own branch; PR opened labelled docs. Do not block on its merge to proceed.

Scope: one PR against <<ARES_REPO_OWNER>>/ares. No host-repo changes.

Steps:

  1. Clone or pull <<ARES_REPO_OWNER>>/ares locally if not already present.
  2. Edit atlas/ecosystem/repo-domains.yaml — add $ORG: $REPO: { domain: <one-of-15>, is_major: true|false, description: "..." }.
  3. Edit dashboard/src/lib/api/allure.ts — add an ALLURE_REPORTS entry with id: "$REPO-cross-repo", path: "/ares/cross-repo/$ORG-$REPO", repository: "$ORG/$REPO", type: "cross-repo". Skip if the host repo emits no Allure artifacts.
  4. Branch feat/ares-$REPO-visibility → commit → PR. Body cites this prompt + the precedent.

Exit: Operator confirms PR landed on ares:main. Vercel dashboard rebuild picks up the changes.

Taskset 3 — Host CI hubble-notify, self-contained

Section titled “Taskset 3 — Host CI hubble-notify, self-contained”

Scope: host repo. One PR that makes CI self-sufficient — no cross-org uses: reference to <<INFRA_CI_REPO>> (private + org-scoped; cross-org reuse is blocked by GitHub policy).

Steps:

  1. Find existing notify-hubble job (if any). If the job references <<INFRA_CI_REPO>>/.github/workflows/publish-hubble-activity.yml@main, inline the curl-to-hubble logic. Source shape: POST https://hubble.devarno.cloud/api/events/ingest with bearer from $HUBBLE_EVENTS_INGEST_TOKEN.
  2. If no notify-hubble job exists, add one as a sibling to existing test jobs. needs: all test jobs, if: always(), compute conclusion from the needs.
  3. Verify HUBBLE_EVENTS_INGEST_TOKEN is in the repo’s Actions secrets. If missing, ask operator to mirror from hubble’s EVENTS_INGEST_TOKEN (single write via gh secret set).

Exit: Operator approves the PR. Merge triggers a main-branch CI run.

Taskset 4 — Org-webhook for ARES ingest (HIGH RISK)

Section titled “Taskset 4 — Org-webhook for ARES ingest (HIGH RISK)”

Scope: GitHub webhook registration. No code changes. HIGH RISK — registers a prod-touching webhook.

Decision points:

  • Scope: Org-level webhook (covers all repos in the org; recommended if $ORG is dedicated to your product family) vs repo-level (tightest blast radius; must re-run per repo).
  • Events: Webhook must subscribe to workflow_run only. Do NOT subscribe to all events — ARES ingest only parses workflow_run; others waste bandwidth.

Compose + execute the registration. The secret must be piped from Railway to gh api in a SINGLE shell expression. Never echo to stdout:

Terminal window
SECRET=$(railway variables --service <<ARES_RAILWAY_SERVICE>> --kv 2>/dev/null \
| awk -F= '/^GITHUB_WEBHOOK_SECRET=/{print substr($0, index($0,"=")+1); exit}')
[ -z "$SECRET" ] && { echo "secret unreadable"; exit 1; }
gh api -X POST orgs/$ORG/hooks \
-f 'name=web' -F 'active=true' -f 'events[]=workflow_run' \
-f 'config[url]=https://cicd.devarno.cloud/api/v1/ingest/github-workflow' \
-f 'config[content_type]=json' \
-f "config[secret]=$SECRET" \
-f 'config[insecure_ssl]=0' \
| jq '{id, active, events, url: .config.url, created_at}'
unset SECRET

ZSH gotcha: [url] globs. Always single-quote 'config[url]=...' when in zsh.

Repo-level fallback: same body against POST repos/$ORG/$REPO/hooks.

Verify:

Terminal window
gh api orgs/$ORG/hooks/<id>/deliveries --jq '.[0] | {status_code, event, action, delivered_at}'

Expect: most recent delivery is a ping with status_code: 200 (ARES accepted the HMAC).

Exit: Operator explicitly authorises the POST before execution. Show them the exact final command with the $SECRET placeholder unresolved. Confirm one-line rollback: gh api -X DELETE orgs/$ORG/hooks/<id>.

Scope: trigger one real workflow run, confirm ingest, confirm dashboard populates.

Steps:

  1. Pick a trivial no-op change or use workflow_dispatch if the repo’s CI declares it.

  2. Trigger: gh workflow run <ci-file> -R $ORG/$REPO --ref <default-branch>.

  3. Poll for completion:

    Terminal window
    until [ "$(gh api repos/$ORG/$REPO/actions/runs/<id> --jq '.status')" = completed ]; do sleep 15; done
  4. Fetch webhook delivery body:

    Terminal window
    gh api orgs/$ORG/hooks/<id>/deliveries --jq '.[] | select(.action=="completed") | .id'
    gh api orgs/$ORG/hooks/<id>/deliveries/<delivery_id> --jq '{status_code, response: .response.payload}'

    Expect: 200 + body {"received": true, "execution_id": "gh-run-..."}.

  5. Browser smoke (operator): cicd.devarno.cloud/history/ shows the row; cicd.devarno.cloud/ecosystem/ shows the org card.

Exit: three cells green: CI completes, webhook delivery 200, test_executions row visible.

Pre-req: the host repo is an airlock handoff consumer AND is on the operator’s Verification matrix. Skip otherwise.

Scope: two PRs. One to <<ARES_REPO_OWNER>>/ares (matrix column slug). One to <<ARES_REPO_OWNER>>/<<DEVARNO_CLOUD_REPO>> (tests/auth-e2e/specs/).

Steps:

  1. ARES PR: add "$REPO" slug to APPS in three files: dashboard/src/app/verification/page.tsx, api/routes/auth_verification.py, api/services/auth_e2e_service.py.
  2. Root PR: new spec tests/auth-e2e/specs/$REPO-handoff.spec.ts modelled on the existing handoff pattern. testName substring is what populates the column. Add "$REPO" to ARCHETYPE_GRANTS[...] and to APP_URLS in tests/auth-e2e/fixtures/index.ts.

Exit: next orchestrate-auth-e2e.yml run populates the column.

Taskset 7 — Optional KAHN-style orchestrator diagnostics

Section titled “Taskset 7 — Optional KAHN-style orchestrator diagnostics”

Pre-req: host repo emits KAHN-grammar transitions. If unsure, skip. (Most repos won’t.)

Scope: mirrors the precedent’s Stream B. Out of scope for generic ARES-wiring — refer to that session’s Stream B notes.

Scope: host repo. One PR.

Steps:

  1. Create docs/deployment/ares-integration.md covering:
    • (a) which workflows are observed
    • (b) which secrets live where
    • (c) how to rotate HUBBLE_EVENTS_INGEST_TOKEN and the webhook secret
    • (d) rollback procedure
    • (e) link to the ARES PR + this session’s audit file
  2. Create docs/decisions/<YYYY-MM-DD>-wire-ares-<slug>.md per the template in petrova-codes:docs/runbooks/ares-wire-rollout.md.
  3. If broader ecosystem doctrine is absent, also emit <<ARES_REPO_PATH>>/atlas/doctrines/ares-wiring-cross-org.doctrine.md distilling the learnings. Skip if atlas already contains it (check first).

Taskset 9 — Contract flip (NEW vs original brief)

Section titled “Taskset 9 — Contract flip (NEW vs original brief)”

Scope: consumer repo. One commit on the same branch as taskset 8.

Update .petrova/contract.yaml.integrations.ares:

ares:
status: wired
declared_at: <YYYY-MM-DD>
evidence:
org_webhook_id: "<id captured at taskset 4>"
ingest_endpoint: https://cicd.devarno.cloud/api/v1/ingest/github-workflow
org_or_repo_scope: <org|repo>
branches_aggregated: [main] # or [main, master], etc.

Commit on the same branch as taskset 8. PR body cites the wave-N decision doc.

Exit: PR merged. petrova-codes’s next petrova doctor sweep observes the wiring.


  • plan-announce: First turn of a new taskset → emit a numbered plan block for that taskset only. Do not execute.
  • await-gate: End the turn with Awaiting GO TASKSET <N> to proceed. and nothing more.
  • execute: On GO TASKSET <N>, execute steps in order. One tool call per atomic action. Narrate each in one short sentence before calling.
  • verify: Run the taskset’s verify block. Do NOT proceed.
  • summarise: Two-line status: what changed, what the operator should see/do next.
  • Read denied → stop, surface command + reason verbatim, ask operator to either authorise once or run the command themselves and paste result.
  • Write denied → never retry with a “cleverer” shape. Stop, surface, ask.
  • Never echo/cat/grep/head/od a file or var that may contain a secret. Pipe; do not print.
  • If extraction is genuinely required and the sandbox blocks, hand the command to the operator. They paste back only the non-secret output you need (e.g. the webhook id, not the secret).

  • All taskset numbers are global. Prefix PR titles feat(ares): [ARES-WIRE/<n>] <summary>.
  • Resources you create in shared infra carry discoverable tags:
    • Railway env vars prefixed ARES_ if ARES-scoped.
    • GitHub webhooks: description ends (managed-by: ARES-WIRE v2.0-petrova).
    • DB rows in shared tables: airlock_org_id = "org:service-<repo>". These tags are the rollback handle.
  • Never assume a repo’s language, framework, or layout. Probe first (package.json, pyproject.toml, go.mod, Cargo.toml), then decide the notify-hubble wiring shape.
  • If a repo is ALREADY partially wired (webhook exists but not registered in repo-domains.yaml), reconcile rather than re-register. List webhooks with gh api orgs/$ORG/hooks before Taskset 4 and treat any existing cicd.devarno.cloud entry as idempotent.
  • Do not commit audit or doctrine files that simply restate this prompt. Write findings only when SPECIFIC to the host repo (existing wiring, non-default branch, unusual CI topology).

IDVerifiable claim
sc-1Webhook id=<captured> exists, active, subscribed to workflow_run only, points at cicd.devarno.cloud/api/v1/ingest/github-workflow
sc-2Most recent webhook delivery for a real completed workflow returned HTTP 200 with body {"received": true, "execution_id": "gh-run-..."}
sc-3cicd.devarno.cloud lists a row whose service_name == $REPO
sc-4<<ARES_REPO_OWNER>>/ares:main atlas/ecosystem/repo-domains.yaml contains $ORG.$REPO with a domain + description
sc-5If repo emits Allure: Reports page lists a tile linking to /ares/cross-repo/$ORG-$REPO. 404 until first nightly cross-repo run is expected and NOT a blocker
sc-6docs/deployment/ares-integration.md documents rollback; rollback procedure tested once (disable webhook, confirm no deliveries, re-enable)
sc-7No secret appears in any commit, log line, PR body, or session transcript
sc-8.petrova/contract.yaml.integrations.ares.status == "wired" and petrova doctor --slug=$REPO reports ares: ok

  1. Acknowledge this mission in one short paragraph. Name the host repo (inferred from pwd or git remote) and the single target: ARES integration per this prompt.
  2. Run Phase 0 (petrova doctor --slug=<self>). If already-wired no-op detected, exit.
  3. Run the preflight probes. Emit results in a compact table.
  4. Present the taskset ladder as a numbered plan tailored to the host repo (note skips for non-Allure-emitting, non-airlock-gated, non-KAHN-grammar cases).
  5. End with Awaiting GO TASKSET 1 to begin the audit. Do nothing else.