Skip to content
Open
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
106 changes: 106 additions & 0 deletions .github/workflows/device-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Device Compute

on:
pull_request:
branches: [main]
paths:
- '.github/workflows/device-tests.yml'
- 'scripts/ci/**'
- 'tests/compatibility/**'
- 'frontend/scripts/probe-browser-compute*'
- 'frontend/package.json'
- 'frontend/package-lock.json'
- '.nvmrc'
- 'docs/CI-MATRIX.md'
- 'docs/TESTING.md'
- 'docs/DEPENDENCY-STRATEGY.md'
- 'docs/SECURITY-*.md'
- 'docs/CODE-REVIEW.md'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: true

defaults:
run:
shell: bash

jobs:
cpu:
name: CPU reference and browser capabilities / Linux x64
runs-on: ubuntu-24.04
timeout-minutes: 15
env:
UV_NO_CONFIG: '1'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
version: '0.12.24'
enable-cache: false
python-version: '3.12.15'
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version-file: .nvmrc
package-manager-cache: false
- name: Prepare the standard-library Python runtime
run: |
mkdir -p "$RUNNER_TEMP/device-compute"
echo "RECORDS=$RUNNER_TEMP/device-compute" >> "$GITHUB_ENV"
uv venv --managed-python --python 3.12.15
echo "$GITHUB_WORKSPACE/.venv/bin" >> "$GITHUB_PATH"
- name: Collect the real environment
id: collect
run: |
python -I scripts/ci/collect_environment.py --profile-id gha-linux-x64-device \
--output "$RECORDS/environment.json"
- name: Prepare the existing locked browser tool
working-directory: frontend
run: |
npm install --global npm@11.21.0
test "$(npm --version)" = 11.21.0
npm ci --ignore-scripts
# Download the paired browser as the job user. No system package installation.
node node_modules/@playwright/test/cli.js install chromium
- name: Probe browser capabilities
id: browser
run: |
node frontend/scripts/probe-browser-compute.mjs --environment "$RECORDS/environment.json" \
--output "$RECORDS/browser.json"
- name: Run CPU reference and attach compute evidence
if: ${{ !cancelled() && steps.collect.outcome == 'success' }}
run: |
args=()
if [ -f "$RECORDS/browser.json" ]; then args+=(--browser-report "$RECORDS/browser.json"); fi
python -I scripts/ci/probe_compute.py --environment "$RECORDS/environment.json" \
--output "$RECORDS/result.json" --report "$RECORDS/compute-probe.json" \
--log "$RECORDS/cpu-reference.log" --summary "$GITHUB_STEP_SUMMARY" "${args[@]}"
- name: Validate the common Result and profile
if: ${{ !cancelled() && steps.collect.outcome == 'success' }}
run: |
python -I scripts/ci/validate_compatibility.py --require-real \
--dependency-strategy docs/DEPENDENCY-STRATEGY.md \
--profile tests/compatibility/profiles/gha-linux-x64-device.json \
--summary "$GITHUB_STEP_SUMMARY" "$RECORDS/result.json"
- name: Run device contract and negative regressions
if: ${{ !cancelled() }}
run: |
python -I scripts/ci/tests/test_device_contract.py --verbose 2>&1 | tee "$RECORDS/contract-tests.log"
python -I scripts/ci/tests/test_compute_probe.py --verbose 2>&1 | tee "$RECORDS/probe-tests.log"
python -I scripts/ci/tests/test_device_environments.py --verbose 2>&1 | tee "$RECORDS/environment-tests.log"
node --test frontend/scripts/probe-browser-compute.test.mjs 2>&1 | tee "$RECORDS/browser-tests.log"
# This bundle remains separate from the measured Result and is always synthetic.
python -I tests/compatibility/fixtures/device-environments/scenarios.py > "$RECORDS/synthetic-environments.json"
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
if: ${{ !cancelled() }}
with:
name: device-compute-linux-x64-attempt-${{ github.run_attempt }}
path: ${{ runner.temp }}/device-compute/
if-no-files-found: error
retention-days: 90
50 changes: 43 additions & 7 deletions docs/CI-MATRIX.md

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions docs/CODE-REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ It is not a security policy (see [SECURITY-ARCHITECTURE.md](SECURITY-ARCHITECTUR

- In effect for every code change, starting at HEAD 8ec5623 (committed 2026-09-21; the repository facts in this document were verified on 2026-10-08). The procedure depends on nothing that is Planned. (Updated 2026-10-10: the Frontend boundary checks were re-checked at 14b9109; unchanged through 3fe4d1a.)
- Tooling: `.github/workflows/ci.yml` runs the baseline backend, frontend, and Playwright checks, plus the pytest and Vitest unit test jobs and the compatibility job of [CI-MATRIX.md](CI-MATRIX.md), on pull requests to `main` and pushes to `main`, on the checked lane only. Since 2026-10-12, `.github/workflows/compatibility.yml` and `.github/workflows/python-abi.yml` run the backend and frontend checks on other GitHub-hosted runner lanes and in UBI containers, and probe CPython 3.15.0 and 3.15t, on pull requests to `main` that change their inputs and on manual dispatch; they are not required checks, and a pull request that changes none of their paths has no run of them. Their Windows jobs run only for a pull request from a branch of this repository or a manual run on `main`, so a fork's pull request has no Windows result ([SECURITY-ARCHITECTURE.md](SECURITY-ARCHITECTURE.md#temporary-exception-windows-administrator-token)). [TESTING.md](TESTING.md) "Continuous integration" lists the jobs and what they do not cover. Its runs are evidence to read (see "Independence and authority" and step 8). GitHub-side integrations, such as review bots and required status checks, are configured outside the repository's files; whether one runs depends on the connected service and its settings, and its output is evidence to read. `.github/` also holds `copilot-instructions.md`, a bridge file that points to [CONTEXT.md](CONTEXT.md), and the advisory issue forms and pull request template described in [CONTEXT.md](CONTEXT.md) "GitHub issues and pull requests"; they are writing aids, not review tooling or evidence. Adding another workflow, or extending `ci.yml` beyond the checked lane, is a separate, explicitly requested change. (Updated 2026-10-12.)
- Device tooling: PR D adds `.github/workflows/device-tests.yml` on GitHub-hosted Ubuntu 24.04, the standard-library CPU/device probe, the existing Playwright-based browser probe, and special-environment fixture regressions. It leaves the three prior workflows unchanged; no GPU/NPU or special-environment support is implied. The compute/device review checks below cover this interface.
- Verification baseline: the automated tests that exist are listed in [TESTING.md](TESTING.md) under "Tests that exist today". They were not executed in this documentation pass. "Exists" and "executed" stay distinct throughout this document.
- The checks under "Boundary-specific checks" for Realtime, Task, and Runtime cover Planned areas. They apply to a change that introduces such code; they never imply the feature exists.

Expand Down Expand Up @@ -119,6 +120,13 @@ Data (ORM, migrations, storage):
- File access goes through the Django storage API. Object-name validation, no-overwrite saves, and presigned URL handling in `backend/core/storage/s3.py` are preserved; any change to them is a security review trigger.
- `DATABASE_URL` parsing stays strict; a new silent fallback is a finding.

Compute/device validation (`scripts/ci/probe_compute.py`, `frontend/scripts/probe-browser-compute.mjs`, the compatibility schema/validator, `tests/compatibility/`, and `device-tests.yml`):

- Read the requested/effective backend linkage, typed probe evidence, and actual reference operation. Runtime/tool presence, API enumeration, device access, completed operation, and correctness must remain separate. GPU-to-CPU/software fallback and detection-only success claims must fail; an unavailable SDK/tool alone must not prove absent hardware. Names in the API catalog do not qualify a runtime.
- Run the device contract, CPU probe, special-environment, and browser tests listed in [TESTING.md](TESTING.md#device-and-compute-workflow). Check intentional wrong-result/error inputs as well as the successful CPU operation. Verify SHA/workflow/job linkage and required-stage failures, and that synthetic results cannot satisfy `--require-real`. Inspect each optional browser outcome; WebGL/WebGPU/WebNN detection is not GPU/NPU execution.
- Check bare metal, VM/WSL2/container layer order; host systemd process management, host systemd/Quadlet container management, and container PID 1 independently; and rootless engine, non-root workload, cgroup delegation, device-plugin metadata, and policy denials independently. Generated fixtures test the model only. No cluster, WSL2 installation, service, or hardware execution can be claimed from them.
- Review the new workflow against the scope and security procedure, including action pins, token, runner, no escalation, public artifacts, failure propagation, and unchanged checks in the three earlier workflows. A CPU reference pass is pipeline evidence, not AI inference or hardware qualification. Unavailable hardware, unexecuted probes, and lower-priority follow-ups remain explicit in the review. Report independent code/security review separately from author tests and self-assessment; neither a green workflow nor a review bot is approval.

### 7. Performance, concurrency, maintainability

- No unprotected process-global mutable state. Shared in-process state uses explicit synchronization; `backend/core/storage/s3.py` uses a `threading.Lock` for its lazy client and is the existing reference. Nothing may rely on the GIL, and a native or third-party dependency the change adds is checked for free-threaded compatibility ([CONTEXT.md](CONTEXT.md) "Concurrency direction").
Expand Down
8 changes: 8 additions & 0 deletions docs/DEPENDENCY-STRATEGY.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ Sources checked on 2026-10-10:
- [Linux on Snapdragon X2 Series early developer preview](https://www.qualcomm.com/developer/blog/2026/09/announcing-linux-on-snapdragon-x2-series-early-developer-preview) and [Qualcomm OnQ: Snapdragon Summit 2026](https://www.qualcomm.com/news/onq/2026/09/snapdragon-summit-agentic-ai-pcs-linux) (Debian by the end of 2026; Ubuntu certification targeted for the first half of 2027).
- [Playwright for Python system requirements](https://playwright.dev/python/docs/intro) and [microsoft/playwright#40202](https://github.com/microsoft/playwright/issues/40202).

### Compute evidence from PR D

`device-tests.yml` adds a CPU reference and device capability lane on GitHub-hosted `ubuntu-24.04`; it changes no lock or support status in the table above. The standard-library Python probe runs a fixed integer matrix multiplication on `cpu` and checks the exact result. This validates the evidence pipeline, not LLM inference, accelerator performance, or an AI framework. The existing Node Playwright dependency also supplies a separate Chromium probe: WebAssembly performs a small operation, while WebGL, WebGPU, and WebNN report context/API/adapter observations only.

The contract can name CUDA, ROCm, oneAPI, Level Zero, OpenCL, Vulkan Compute, DirectCompute, DirectML, Metal, MPS, Core ML, MLX, QNN, WebGPU, WebGL, WebNN, and WebAssembly. A name in that catalog is not an implementation or qualification. No CUDA/ROCm/oneAPI/QNN SDK, PyTorch, TensorFlow, or ONNX Runtime is introduced. The native accelerator probe observes only installed tool paths and fixed device-node classes/access; it runs no vendor utility or accelerator kernel. Missing tools leave runtime, driver, and hardware support `unknown`, and accelerator execution stays `not-run` with its reason. A future execution probe with an unavailable required device reports `blocked`; an unexpected execution error, wrong answer, or CPU/software fallback cannot pass the hardware lane.

The result distinguishes requested and effective backends, detection from execution, correctness, device access, software fallback, and evidence tied to the environment record. A WebGPU API, adapter, or software renderer is not hardware GPU execution; WebNN presence is not NPU execution. Synthetic WSL2, VM, container, systemd, and Kubernetes-family fixtures exercise the contract only. Their validation cannot promote a hardware or platform lane to Checked. Commands and the exact CI scope are in [TESTING.md](TESTING.md#device-and-compute-workflow); the contract is in [CI-MATRIX.md](CI-MATRIX.md#device-and-compute-evidence).

## Observed lane results, 2026-10-12

Added 2026-10-12. The first runs of `.github/workflows/compatibility.yml` (run 38210201779, 11 jobs) and `.github/workflows/python-abi.yml` (run 38210201628, 12 jobs), both green, on pull request [#19](https://github.com/P-R-N-D/Claus-AI/pull/19) at head `f7ccd3d`, tested as merge commit `aaaa80c1` onto `main` at `5f27b1c`. Each job's result record and probe reports are artifacts of its run, kept for 90 days. A run is evidence about one commit on one runner image; the lane table above remains the only record of status, and these runs change no status in it. Promoting a status, for example Linux aarch64 glibc to Checked, is a separate edit to that table. Every record is `incomplete` overall, because no lane runs the security and performance stages.
Expand Down
12 changes: 12 additions & 0 deletions docs/SECURITY-ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,18 @@ Added 2026-10-12. Line numbers below are `compatibility.yml`'s unless `python-ab
- Artifacts: each job uploads its result record, probe reports, and logs whether or not validation passed, kept for 90 days (lines 264-271, 545-551; `python-abi.yml` lines 167-174). They describe the runner and the lock's public packages, not the repository's users; the collector's and validator's secret-shaped value checks apply to the records, as in `ci.yml`, and nothing else is scanned.
- The limits of the `ci.yml` checks apply here too: a pull request that changes these workflows, the probes, the validator, or their tests runs them as changed, so those changes need review in the diff.

### Device and compute workflow (`.github/workflows/device-tests.yml`)

PR D adds one GitHub-hosted `ubuntu-24.04` job. It runs for path-filtered pull requests to `main` and `workflow_dispatch`, with `contents: read`, checkout credentials disabled, full commit SHA action pins, a bounded timeout, and no secrets, OIDC permission, self-hosted runner, privilege escalation, or `continue-on-error`. It applies the default compatibility privilege policy; there is no Windows job and no inherited policy exception. The existing three workflows and their checks remain in place.

`scripts/ci/probe_compute.py` reads the collected environment, records only presence/access observations for allowlisted tool names and device-node classes, and executes a fixed CPU reference operation with the Python standard library. It does not run vendor diagnostic commands, install an SDK, open an accelerator for computation, or change device permissions. Its result records the tool/runtime/process, requested and effective backend, execution and correctness, and log/artifact references. The browser probe uses the existing frontend Playwright dependency and Chromium for a local fixed page; WebAssembly is the only browser operation checked for correctness. WebGL context creation and WebGPU/WebNN detection do not establish hardware computation. Published reports must exclude serial numbers, host/account names, addresses, raw environment dumps, and raw driver output. Reports and job summaries are public evidence, not confidential storage.

Device access, host administrator rights, a rootful engine, a container's UID 0, capabilities, and application identity remain independent facts. Device access must never trigger fallback to `sudo`, rootful containers, or `--privileged`. A future lane must use a non-root application and rootless engine where possible, restrict access to named devices, and retain the existing exception contract for any approved deviation: scope, approval reference, verification, and end condition. Systemd as host process manager, host systemd/Quadlet managing a container, and systemd as container PID 1 are distinct configurations. cgroup v2 delegation is separate from engine mode, and container systemd does not imply a privileged container. Kubernetes workload user, no privilege escalation, engine mode, device-plugin access, and orchestration scope are likewise separate.

Future hardware execution requires a suitable physical GPU/NPU, compatible runtime/driver, a reviewed operation with a known expected result, and narrowly granted device access. A trusted runner must be isolated from public pull request code, other tenants, credentials, and persistent host state; use an owner-controlled workflow and reviewed immutable revision with explicit authorization for that environment, ephemeral workspace/cleanup, and an artifact that binds the tested SHA, workflow/job/run, requested device, effective device, and correctness evidence. Merely gating a self-hosted `runs-on` expression in a pull request's editable workflow is not this boundary. PR D registers no runner, changes no GitHub setting, and never schedules public pull request code on hardware runners. The validator checks consistency of reported evidence; it cannot attest that a malicious runner or modified probe told the truth.

The Windows administrator-token exception below remains confined to PR C's two jobs. The owner's disposition of PR #19's Codex finding accepted that risk; it did not verify a non-administrator Windows run. Non-administrator Windows execution and a token-privilege probe remain follow-up work, with the **2026-11-08** review date unchanged.

### Temporary exception: Windows administrator token

Approved 2026-10-12 by the repository owner for pull request #19 (PR C), which adds the two jobs below. It is a temporary security exception for the functional and ABI checks those jobs run on GitHub-hosted Windows runners. It covers every run of those jobs that meets their condition, before and after that pull request is merged, until an end condition below is met. It does not mean that a run without administrator rights was verified, and it does not relax the default privilege policy ([CI-MATRIX.md](CI-MATRIX.md) "Policy"), which every other job and record is still held to.
Expand Down
Loading
Loading