Skip to content

PR C: multi-platform and Python 3.15/3.15t ABI compatibility lanes - #19

Merged
P-R-N-D merged 9 commits into
mainfrom
claude/pr-c-platform-abi-compat-dykivt
Oct 12, 2026
Merged

P-R-N-D merged 9 commits into
mainfrom
claude/pr-c-platform-abi-compat-dykivt

Conversation

@P-R-N-D

@P-R-N-D P-R-N-D commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Requested by 김제석 · project thread

Summary

Before: only the checked lane (GitHub-hosted ubuntu-24.04, x86-64, CPython 3.12.15) ran in CI, and the compatibility collector could describe Linux only.

After: two new workflows install the hashed backend lock and run its checks on GitHub-hosted Linux, macOS and Windows runners on x86-64 and Arm64, in UBI 9 and UBI 10 containers under rootless Podman, and on CPython 3.15.0 and 3.15t. Each job writes a record of the runner and the stage outcomes, validates it against a committed profile, and uploads it as an artifact. No run changes a support status in docs/DEPENDENCY-STRATEGY.md.

The Windows lanes run in their own jobs, platform-windows and abi-windows, because GitHub-hosted Windows runners give the job an administrator token. The owner approved that as a temporary security exception limited to the functional and ABI checks this PR adds. It covers those jobs' runs after merge too, until its end conditions are met, and the owner reviews it by 2026-11-08. The jobs run only for a pull request from a branch of this repository and for a manual run on main. A fork's pull request that leaves the job condition unchanged skips them: that is an intentional not-run, not a pass. The condition is not a control against a malicious fork, which can edit it (see Security Impact). Their records are validated with --no-policy and say that the policy was skipped, security is not verified, and compatibility is incomplete. The default privilege policy is unchanged.

When a lane cannot install the lock, its record says why: blocked, naming the missing wheel or the requirement the lock does not pin. The later stages are then blocked, and the job stays green unless the lane's profile requires those stages. An install failure the probe cannot explain from the installer output is recorded as failed and fails the job.

Changes / Scope

Requested in the project thread linked above.

Workflows

  • .github/workflows/compatibility.yml (new)
    • platform, 4 lanes: linux-x64, linux-arm64, macos-arm64, macos-x64.
    • platform-windows, 3 lanes: windows-x64, windows-arm64, and windows-arm64-x64 (x64 Python and Node emulated on Windows on Arm). It runs the same steps and env as platform through YAML aliases.
    • ubi, 4 lanes: UBI 9.8 and UBI 10.2 on x86-64 and Arm64. Images are pinned by digest. Podman must report rootless, or the lane records blocked and fails, with no Docker, rootful or sudo fallback. Containers run with --userns=keep-id, --cap-drop=all and no-new-privileges, no --privileged and no devices. The image's system Python is recorded but not used; every lane uses uv's CPython 3.12.15.
  • .github/workflows/python-abi.yml (new): abi on the 4 Linux and macOS runners and abi-windows on the 2 Windows runners, each for both cp315 and cp315t (8 + 4 jobs). Only these jobs use uv 0.13.0. The backend jobs keep uv 0.12.24.
  • The Windows jobs (platform-windows, abi-windows):
    • job condition: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository, or github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main'. It reads only the github context, because a job's if is evaluated before its matrix is expanded;
    • only there, and only on a Windows runner, does the validator run with --no-policy. The record gets x-policy-exception (policy skipped, security not-verified, compatibility incomplete, non-administrator run not-run), and the security stage reason says the same. A warning annotation and the step summary repeat it;
    • a Windows runner in platform or abi fails the job at its first run step;
    • stage evidence names the running job, so the seven Windows profiles name platform-windows or abi-windows as their evidence source.
  • Both workflows:
    • run on pull_request to main with a path filter, and on workflow_dispatch;
    • grant contents: read, use persist-credentials: false, and pin every action to a full commit SHA;
    • run on GitHub-hosted runners only, with no secrets, no OIDC and no continue-on-error;
    • keep artifacts for 90 days, and are not required checks.
  • ci.yml is unchanged.

