Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
240767d
scripts : add Strix host-memory watchdog
Sep 12, 2026
41dbf04
scripts : clean up watchdog process group on signals
Sep 12, 2026
da5ce95
scripts : preserve child signals and monitor descendants
Sep 12, 2026
93aff41
scripts : classify soft descendant escalation as timeout
Sep 12, 2026
2e27f6e
merge : sync repaired DeepSeek V4.1 schema base
Sep 13, 2026
0ca941a
merge : sync DeepSeek V4.1 RoPE classification
Sep 13, 2026
58533e7
deepseek41 : add cross-runtime trace harness
Sep 13, 2026
7a8d939
deepseek41 : harden trace validation
Sep 13, 2026
c6712f9
merge : update DeepSeek V4.1 expert execution
Sep 13, 2026
62545e5
deepseek41 : attest trace executables
Sep 13, 2026
b1ffc5f
merge : update final DeepSeek V4.1 expert execution
Sep 13, 2026
520706e
deepseek41 : harden trace audit contract
Sep 13, 2026
23a89dd
deepseek41 : complete trace attestations
Sep 13, 2026
61e9ea5
merge : integrate DeepSeek V4.1 full graph
Sep 13, 2026
090b581
deepseek41 : integrate trace producer contract
Sep 13, 2026
08f6fe7
merge : integrate corrected DeepSeek V4.1 full graph
Sep 13, 2026
7ae899e
deepseek41 : reject malformed trace names
Sep 13, 2026
5dc4dc7
merge : update final DeepSeek V4.1 full graph
Sep 13, 2026
8acdb46
scripts : forward SIGHUP through memory watchdog
Sep 13, 2026
5983301
scripts : publish watchdog-owned validation lease
Sep 13, 2026
c4598ee
scripts : harden watchdog fail-closed lease
Sep 13, 2026
0071e8f
scripts : harden watchdog cleanup lease
Sep 13, 2026
cd97b50
scripts : enforce cleanup on guardian errors
Sep 13, 2026
f6b4da4
scripts : preserve watchdog failure cause
Sep 13, 2026
778db6f
scripts : retain watchdog artifact evidence
Sep 13, 2026
6d4acd6
deepseek41 : harden correctness trace admission
Sep 13, 2026
0139bb2
deepseek41 : attest host architecture and storage
Sep 13, 2026
11b18e3
trace : split runtime host attestations
Sep 13, 2026
0fb4043
trace : record session provenance
Sep 13, 2026
21f1908
trace : close exporter attestation gaps
Sep 13, 2026
e1732bc
trace : validate lexical temporary directory
Sep 13, 2026
5694bfa
trace : bind canonical watchdog artifacts
Sep 13, 2026
de8879f
trace : align canonical terminal schema
Sep 13, 2026
c313edd
trace : enforce ds4 exporter approval
Sep 13, 2026
c5fb91f
trace : reject null secondary watchdog errors
Sep 13, 2026
a414f2c
trace : record Copilot session provenance
Sep 13, 2026
190e103
merge : integrate approved Strix memory watchdog
Sep 13, 2026
5c029ea
trace : bind loaded exporter runtime
Sep 13, 2026
a93a2c3
trace : bind complete runtime library closure
Sep 13, 2026
9996323
trace : ignore non-project loader images
Sep 13, 2026
a246459
tests : verify unsigned manifest rejection
Sep 13, 2026
88c27b4
deepseek41 : seal correctness trace bundles
Sep 13, 2026
82386e3
tools: require external trace executable approvals
Sep 13, 2026
c5c665f
tools: bind trace tokenizer and loader trust
Sep 13, 2026
12ee292
trace : bind ds4 exporter to immutable approval
Sep 13, 2026
5a7452b
trace : attest ds4 failures before returning
Sep 13, 2026
2eaec20
trace : contain ds4 process failures
Sep 13, 2026
3fb4a39
trace : own approved process descendants
Sep 13, 2026
a34c30c
trace : harden approved process containment
Sep 13, 2026
76a685c
trace : contain Linux execution in native namespace helper
Sep 13, 2026
90ea4d3
trace : isolate Linux target privileges
Sep 14, 2026
bf3d930
trace : diagnose Linux containment startup
Sep 14, 2026
b322ddf
trace : validate Linux protocol descriptors
Sep 14, 2026
0c398a5
trace : clear namespace groups before mapping
Sep 14, 2026
e4beb4d
trace : require zero-group Linux service
Sep 14, 2026
3b5bdd5
trace : require zero-group Linux service
Sep 14, 2026
8e3de1b
trace : replay correctness harness on accepted graph
Sep 14, 2026
927eab6
trace : bind replay session provenance
Sep 14, 2026
5f32d71
trace : bind model and watchdog identities
Sep 14, 2026
924ad46
trace : join PR8 publication lineage
Sep 14, 2026
170796f
ci : run DeepSeek V4.1 trace test on Linux
Sep 14, 2026
4a12c80
ci : prove DeepSeek trace pidns runs once
Sep 14, 2026
b453d01
ci : bind DeepSeek trace to Python 3.11
Sep 14, 2026
fc88e35
ci : normalize DeepSeek trace runner identity
Sep 14, 2026
d191459
ci : validate CTest trace numbering
Sep 14, 2026
0ab98b2
ci : capture hosted namespace policy controls
Sep 14, 2026
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
1,445 changes: 1,438 additions & 7 deletions .github/workflows/server.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ Everything else is upstream `llama.cpp`. The additions currently carried here:
| Speculative checkpoints on device | | `llama-server` keeps speculative-decoding checkpoints in device memory instead of copying them to the host |
| ROCmFPx quant types | `llama-quantize` types `Q4_0_ROCMFP4`, `Q4_0_ROCMFP4_FAST`, `Q2/Q3/Q6/Q8_0_ROCMFPX` and the `_LEAN`/`_COHERENT`/`_STRIX` recipes | Loads the ROCmFP4 GGUFs published for Strix Halo. CPU codecs plus Vulkan dequant, mat-vec, matmul and integer-dot kernels. Weight formats only: not accepted as KV-cache types |
| Repeatable output at depth | | Freed KV cells are zeroed so masked-out rows never carry stale K/V, and the Vulkan radix top-k assigns output slots deterministically |
| Host-memory watchdog | [`scripts/strix_memory_watchdog.py`](docs/strix-memory-watchdog.md) | Runs a command in a process group, requires zero active swap, and stops before host-wide memory reaches the 120 GiB validation ceiling |

