Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions .github/workflows/harness-coauthor-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
Expand All @@ -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
Expand All @@ -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"]}
Expand Down
15 changes: 12 additions & 3 deletions .github/workflows/pip-leak-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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"
10 changes: 7 additions & 3 deletions .github/workflows/solution-leak-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)"
Expand All @@ -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.
Expand Down
Loading