Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 63 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,39 @@ jobs:
- name: Verify the public distribution boundary
run: python scripts/check_source_boundary.py --require-dist

- name: Refuse conflicting immutable PyPI files
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
version="${RELEASE_TAG#v}"
test "$RELEASE_TAG" = "v${version}"
python scripts/verify_pypi_release.py \
--directory dist \
--version "$version" \
--allow-matching-subset \
--wait-seconds 300 \
--poll-seconds 10

- name: Publish to PyPI with OIDC
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
print-hash: true
skip-existing: true

- name: Verify immutable PyPI publication bytes
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
version="${RELEASE_TAG#v}"
test "$RELEASE_TAG" = "v${version}"
python scripts/verify_pypi_release.py \
--directory dist \
--version "$version" \
--wait-seconds 300 \
--poll-seconds 10

publish-github-release:
needs:
- authorize-release-tag
Expand All @@ -277,29 +304,50 @@ jobs:
runs-on: ubuntu-latest
environment: pypi
permissions:
contents: write
contents: read
steps:
- name: Checkout the exact release tag
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- name: Create the release App token
id: release-app
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ vars.OPENADAPT_RELEASE_APP_ID }}
private-key: ${{ secrets.OPENADAPT_RELEASE_APP_PRIVATE_KEY }}
owner: OpenAdaptAI
repositories: openadapt-evals
permission-contents: write

- name: Verify the release App identity
env:
APP_SLUG: ${{ steps.release-app.outputs.app-slug }}
APP_TOKEN: ${{ steps.release-app.outputs.token }}
EXPECTED_APP_ID: ${{ vars.OPENADAPT_RELEASE_APP_ID }}
run: |
set -euo pipefail
test "$APP_SLUG" = 'openadapt-release'
test -n "$APP_TOKEN"
case "$EXPECTED_APP_ID" in
''|*[!0-9]*)
echo '::error::OPENADAPT_RELEASE_APP_ID must be a positive integer.'
exit 1
;;
esac
test "$EXPECTED_APP_ID" -gt 0

- name: Publish the exact GitHub release
env:
GH_TOKEN: ${{ github.token }}
GH_TOKEN: ${{ steps.release-app.outputs.token }}
RELEASE_TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
test "$(git cat-file -t "$GITHUB_REF")" = 'tag'
test "$(git rev-parse "${GITHUB_REF}^{commit}")" = "$GITHUB_SHA"
if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
state=$(gh release view "$RELEASE_TAG" \
--repo "$GITHUB_REPOSITORY" \
--json isDraft,isPrerelease,tagName)
test "$(jq -r '.tagName' <<<"$state")" = "$RELEASE_TAG"
test "$(jq -r '.isDraft' <<<"$state")" = 'false'
test "$(jq -r '.isPrerelease' <<<"$state")" = 'false'
echo 'The exact GitHub release already exists.'
else
gh release create "$RELEASE_TAG" \
Expand All @@ -308,3 +356,10 @@ jobs:
--generate-notes \
--title "$RELEASE_TAG"
fi
state=$(gh release view "$RELEASE_TAG" \
--repo "$GITHUB_REPOSITORY" \
--json author,isDraft,isPrerelease,tagName)
test "$(jq -r '.tagName' <<<"$state")" = "$RELEASE_TAG"
test "$(jq -r '.isDraft' <<<"$state")" = 'false'
test "$(jq -r '.isPrerelease' <<<"$state")" = 'false'
test "$(jq -r '.author.login' <<<"$state")" = 'openadapt-release[bot]'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@

## v0.94.1 (2026-08-26)

### Features

- **evidence**: Build signed six-class campaigns and content-addressed public lifecycle summaries.

### Bug Fixes

