diff --git a/.github/workflows/harness-coauthor-guard.yml b/.github/workflows/harness-coauthor-guard.yml index 63b347d12d..f47e899332 100644 --- a/.github/workflows/harness-coauthor-guard.yml +++ b/.github/workflows/harness-coauthor-guard.yml @@ -91,17 +91,21 @@ jobs: # Per the c.1331+107-L2 lesson, the script always exits 0 here on a # clean working tree; we capture findings via JSON, not exit code, to # distinguish "0 findings" from "detector crashed". + # NOTE (collision /tmp, 2026-09-28) : chemins en `${{ runner.temp }}` (per-slot) + # au lieu de `/tmp` nu -- `/tmp` est hote-global sur le runner a slots + # partages, et pip/solution-leak-guard y ecrivaient les memes noms au + # format LISTE (cf pip-leak-guard.yml, #18059). - name: HEAD scan id: head_scan run: | - python scripts/notebook_tools/check_harness_coauthor.py --json > /tmp/head.json + python scripts/notebook_tools/check_harness_coauthor.py --json > "${{ runner.temp }}/coauthor-head.json" rc=$? if [ "$rc" -ne 0 ] && [ "$rc" -ne 1 ]; then echo "::error title=Detector crashed::check_harness_coauthor.py exited with non-standard code $rc. The gate cannot be trusted -- investigate before merging." exit 1 fi - HEAD_VERDICT=$(python -c "import json; print(json.load(open('/tmp/head.json'))['verdict'])") - HEAD_TOTAL=$(python -c "import json; print(json.load(open('/tmp/head.json'))['total_findings'])") + HEAD_VERDICT=$(python -c "import json; print(json.load(open('${{ runner.temp }}/coauthor-head.json'))['verdict'])") + HEAD_TOTAL=$(python -c "import json; print(json.load(open('${{ runner.temp }}/coauthor-head.json'))['total_findings'])") echo "head_verdict=$HEAD_VERDICT" >> "$GITHUB_OUTPUT" echo "head_total=$HEAD_TOTAL" >> "$GITHUB_OUTPUT" echo "HEAD verdict: $HEAD_VERDICT ($HEAD_TOTAL findings)" @@ -124,7 +128,7 @@ jobs: - name: BASE scan if: github.event_name == 'pull_request' run: | - python scripts/notebook_tools/check_harness_coauthor.py --json --repo-root _base > /tmp/base.json || true + python scripts/notebook_tools/check_harness_coauthor.py --json --repo-root _base > "${{ runner.temp }}/coauthor-base.json" || true # DELTA check: a NEW finding introduced by the PR fails the gate. # Inherited findings (post-Phase-1 main = 0) are tolerated, mirroring @@ -139,8 +143,8 @@ jobs: import json import sys - base = json.load(open("/tmp/base.json")) - head = json.load(open("/tmp/head.json")) + base = json.load(open("${{ runner.temp }}/coauthor-base.json")) + head = json.load(open("${{ runner.temp }}/coauthor-head.json")) base_keys = {(f["file"], f["line"], f["match"]) for f in base["findings"]} head_keys = {(f["file"], f["line"], f["match"]) for f in head["findings"]} diff --git a/.github/workflows/pip-leak-guard.yml b/.github/workflows/pip-leak-guard.yml index 15abe401ad..ebfbe9fbf9 100644 --- a/.github/workflows/pip-leak-guard.yml +++ b/.github/workflows/pip-leak-guard.yml @@ -50,10 +50,19 @@ jobs: with: python-version: '3.11' + # NOTE (collision /tmp, 2026-09-28) : les chemins de travail passent par + # `${{ runner.temp }}` (per-slot/per-job), jamais `/tmp` nu. `/tmp` est + # hote-global sur le runner a slots partages : `harness-coauthor-guard.yml` + # et `solution-leak-guard.yml` y ecrivaient AUSSI `/tmp/head.json`, mais au + # format DICT -- un job parallele lisait le fichier d'un autre et + # `pip_leak_delta.py` crashait (`'str' object has no attribute 'get'`, + # measure sur #18059, job 109030466607). Un prefixe par workflow ne + # suffirait pas (deux PRs du meme workflow sur deux slots collisionnent) : + # runner.temp est la seule borne per-job. - name: HEAD scan (PR head) run: | python scripts/notebook_tools/audit_pip_install_cells.py --scan-all - python scripts/notebook_tools/audit_pip_install_cells.py --scan-all --json > /tmp/head.json + python scripts/notebook_tools/audit_pip_install_cells.py --scan-all --json > "${{ runner.temp }}/pip-head.json" # Swap MyIA.AI.Notebooks/ to the PR base ref, scan, then restore. head.json # is already captured above, so the swap cannot contaminate the delta. @@ -66,9 +75,9 @@ jobs: # (le working tree est restore depuis ce checkout juste apres). git fetch --depth=1 origin "${{ github.event.pull_request.base.sha }}" -q git checkout ${{ github.event.pull_request.base.sha }} -- MyIA.AI.Notebooks - python scripts/notebook_tools/audit_pip_install_cells.py --scan-all --json > /tmp/base.json + python scripts/notebook_tools/audit_pip_install_cells.py --scan-all --json > "${{ runner.temp }}/pip-base.json" git checkout HEAD -- MyIA.AI.Notebooks - name: "Fail if HIGH delta > 0 (new !pip install leaks introduced)" if: github.event_name == 'pull_request' - run: python scripts/notebook_tools/pip_leak_delta.py /tmp/base.json /tmp/head.json + run: python scripts/notebook_tools/pip_leak_delta.py "${{ runner.temp }}/pip-base.json" "${{ runner.temp }}/pip-head.json" diff --git a/.github/workflows/solution-leak-guard.yml b/.github/workflows/solution-leak-guard.yml index f4ff5e4582..c0b28ea3d1 100644 --- a/.github/workflows/solution-leak-guard.yml +++ b/.github/workflows/solution-leak-guard.yml @@ -84,9 +84,13 @@ jobs: with: python-version: '3.11' + # NOTE (collision /tmp, 2026-09-28) : `${{ runner.temp }}` (per-slot) + # au lieu de `/tmp` nu -- `/tmp` est hote-global sur le runner a slots + # partages et `harness-coauthor-guard.yml` y ecrivait le meme + # `/tmp/head.json` au format dict (cf pip-leak-guard.yml, #18059). - name: HEAD scan (PR head) run: | - python scripts/notebook_tools/audit_solution_leaks.py --json > /tmp/head.json + python scripts/notebook_tools/audit_solution_leaks.py --json > "${{ runner.temp }}/solution-head.json" # Swap MyIA.AI.Notebooks/ to the PR base ref, scan, then restore. head.json # is already captured above, so the swap cannot contaminate the delta. @@ -99,7 +103,7 @@ jobs: # (le working tree est restore depuis ce checkout juste apres). git fetch --depth=1 origin "${{ github.event.pull_request.base.sha }}" -q git checkout ${{ github.event.pull_request.base.sha }} -- MyIA.AI.Notebooks - python scripts/notebook_tools/audit_solution_leaks.py --json > /tmp/base.json + python scripts/notebook_tools/audit_solution_leaks.py --json > "${{ runner.temp }}/solution-base.json" git checkout HEAD -- MyIA.AI.Notebooks - name: "Report HIGH delta (WARN — never fails)" @@ -113,7 +117,7 @@ jobs: echo "Detector candidates, not auto-verdicts: verify by CONTENT" echo "(cf exercise-example-labeling.md) — a guided example is legitimate._" echo "" - python scripts/notebook_tools/solution_leak_delta.py /tmp/base.json /tmp/head.json + python scripts/notebook_tools/solution_leak_delta.py "${{ runner.temp }}/solution-base.json" "${{ runner.temp }}/solution-head.json" } >> "$GITHUB_STEP_SUMMARY" # workflow_dispatch (no base ref): single scan, full markdown report to summary.