name: Performance contracts on: schedule: - cron: '15 9 * * *' workflow_dispatch: pull_request: types: [opened, synchronize, reopened, ready_for_review, converted_to_draft] paths: - '.github/workflows/performance-contracts.yml' - 'config/vitest.performance.config.ts' - 'config/oxlint-performance-audit.json' - 'config/oxlint-plugins/*performance.mjs' - 'config/oxlint-plugins/quadratic-buffer-concat.mjs' - 'config/scripts/*-plugin.test.mjs' - '!config/scripts/renderer-scrollbar-style-plugin.test.mjs' # Keep in sync with the contract list in config/vitest.performance.config.ts; # without these a rename lands green and only breaks the next nightly. - 'src/main/ipc/pty-spawn-scaling.performance.test.ts' - 'src/main/ipc/pty/runtime/spawn-preflight-saved-resume.test.ts' - 'src/main/native-chat/agent-session-wire/structured-agent-session-terminal-writer-acquire.test.ts' - 'src/main/runtime/hook-status-resume-sleep-ordering.test.ts' - 'src/renderer/src/hooks/ipc-events/agent-status-refused-resume.performance.test.ts' - 'src/renderer/src/components/terminal-pane/pty-connection/saved-resume-cancellation.test.ts' - 'src/main/sqlite/sync-database.test.ts' - 'src/main/runtime/orchestration/db/row-column-lists.test.ts' - 'src/shared/native-chat/tools/native-chat-tool-attribution-allocation.test.ts' - 'src/shared/native-chat/tools/native-chat-tool-pairing.performance.test.ts' - 'src/main/codex-usage/codex-rollout-file-lifetime.test.ts' - 'src/main/codex-usage/scanner-incremental-append.test.ts' - 'src/main/usage/jsonl-file-reader.test.ts' - 'src/main/usage/jsonl-file-snapshot.test.ts' - 'src/renderer/src/components/editor/rich-markdown-list-tokenizers.test.ts' - 'src/renderer/src/components/editor/rich-markdown-lowlight-cache.test.ts' - 'src/renderer/src/components/terminal-pane/agent-completion-coordinator-queued-inspection-disposal.test.ts' - 'src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler-queue-retention.test.ts' - 'src/main/claude-usage/scanner-incremental-append.test.ts' - 'src/main/claude-usage/store-checkpoint-persistence.test.ts' permissions: contents: read concurrency: group: performance-contracts-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: contracts: if: github.event_name != 'pull_request' || github.event.pull_request.draft != true strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] # Operation-count and retention contracts, not wall-clock budgets: use the hosted images the cache warmers seed. runs-on: ${{ fromJSON('{"ubuntu-latest":"ubuntu-24.04","macos-latest":"macos-15","windows-latest":"windows-2022"}')[matrix.os] || matrix.os }} timeout-minutes: 20 steps: - uses: actions/checkout@v6 with: persist-credentials: false - uses: ./.github/actions/install-node-dependencies - name: Run operation-count and retention contracts run: pnpm test:perf:contracts --reporter=default --reporter=json --outputFile=performance-contracts.json # Source-only scan: identical on every OS, so run it once. - name: Audit production performance patterns if: always() && matrix.os == 'ubuntu-latest' shell: bash run: pnpm --silent audit:perf > performance-audit.json - uses: actions/upload-artifact@v7 if: always() with: name: performance-contracts-${{ matrix.os }} path: performance-contracts.json if-no-files-found: error - uses: actions/upload-artifact@v7 if: always() && matrix.os == 'ubuntu-latest' with: name: performance-audit path: performance-audit.json if-no-files-found: error