Skip to content

ci

ci #409

Workflow file for this run

# Agent Guild — production-truth CI matrix.
# A clean checkout must pass every leg: both store backends, migrations +
# concurrency (inside the pytest suite), strict credential-KDF policy,
# offline verifiers, contract conformance (zero surface drift), and
# independent third-party VC verification in Python AND Node.
name: ci
# Trigger model (2026-07-23, machine-loop approval-gate fix):
# push: [main, "ship/**", "codex/**"] + workflow_dispatch — deliberately NO
# `pull_request`.
#
# Why no pull_request: GitHub forces the pull_request-triggered runs of a PR
# that was OPENED or UPDATED with GITHUB_TOKEN into an "approval required"
# state (a maintainer must click "Approve workflows to run"). The machine ship
# loop opens its PR with GITHUB_TOKEN, so every release sat behind that human
# click — and the gated pull_request "Expected — Waiting for status to be
# reported" placeholders block the merge even though the loop's own
# workflow_dispatch ci runs are green (observed live on PR #5). Removing the
# pull_request trigger removes those placeholders entirely.
#
# What replaces it: push checks on ship/** and codex/**. These branches are pushed from an
# authenticated USER session (never GITHUB_TOKEN), so its push-event ci runs
# start automatically with NO approval gate and report the required contexts
# on the exact branch head SHA — which is the PR head — satisfying branch
# protection. The loop's workflow_dispatch path is kept for branches the loop
# itself pushes with GITHUB_TOKEN (the revert-recovery branches), where the
# push-event recursion guard suppresses a push run.
#
# Net effect: required checks still all run, branch protection is unchanged,
# exact-SHA deploy verification and recovery are untouched — only the human
# approval click is gone. A human fork PR still cannot auto-run these checks
# (it can't push to these branches on origin), so protections are TIGHTER, never
# relaxed.
on:
push:
branches: [main, "ship/**", "codex/**"]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
store: [json, sqlite]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install -r live/guild/requirements.txt
- name: pytest (GUILD_STORE=${{ matrix.store }})
working-directory: live/guild
env:
GUILD_STORE: ${{ matrix.store }}
GUILD_ALLOW_WEAK_KDF: "1"
run: python -m pytest tests -q
strict-kdf:
# hashed credentials at full production PBKDF2 cost — no weak-KDF escape hatch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install -r live/guild/requirements.txt
- working-directory: live/guild
run: python -m pytest tests/test_kdf_policy.py tests/test_credential_hardening.py tests/test_credential_lifecycle.py tests/test_credential_concurrency.py -q
contract:
# regenerating the canonical contract + derived artifacts must be a no-op
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install -r live/guild/requirements.txt
- working-directory: live/guild
run: python contract/generate.py
- run: |
git diff --exit-code live/guild/contract/contract.json server.json \
registry/x402-payment-safety/server.json docs/INTERFACE.md \
|| (echo "::error::contract drift — run 'make contract' and commit" && exit 1)
independent-vc-verification:
# third-party verification: Digital Bazaar (Node) + rfc8785/pyca (Python)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- uses: actions/setup-node@v4
with:
node-version: "22"
- run: pip install -r live/guild/requirements.txt rfc8785 base58
- name: generate vector from issuer code
working-directory: live/guild
run: python ../../verifiers/gen_vector.py ../../verifiers/vector.json
- name: independent Python verification (rfc8785 + pyca)
run: python verifiers/verify_python_independent.py verifiers/vector.json
- name: independent Node verification (Digital Bazaar Data Integrity)
working-directory: verifiers
run: |
npm install --no-fund --no-audit
node verify_node_digitalbazaar.mjs vector.json
caller-proof-wallet-verification:
# did:key + one-wallet EVM caller proofs and wallet-binding credential from
# genuinely CLEAN Python and Node environments: the vector is generated
# by the live issuer code, then verified by third-party-primitive-only
# verifiers installed from their own pinned manifests (never the repo's
# runtime environment). The Node deps ship in verifiers/package.json;
# the Python deps in verifiers/requirements.txt.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- uses: actions/setup-node@v4
with:
node-version: "22"
- name: generate vector from the live issuer code (own venv)
run: |
python -m venv .venv-gen
.venv-gen/bin/pip install --upgrade pip
.venv-gen/bin/pip install -r live/guild/requirements.txt
.venv-gen/bin/python verifiers/gen_caller_proof_vector.py verifiers/caller_proof_vector.json
- name: independent Python verification (CLEAN venv, pinned manifest)
run: |
python -m venv .venv-cpverify
.venv-cpverify/bin/pip install --upgrade pip
.venv-cpverify/bin/pip install -r verifiers/requirements.txt
.venv-cpverify/bin/python verifiers/verify_caller_proof_python.py verifiers/caller_proof_vector.json
- name: independent Node verification (CLEAN install from package.json)
working-directory: verifiers
run: |
npm install --no-fund --no-audit
npm run verify-caller-proof
trustplane:
# trust-plane core: verify-before-use client, binding invariants, cache
# pin persistence/rotation, sidecar, outcomes readback + local conformance
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install -r live/guild/requirements.txt -r live/trustplane/requirements/core.txt
- name: trust-plane tests (core)
working-directory: live/trustplane
run: python -m pytest tests -q
- name: AGI-1 conformance (local issuer)
working-directory: live/trustplane
run: python -m pytest conformance/ -q
trustplane-integrations:
# each framework extra resolves in a CLEAN environment (this is the
# install-resolution gate) and its NATIVE adapter tests run there.
# crewai and the mcp proxy pin different mcp versions on purpose — they
# are separate environments; see live/trustplane/requirements/.
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
extra: [crewai, langchain, openai-agents, mcp]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: clean install resolution (${{ matrix.extra }})
run: |
python -m venv .venv-${{ matrix.extra }}
.venv-${{ matrix.extra }}/bin/pip install --upgrade pip
.venv-${{ matrix.extra }}/bin/pip install \
-r live/trustplane/requirements/${{ matrix.extra }}.txt \
-r live/guild/requirements.txt pytest
- name: native adapter tests (${{ matrix.extra }})
working-directory: live/trustplane
run: ../../.venv-${{ matrix.extra }}/bin/python -m pytest tests -q
x402-interop:
# x402 v2 interoperability in a CLEAN environment: the OFFICIAL x402
# client SDK (with a real EVM signer) makes the paid request end-to-end
# over real HTTP against the Guild server + a deterministic local fake
# facilitator that cryptographically verifies the EIP-3009 authorization.
# No mainnet, no funds, no gating on external networks.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: clean install (official x402 client + EVM signer deps)
run: |
python -m venv .venv-x402
.venv-x402/bin/pip install --upgrade pip
.venv-x402/bin/pip install -r live/guild/requirements.txt \
'x402[httpx,evm]==2.15.0' 'eth-account>=0.13' pytest
- name: x402 v2 interop (independent official client)
working-directory: live/guild
env:
GUILD_ALLOW_WEAK_KDF: "1"
run: ../../.venv-x402/bin/python -m pytest tests_x402_interop -q
release-gate:
# THE deployment-aware gate: a release is not green unless production
# serves the exact pushed SHA and that running build passes the live
# contract probe, live AGI-1 conformance, signed-decision verification
# (incl. decision.agent_id == routing.provider_id) and issuer/checkpoint
# continuity. NO continue-on-error: a red gate is a red release.
# Concurrency: newest push wins; an older run can never certify a newer
# deployment (and the SHA equality check makes cross-certification
# structurally impossible in the other direction).
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [test, contract, trustplane]
runs-on: ubuntu-latest
concurrency:
group: release-gate-production
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install -r live/guild/requirements.txt -r live/trustplane/requirements/core.txt
- name: wait for production to serve THIS SHA, then verify the live release
run: |
python live/scripts/release_gate.py \
--sha "${{ github.sha }}" \
--timeout 900 --interval 20 \
--attestation release_attestation.json
- name: upload release attestation (machine-readable)
if: always()
uses: actions/upload-artifact@v4
with:
name: release-attestation-${{ github.sha }}
path: release_attestation.json
if-no-files-found: warn