- **evidence**: Match the retention digests the Cloud writer emits (#311) ([`df12b3c`](https://github.com/OpenAdaptAI/openadapt-evals/commit/df12b3ce72ad02992a7c7e389d8ccf2cfd01774c))

### Continuous Integration

- **release**: Keep a durable App-authored draft and verify its exact bytes before publication.


## v0.94.0 (2026-08-26)

Expand Down
57 changes: 46 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# OpenAdapt Evals

> [!IMPORTANT]
> **Status: Research infrastructure, not a required part of the product.** This
> package is evaluation and benchmarking tooling for GUI agents and for the
> OpenAdapt demonstration compiler. It is evidence-generating research work. It
> is not required to record, compile, or replay a workflow, and no end user
> needs it installed.
> **Lifecycle: Support.** This maintained public repository produces
> qualification and release evidence for OpenAdapt. The seven product targets
> use signed admissions to determine their Production state. Evals supplies
> evidence for those decisions and remains a separate operational tool.
>
> The OpenAdapt product is the governed demonstration compiler,
> End users don't install Evals to run a workflow. The OpenAdapt product is the
> governed demonstration compiler,
> [`openadapt-flow`](https://github.com/OpenAdaptAI/openadapt-flow), installed
> via the [`OpenAdapt`](https://github.com/OpenAdaptAI/openadapt) launcher
> (`pip install openadapt`). It compiles a demonstrated GUI workflow into a
Expand Down Expand Up @@ -43,10 +43,45 @@ dimensions that matter to a governed compiler:
- **Cost and model-call accounting**: model calls, latency, and dollar cost per
successful task, including the ~0-model-call healthy replay path.

This is internal research tooling. It is not a packaged end-user product and it
is not needed to use OpenAdapt. If you want to record, compile, and replay a
workflow, use the [`OpenAdapt`](https://github.com/OpenAdaptAI/openadapt)
launcher, not this repository.
Operators use this package to run qualification and publication gates. If you
want to record, compile, and replay a workflow, use the
[`OpenAdapt`](https://github.com/OpenAdaptAI/openadapt) launcher.

### Qualification and release evidence

The v3 campaign producer records six required classes for each task: healthy,
safe halt, idempotency replay, uncertain delivery, declared attended, and
governed repair. Each task and condition needs at least three signed trials.
Evals derives silent incorrect success and over-halt from the signed runner,
observer, and delivery facts. It doesn't trust author-supplied failure counts.

Campaign payloads and trial receipts stay inside the approved private evidence
boundary. A public lifecycle summary uses the remote-safe decision receipt,
the public qualification admission, and the production acceptance manifest. It
contains aggregate class counts and commitments, without task names,
application or environment values, or live identities.

`scripts/build_production_evidence.py` builds that summary and the paired
content-addressed v2 references. The pair command preserves the raw Sigstore
bundle bytes. Run it only after the referenced objects exist in an exact merged
registry commit. The summary uses a later registry append, which avoids a
commit-hash cycle.

```bash
python scripts/build_production_evidence.py summary \
--input public-summary-input.json \
--output production-acceptance-summary.json

python scripts/build_production_evidence.py pair \
--kind production-acceptance-summary \
--object production-acceptance-summary.json \
--sigstore-bundle production-acceptance-summary.sigstore.json \
--registry-source-commit "$MERGED_REGISTRY_COMMIT" \
--registry-revision "$REGISTRY_REVISION" \
--registry-head-sha256 "$REGISTRY_HEAD_SHA256" \
--output-root public-registry-candidate \
--references-output production-acceptance-summary.references.json
```

### Relationship to the rest of OpenAdapt

Expand Down Expand Up @@ -79,7 +114,7 @@ does not claim maturity it has not measured.

## What is inside

- **openadapt-flow evaluation** (`openadapt_evals/flow/`): the paradigm-correct
- **openadapt-flow evaluation** (`openadapt_evals/flow/`): the release-path
eval for a demonstration compiler. A `replay` runner compiles one demonstration
into an openadapt-flow bundle and replays it against the WAA in-guest server
with roughly zero model calls, and a `hybrid` agent runs compiled replay first
Expand Down
Loading