prodex 0.57.0

OpenAI profile pooling and safe auto-rotate for Codex CLI and Claude Code
Documentation
name: upstream compatibility watchdog

on:
  schedule:
    - cron: "17 6 * * *"
  workflow_dispatch:
    inputs:
      baseline_path:
        description: Baseline path for the watchdog report
        required: false
        default: scripts/compat/upstream-baseline.json
        type: string
      fail_on_drift:
        description: Fail the workflow when upstream drift is detected
        required: false
        default: true
        type: boolean

permissions:
  contents: read

concurrency:
  group: upstream-compat-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  watch:
    runs-on: ubuntu-latest
    timeout-minutes: 20

    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Install Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 22
          package-manager-cache: false

      - name: Run upstream compatibility watchdog
        shell: bash
        run: |
          set -euo pipefail
          artifact_dir="${RUNNER_TEMP}/upstream-compat"
          report="${artifact_dir}/report.json"
          text_report="${artifact_dir}/watchdog.txt"
          guard_report="${artifact_dir}/baseline-guard.json"
          guard_text="${artifact_dir}/baseline-guard.txt"
          summary="${artifact_dir}/summary.md"
          metadata="${artifact_dir}/metadata.json"
          mkdir -p "${artifact_dir}"

          baseline_path="scripts/compat/upstream-baseline.json"
          fail_on_drift="true"
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            if [ -n "${{ inputs.baseline_path }}" ]; then
              baseline_path="${{ inputs.baseline_path }}"
            fi
            if [ "${{ inputs.fail_on_drift }}" = "false" ]; then
              fail_on_drift="false"
            fi
          fi

          node -e "const fs = require('node:fs'); fs.writeFileSync(process.argv[1], JSON.stringify({ event_name: process.env.GITHUB_EVENT_NAME, ref: process.env.GITHUB_REF, sha: process.env.GITHUB_SHA, run_id: process.env.GITHUB_RUN_ID, run_attempt: process.env.GITHUB_RUN_ATTEMPT, baseline_path: process.argv[2] }, null, 2) + '\n');" "${metadata}" "${baseline_path}"

          set +e
          node scripts/compat/check-upstream-baseline.mjs --baseline "${baseline_path}" --report "${guard_report}" > "${guard_text}" 2>&1
          guard_status=$?
          set -e

          if [ "${guard_status}" -ne 0 ]; then
            {
              echo "## Upstream compatibility"
              echo
              echo "- Baseline: \`${baseline_path}\`"
              echo "- Offline guard: \`failed\`"
              echo
              echo "### Guard output"
              echo '```'
              sed -n '1,120p' "${guard_text}"
              echo '```'
            } > "${summary}"
            cat "${summary}" >> "${GITHUB_STEP_SUMMARY}"
            exit "${guard_status}"
          fi

          set +e
          node scripts/compat/watch-upstream.mjs --baseline "${baseline_path}" --report "${report}" > "${text_report}" 2>&1
          status=$?
          set -e

          node - "${report}" "${summary}" "${status}" "${baseline_path}" "${fail_on_drift}" <<'EOF'
          const fs = require("node:fs");

          const [, , reportPath, summaryPath, statusCodeRaw, baselinePath, failOnDrift] = process.argv;
          const statusCode = Number.parseInt(statusCodeRaw, 10) || 0;
          const lines = ["## Upstream compatibility", ""];
          lines.push(`- Event: \`${process.env.GITHUB_EVENT_NAME}\``);
          lines.push(`- Ref: \`${process.env.GITHUB_REF}\``);
          lines.push(`- Baseline: \`${baselinePath}\``);
          lines.push("- Offline guard: `passed`");
          lines.push(`- Fail on drift: \`${failOnDrift}\``);

          if (fs.existsSync(reportPath)) {
            const report = JSON.parse(fs.readFileSync(reportPath, "utf8"));
            const codex = report.current?.codex?.latestRelease ?? {};
            const claude = report.current?.claude?.latestRelease ?? {};
            const diffs = Array.isArray(report.diffs) ? report.diffs : [];

            lines.push(`- Codex latest release: [${codex.tag_name || "unknown"}](${codex.html_url || "https://github.com/openai/codex/releases/latest"})`);
            lines.push(`- Claude latest release: [${claude.tag_name || "unknown"}](${claude.html_url || "https://github.com/anthropics/claude-code/releases/latest"})`);
            lines.push(`- Report generated: \`${report.generated_at || "unknown"}\``);
            lines.push("");

            if (diffs.length === 0) {
              lines.push("Status: in sync");
            } else {
              lines.push(`Status: drift detected (${diffs.length} change${diffs.length === 1 ? "" : "s"})`);
              lines.push("");
              lines.push("### Drift paths");
              for (const diff of diffs.slice(0, 20)) {
                lines.push(`- \`${diff.path}\``);
              }
              if (diffs.length > 20) {
                lines.push(`- ... and ${diffs.length - 20} more`);
              }
            }
          } else {
            lines.push("");
            lines.push(`Status: watchdog failed before report generation (exit ${statusCode})`);
          }

          if (statusCode !== 0 && failOnDrift === "false") {
            lines.push("");
            lines.push("Manual override: drift does not fail this run. Inspect the uploaded artifact for details.");
          }

          fs.writeFileSync(summaryPath, `${lines.join("\n")}\n`);
          EOF

          cat "${summary}" >> "${GITHUB_STEP_SUMMARY}"

          if [ "${status}" -ne 0 ] && [ "${fail_on_drift}" = "true" ]; then
            exit "${status}"
          fi

      - name: Upload compatibility report
        if: always()
        uses: actions/upload-artifact@v7
        with:
          name: upstream-compat-${{ github.run_id }}-${{ github.run_attempt }}
          path: ${{ runner.temp }}/upstream-compat
          if-no-files-found: error
          retention-days: 14