diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index ce844d8..9be6d0a 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -30,8 +30,86 @@ jobs: - run: go test ./... - run: go build ./... - validate: - name: Release authority and full validation + release: + name: Release and package controls + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: "24" + cache: npm + - run: npm ci --ignore-scripts + - run: npm run test:release + - run: node scripts/check-release-control.mjs + + typescript: + name: TypeScript SDK and npm package + runs-on: ubuntu-latest + defaults: + run: + working-directory: sdk/typescript + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: "24" + - run: npm test + - run: npm run build + - name: Pack, install, and import the SDK + run: | + tarball="$RUNNER_TEMP/$(npm pack --silent --pack-destination "$RUNNER_TEMP")" + smoke_dir="$(mktemp -d)" + cd "$smoke_dir" + npm init -y >/dev/null + npm install "$tarball" >/dev/null + node --input-type=module -e 'import { defineSkill } from "@operatorstack/yield"; if (typeof defineSkill !== "function") process.exit(1)' + + python: + name: Python SDK + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 + with: + python-version: "3.12" + - run: python -m unittest discover -s sdk/python -p 'test_*.py' + + rust: + name: Rust SDK + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2 + with: + workspaces: sdk/rust + - run: cargo test --manifest-path sdk/rust/Cargo.toml + + conformance: + name: Four-language conformance + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + with: + go-version-file: go.mod + cache: true + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: "24" + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 + with: + python-version: "3.12" + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2 + with: + workspaces: | + sdk/rust + internal/conformance/testdata/skill-rs + - run: go vet ./... + - run: go test ./... + + examples: + name: Example workflows and evaluations runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 @@ -42,7 +120,6 @@ jobs: - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 with: node-version: "24" - cache: npm - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 with: python-version: "3.12" @@ -52,34 +129,12 @@ jobs: sdk/rust examples/data-migration examples/library/rust - internal/conformance/testdata/skill-rs - - run: npm ci --ignore-scripts - - name: Verify release authority and package assembly - run: | - npm run test:release - node scripts/check-release-control.mjs - python -m unittest discover -s sdk/python -p 'test_*.py' - name: Rerun first-party evaluations working-directory: evals run: | npm ci npm test - - name: Build and smoke-test the packed TypeScript SDK - working-directory: sdk/typescript - run: | - npm test - npm run build - tarball="$RUNNER_TEMP/$(npm pack --silent --pack-destination "$RUNNER_TEMP")" - smoke_dir="$(mktemp -d)" - cd "$smoke_dir" - npm init -y >/dev/null - npm install "$tarball" >/dev/null - node --input-type=module -e 'import { defineSkill } from "@operatorstack/yield"; if (typeof defineSkill !== "function") process.exit(1)' - - name: Vet and test four-language conformance - run: | - go vet ./... - go test ./... - - name: Run example workflow fixtures + - name: Run every example fixture run: | go build -o "$RUNNER_TEMP/yskill" ./cmd/yskill "$RUNNER_TEMP/yskill" test examples/investigate @@ -88,3 +143,22 @@ jobs: "$RUNNER_TEMP/yskill" test examples/data-migration YSKILL="$RUNNER_TEMP/yskill" "$RUNNER_TEMP/yskill" test examples/convert-skill YSKILL="$RUNNER_TEMP/yskill" bash ./examples/library/test-all.sh + + validate: + name: Release authority and full validation + if: ${{ always() }} + needs: [go, release, typescript, python, rust, conformance, examples] + runs-on: ubuntu-latest + steps: + - name: Require every validation job + env: + RESULTS: ${{ toJSON(needs) }} + run: | + node -e ' + const results = JSON.parse(process.env.RESULTS); + const failed = Object.entries(results).filter(([, value]) => value.result !== "success"); + if (failed.length) { + console.error(failed.map(([name, value]) => `${name}: ${value.result}`).join("\n")); + process.exit(1); + } + ' diff --git a/README.md b/README.md index 62dc8c3..c35e5fc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- Yield + Yield

diff --git a/evals/results/latest.json b/evals/results/latest.json index bbeeafa..563da73 100644 --- a/evals/results/latest.json +++ b/evals/results/latest.json @@ -1,7 +1,7 @@ { "schema_version": 2, "methodology_version": "1.1", - "generated_at": "2026-08-07T11:37:55.058Z", + "generated_at": "2026-08-07T11:49:51.097Z", "source_digest": "d75c9a27b4782ff37a16c76b472327ecb6c8ab1b014dcf8e01626870340a82ac", "status": "passed", "workflow_conformance": { diff --git a/scripts/check-release-control.mjs b/scripts/check-release-control.mjs index 3a23b8a..acd3845 100644 --- a/scripts/check-release-control.mjs +++ b/scripts/check-release-control.mjs @@ -43,6 +43,17 @@ export async function checkReleaseControl(root = resolve(import.meta.dirname, ". expect(!(await exists(resolve(root, "UPSTREAM.json"))), "UPSTREAM.json must be removed after graduation"); expect(!names.includes("sync-upstream.yml"), "projection sync workflow must be removed after graduation"); + const verify = workflows["verify.yml"]; + const validationJobs = ["go", "release", "typescript", "python", "rust", "conformance", "examples"]; + expect(verify, "verify.yml is required"); + expect(verify.on?.pull_request !== undefined, "verification must run on every pull request"); + expect(validationJobs.every((name) => verify.jobs?.[name]), "verification must expose every SDK and package boundary"); + expect( + JSON.stringify([...(verify.jobs?.validate?.needs ?? [])].sort()) === JSON.stringify([...validationJobs].sort()), + "the final validation gate must depend on every visible validation job", + ); + expect(verify.jobs?.validate?.name === "Release authority and full validation", "the protected validation context must remain stable"); + const release = workflows["release.yml"]; expect(release, "release.yml is required"); expect(JSON.stringify(Object.keys(release.on ?? {}).sort()) === JSON.stringify(["workflow_dispatch"]), "stable release must be dispatch-only"); diff --git a/scripts/readme.test.mjs b/scripts/readme.test.mjs index cada309..a49dd99 100644 --- a/scripts/readme.test.mjs +++ b/scripts/readme.test.mjs @@ -52,3 +52,9 @@ test("README agent claims match the pinned registry", async () => { ); assert.doesNotMatch(readme, /Agent Plugins and Yield/); }); + +test("README uses the compact Yield mark", async () => { + const readme = await text("README.md"); + assert.match(readme, /https:\/\/yield\.operatorstack\.systems\/favicon\.svg/); + assert.doesNotMatch(readme, /apple-touch-icon\.png/); +});