Scripts

  • scripts/ci/collect_environment.py
    • reads macOS sysctl values;
    • reads, on Windows, IsWow64Process2, the BIOS registry values and the token (elevated, Administrators, LocalSystem);
    • records Windows capabilities as unknown, because token privileges are not read;
    • adds --amend-container, which adds the engine's view of a container (rootless mode, privileged flag, devices);
    • adds --extension, which attaches JSON reports such as x-python-abi, x-frontend and x-policy-exception.
  • scripts/ci/probe_python_abi.py (new):
    • wheels: for each locked package, records which of the cp315-cp315, cp315-cp315t, cp315-abi3, cp315-abi3t and cp315-abi3.abi3t tags are published, and whether the interpreter accepts them (yanked files and files whose Requires-Python excludes the interpreter are not counted);
    • packages: installs each lock-hashed binary wheel with --no-deps, then imports and calls it in a fresh python -I process, recording the GIL state before and after. A package fails the job when it re-enables the GIL, or when its process exits with a nonzero status or a signal, even after printing a passing result. The report records the exit (exit: status, return code, signal name) and the step summary shows it in an Exit column;
    • install-stage: decides between blocked and failed from the uv log, the uv pip check output and the requirement report.

Tests and profiles

  • scripts/ci/tests/test_environment_probe.py (extended) and scripts/ci/tests/test_python_abi_probe.py (new, 35 tests). The exit tests cover a clean exit, a nonzero exit after the result (os._exit(3) from an atexit hook), a signal after the result (SIGKILL, skipped on Windows), a process that prints no result, and mocked return codes 0, 3, -11, -200 and 0xC0000005.
  • tests/compatibility/profiles/gha-*.json: 23 new real profiles, 24 with the existing linux-x64-gha.json.

Docs

  • SECURITY-ARCHITECTURE: a subsection on both workflows, and "Temporary exception: Windows administrator token" with its scope, when the jobs run, what a manual run means, risks, approval basis, end conditions and the follow-up. 465bea6 changes only this section and the Triggers sentence that points to it (see Notes).
  • CI-MATRIX, TESTING, DEPENDENCY-STRATEGY (observed lane results; freshness and provenance reviews of uv 0.13.0, CPython 3.15.0 and the UBI images), SECURITY-REVIEW, CODE-REVIEW, CONTEXT, ARCHITECTURE, and README.en/README.ko.

