name: Tests on: pull_request: branches: [master] push: branches: [master] jobs: # Forward-looking Python lint gate (ruff). The Python twin of the ESLint runtime # guard. Runs the curated [tool.ruff] ruleset (E9 + F + B) but only on lines this # PR adds/modifies vs the merge-base — so it keeps NEW code clean without demanding # a reformat of the existing tree's cosmetic backlog (#3273). Fast, fails early. lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: # Need history so the gate can diff against the merge-base with master. fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.12' - name: Install ruff run: pip install ruff - name: Ensure origin/master ref is available for the diff gate run: git fetch --no-tags --depth=1 origin master || true # Whole-tree Python syntax gate. The Python analog of the JS `node --check` # pass. The ruff E9 gate below is diff-scoped (new/changed lines only), so a # SyntaxError/IndentationError whose parser-reported line sits on an UNTOUCHED # line (e.g. a dedented `try:` above an unchanged import) can slip the diff # filter and only surface as a confusing mass-failure of every test shard at # the conftest server-boot fixture. compileall fails in ~2s with a clear # file:line, before the matrix suite runs. Whole-tree + unconditional so it # cannot be bypassed by the diff scope. (#4641) - name: Python syntax gate (whole tree — fails fast on any unparseable .py) run: python3 -m compileall -q api server.py bootstrap.py mcp_server.py tests scripts - name: Ruff forward gate (new/changed lines only) run: python3 scripts/ruff_lint.py --diff origin/master - name: Ruff whole-tree report (informational — never blocks) if: always() run: python3 scripts/ruff_lint.py --all # Static-JS runtime-error guards. These catch brick-class bugs that throw only # when the browser executes the code — node --check, source-presence tests, and # the mocked pytest suite all miss them. Two complementary ESLint passes: # * runtime-guard config: no-const-assign / no-import-assign (#3162 class) # * scope_undef_gate.py: no-undef across the shared classic-