Every ROCm/HIP change above is guarded on architecture, shape and layout, so other devices see upstream behaviour.
Run `--help`, or see [tools/server/README.md](tools/server/README.md), for the full options.
Expand Down
2 changes: 1 addition & 1 deletion cmake/build-info.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ endif()
# Get the commit count and hash
if(Git_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE
Expand Down
94 changes: 94 additions & 0 deletions docs/strix-memory-watchdog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Strix host-memory watchdog

`scripts/strix_memory_watchdog.py` is an external Linux command wrapper for headless Strix Halo validation. It does not change model loading or cache sizing. It measures host-wide memory from procfs and controls the launched command's process group.

```sh
./scripts/strix_memory_watchdog.py -- ./build/bin/llama-server <arguments>
```

The wrapper performs these checks and actions:

- It refuses to launch if `/proc/swaps` contains any active entry.
- It calculates used memory as `MemTotal - MemAvailable`. Linux reports these fields in KiB, so the wrapper multiplies each value by 1024 and keeps all accounting as integer bytes.
- It sends `SIGTERM` to the process group at 116 GiB used.
- It sends `SIGKILL` at 118 GiB used or 30 seconds after `SIGTERM`.
- It reports `grace_timeout` if any descendant requires `SIGKILL` after the soft-threshold grace period, even when the direct child exited earlier.
- It sends `SIGKILL` and fails if swap appears or required procfs data becomes unavailable during execution.
- It forwards wrapper `SIGHUP`, `SIGINT`, or `SIGTERM` to the process group, waits the configured grace period, then sends `SIGKILL` if any group member remains.
- It checks the process group after the direct child exits and cleans up remaining descendants before returning the child's classification.
- It applies the same bounded process-group cleanup if an unexpected post-launch error occurs.
- It propagates an unmonitored child exit code. A signal exit uses the shell convention `128 + signal`.

The 118 GiB emergency threshold leaves a 2 GiB sampling margin below the strict 120 GiB ceiling. The default sample interval is one second. This margin cannot guarantee the ceiling for a workload that can allocate more than 2 GiB between samples. Lower `--emergency-gib` or shorten `--sample-interval-seconds` for such a workload.

Use `--procfs-root` to select a different procfs mount or a test fixture. `--soft-gib`, `--emergency-gib`, `--grace-seconds`, and `--sample-interval-seconds` override the other defaults. The emergency threshold must remain below 120 GiB. The fail-closed timing bounds are a maximum 30-second grace, maximum one-second sample interval, and maximum five-second heartbeat age.

The wrapper writes timestamped JSON Lines records to standard error. Preflight, sample, signal, and final records include total, available, used, and peak-used bytes, swap entry count, child status, process-group status, threshold reason, and final classification where applicable. Signal records are written immediately after each process-group signal. Child standard input, standard output, and standard error are inherited unchanged.

## Watchdog-owned validation lease

Use all three artifact options together when another process must prove that it is inside the active watchdog process group:

```sh
./scripts/strix_memory_watchdog.py \
--lease-path /run/deepseek-v41/watchdog-lease.json \
--heartbeat-path /run/deepseek-v41/watchdog-heartbeat.json \
--audit-path /run/deepseek-v41/watchdog-audit.jsonl \
-- \
python3 tools/deepseek-v41-trace/run_matrix.py <arguments>
```

The watchdog creates and exclusively locks the persistent audit before launch. It then starts an internal guardian as the new session and process-group leader; the guardian starts the supplied command in that same group without inheriting the private control pipe. After the guardian reports the payload PID, the watchdog atomically creates the lease and heartbeat. Existing artifact paths are rejected rather than overwritten. The payload receives the resolved paths through `STRIX_MEMORY_WATCHDOG_LEASE_PATH`, `STRIX_MEMORY_WATCHDOG_HEARTBEAT_PATH`, and `STRIX_MEMORY_WATCHDOG_AUDIT_PATH`. It also receives `STRIX_MEMORY_WATCHDOG_HEARTBEAT_MAX_AGE_SECONDS`.

The child can run before the first atomic lease rename. A matching preflight must retry the inherited lease path for a bounded interval and fail closed if a complete valid lease does not appear. It must not accept a lease path supplied separately by the operator. Consumers must require version 2; version 1 does not describe the guardian topology or timing policy and is rejected.

Lease format `strix-memory-watchdog-lease`, version 2, contains:

- `lease_id` and active/final `state`
- `watchdog_pid`, `watchdog_start_time_utc`, Linux `watchdog_start_time_ticks`, `watchdog_executable_path`, `watchdog_command_sha256`, `watchdog_script_path`, and `watchdog_script_sha256`
- exact `soft_bytes`, `emergency_bytes`, `strict_ceiling_bytes`, `grace_seconds`, and `sample_interval_seconds`
- `procfs_root`
- `guardian_pid`, payload `child_pid`, `child_process_group_id`, `command`, and `child_command_sha256`
- `heartbeat_path`, `max_heartbeat_age_seconds`, and `audit_path`
- device, inode, owner, and mode identity for atomic JSON artifacts, plus the watchdog-held audit descriptor identity
- the authoritative `final` audit record after termination

Heartbeat format `strix-memory-watchdog-heartbeat`, version 2, binds `lease_id`, watchdog PID/start ticks, child PID/process group, sequence, state, and update timestamps. Every memory sample first checks swap and memory thresholds, pulses the guardian through the private nonblocking pipe, then atomically replaces the heartbeat with the complete sample audit record and its persistent-audit record hash. It pulses again after persistence succeeds. A blocked audit or heartbeat write cannot delay the emergency signal; if persistence stalls past the guardian deadline, the guardian fails closed. A final heartbeat and final lease update remain on disk with the persistent JSONL audit; the watchdog does not delete this evidence.

The guardian uses Linux `PR_SET_PDEATHSIG` with a parent-race check. It kills its process group on watchdog death, control-pipe EOF/error, or a missed pulse deadline, including a stopped or wedged watchdog. When the watchdog sends a graceful signal, it also puts the guardian into a bounded grace mode and continues private pulses while it waits. This lets the watchdog own the configured grace deadline and record any `SIGKILL` escalation instead of letting the shorter heartbeat deadline preempt cleanup. If the grace control message or a cleanup pulse fails, the watchdog independently sends `SIGKILL` to the process group and reaps the child before it reports `signal_error`. The payload must call `start_process_group_lease_guard()` before it starts exporter descendants. This validates the lease with bounded startup retries, arms a second parent-death link to the guardian, and starts a thread that kills the process group if any validation or artifact operation fails or the watchdog evidence becomes stale.

A matching Linux preflight must verify all of the following:

- The inherited lease, heartbeat, and audit paths match the paths inside the lease.
- `/proc/<watchdog_pid>/exe` is the exact expected Python executable and argv position 1 is the exact repository watchdog script. `-c`, `-m`, helper-script, inert-argument, and interpreter-option substitutions are rejected.
- The watchdog command line itself supplies the exact 116/118 GiB thresholds, `/proc`, inherited artifact paths, timing policy, and command after `--`; the lease cannot override those expectations.
- `/proc/<watchdog_pid>/stat` start ticks and `/proc/<watchdog_pid>/cmdline` SHA-256 match the lease and remain stable across validation. A pidfd is held during validation when Linux provides `pidfd_open`.
- The topology is watchdog parent -> guardian process-group leader -> payload child. The current process must be inside `child_process_group_id`.
- The command identity is expected, the procfs root is `/proc`, and thresholds are exactly 116 GiB soft, 118 GiB emergency, and 120 GiB strict ceiling for the final run.
- Lease and heartbeat files are regular, mode 0600, owned by the current UID, opened with `O_NOFOLLOW`, and match their recorded device/inode identity.
- The heartbeat identity matches the lease, its monotonic timestamp is not older than `max_heartbeat_age_seconds`, and its audit-record hash exists in the persistent audit.
- The persistent audit matches the watchdog-held descriptor device/inode and remains exclusively locked by the live watchdog.

These checks reject accidental or helper-process substitution and make regular-file heartbeat forgery unable to keep the process group alive after private pulses stop. They are not a security boundary against intentionally hostile code running as the same UID; use a separately owned systemd user service or cgroup if that threat is in scope.

The guardian controls only the process group. A payload that deliberately calls `setsid()` can escape it. The correctness harness must not do that. If arbitrary payload code is in scope, launch the watchdog in a service/cgroup configured to kill every member when the unit stops.

Exit classifications are authoritative in the last final JSON record. If final artifact persistence fails after a primary safety failure, the primary classification and exit code remain unchanged and the artifact failure is listed in `secondary_errors`. Operational failures use these exit codes:

| Exit code | Classification |
| ---: | --- |
| 2 | procfs or configuration error |
| 3 | swap active at startup or detected during execution |
| 4 | soft threshold reached |
| 5 | emergency threshold reached |
| 6 | soft-threshold grace period expired |
| 7 | process-group signaling or termination failure |
| 8 | lease, heartbeat, or persistent audit failure |
| 70 | unexpected post-launch error |
| 127 | command launch failure |

No model, backend, or ROCm package is required to run the unit tests:

```sh
python3 tests/test_strix_memory_watchdog.py
```
2 changes: 1 addition & 1 deletion ggml/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
find_program(GIT_EXE NAMES git git.exe NO_CMAKE_FIND_ROOT_PATH)
if(GIT_EXE)
# Get current git commit hash
execute_process(COMMAND ${GIT_EXE} rev-parse --short HEAD
execute_process(COMMAND ${GIT_EXE} rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GGML_BUILD_COMMIT
OUTPUT_STRIP_TRAILING_WHITESPACE
Expand Down
Loading
Loading