Out of scope, unchanged

  • Lock files: backend/locks/* and frontend/package-lock.json have no diff. No new production package, no lock refresh, no lowered security floor, no source builds, and no renamed wheels or tags.
  • The validator, its schema and its default policy (scripts/ci/validate_compatibility.py, tests/compatibility/schema.json) have no diff.
  • Also unchanged: product API, DB/ORM and auth; Issue Recheck the dependency exceptions recorded in PR #14 (by 2026-11-08) #15, other PRs, repository settings and branch protection.
  • Not done: a Windows environment without an administrator token (follow-up), Postman/Newman, CUDA/ROCm/QNN, PyTorch, Containerfile, K8s/Helm, systemd, self-hosted or GPU runners, WSL2, and PR D.

Implementation Status

  • No feature status and no SEC-* status changes. The diff cites no SEC-* ID.
  • The lane statuses in the profiles are copied from the lane table in docs/DEPENDENCY-STRATEGY.md, or recorded as not-assessed.
  • No lane is promoted. A green lane is evidence about one runner image and one commit.

Validation

CI on the final head

Head 465bea6 (one doc-only commit on top of c2e2f59: docs/SECURITY-ARCHITECTURE.md, 9 insertions and 8 deletions): 30/30 checks passed.

Workflow Run Result
CI (ci.yml, unchanged) 38233665193 7/7
Compatibility 38233665209 11/11 (platform 4, platform-windows 3, ubi 4)
Python ABI 38233665188 12/12 (abi 8, abi-windows 4)

The Windows jobs ran because this pull request's head branch is in this repository. All 11 Compatibility records of 465bea6 have the same stage results, overall and superuser as those of c2e2f59, and the three platform-windows records still hold x-policy-exception.

Checked in the artifacts and logs of c2e2f59 (CI 38225035053, Compatibility 38225034884, Python ABI 38225034916, also 30/30), whose code 465bea6 keeps unchanged:

  • All 11 Compatibility records: the stage results are the same as on the previous head 286dff0 (table below). Each record names the job that wrote it (platform, platform-windows or ubi).
  • The three platform-windows records and the Python ABI records of windows-x64 cp315 and windows-arm64 cp315t hold x-policy-exception and the "not verified" security reason. The linux-x64 records have neither.
  • The windows-x64 cp315 job log shows the "Privilege policy skipped" warning and valid result (0 errors, 1 warnings) with policy-skipped.
  • In the Python ABI reports read (linux-x64 cp315, windows-x64 cp315, windows-arm64 cp315t), every installed package's probe has exit passed with return code 0. The packages step fails on any failed exit, and it passed in all 12 jobs.

Lane results (CPython 3.12.15, hashed lock)

Lane install Django check, tests, pytest Frontend
linux-x64, linux-arm64, macos-arm64 passed passed passed
UBI 9.8 and 10.2, x86-64 and Arm64 (rootless) passed passed not in this job
macos-x64 blocked: no wheel for autobahn, cbor2, cryptography blocked passed
windows-x64, windows-arm64-x64 blocked: the lock does not pin tzdata, which django and psycopg require on win32 blocked passed on windows-x64; this lane runs none
windows-arm64 blocked: no wheel for autobahn, cryptography, psycopg-binary blocked passed
  • Overall is incomplete everywhere: CI runs no security or performance stage.
  • Linux, macOS and UBI ran as non-root (uid 1001 on Linux and UBI, 501 on macOS) and were checked against the default policy.
  • Windows ran with an administrator token. It is recorded as superuser: true, validated with --no-policy, and reported as policy-skipped, under the exception below.

CPython 3.15.0 and 3.15t

  • Install is blocked on every job, because some locked packages publish no usable wheel. Every package that installed was imported and called successfully, and its process exited 0.
  • No package re-enabled the GIL. Thread safety was not tested.
  • cffi, greenlet, msgpack, pydantic-core and ujson installed on all 12 interpreters.
  • cryptography installed through its cp315-abi3.abi3t wheel where one exists.
  • psycopg-binary has no cp315t or abi3t wheel.
  • autobahn and zope-interface have no 3.15 wheel.

Earlier heads

  • c2e2f59: 30/30 passed (runs above).
  • 286dff0: 30/30 passed (CI 38215048118, Compatibility 38215048102, Python ABI 38215048106).
  • 2a45b6f: the four Windows Python ABI jobs failed in a new test that wrote the lock with write_text, which gives CRLF line endings on Windows. 286dff0 writes it as bytes.

Local runs (author, self-assessment)

  • scripts/ci/tests/test_python_abi_probe.py: 35 OK on CPython 3.12.15 (2 skipped) and on 3.15.0 and 3.15t (1 skipped each). The new exit tests fail against the probe of 286dff0.
  • scripts/ci/tests/test_compatibility_schema.py: 95 OK.
  • scripts/ci/tests/test_environment_probe.py: 84 OK.
  • scripts/ci/tests/test_check_test_lock.py: 49 OK.
  • validate_compatibility.py --require-real --dependency-strategy docs/DEPENDENCY-STRATEGY.md tests/compatibility/profiles/*.json: 24 valid profiles, 0 errors.
  • Both workflows parsed with PyYAML: the aliases resolve to the same steps and env, and Windows runners appear only in the Windows jobs.
  • The changed step scripts run under bash with fake GITHUB_JOB and RUNNER_OS: --no-policy, the warning, the summary and x-policy-exception appear only for platform-windows or abi-windows on Windows; the guard fails only a Windows runner in platform or abi.
  • git diff --check: clean.
  • 465bea6: git diff --check clean, no em or en dash in the changed file, the section anchor unchanged, and git show --stat lists only docs/SECURITY-ARCHITECTURE.md.

Not run

  • The fork path: no pull request from a fork was opened, so the skip of the Windows jobs was not observed on GitHub. It follows from the job condition, which was checked by reading and by the simulation above.
  • A manual run on main: workflow_dispatch needs the workflow on the default branch, so it cannot run before merge.
  • A Windows run without an administrator token, and a policy check on Windows: hosted runners give an administrator token only. This is the follow-up.
  • Security and performance stages: not run in CI.
  • RHEL hosts and SELinux enforcing: not available on hosted runners. A UBI pass is a UBI user space on an Ubuntu kernel.
  • Django and the application on 3.15/3.15t: the lock does not install there.
  • UBI image signature verification: not done.
  • Postman/Newman: excluded by the request.

Reviews

  • An independent AI agent (not a person) reviewed the final head c2e2f59 for code and security once, along five lines: the probe's exit handling, the Actions job gating, security per SECURITY-REVIEW.md (including the step 7 secret-keyword check, whose hits were all prose about tokens or the secret-shape checker), documentation accuracy, and records and validation. It found no P0, P1 or P2 issue. It recorded 15 P3 findings (11 distinct), left unfixed as the owner asked; the owner then asked for the four about the exception section's wording, which 465bea6 fixes. See Notes.
  • An independent AI agent review (not a person) of the 465bea6 doc change before it was committed, along three lines: accuracy against the workflows and the validator, the owner's instructions and scope, and security claims. Each P0-P2 finding went to a separate agent that tried to refute it. One P2 survived, reported three times: the text said a repository setting could add an approval gate to manual runs, but environment protection rules apply only to jobs that name an environment, and these jobs name none. It is fixed in 465bea6. Of its P3 findings, four small ones about the same section's wording are applied (the approval is "for", not "in", pull request PR C: multi-platform and Python 3.15/3.15t ABI compatibility lanes #19; the reviewer is named as Codex; "at least" two things for the end condition; nothing reads the review date), one sentence it judged an unrequested new rule is dropped, and the rest are not applied; see Notes.
  • Earlier: an independent agent review of 9f0a8d9 (no P0 or P1; its 3 P2 and 5 of 7 P3 fixed in 2a45b6f), and Codex automated reviews of f7ccd3d (5 findings, 4 fixed and resolved, 1 open; see Notes).
  • No person has reviewed this PR.

Security Impact

  • Matches the CODE-REVIEW.md step 9 trigger for CI workflows and scripts/ci/* / tests/compatibility/*. SECURITY-REVIEW.md maps that trigger to SEC-SECRET-001 as the primary area. This PR claims no status for it.
  • What the workflows can reach:
    • triggers are pull_request and workflow_dispatch only, with no pull_request_target or workflow_run;
    • every job gets contents: read, and no secret or OIDC token is referenced;
    • actions are SHA-pinned;
    • runs-on labels are GitHub-hosted (ubuntu-24.04, ubuntu-24.04-arm, windows-2025, windows-11-arm, macos-15, macos-15-intel).
  • Windows administrator token (temporary exception, docs/SECURITY-ARCHITECTURE.md "Temporary exception: Windows administrator token"):
    • pull request code runs with administrator rights on an ephemeral GitHub-hosted VM, with the read-only token and no secret;
    • the jobs run only for this repository's pull requests and manual runs on main. A manual run needs write access to the repository, and nothing else gates it: no job names an environment, so a repository setting alone cannot add a reviewer;
    • the job condition is not a control against a malicious fork. A pull_request run uses the workflow file of the merge commit, so a fork's pull request that edits the condition runs the jobs as edited. Whether it starts without a maintainer's approval depends on the repository's GitHub Actions setting for fork pull request workflows. By GitHub's default only first-time contributors need approval; the level this repository uses was not checked, and changing it is the owner's decision. Beyond that, the read-only token is the limit;
    • the default policy is unchanged, and every other job is still checked against it.
  • Containers: digest-pinned UBI images, rootless Podman with no fallback, all capabilities dropped, no-new-privileges, no --privileged or devices. The writable mounts are the checkout and the job's records directory. uv and the event file are mounted read-only.
  • The probes read public PyPI JSON metadata, and install only wheels whose SHA-256 is in the lock.
  • In recorded warning text, the interpreter and home directory paths are replaced, and control characters are removed.
  • Security review: the independent agent review of c2e2f59, and of the 465bea6 doc change, which adds no code (above). The Codex security review of f7ccd3d is older.

Notes / Risks

  • Owner decision (approval basis of the exception). On 2026-10-12 08:20Z, in the project thread linked above, the repository owner (김제석) decided:

    GitHub-hosted Windows 관리자 토큰은 PR C의 기능·ABI 검증에 한정하여 임시 보안 예외로 승인합니다. 이 예외는 비관리자 실행 검증의 성공을 의미하지 않습니다.

    In English: the GitHub-hosted Windows administrator token is approved as a temporary security exception, limited to PR C's functional and ABI checks; it does not mean a non-administrator run was verified. The same decision limits Windows runs to this repository's pull requests and manual runs on main (started by a user with write access; nothing else gates them), keeps --no-policy to those Windows jobs, keeps the Rootless First default policy, and moves a non-administrator Windows environment to a follow-up.

  • Exception review date: 2026-11-08, confirmed by the owner on 2026-10-12. It is also the recheck date of the dependency exceptions in DEPENDENCY-STRATEGY.md. Nothing in the workflows reads the date: the jobs keep running with --no-policy until a change removes it.

  • Codex finding on the Windows administrator token: an owner-approved, time-limited security exception, not a code fix. The finding asked for the Windows lanes to run under a non-administrator token. No code change does that: GitHub-hosted Windows runners offer no such token. The owner accepted it as the temporary exception above, and the exception section records it so (465bea6). Its review thread is left open and unanswered, because replying to it or resolving it is not part of what this session was asked to do; that is the owner's step.

  • P3 findings of the review of c2e2f59. At the owner's request, 465bea6 fixes the four about the exception section's wording:

    • it said "for pull request PR C: multi-platform and Python 3.15/3.15t ABI compatibility lanes #19 only", while the jobs keep running under the exception after merge; it now says the exception covers every run of those jobs that meets their condition, before and after merge, until an end condition is met;
    • it said a Windows record's overall "stays incomplete"; it now says overall is never passed: incomplete, or failed when a stage failed;
    • the end condition now says that passing the default policy needs at least a Windows run without an administrator token (app-non-root) and a collector that reads Windows token privileges (minimal-capabilities), since Windows capabilities are recorded as unknown today;
    • the fork-approval risk now says the job condition is not a control against a malicious fork, that the outcome depends on the repository's fork approval setting, and that by GitHub's default only first-time contributors need approval.

    The other P3 findings are left as they are, as the owner asked:

    • two line citations stop one line short of the --stage security=not-run argument (compatibility.yml 221, python-abi.yml 145);
    • TESTING.md's artifact list omits frontend.json and policy-exception.json;
    • DEPENDENCY-STRATEGY.md's note on the first 3.15 run lacks a "since then" remark for the exit check;
    • the shared-steps guard does not stop the frontend steps from running in the wrong job (not reachable today);
    • a probe result line that is a JSON object without import and call stops the packages command with a traceback (fails closed);
    • no test ties a profile's evidence job to the matrix that produces it.
  • Fork wording outside the exception section, not changed here. These still say that a fork's pull request skips the Windows jobs, without the caveat that one which edits the condition runs them: CI-MATRIX.md line 127, TESTING.md lines 165 and 170, CODE-REVIEW.md line 10, and the job comments at compatibility.yml line 277 and python-abi.yml line 180. None of them claims the condition stops a malicious fork, and the documents link to the exception section. The owner limited this round to that section, so they are left for a follow-up if wanted.

  • install-stage relies on the format of uv 0.12.24's uv pip check output. If that format changes, a lane that would be blocked reads as failed instead and its job fails.

  • tzdata on Windows: whether a platform lock is wanted is left as a separate decision. This PR only records the evidence.

  • Missing wheels for macOS Intel and Windows Arm64, and missing 3.15/3.15t wheels, are upstream gaps. Re-locking does not fix them.

  • Not merged here; the owner merges. PR D is not started.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao

On macOS the collector reads sysctl values for the VM marker, the model,
the OS release, the machine architecture and Rosetta translation. On
Windows it reads the native machine from IsWow64Process2, the BIOS
manufacturer and product name, and whether the process token is
elevated, holds the Administrators group, or is LocalSystem. Both mark
the Linux isolation interfaces not-applicable. An administrator token is
recorded as the superuser, so a Windows runner's record cannot pass
app-non-root.

--amend-container runs podman info and podman container inspect on the
host and adds the engine's rootless mode, the privileged flag and the
devices to a record taken inside that container. --extension adds a
JSON object file to the record's extensions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
scripts/ci/probe_python_abi.py reads the interpreter's wheel tags with
packaging and PyPI's JSON metadata for each locked version, and reports
which lock packages have a wheel this interpreter accepts, which ABI each
wheel serves (cp315, cp315t, abi3, abi3t, abi3.abi3t), and whether the
hash is in the lock. Its packages command installs each native package
binary-only with the lock's hashes and no dependencies, imports and calls
it once in a fresh process, and records the GIL state before and after.
Thread safety is not tested.

install-stage decides a lane's install stage from uv's exit statuses and
the reports: blocked only when the installer names a package that has no
wheel for the interpreter, or uv pip check finds only requirements the
lock does not pin; any other failure is failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
compatibility.yml runs the backend lock install, Django check, the
Django tests and pytest, and the frontend checks, on GitHub-hosted
Linux, Windows and macOS runners on x86-64 and Arm64, plus an x64 Python
emulated on Windows on Arm, and records each runner against its profile.
Its ubi job runs the backend checks in UBI 9 and 10 containers pinned by
digest, in rootless Podman as the runner's user with every capability
dropped, and adds the engine's facts from the host.

python-abi.yml probes CPython 3.15.0 and 3.15t from uv 0.13.0 on the
same six runners. Both workflows run on pull requests that touch their
paths and on manual dispatch, are not required checks, and change no
support status. The 23 profiles copy their lane's status or record
not-assessed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T06:13:06.800083Z f7ccd3d PR opened
🔒 Security Review ✅ Completed 2026-10-12T06:04:21.433570Z f7ccd3d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f7ccd3da0b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/ci/probe_python_abi.py Outdated
Comment thread .github/workflows/compatibility.yml
Comment thread .github/workflows/compatibility.yml
Comment thread .github/workflows/compatibility.yml Outdated
Comment thread scripts/ci/probe_python_abi.py Outdated
CI-MATRIX.md and TESTING.md describe the platform, UBI and Python ABI
jobs, the collector's macOS, Windows and Podman sources, and the probe's
tests. DEPENDENCY-STRATEGY.md records the third freshness batch (uv
0.13.0 for the ABI workflow, the CPython 3.15.0 builds, and the UBI 9.8
and 10.2 image digests) and the results of runs 38210201779 and
38210201628, without changing any lane status. SECURITY-ARCHITECTURE.md
records the new workflows' triggers, permissions, downloads, PyPI
metadata reads, Windows administrator token, and rootless container
options; SECURITY-REVIEW.md and CODE-REVIEW.md point to them. CONTEXT.md,
ARCHITECTURE.md and the READMEs no longer say other lanes were never run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
- probe_python_abi: a package that enables the GIL in a build that started
  without it fails execute and the job; wheels whose Requires-Python
  excludes the interpreter are not counted as installable; unmet
  requirements include installed versions a requirement excludes; the
  install stage is blocked on missing requirements only when every
  problem uv pip check prints, and its count, says so; a uv line names a
  missing wheel only when it says the package has none; recorded warning
  text loses control characters.
- collect_environment: Windows capabilities are unknown, not
  not-applicable, because token privileges are not read, so a Windows
  record cannot pass minimal-capabilities unmeasured.
- compatibility.yml: the frontend steps' outcomes go in the record as
  x-frontend.
- Tests for these paths, probe_package and the packages command; docs
  updated to match, with corrected line citations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
Path.write_text translates newlines on Windows, so the lock file on disk
had CRLF line endings and its sha256 no longer matched the hash the test
computes from the text. The four Windows python-abi jobs failed on this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
import_probe read the result line the fresh python -I process printed and
ignored how the process then ended, so a package that printed a passing
import and call and crashed at shutdown, exited nonzero or was killed by a
signal still passed.

The probe now records the process's exit under "exit" (status, returncode,
and on POSIX the signal name) beside the result it printed, and overall()
counts a failed exit as a broken package, so execute fails and the
packages command exits 1. A process that prints no result is a failed
import with "no result" and its exit recorded. The summary table gains an
Exit column.

Tests: the exit after a printed result with subprocess.run replaced
(0, 3, -11/SIGSEGV, an unknown signal, 0xC0000005), and in real processes
an atexit os._exit(3), an atexit SIGKILL (POSIX only), and an exit before
any result; overall() and the packages command with a failed exit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
GitHub-hosted Windows runners give the job's user an elevated
administrator token only. The owner approved that on 2026-10-12 as a
temporary exception limited to PR C's functional and ABI checks.

- The Windows lanes move out of the platform and abi matrices into
  platform-windows and abi-windows, which run the same steps and env
  through YAML aliases. Their job-level if reads only the github context,
  since a job's if is evaluated before its matrix: a pull request whose
  head repository is this one, or a workflow_dispatch on refs/heads/main.
  A fork's pull request skips them (an intentional not-run). Linux, macOS
  and UBI jobs are unchanged.
- --no-policy is passed only in those two jobs on a Windows runner. Their
  records hold x-policy-exception (policy skipped, security not-verified,
  compatibility incomplete, non-administrator run not-run), the security
  stage's reason says the same, and the step summary and a warning
  annotation repeat it. A Windows runner in any other job fails at once.
- Stage evidence names the running job (GITHUB_JOB); the seven Windows
  profiles name the new jobs as their evidence sources.
- SECURITY-ARCHITECTURE.md gains "Temporary exception: Windows
  administrator token" (scope, risks including a fork editing the
  condition, approval basis, end conditions, and the non-administrator
  Windows follow-up); CI-MATRIX, TESTING, DEPENDENCY-STRATEGY and
  CODE-REVIEW describe the jobs, the not-run, and the probe's exit check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
Doc-only change to the "Temporary exception: Windows administrator token"
section of docs/SECURITY-ARCHITECTURE.md and the Triggers sentence that
points to it. No workflow, script, test, or profile changes.

- Scope: the exception covers every run of platform-windows and
  abi-windows that meets their condition, before and after pull request
  #19 is merged, until an end condition is met, instead of saying it is
  for that pull request only.
- overall: a record from these jobs is never passed; it is incomplete,
  or failed when a stage failed.
- End conditions: the records must pass the default policy without
  --no-policy, which needs at least a Windows run without an
  administrator token (app-non-root) and a collector that reads Windows
  token privileges (minimal-capabilities, recorded as unknown today).
  Nothing in the workflows reads the review date.
- Fork approval: the job condition is not a control against a malicious
  fork, because a pull_request run uses the workflow file of the merge
  commit. Whether an edited fork run starts without approval depends on
  the repository's GitHub Actions fork approval setting, which the owner
  decides; the level in use was not checked.
- Manual runs: a workflow_dispatch run needs write access and nothing
  else gates it. A setting alone cannot add a gate, because environment
  protection rules apply only to jobs that name an environment.
- Review date 2026-11-08, confirmed by the owner on 2026-10-12.
- The Codex finding on the Windows administrator token is recorded as
  accepted as this owner-approved, time-limited exception, not fixed in
  code.

Related: #19

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGH7FAsq1H9HmCR27Cj2Ao
@P-R-N-D
P-R-N-D merged commit 74801fe into main Oct 12, 2026
30 checks passed
@P-R-N-D
P-R-N-D deleted the claude/pr-c-platform-abi-compat-dykivt branch October 12, 2026 10:26
@P-R-N-D P-R-N-D self-assigned this Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants