name: Develop PR # Lightweight gate for pull requests targeting `develop`: lint, typecheck, and # build only. The full test/e2e/scenario/benchmark surface runs post-merge on # push to `develop` (and nightly/on-demand), not on every PR — so PR feedback # stays fast and hosted-runner capacity is spent on the ~200 daily PRs' fast # signal rather than the whole integration matrix. `main` PRs keep the heavy # gates via `ci.yaml`, `test.yml`'s peers, and `quality.yml`. Steps mirror # `ci.yaml` so PR and post-merge lanes stay in agreement. on: pull_request: branches: [develop] types: [opened, synchronize, reopened, ready_for_review] concurrency: group: develop-pr-${{ github.event.pull_request.number }} cancel-in-progress: true # Default to least privilege. Override per-job where needed. permissions: contents: read jobs: lane-coverage: name: Test Integrity (lane coverage) runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: submodules: false # Full history: the error-policy ratchet diffs every touched file # against its content at the merge-base with origin/develop. fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: node-version: "24.15.0" - name: Per-plugin e2e coverage run: node packages/scripts/lint-lane-coverage.mjs # Binding policy audits from CLAUDE.md that previously ran nowhere in # CI. Both are dependency-free node scripts (<5s): the error-policy # ratchet fails only when a file this PR touches ADDS an empty catch or # server-side console.* call; test-integrity statically lints test # sources for larp patterns. - name: Error-policy ratchet (diff-scoped) run: | git fetch --no-tags origin develop:refs/remotes/origin/develop || true node packages/scripts/error-policy-ratchet.mjs - name: Test-integrity audit run: node packages/scripts/lint-test-integrity.mjs - name: Test-integrity audit self-test run: node packages/scripts/lint-test-integrity.self-test.mjs - name: Changed-file coverage classifier self-tests run: | while IFS= read -r self_test; do if [ ! -f "$self_test" ]; then echo "registered coverage self-test is missing: $self_test" exit 1 fi node "$self_test" done < scripts/security/coverage-node-self-tests.txt # View→action ratchet (#14369): every builtin-view on-screen mutation # must map to a registered agent action (chat twin), and the generated # action catalog must reflect the real registered surface. Dependency-free # (node stdlib only) like the other audits in this job. - name: View-action ratchet self-test run: node packages/scripts/view-action-ratchet.mjs --self-test - name: View-action ratchet run: node packages/scripts/view-action-ratchet.mjs lint: runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 - name: Setup Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: node-version: "24.15.0" - name: Setup workspace dependencies uses: ./.github/actions/setup-bun-workspace with: bun-version: "1.3.14" # pinned: floating canary writes lockfileVersion 2 and breaks --frozen-lockfile (#11184/#9454) install-command: bun install install-native-deps: "false" install-protoc: "false" setup-python: "false" skip-avatar-clone: "true" no-vision-deps: "true" - name: Run lint run: bun run lint - name: Check formatting run: bun run format:check typecheck: runs-on: ubuntu-latest # 35 not 20: at --concurrency=4 a near-total affected cone (~250 packages) # needs headroom — the one green full-cone run spent 11 minutes in the # typecheck step alone, on top of checkout/install/build:core (#15140). timeout-minutes: 35 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with: # Full history so `turbo run typecheck --affected` can resolve the PR # merge base (#12341); a shallow clone degrades to typechecking all. fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: node-version: "24.15.0" - name: Setup workspace dependencies uses: ./.github/actions/setup-bun-workspace with: bun-version: "1.3.14" # pinned: floating canary writes lockfileVersion 2 and breaks --frozen-lockfile (#11184/#9454) install-command: bun install install-native-deps: "false" install-protoc: "false" setup-python: "false" skip-avatar-clone: "true" no-vision-deps: "true" # Typecheck resolves `@elizaos/core` types from its built dist, so build # core before running tsc across the affected cone. - name: Build core run: bun run build:core # --concurrency=4 not 8: hosted ubuntu-latest runners have 4 vCPUs and # 16 GB RAM, and when the affected cone goes near-total (a base-branch # commit touching turbo globalDependencies like root package.json / # turbo.json makes every stale-base PR typecheck all ~250 packages) eight # concurrent tsgo processes exhaust the runner — the OS SIGKILLs tasks or # the runner VM itself dies (#15140). NODE_OPTIONS only bounds node-based # tools, not native tsgo, so concurrency is the memory lever here. - name: Run typecheck (affected) run: NODE_OPTIONS='--max-old-space-size=8192' node packages/scripts/run-turbo.mjs run typecheck --concurrency=4 --affected env: TURBO_SCM_BASE: ${{ github.event.pull_request.base.sha }} build: runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 - name: Setup Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: node-version: "24.15.0" - name: Setup workspace dependencies uses: ./.github/actions/setup-bun-workspace with: bun-version: "1.3.14" # pinned: floating canary writes lockfileVersion 2 and breaks --frozen-lockfile (#11184/#9454) install-command: bun install install-native-deps: "false" install-protoc: "false" setup-python: "false" skip-avatar-clone: "true" no-vision-deps: "true" - name: Build packages run: bun run build:core