GGUF
English
Japanese
misaka-palw
misaka
palw
proof-of-compute
deterministic-inference
integer-quantization
conversational
Instructions to use Misakachain/Qwen3.6-35B-A3B-PALW-runtime with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use Misakachain/Qwen3.6-35B-A3B-PALW-runtime with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M # Run inference directly in the terminal: llama cli -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M # Run inference directly in the terminal: llama cli -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Use Docker
docker model run hf.co/Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
- LM Studio
- Jan
- Ollama
How to use Misakachain/Qwen3.6-35B-A3B-PALW-runtime with Ollama:
ollama run hf.co/Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
- Unsloth Desktop
- Pi
How to use Misakachain/Qwen3.6-35B-A3B-PALW-runtime with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use Misakachain/Qwen3.6-35B-A3B-PALW-runtime with Docker Model Runner:
docker model run hf.co/Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
- Lemonade
How to use Misakachain/Qwen3.6-35B-A3B-PALW-runtime with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Run and chat with the model
lemonade run user.Qwen3.6-35B-A3B-PALW-runtime-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use Misakachain/Qwen3.6-35B-A3B-PALW-runtime with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use Misakachain/Qwen3.6-35B-A3B-PALW-runtime with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "Misakachain/Qwen3.6-35B-A3B-PALW-runtime:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
Initial import: PALW proof-of-compute runtime for Qwen3.6-35B-A3B (code + docs, no model weights)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .github/workflows/palw-ci.yml +182 -0
- .gitignore +58 -0
- .python-version +1 -0
- LICENSE +202 -0
- LICENSES/llama.cpp-MIT.txt +29 -0
- NOTICE +46 -0
- README.md +271 -0
- SECURITY.md +34 -0
- config/qwen3.6-35b-a3b-claude-4.7-base-metadata.sha256 +7 -0
- config/qwen3.6-35b-a3b-claude-4.7-profile.json +112 -0
- config/runtime-pins.sh +118 -0
- docs/SETUP.md +81 -0
- docs/architecture.md +291 -0
- docs/cuda-receipt-v2-design.md +121 -0
- docs/evidence/cuda-v3-full-hook-sm89-2026-07-16.md +204 -0
- docs/evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md +188 -0
- docs/evidence/cuda-v3-release-kernel-manifest-sm89-2026-07-16.json +420 -0
- docs/evidence/cuda-v3-runtime-entrypoint-info-sm89-2026-07-16.json +90 -0
- docs/evidence/cuda-wsl-sm89-2026-07-15.md +175 -0
- docs/evidence/metal-hybrid-qwen36-2026-07-19.md +90 -0
- docs/evidence/metal-smoke-2026-07-15.md +336 -0
- docs/evidence/metal-smoke-schema-v4-2026-07-15.md +75 -0
- docs/protocol-v1.md +954 -0
- docs/receipt-implementation-qwen36.md +656 -0
- docs/receipt-review-remediation.md +214 -0
- docs/requirements.md +125 -0
- docs/runbook.md +493 -0
- docs/security-model.md +269 -0
- docs/state-machines.md +551 -0
- models/.gitkeep +1 -0
- patches/llama.cpp-palw-full.patch +0 -0
- patches/llama.cpp-palw-observer.patch +1792 -0
- pyproject.toml +12 -0
- receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.complete +4 -0
- receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.json +63 -0
- receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw +0 -0
- receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.complete +4 -0
- receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.json +63 -0
- receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.palw +0 -0
- receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.complete +4 -0
- receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.json +87 -0
- receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.palw +0 -0
- runtime-palw/Cargo.lock +852 -0
- runtime-palw/Cargo.toml +62 -0
- runtime-palw/cuda/CMakeLists.txt +168 -0
- runtime-palw/cuda/README.md +683 -0
- runtime-palw/cuda/abi_contract_test.cpp +723 -0
- runtime-palw/cuda/accumulator.cu +411 -0
- runtime-palw/cuda/attention_trace.cu +58 -0
- runtime-palw/cuda/cuda_trace_test.cu +522 -0
.github/workflows/palw-ci.yml
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: PALW protocol gates
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
pull_request:
|
| 6 |
+
workflow_dispatch:
|
| 7 |
+
inputs:
|
| 8 |
+
run_nvidia_experimental:
|
| 9 |
+
description: Run the non-production CUDA transport test on a labelled self-hosted runner
|
| 10 |
+
required: true
|
| 11 |
+
default: false
|
| 12 |
+
type: boolean
|
| 13 |
+
cuda_architecture:
|
| 14 |
+
description: Exact real SM architecture for the experimental CUDA build
|
| 15 |
+
required: true
|
| 16 |
+
default: 90-real
|
| 17 |
+
type: choice
|
| 18 |
+
options:
|
| 19 |
+
- 80-real
|
| 20 |
+
- 86-real
|
| 21 |
+
- 89-real
|
| 22 |
+
- 90-real
|
| 23 |
+
|
| 24 |
+
permissions:
|
| 25 |
+
contents: read
|
| 26 |
+
|
| 27 |
+
concurrency:
|
| 28 |
+
group: palw-${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
| 29 |
+
cancel-in-progress: ${{ github.event_name != 'workflow_dispatch' }}
|
| 30 |
+
|
| 31 |
+
env:
|
| 32 |
+
CARGO_TERM_COLOR: always
|
| 33 |
+
|
| 34 |
+
jobs:
|
| 35 |
+
rust-msrv:
|
| 36 |
+
name: Rust 1.81 protocol core
|
| 37 |
+
runs-on: ubuntu-24.04
|
| 38 |
+
timeout-minutes: 20
|
| 39 |
+
steps:
|
| 40 |
+
- name: Check out sources
|
| 41 |
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
| 42 |
+
with:
|
| 43 |
+
persist-credentials: false
|
| 44 |
+
- name: Install declared MSRV
|
| 45 |
+
run: rustup toolchain install 1.81.0 --profile minimal --component rustfmt,clippy
|
| 46 |
+
- name: Format
|
| 47 |
+
working-directory: runtime-palw
|
| 48 |
+
run: cargo +1.81.0 fmt --all -- --check
|
| 49 |
+
- name: Lint every target
|
| 50 |
+
working-directory: runtime-palw
|
| 51 |
+
run: cargo +1.81.0 clippy --locked --all-targets -- -D warnings
|
| 52 |
+
- name: Test every target
|
| 53 |
+
working-directory: runtime-palw
|
| 54 |
+
run: cargo +1.81.0 test --locked --all-targets
|
| 55 |
+
|
| 56 |
+
observer-clean-patch:
|
| 57 |
+
name: Pinned llama.cpp clean patch and native targets
|
| 58 |
+
runs-on: ubuntu-24.04
|
| 59 |
+
timeout-minutes: 30
|
| 60 |
+
steps:
|
| 61 |
+
- name: Check out PALW sources
|
| 62 |
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
| 63 |
+
with:
|
| 64 |
+
persist-credentials: false
|
| 65 |
+
path: palw
|
| 66 |
+
- name: Check out the exact upstream llama.cpp commit
|
| 67 |
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
| 68 |
+
with:
|
| 69 |
+
repository: ggml-org/llama.cpp
|
| 70 |
+
ref: 12127defda4f41b7679cb2477a4b0d65ee6a0c8f
|
| 71 |
+
fetch-depth: 1
|
| 72 |
+
persist-credentials: false
|
| 73 |
+
path: llama.cpp
|
| 74 |
+
- name: Verify and apply the pinned observer patch
|
| 75 |
+
working-directory: llama.cpp
|
| 76 |
+
run: |
|
| 77 |
+
source ../palw/config/runtime-pins.sh
|
| 78 |
+
test "$(git rev-parse HEAD)" = "${PALW_LLAMA_COMMIT}"
|
| 79 |
+
test "$(sha256sum ../palw/${PALW_LLAMA_PATCH_REL} | cut -d' ' -f1)" = "${PALW_LLAMA_PATCH_SHA256}"
|
| 80 |
+
git apply --check ../palw/${PALW_LLAMA_PATCH_REL}
|
| 81 |
+
git apply ../palw/${PALW_LLAMA_PATCH_REL}
|
| 82 |
+
git apply --reverse --check ../palw/${PALW_LLAMA_PATCH_REL}
|
| 83 |
+
- name: Configure deterministic CPU compile contract
|
| 84 |
+
run: >-
|
| 85 |
+
cmake -S llama.cpp -B build/llama-observer-ci
|
| 86 |
+
-DGGML_NATIVE=OFF
|
| 87 |
+
-DGGML_METAL=OFF
|
| 88 |
+
-DGGML_CUDA=OFF
|
| 89 |
+
-DGGML_CPU=ON
|
| 90 |
+
-DGGML_CPU_KLEIDIAI=OFF
|
| 91 |
+
-DGGML_ACCELERATE=OFF
|
| 92 |
+
-DGGML_BLAS=OFF
|
| 93 |
+
-DGGML_LTO=OFF
|
| 94 |
+
-DBUILD_SHARED_LIBS=ON
|
| 95 |
+
-DLLAMA_CURL=OFF
|
| 96 |
+
-DLLAMA_BUILD_TESTS=OFF
|
| 97 |
+
-DLLAMA_BUILD_EXAMPLES=OFF
|
| 98 |
+
-DLLAMA_BUILD_TOOLS=ON
|
| 99 |
+
-DLLAMA_BUILD_SERVER=ON
|
| 100 |
+
-DLLAMA_BUILD_APP=OFF
|
| 101 |
+
-DLLAMA_BUILD_UI=OFF
|
| 102 |
+
-DLLAMA_USE_PREBUILT_UI=OFF
|
| 103 |
+
-DLLAMA_OPENSSL=OFF
|
| 104 |
+
-DLLAMA_BUILD_NUMBER=10015
|
| 105 |
+
-DLLAMA_BUILD_COMMIT=12127def
|
| 106 |
+
-DCMAKE_BUILD_TYPE=Release
|
| 107 |
+
- name: Build every pinned native target
|
| 108 |
+
run: >-
|
| 109 |
+
cmake --build build/llama-observer-ci --parallel 2
|
| 110 |
+
--target llama-palw-observer llama-tokenize llama-cli llama-server
|
| 111 |
+
- name: Require the pinned runtime version and exact patch state
|
| 112 |
+
run: |
|
| 113 |
+
source palw/config/runtime-pins.sh
|
| 114 |
+
./build/llama-observer-ci/bin/llama-palw-observer --version | grep -F 'version: 10015 (12127def)'
|
| 115 |
+
git -C llama.cpp apply --reverse --check ../palw/${PALW_LLAMA_PATCH_REL}
|
| 116 |
+
|
| 117 |
+
host-abi-sanitizers:
|
| 118 |
+
name: CUDA transport host ABI (ASan + UBSan)
|
| 119 |
+
runs-on: ubuntu-24.04
|
| 120 |
+
timeout-minutes: 15
|
| 121 |
+
steps:
|
| 122 |
+
- name: Check out sources
|
| 123 |
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
| 124 |
+
with:
|
| 125 |
+
persist-credentials: false
|
| 126 |
+
- name: Configure host-only contracts
|
| 127 |
+
run: >-
|
| 128 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda-sanitize
|
| 129 |
+
-DPALW_CUDA_TRACE_ENABLE_CUDA=OFF
|
| 130 |
+
-DBUILD_TESTING=ON
|
| 131 |
+
-DCMAKE_BUILD_TYPE=Debug
|
| 132 |
+
-DCMAKE_C_FLAGS=-Wall\ -Wextra\ -Wpedantic\ -Werror\ -fsanitize=address,undefined\ -fno-omit-frame-pointer
|
| 133 |
+
-DCMAKE_CXX_FLAGS=-Wall\ -Wextra\ -Wpedantic\ -Werror\ -fsanitize=address,undefined\ -fno-omit-frame-pointer
|
| 134 |
+
-DCMAKE_EXE_LINKER_FLAGS=-fsanitize=address,undefined
|
| 135 |
+
- name: Build host-only contracts
|
| 136 |
+
run: cmake --build build/palw-cuda-sanitize --parallel
|
| 137 |
+
- name: Test ABI, codec, and closed production gate
|
| 138 |
+
env:
|
| 139 |
+
ASAN_OPTIONS: detect_leaks=1:abort_on_error=1
|
| 140 |
+
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
| 141 |
+
run: ctest --test-dir build/palw-cuda-sanitize --output-on-failure -L host
|
| 142 |
+
|
| 143 |
+
cuda-device-experimental:
|
| 144 |
+
name: Experimental CUDA device transport (not R32)
|
| 145 |
+
if: github.event_name == 'workflow_dispatch' && inputs.run_nvidia_experimental
|
| 146 |
+
runs-on: [self-hosted, linux, x64, nvidia]
|
| 147 |
+
timeout-minutes: 30
|
| 148 |
+
env:
|
| 149 |
+
CUDA_VISIBLE_DEVICES: "0"
|
| 150 |
+
steps:
|
| 151 |
+
- name: Check out sources
|
| 152 |
+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
| 153 |
+
with:
|
| 154 |
+
persist-credentials: false
|
| 155 |
+
- name: Record NVIDIA toolchain and device
|
| 156 |
+
run: |
|
| 157 |
+
nvcc --version
|
| 158 |
+
nvidia-smi
|
| 159 |
+
- name: Require the selected device to match the exact SM class
|
| 160 |
+
env:
|
| 161 |
+
EXPECTED_ARCHITECTURE: ${{ inputs.cuda_architecture }}
|
| 162 |
+
run: |
|
| 163 |
+
compute_capability="$(nvidia-smi -i 0 --query-gpu=compute_cap --format=csv,noheader,nounits | tr -d '[:space:].')"
|
| 164 |
+
actual_architecture="${compute_capability}-real"
|
| 165 |
+
if [[ "${actual_architecture}" != "${EXPECTED_ARCHITECTURE}" ]]; then
|
| 166 |
+
echo "device 0 architecture ${actual_architecture} does not match ${EXPECTED_ARCHITECTURE}" >&2
|
| 167 |
+
exit 1
|
| 168 |
+
fi
|
| 169 |
+
- name: Configure one exact CUDA architecture
|
| 170 |
+
run: >-
|
| 171 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda-device
|
| 172 |
+
-DPALW_CUDA_TRACE_ENABLE_CUDA=ON
|
| 173 |
+
-DPALW_CUDA_PRODUCTION_KERNEL_TRACE=OFF
|
| 174 |
+
-DBUILD_TESTING=ON
|
| 175 |
+
-DCMAKE_BUILD_TYPE=Release
|
| 176 |
+
-DCMAKE_CUDA_ARCHITECTURES=${{ inputs.cuda_architecture }}
|
| 177 |
+
- name: Build experimental CUDA transport
|
| 178 |
+
run: cmake --build build/palw-cuda-device --parallel
|
| 179 |
+
- name: Require both real device tests (skip 77 is a failure here)
|
| 180 |
+
run: |
|
| 181 |
+
./build/palw-cuda-device/palw_cuda_trace_device_test
|
| 182 |
+
./build/palw-cuda-device/palw_cuda_producer_device_test
|
.gitignore
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ── OS / editor ───────────────────────────────────────────────
|
| 2 |
+
.DS_Store
|
| 3 |
+
|
| 4 |
+
# ── Python env / caches ───────────────────────────────────────
|
| 5 |
+
.venv/
|
| 6 |
+
.pytest_cache/
|
| 7 |
+
.ruff_cache/
|
| 8 |
+
__pycache__/
|
| 9 |
+
*.py[cod]
|
| 10 |
+
|
| 11 |
+
# ── Rust build artifacts ──────────────────────────────────────
|
| 12 |
+
# Reproduced with `cargo build --locked` from the committed Cargo.lock.
|
| 13 |
+
runtime-palw/target/
|
| 14 |
+
runtime-palw/target-msrv/
|
| 15 |
+
**/target/
|
| 16 |
+
|
| 17 |
+
# ── CMake / native build outputs ──────────────────────────────
|
| 18 |
+
build/
|
| 19 |
+
runtime-palw/cuda/build-host-*/
|
| 20 |
+
**/CMakeCache.txt
|
| 21 |
+
**/CMakeFiles/
|
| 22 |
+
|
| 23 |
+
# ── Vendored llama.cpp ────────────────────────────────────────
|
| 24 |
+
# NOT committed (nested .git + large blobs). Reconstruct deterministically:
|
| 25 |
+
# git clone https://github.com/ggml-org/llama.cpp.git vendor/llama.cpp
|
| 26 |
+
# git -C vendor/llama.cpp checkout --detach 12127defda4f41b7679cb2477a4b0d65ee6a0c8f
|
| 27 |
+
# git -C vendor/llama.cpp apply ../../patches/llama.cpp-palw-full.patch
|
| 28 |
+
# See docs/SETUP.md.
|
| 29 |
+
vendor/
|
| 30 |
+
|
| 31 |
+
# ── Model weights (fetched at pinned revisions) ───────────────
|
| 32 |
+
# Fetch with scripts/hf_snapshot_download.py; verified against config/runtime-pins.sh hashes.
|
| 33 |
+
models/*
|
| 34 |
+
!models/.gitkeep
|
| 35 |
+
*.gguf
|
| 36 |
+
*.safetensors
|
| 37 |
+
|
| 38 |
+
# ── Runtime SQLite state (may embed sensitive execution state) ─
|
| 39 |
+
*.sqlite3
|
| 40 |
+
*.sqlite3-wal
|
| 41 |
+
*.sqlite3-shm
|
| 42 |
+
|
| 43 |
+
# ── Encrypted receipt bundles — NEVER publish ─────────────────
|
| 44 |
+
# .palw.bundle carries secret openings, signing key material, and registry
|
| 45 |
+
# snapshots (AEAD-sealed). Excluded everywhere by policy.
|
| 46 |
+
*.palw.bundle
|
| 47 |
+
|
| 48 |
+
# ── Receipts: keep only the README-referenced canonical evidence ─
|
| 49 |
+
# Track only the signed canonical receipt (.palw), public JSON (.json), and
|
| 50 |
+
# completion marker (.complete) under final-v5 / final-v6 / final-v7. Everything
|
| 51 |
+
# else (older runs, state DBs, bundles) stays local.
|
| 52 |
+
receipts/*
|
| 53 |
+
!receipts/final-v5/
|
| 54 |
+
!receipts/final-v6/
|
| 55 |
+
!receipts/final-v7/
|
| 56 |
+
receipts/final-v5/palw-state.sqlite3
|
| 57 |
+
receipts/final-v6/palw-state.sqlite3
|
| 58 |
+
receipts/final-v7/palw-state.sqlite3
|
.python-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
3.12
|
LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Apache License
|
| 3 |
+
Version 2.0, January 2004
|
| 4 |
+
http://www.apache.org/licenses/
|
| 5 |
+
|
| 6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 7 |
+
|
| 8 |
+
1. Definitions.
|
| 9 |
+
|
| 10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 12 |
+
|
| 13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 14 |
+
the copyright owner that is granting the License.
|
| 15 |
+
|
| 16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 17 |
+
other entities that control, are controlled by, or are under common
|
| 18 |
+
control with that entity. For the purposes of this definition,
|
| 19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 20 |
+
direction or management of such entity, whether by contract or
|
| 21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 23 |
+
|
| 24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 25 |
+
exercising permissions granted by this License.
|
| 26 |
+
|
| 27 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 28 |
+
including but not limited to software source code, documentation
|
| 29 |
+
source, and configuration files.
|
| 30 |
+
|
| 31 |
+
"Object" form shall mean any form resulting from mechanical
|
| 32 |
+
transformation or translation of a Source form, including but
|
| 33 |
+
not limited to compiled object code, generated documentation,
|
| 34 |
+
and conversions to other media types.
|
| 35 |
+
|
| 36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 37 |
+
Object form, made available under the License, as indicated by a
|
| 38 |
+
copyright notice that is included in or attached to the work
|
| 39 |
+
(an example is provided in the Appendix below).
|
| 40 |
+
|
| 41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 42 |
+
form, that is based on (or derived from) the Work and for which the
|
| 43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 45 |
+
of this License, Derivative Works shall not include works that remain
|
| 46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 47 |
+
the Work and Derivative Works thereof.
|
| 48 |
+
|
| 49 |
+
"Contribution" shall mean any work of authorship, including
|
| 50 |
+
the original version of the Work and any modifications or additions
|
| 51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 55 |
+
means any form of electronic, verbal, or written communication sent
|
| 56 |
+
to the Licensor or its representatives, including but not limited to
|
| 57 |
+
communication on electronic mailing lists, source code control systems,
|
| 58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 60 |
+
excluding communication that is conspicuously marked or otherwise
|
| 61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 62 |
+
|
| 63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 65 |
+
subsequently incorporated within the Work.
|
| 66 |
+
|
| 67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 72 |
+
Work and such Derivative Works in Source or Object form.
|
| 73 |
+
|
| 74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 77 |
+
(except as stated in this section) patent license to make, have made,
|
| 78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 79 |
+
where such license applies only to those patent claims licensable
|
| 80 |
+
by such Contributor that are necessarily infringed by their
|
| 81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 83 |
+
institute patent litigation against any entity (including a
|
| 84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 85 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 86 |
+
or contributory patent infringement, then any patent licenses
|
| 87 |
+
granted to You under this License for that Work shall terminate
|
| 88 |
+
as of the date such litigation is filed.
|
| 89 |
+
|
| 90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 91 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 92 |
+
modifications, and in Source or Object form, provided that You
|
| 93 |
+
meet the following conditions:
|
| 94 |
+
|
| 95 |
+
(a) You must give any other recipients of the Work or
|
| 96 |
+
Derivative Works a copy of this License; and
|
| 97 |
+
|
| 98 |
+
(b) You must cause any modified files to carry prominent notices
|
| 99 |
+
stating that You changed the files; and
|
| 100 |
+
|
| 101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 102 |
+
that You distribute, all copyright, patent, trademark, and
|
| 103 |
+
attribution notices from the Source form of the Work,
|
| 104 |
+
excluding those notices that do not pertain to any part of
|
| 105 |
+
the Derivative Works; and
|
| 106 |
+
|
| 107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 108 |
+
distribution, then any Derivative Works that You distribute must
|
| 109 |
+
include a readable copy of the attribution notices contained
|
| 110 |
+
within such NOTICE file, excluding those notices that do not
|
| 111 |
+
pertain to any part of the Derivative Works, in at least one
|
| 112 |
+
of the following places: within a NOTICE text file distributed
|
| 113 |
+
as part of the Derivative Works; within the Source form or
|
| 114 |
+
documentation, if provided along with the Derivative Works; or,
|
| 115 |
+
within a display generated by the Derivative Works, if and
|
| 116 |
+
wherever such third-party notices normally appear. The contents
|
| 117 |
+
of the NOTICE file are for informational purposes only and
|
| 118 |
+
do not modify the License. You may add Your own attribution
|
| 119 |
+
notices within Derivative Works that You distribute, alongside
|
| 120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 121 |
+
that such additional attribution notices cannot be construed
|
| 122 |
+
as modifying the License.
|
| 123 |
+
|
| 124 |
+
You may add Your own copyright statement to Your modifications and
|
| 125 |
+
may provide additional or different license terms and conditions
|
| 126 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 127 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 128 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 129 |
+
the conditions stated in this License.
|
| 130 |
+
|
| 131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 133 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 134 |
+
this License, without any additional terms or conditions.
|
| 135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 136 |
+
the terms of any separate license agreement you may have executed
|
| 137 |
+
with Licensor regarding such Contributions.
|
| 138 |
+
|
| 139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 141 |
+
except as required for reasonable and customary use in describing the
|
| 142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 143 |
+
|
| 144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 145 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 148 |
+
implied, including, without limitation, any warranties or conditions
|
| 149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 151 |
+
appropriateness of using or redistributing the Work and assume any
|
| 152 |
+
risks associated with Your exercise of permissions under this License.
|
| 153 |
+
|
| 154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 155 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 156 |
+
unless required by applicable law (such as deliberate and grossly
|
| 157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 158 |
+
liable to You for damages, including any direct, indirect, special,
|
| 159 |
+
incidental, or consequential damages of any character arising as a
|
| 160 |
+
result of this License or out of the use or inability to use the
|
| 161 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 162 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 163 |
+
other commercial damages or losses), even if such Contributor
|
| 164 |
+
has been advised of the possibility of such damages.
|
| 165 |
+
|
| 166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 169 |
+
or other liability obligations and/or rights consistent with this
|
| 170 |
+
License. However, in accepting such obligations, You may act only
|
| 171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 172 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 173 |
+
defend, and hold each Contributor harmless for any liability
|
| 174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 175 |
+
of your accepting any such warranty or additional liability.
|
| 176 |
+
|
| 177 |
+
END OF TERMS AND CONDITIONS
|
| 178 |
+
|
| 179 |
+
APPENDIX: How to apply the Apache License to your work.
|
| 180 |
+
|
| 181 |
+
To apply the Apache License to your work, attach the following
|
| 182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 183 |
+
replaced with your own identifying information. (Don't include
|
| 184 |
+
the brackets!) The text should be enclosed in the appropriate
|
| 185 |
+
comment syntax for the file format. We also recommend that a
|
| 186 |
+
file or class name and description of purpose be included on the
|
| 187 |
+
same "printed page" as the copyright notice for easier
|
| 188 |
+
identification within third-party archives.
|
| 189 |
+
|
| 190 |
+
Copyright 2026 MISAKA-BTC
|
| 191 |
+
|
| 192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 193 |
+
you may not use this file except in compliance with the License.
|
| 194 |
+
You may obtain a copy of the License at
|
| 195 |
+
|
| 196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 197 |
+
|
| 198 |
+
Unless required by applicable law or agreed to in writing, software
|
| 199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 201 |
+
See the License for the specific language governing permissions and
|
| 202 |
+
limitations under the License.
|
LICENSES/llama.cpp-MIT.txt
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
The following MIT License applies to ggml-org/llama.cpp, pinned at commit
|
| 2 |
+
12127defda4f41b7679cb2477a4b0d65ee6a0c8f. This repository does not vendor the
|
| 3 |
+
llama.cpp source, but patches/llama.cpp-palw-full.patch redistributes
|
| 4 |
+
modifications to llama.cpp source files (a read-only graph observer and
|
| 5 |
+
experimental CUDA trace hooks) under this license.
|
| 6 |
+
|
| 7 |
+
--------------------------------------------------------------------------------
|
| 8 |
+
|
| 9 |
+
MIT License
|
| 10 |
+
|
| 11 |
+
Copyright (c) 2023-2026 The ggml authors
|
| 12 |
+
|
| 13 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 14 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 15 |
+
in the Software without restriction, including without limitation the rights
|
| 16 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 17 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 18 |
+
furnished to do so, subject to the following conditions:
|
| 19 |
+
|
| 20 |
+
The above copyright notice and this permission notice shall be included in all
|
| 21 |
+
copies or substantial portions of the Software.
|
| 22 |
+
|
| 23 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 24 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 25 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 26 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 27 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 28 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 29 |
+
SOFTWARE.
|
NOTICE
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MISAKA PALW runtime for Qwen3.6-35B-A3B
|
| 2 |
+
Copyright 2026 MISAKA-BTC
|
| 3 |
+
|
| 4 |
+
This product is licensed under the Apache License, Version 2.0 (see LICENSE).
|
| 5 |
+
|
| 6 |
+
================================================================================
|
| 7 |
+
IMPORTANT — what this project is
|
| 8 |
+
================================================================================
|
| 9 |
+
This repository is a PROOF-OF-COMPUTE RUNTIME that executes an unmodified
|
| 10 |
+
upstream Qwen3.6-35B-A3B mixture-of-experts model as a local compute worker and
|
| 11 |
+
commits the execution as a signed `ComputeReceiptV1`. It does NOT train,
|
| 12 |
+
fine-tune, or otherwise modify the model, and it is NOT itself a new language
|
| 13 |
+
model. Model weights are not distributed in this repository; they are fetched at
|
| 14 |
+
pinned upstream artifacts (see config/runtime-pins.sh). Production Network
|
| 15 |
+
readiness is NOT claimed — see docs/requirements.md for the In-progress
|
| 16 |
+
requirements.
|
| 17 |
+
|
| 18 |
+
================================================================================
|
| 19 |
+
Third-party components
|
| 20 |
+
================================================================================
|
| 21 |
+
|
| 22 |
+
1. Qwen3.6-35B-A3B (huihui-ai abliterated release)
|
| 23 |
+
Base architecture Copyright Alibaba Cloud, licensed under the Apache License,
|
| 24 |
+
Version 2.0. Abliterated derivative by huihui-ai.
|
| 25 |
+
https://huggingface.co/huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated
|
| 26 |
+
https://ollama.com/huihui_ai/Qwen3.6-abliterated
|
| 27 |
+
Base metadata revision: ac18882735d037f6074a7630eb68d85db8234c25
|
| 28 |
+
GGUF artifact: Ollama huihui_ai/Qwen3.6-abliterated:35b-Claude-4.7,
|
| 29 |
+
blob sha256 1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b (Q4_K_M)
|
| 30 |
+
The upstream artifact is executed unmodified. Weights are fetched at the
|
| 31 |
+
pinned artifacts above and are not redistributed in this repository.
|
| 32 |
+
|
| 33 |
+
2. llama.cpp (ggml-org/llama.cpp)
|
| 34 |
+
Copyright (c) 2023-2026 The ggml authors
|
| 35 |
+
Licensed under the MIT License.
|
| 36 |
+
https://github.com/ggml-org/llama.cpp
|
| 37 |
+
Pinned at commit 12127defda4f41b7679cb2477a4b0d65ee6a0c8f.
|
| 38 |
+
patches/llama.cpp-palw-observer.patch redistributes MODIFICATIONS to llama.cpp
|
| 39 |
+
source (a read-only graph observer and qwen35moe loader/graph fixes required
|
| 40 |
+
to run the pinned GGUF) under the MIT License. The llama.cpp source itself is
|
| 41 |
+
not vendored in this repository; it is reconstructed from the pinned commit
|
| 42 |
+
(see docs/SETUP.md). The full MIT license text is included at
|
| 43 |
+
LICENSES/llama.cpp-MIT.txt.
|
| 44 |
+
|
| 45 |
+
Rust crate dependencies retain their own upstream licenses as declared in
|
| 46 |
+
runtime-palw/Cargo.toml and runtime-palw/Cargo.lock.
|
README.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MISAKA PALW Runtime for Qwen3.6-35B-A3B (Claude-4.7, abliterated)
|
| 2 |
+
|
| 3 |
+
> **What this is — please read first.**
|
| 4 |
+
> This repository is a **proof-of-compute runtime** that runs an **unmodified,
|
| 5 |
+
> upstream Qwen3.6-35B-A3B** mixture-of-experts model as a local worker and
|
| 6 |
+
> commits a signed `ComputeReceiptV1` of the execution. The specific worker is
|
| 7 |
+
> `huihui_ai/Qwen3.6-abliterated:35b-Claude-4.7` (the abliterated
|
| 8 |
+
> `Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus` release). Earlier revisions of this
|
| 9 |
+
> runtime targeted dense Qwen3-8B; that dense profile has since been removed and
|
| 10 |
+
> Qwen3.6-35B-A3B is now the sole supported model.
|
| 11 |
+
> - It is **not** a newly trained or fine-tuned language model. The runtime is a
|
| 12 |
+
> wrapper around the upstream model, not a distinct model.
|
| 13 |
+
> - It does **not** contain or distribute model weights — the GGUF is fetched
|
| 14 |
+
> from the Ollama registry at a pinned blob digest and base metadata from the
|
| 15 |
+
> pinned Hugging Face revision (see [`config/runtime-pins.sh`](config/runtime-pins.sh)).
|
| 16 |
+
> - The model is **abliterated** (its refusal behavior has been reduced upstream).
|
| 17 |
+
> This runtime makes no claim about the model's safety properties; it only
|
| 18 |
+
> attests *that* a pinned computation ran.
|
| 19 |
+
> - It is **not production-ready**. Several protocol requirements
|
| 20 |
+
> (R13/R21/R23/R24/R26/R27/R32/R35) are still *In progress* and production
|
| 21 |
+
> Receipt issuance is intentionally fail-closed (see
|
| 22 |
+
> [`docs/requirements.md`](docs/requirements.md)).
|
| 23 |
+
> - A single self-attested Receipt is **not** a trustless or zero-knowledge
|
| 24 |
+
> proof of physical GPU execution; the design makes no TEE/ZK claims (see
|
| 25 |
+
> [`docs/security-model.md`](docs/security-model.md)).
|
| 26 |
+
>
|
| 27 |
+
> Licensed under Apache-2.0 — see [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE).
|
| 28 |
+
> Third-party attribution (Qwen3.6-35B-A3B, llama.cpp) is in [`NOTICE`](NOTICE).
|
| 29 |
+
|
| 30 |
+
Qwen3.6-35B-A3B(MoE)をローカル計算ワーカーとして実行し、実行内容を
|
| 31 |
+
`ComputeReceiptV1` としてコミットするランタイムです。モデルの学習や
|
| 32 |
+
fine-tuning は行わず、PALW のロジックはすべてランタイム側に置きます。この
|
| 33 |
+
モデルは linear-attention(state-space / gated-delta-net)層と mixture-of-experts
|
| 34 |
+
層を組み合わせたハイブリッド構成のため、MoE/SSM 演算を**忠実な canonical operation**へ写像し
|
| 35 |
+
(`ExpertRoute`/`ExpertGemm`/`SsmConv`/`GatedDeltaNet` 等)、CU は graph 非依存の
|
| 36 |
+
**semantic ルールセット v3** で commit し、各 GEMM を実 Metal kernel dispatch へ束縛します
|
| 37 |
+
(compute-gate track M1-M5、全て実機検証済み)。
|
| 38 |
+
|
| 39 |
+
このリポジトリは次の三層を分離します。
|
| 40 |
+
|
| 41 |
+
1. `runtime-palw/`: Receipt、commitment、CU、schedule、検証、永続状態、
|
| 42 |
+
replica/audit/bond policy
|
| 43 |
+
2. `vendor/llama.cpp/`: commit を固定した Qwen 推論ランタイムと read-only graph observer
|
| 44 |
+
3. `runtime-palw/cuda/`: 実験的な CUDA V1/V2 trace transport(production 非発行)
|
| 45 |
+
|
| 46 |
+
## 固定する上流 artifact
|
| 47 |
+
|
| 48 |
+
| Artifact | Upstream | Revision / variant |
|
| 49 |
+
|---|---|---|
|
| 50 |
+
| Base metadata | `huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated` | `ac18882735d037f6074a7630eb68d85db8234c25` |
|
| 51 |
+
| Local model artifact | Ollama `huihui_ai/Qwen3.6-abliterated:35b-Claude-4.7` | blob `1dc494614bee…a671b`, `Q4_K_M` |
|
| 52 |
+
| Runtime | `ggml-org/llama.cpp` | `12127defda4f41b7679cb2477a4b0d65ee6a0c8f`(PALW patch 適用) |
|
| 53 |
+
|
| 54 |
+
`Q4_K_M` は Qwen 公式配布 artifact をそのまま使用します。量子化は
|
| 55 |
+
`runtime_class_id` と manifest に含め、別の精度・量子化とは照合しません。
|
| 56 |
+
|
| 57 |
+
## Quickstart — 自分のハードウェアで Qwen3.6 を測定する
|
| 58 |
+
|
| 59 |
+
**誰でも自分の Apple Silicon Mac で** pin された Qwen3.6-35B-A3B を実行し、署名済み Receipt を
|
| 60 |
+
発行して別 process で検証できます。現状サポートは **Metal arm64**(Apple Silicon)です。手順の正本は
|
| 61 |
+
[`docs/runbook.md`](docs/runbook.md)。前提: Apple Silicon Mac、約 24GB の unified memory 推奨、
|
| 62 |
+
約 30GB の空き、`git`/CMake/`uv`/`rustup`。
|
| 63 |
+
|
| 64 |
+
```sh
|
| 65 |
+
# 1. clean checkout から一括導入(llama.cpp @ pinned commit + PALW patch を build、
|
| 66 |
+
# Ollama registry blob から Qwen3.6 GGUF(約24GB)+ base metadata を取得・照合)
|
| 67 |
+
./scripts/install.sh
|
| 68 |
+
./scripts/verify-install.sh # 固定 artifact hash / commit / Metal offload を独立検証
|
| 69 |
+
|
| 70 |
+
# 2. audit key(exact 32 raw bytes)を output の外に一度だけ作成
|
| 71 |
+
AUDIT_KEY="$HOME/.config/misaka-palw/audit-keys/local-audit.key"
|
| 72 |
+
install -d -m 700 "$(dirname "$AUDIT_KEY")"; test ! -e "$AUDIT_KEY"
|
| 73 |
+
(umask 077 && openssl rand 32 > "$AUDIT_KEY"); chmod 600 "$AUDIT_KEY"
|
| 74 |
+
|
| 75 |
+
# 3. Receipt 発行(prompt は stdin。ここでは例として capital-of-France を 2 token 生成)
|
| 76 |
+
OUT="receipts/manual-$(date +%Y%m%d-%H%M%S)"
|
| 77 |
+
printf '%s' 'The capital of France is' | runtime-palw/target/release/palw-metal-receipt \
|
| 78 |
+
--prompt-stdin --audit-key-file "$AUDIT_KEY" --output-dir "$OUT" --n-predict 2
|
| 79 |
+
|
| 80 |
+
# 4. 別 process で検証(status=local_restored / trust_scope=embedded_local_snapshot なら成功)
|
| 81 |
+
ID=$(basename "$OUT"/*.palw .palw)
|
| 82 |
+
runtime-palw/target/release/palw-verify-bundle \
|
| 83 |
+
--receipt "$OUT/$ID.palw" --bundle "$OUT/$ID.palw.bundle" \
|
| 84 |
+
--public-json "$OUT/$ID.json" --audit-key-file "$AUDIT_KEY" \
|
| 85 |
+
--state-db "$OUT/palw-state.sqlite3"
|
| 86 |
+
```
|
| 87 |
+
|
| 88 |
+
発行される公開 metadata(`<id>.json`)には CU ルールセット v3 の `canonical_compute_units`、
|
| 89 |
+
`semantic_schedule`、実捕捉 `expert_route`、`trace_evidence=metal_kernel`(各 GEMM を実 Metal
|
| 90 |
+
kernel dispatch へ束縛)、および `mint`(常に `eligible=false`、失格理由を自己申告)が含まれます。
|
| 91 |
+
job ID/nonce/salt/signing key は実行ごとに OS CSPRNG で生成されるため Receipt ID は証跡例と一致しません。
|
| 92 |
+
参照 receipt は [`receipts/final-v7/`](receipts/final-v7)。**この Receipt は mint-grade ではなく、
|
| 93 |
+
mainnet 報酬には外部インフラが別途必要です**(下記「セキュリティ上の境界」)。
|
| 94 |
+
|
| 95 |
+
## 現在の状態
|
| 96 |
+
|
| 97 |
+
Rust core、Metal graph observer、署名済み Self Local Receipt、schema v4 SQLite
|
| 98 |
+
replay/state registry、adversarial test suite は実装・実行済みです。対象モデルを
|
| 99 |
+
dense Qwen3-8B から hybrid Qwen3.6-35B-A3B(`huihui_ai/Qwen3.6-abliterated:35b-Claude-4.7`)へ
|
| 100 |
+
移行し、Apple M1 Max(Metal、41/41 layer GPU offload)で実機ロード・推論・Receipt
|
| 101 |
+
発行・別 process 検証まで確認しています。
|
| 102 |
+
|
| 103 |
+
hybrid モデルは linear-attention(SSM / gated-delta-net)層と mixture-of-experts 層を
|
| 104 |
+
持つため、次を追加しました。
|
| 105 |
+
|
| 106 |
+
- pinned llama.cpp への qwen35moe loader/graph 互換修正(`vendor/llama.cpp/src/models/qwen35moe.cpp`、
|
| 107 |
+
PALW observer patch に同梱)。3-section mrope、`ssm_dt` naming、per-layer KV-head、
|
| 108 |
+
bundled vision/MTP tensor、per-layer attention reshape を扱う。
|
| 109 |
+
- Rust adapter の hybrid profile(`AdapterProfile::HybridQwen36A3B`): dense 演算は正確な
|
| 110 |
+
canonical operation へ**忠実に**写像する(`MUL_MAT_ID→ExpertGemm`、`ARGSORT→ExpertRoute`、
|
| 111 |
+
`SSM_CONV→SsmConv`、`GATED_DELTA_NET→GatedDeltaNet`、`L2_NORM→L2Norm`、`SUM_ROWS→Reduction`、
|
| 112 |
+
`CONCAT/CONT/CPY→TensorCopy`、`UNARY/SCALE/DIV/CLAMP→Elementwise`)。`VIEW`/`RESHAPE`/`PERMUTE`/
|
| 113 |
+
`TRANSPOSE` は layout-only、未列挙 op は fail-closed。**`Generic` 演算は廃止(M3)。**
|
| 114 |
+
- CU ルールセットは **v3 semantic**(`ComputeUnitRules::v3`): 観測 schedule は commitment-only とし、
|
| 115 |
+
canonical CU は pinned model 構造 + token 数から算出した graph 非依存の semantic 値を署名 commit。
|
| 116 |
+
dense Receipt は v1 のまま identity 不変。
|
| 117 |
+
|
| 118 |
+
Receipt 実装の詳細(observer JSONL v2、adapter 写像、CU 語彙、schedule、manifest、builder/verifier、
|
| 119 |
+
bundle、永続化、CLI 契約、実測値)は
|
| 120 |
+
[`docs/receipt-implementation-qwen36.md`](docs/receipt-implementation-qwen36.md) を正本とします。
|
| 121 |
+
|
| 122 |
+
**この Receipt は mint-grade ではありません。** `assess_mint_eligibility`(`runtime-palw/src/mint.rs`)
|
| 123 |
+
が全 receipt を `eligible=false, weight=0` と判定し、公開 JSON の `mint` ブロックに自己申告します。
|
| 124 |
+
用途はローカル自己整合 receipt / testnet 計測 / Self-Local 非報酬に限られます。compute-gate track
|
| 125 |
+
(M1-M5、全て実機検証済み)で semantic CU v3 の canonical commitment・`Generic` 廃止・canonical
|
| 126 |
+
semantic schedule 再生成・実 MoE routing 捕捉・**各 GEMM の実 Metal kernel dispatch 束縛
|
| 127 |
+
(`trace_evidence=metal_kernel`、graph-fallback から昇格)** を実装しました。ただし Metal の
|
| 128 |
+
kernel-level trace は launch-geometry 束縛であり、CUDA V3 相当の intra-kernel accumulator proof
|
| 129 |
+
ではないため mint 不適格のまま(honest labeling)。残る失格理由は「Metal kernel-launch-bound sketch,
|
| 130 |
+
not an intra-kernel accumulator proof」/ 非 network-anchored / 非 bonded の 3 件。是正計画は
|
| 131 |
+
[`docs/receipt-review-remediation.md`](docs/receipt-review-remediation.md) を参照してください。
|
| 132 |
+
|
| 133 |
+
Apple M1 Max(macOS Metal)で hybrid モデルから生成した schema-v4 E2E artifact は
|
| 134 |
+
[`receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.palw`](receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.palw)、
|
| 135 |
+
公開測定値は
|
| 136 |
+
[`receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.json`](receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.json)
|
| 137 |
+
にあります。Receipt ID は `8e2dd34b…6053f9`、verification bundle ID は `f5b8a296…dcf9db`、
|
| 138 |
+
CU ルールセットは **v3 semantic**(`43a5feef…7870ce`)、`evidence_level=gemm_traced`、
|
| 139 |
+
**`trace_evidence=metal_kernel`**。prompt 5 token + 2 生成 token の実行で observed schedule
|
| 140 |
+
13,770 件(commitment-only)・GEMM sketch 2,466 件(各々実 Metal kernel dispatch へ束縛)・
|
| 141 |
+
**canonical compute units 41,692(v3 semantic)**、`semantic_schedule`(80 expert-route ops)、
|
| 142 |
+
**実捕捉した `expert_route`(240 record)** を committ し、別 process の `palw-verify-bundle` が
|
| 143 |
+
`status=local_restored` / `trust_scope=embedded_local_snapshot` で再検証しました。
|
| 144 |
+
|
| 145 |
+
dense Qwen3-8B の schema-v4 E2E artifact(Receipt ID `eb51b08c…78131`、bundle
|
| 146 |
+
`359f1bed…096e9`、`receipts/final-v6/`)と schema-v3 artifact(`receipts/final-v5/`)は、
|
| 147 |
+
移行前の検証証跡として履歴保持します。hybrid モデルの Receipt は実行ごとに OS CSPRNG で
|
| 148 |
+
identity を生成するため ID は再現しません(`docs/runbook.md` の手順で生成・検証)。
|
| 149 |
+
|
| 150 |
+
現行 release CLI が発行する単位は、署名済み `.palw`、認証付き暗号化
|
| 151 |
+
`.palw.bundle`、検証対象の公開 JSON、schema v4 の SQLite state、最後に作成する
|
| 152 |
+
`misaka.palw.receipt-set.v2` completion marker の一式です。秘密 opening、署名済み
|
| 153 |
+
request/assignment、検証用 registry snapshot は公開 JSON ではなく暗号化 bundle に封入します。
|
| 154 |
+
公開 metadata は strict `misaka.palw.public-receipt.v2` で、unknown field を拒否し、保持する
|
| 155 |
+
artifact/observer field を authenticated bundle と照合します。`palw-verify-bundle` がこの一式を
|
| 156 |
+
別 process で復元・再検証します。上記 `final-v5` のDBは旧schema v3であり、当時の検証証跡として
|
| 157 |
+
保持します。schema v4 sourceはsilent migrationを行わず、旧DBをcurrent stateとしてopenしません。
|
| 158 |
+
|
| 159 |
+
repository-scope の設計・実装・evidence baseline はこの版で固定しますが、これは Production Network
|
| 160 |
+
readiness の完了を意味しません。R13/R21/R23/R24/R26/R27/R35 の未達gateは内部統合と外部境界を
|
| 161 |
+
[`docs/requirements.md`](docs/requirements.md) で分離し、R32 は `In progress` です。以下の CUDA
|
| 162 |
+
producer evidence は移行前 dense Qwen3-8B を対象とした legacy V2 CUDA track の測定記録で、現行 35B の
|
| 163 |
+
main path(Metal、41/41 offload)とは別系統として保持します。Windows WSL2の
|
| 164 |
+
Ubuntu 24.04、RTX 4060 Ti(sm_89)、CUDA Toolkit 13.3.1 / nvcc 13.3.73で、当時の固定 Qwen3-8B GGUFの37/37 layer CUDA
|
| 165 |
+
offloadとbatch 1 graph observerの6/6同一diagnostic streamを確認しました。さらにstandaloneの
|
| 166 |
+
producer-internal FP32 accumulator採取primitiveはsm_89 standalone device gate 7/7と20/20同一diagnostic
|
| 167 |
+
fingerprintを通過しています。vendored llama.cppのQ4_K/Q6_K MMVQ full-K pre-epilogue hookも
|
| 168 |
+
traced llama contextと同じCUDA backendへattachし、FA-off 1-token diagnostic E2Eで253 launch(Q4_K 216 /
|
| 169 |
+
Q6_K 37)を取得します。さらにFA-off eager attentionのQK GEMM 36、softmax 36、PV GEMM 36を同じ
|
| 170 |
+
request-local V3 producerへ統合し、合計361 recordを3回連続で完全取得して同一fingerprintとなること、
|
| 171 |
+
5 work classそれぞれの先頭拒否がfail closedになることを確認しました。
|
| 172 |
+
|
| 173 |
+
CUDAはadditive 184-byte V2 codec、strict Rust full-stream/dispatch/runtime binder、authority署名と
|
| 174 |
+
runtime/job/schedule/integrationへbindする将来のReceipt V2 evidence candidateに加え、FA-off attentionの
|
| 175 |
+
canonical 3-sublaunch groupingを持つ452-byte V3 schema/binderを実装しています。
|
| 176 |
+
`ComputeReceiptV1`にはこのprovenanceをcommitするfieldがないため、builderとverifierはCUDA
|
| 177 |
+
`KernelSketch`をともにfail closedで拒否します。現行deterministic profileのFA-off eager attentionには
|
| 178 |
+
V3 schema/binderに加え、実QK-score/softmax/value-aggregation work直後の同一stream collectorと
|
| 179 |
+
typed graph associationをsourceへ統合しました。実機361-launch gate、exact mangled entry point、
|
| 180 |
+
runtime CUDA attributes、DSO/fatbin/cubin/section hashを結ぶrelease manifest、361-launchを厳密にbindする
|
| 181 |
+
Receipt/RuntimeManifest/Request/Assignment V2、暗号化Bundle V2、原子的SQLite V2は実装・検証済みです。
|
| 182 |
+
ただしlive C++ smokeはdiagnostic callbackであり、authority提供のcanonical physical-layout IDから
|
| 183 |
+
production署名Receiptを発行する経路ではありません。このため
|
| 184 |
+
`PALW_CUDA_TRACE_PRODUCTION_CAPABLE=0`、`PALW_CUDA_PRODUCER_VENDOR_RUNTIME_INTEGRATED=0`、
|
| 185 |
+
`PALW_CUDA_PRODUCER_RECEIPT_MAPPING_AVAILABLE=0`、`PALW_CUDA_PRODUCER_PRODUCTION_CAPABLE=0`
|
| 186 |
+
のままproduction CUDA Receipt発行は拒否されます。
|
| 187 |
+
要件別の状態は同requirements matrixを正本とします。
|
| 188 |
+
|
| 189 |
+
Rust crate の宣言 MSRV は 1.81 です。open な transitive range が edition-2024 manifest の
|
| 190 |
+
`zeroize 1.9` / `base64ct 1.8.3` を選ぶと Cargo 1.81 が manifest を読めないため、互換版
|
| 191 |
+
`zeroize 1.8.1` / `base64ct 1.7.3` を exact pin しています。MSRV、host sanitizer、手動
|
| 192 |
+
experimental NVIDIA gate は [`.github/workflows/palw-ci.yml`](.github/workflows/palw-ci.yml)
|
| 193 |
+
にも定義しています。NVIDIA job は production approval や R32 completion を意味しません。
|
| 194 |
+
|
| 195 |
+
## 開発・検証コマンド
|
| 196 |
+
|
| 197 |
+
依存ツールとモデル取得用 Python 環境:
|
| 198 |
+
|
| 199 |
+
```sh
|
| 200 |
+
uv sync --frozen
|
| 201 |
+
```
|
| 202 |
+
|
| 203 |
+
固定 artifact、4つの llama.cpp target、Metal device を再検証:
|
| 204 |
+
|
| 205 |
+
```sh
|
| 206 |
+
./scripts/verify-install.sh
|
| 207 |
+
```
|
| 208 |
+
|
| 209 |
+
Rust 1.81 MSRV core gate と release CLI:
|
| 210 |
+
|
| 211 |
+
```sh
|
| 212 |
+
rustup toolchain install 1.81.0 --profile minimal --component rustfmt,clippy
|
| 213 |
+
cargo +1.81.0 fmt --manifest-path runtime-palw/Cargo.toml --all -- --check
|
| 214 |
+
cargo +1.81.0 clippy --manifest-path runtime-palw/Cargo.toml --locked --all-targets -- -D warnings
|
| 215 |
+
cargo +1.81.0 test --manifest-path runtime-palw/Cargo.toml --locked --all-targets
|
| 216 |
+
cargo +1.81.0 build --release --locked --manifest-path runtime-palw/Cargo.toml \
|
| 217 |
+
--bin palw-metal-receipt --bin palw-verify-bundle
|
| 218 |
+
```
|
| 219 |
+
|
| 220 |
+
現行 MSRV test result は 224 passed、2 ignored(226 discovered)です。ignored 2件は pinned Qwen
|
| 221 |
+
model と Metal observer を必要とする実モデル test で、release build と汚染した親環境を使った
|
| 222 |
+
手動 gate では 2/2 passed です。
|
| 223 |
+
|
| 224 |
+
実モデル Receipt の生成、SQLite 検査、CUDA host/device gate は
|
| 225 |
+
[`docs/runbook.md`](docs/runbook.md) に記載します。実測証跡は
|
| 226 |
+
[`docs/evidence/metal-smoke-schema-v4-2026-07-15.md`](docs/evidence/metal-smoke-schema-v4-2026-07-15.md)
|
| 227 |
+
と
|
| 228 |
+
[`docs/evidence/cuda-wsl-sm89-2026-07-15.md`](docs/evidence/cuda-wsl-sm89-2026-07-15.md)
|
| 229 |
+
と
|
| 230 |
+
[`docs/evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md`](docs/evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md)
|
| 231 |
+
と
|
| 232 |
+
[`docs/evidence/cuda-v3-full-hook-sm89-2026-07-16.md`](docs/evidence/cuda-v3-full-hook-sm89-2026-07-16.md)
|
| 233 |
+
を参照してください。旧 schema-v3 の証跡は
|
| 234 |
+
[`docs/evidence/metal-smoke-2026-07-15.md`](docs/evidence/metal-smoke-2026-07-15.md)
|
| 235 |
+
に履歴として残します。
|
| 236 |
+
|
| 237 |
+
## セキュリティ上の境界
|
| 238 |
+
|
| 239 |
+
Receipt は prompt、prompt token IDs、generated token IDs、出力 bytes、opening、private key、
|
| 240 |
+
owner salt を公開しません。Receipt CLI は `--prompt-stdin`、`--audit-key-file`、`--output-dir`
|
| 241 |
+
をすべて必須とし、prompt は UTF-8・非空・最大 1 MiB に限定します。argv で prompt を受ける
|
| 242 |
+
互換入口はありません。Qwen adapter も prompt を tokenizer/native observer の argv に置かず
|
| 243 |
+
専用 stdin pipe で渡し、通常の Receipt 実行では decoded output bytes を IPC JSONL から省略します。
|
| 244 |
+
|
| 245 |
+
audit key は output directory の外に置く exact 32-byte raw key で、同一 owner、single-link の
|
| 246 |
+
regular file、mode `0400` または `0600` を要求します。output directory は owner-only `0700`、
|
| 247 |
+
bundle と DB は `0600`、公開 `.palw` / JSON / marker は `0644` です。v2 marker は receipt ID、
|
| 248 |
+
bundle ID、公開 JSON の SHA-256 を結ぶ crash-completion signal ですが、秘密鍵付き MAC や
|
| 249 |
+
network authority の署名ではありません。marker 単独を真正性や maturity の根拠にせず、必ず
|
| 250 |
+
bundle verifier と trust policy を通します。
|
| 251 |
+
|
| 252 |
+
一方、単独ノードが発行する Receipt はそれだけでゼロ知識の計算証明になるものでは
|
| 253 |
+
ありません。PALW の不正耐性は runtime/model digest、署名、k=2 replica、future audit、
|
| 254 |
+
canary、bond/slashing を組み合わせて成立します。Metal の graph fallback は CUDA kernel
|
| 255 |
+
trace ではありません。詳細は [`docs/security-model.md`](docs/security-model.md) を参照してください。
|
| 256 |
+
|
| 257 |
+
ローカル CLI が実行ごとに生成する scheduler/worker signing key、network ID、job ID は、この
|
| 258 |
+
ローカル証跡を相互に bind するための値です。production network の登録済み scheduler、worker
|
| 259 |
+
credential、beacon service、auditor、payment/escrow authority を表すものではありません。
|
| 260 |
+
replication/future auditに加え、scheduler-signed durable canary、authority-signed bond funding/appeal/
|
| 261 |
+
decision、assignment lock/release/slash/health、authority-confirmed External settlementのschema-v4 coreは
|
| 262 |
+
統合されています。maturityは必要なassignment bondをrelease/linkし、`WorkTicketV2`はmaturity basisと
|
| 263 |
+
External weight grantをbindします。External settlementはterminal confirmation、両bond release、maturity、
|
| 264 |
+
ticketをlocal SQLite transactionでatomicにしますが、実payment railの資金移動そのものとのdistributed
|
| 265 |
+
atomicityは主張しません。これらを運用するproduction authority/governance/payment serviceはrepositoryの
|
| 266 |
+
完了範囲外です。
|
| 267 |
+
|
| 268 |
+
Work Ticket の maturity は caller が raw flag で登録できません。field/constructor が非公開の
|
| 269 |
+
`MatureEvidence` を Self Local audit の `Mature` state、Self Replicated の typed k=2 pair、または
|
| 270 |
+
authority-confirmed External settlement だけが生成し、SQLite はその証拠、`maturity_basis_id`、
|
| 271 |
+
`mature_epoch`、必要なbond release linkを検査してから一回だけ`WorkTicketV2`へ消費します。
|
SECURITY.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Security Policy
|
| 2 |
+
|
| 3 |
+
MisakaLM3-8B (the PALW runtime) is a cryptographic proof-of-compute project —
|
| 4 |
+
it uses Ed25519 signatures, XChaCha20-Poly1305 authenticated encryption, and a
|
| 5 |
+
bond/slashing protocol. We take security reports seriously.
|
| 6 |
+
|
| 7 |
+
## Reporting a vulnerability
|
| 8 |
+
|
| 9 |
+
Please report vulnerabilities **privately** — do not open a public issue.
|
| 10 |
+
|
| 11 |
+
- **Preferred:** GitHub private security advisory —
|
| 12 |
+
*Security → Advisories → Report a vulnerability* on this repository.
|
| 13 |
+
- **Email:** info@misakachain.com
|
| 14 |
+
|
| 15 |
+
Include a description, the affected files/paths, and a reproduction if possible.
|
| 16 |
+
We aim to acknowledge within a few business days.
|
| 17 |
+
|
| 18 |
+
## Scope and status
|
| 19 |
+
|
| 20 |
+
This is a **repository-scope research baseline, not a production deployment.**
|
| 21 |
+
Before reporting, please review:
|
| 22 |
+
|
| 23 |
+
- [`docs/security-model.md`](docs/security-model.md) — threat model and the
|
| 24 |
+
explicit, documented trust boundaries. In particular, a single self-attested
|
| 25 |
+
`ComputeReceiptV1` is **not** an independent cryptographic proof that a
|
| 26 |
+
specific physical GPU executed the work; the design makes no TEE/ZK claims,
|
| 27 |
+
and replica/audit tiers provide the compensating controls.
|
| 28 |
+
- [`docs/requirements.md`](docs/requirements.md) — requirements still marked
|
| 29 |
+
*In progress* (R13/R21/R23/R24/R26/R27/R32/R35); production Receipt issuance
|
| 30 |
+
is intentionally fail-closed while these are unmet.
|
| 31 |
+
|
| 32 |
+
Reports that restate these documented boundaries as if they were undisclosed
|
| 33 |
+
vulnerabilities may be closed with a pointer here, but genuine deviations from
|
| 34 |
+
the stated model are in scope and welcome.
|
config/qwen3.6-35b-a3b-claude-4.7-base-metadata.sha256
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
af5f5d80880bf4e84c3c9d079dc0cb7839be2c4c9c11de7b48045c4458212dc6 README.md
|
| 2 |
+
55d4931433fe502b794226ee7f4d206a6bdd436ac9f80eb7d8ebb4c639f9ea0c chat_template.jinja
|
| 3 |
+
5e75e90b919ad0707bdb2bc609d25946a6ef27036dc2140620d0e6ea4d0d11ec config.json
|
| 4 |
+
41b9356101ebf8e7519e150dc811f80c4226e727301fbb032b890f006ed0be83 model.safetensors.index.json
|
| 5 |
+
14932921ca485d458a04dafd8069fbb0a4505622a48208d19ed247115801385b processor_config.json
|
| 6 |
+
87a7830d63fcf43bf241c3c5242e96e62dd3fdc29224ca26fed8ea333db72de4 tokenizer.json
|
| 7 |
+
a8fd45a0a19ff87cad15511ecb8c576a6907d697018e0f55decb3d1d075a4499 tokenizer_config.json
|
config/qwen3.6-35b-a3b-claude-4.7-profile.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "misaka.palw.model-profile-pin.v2",
|
| 3 |
+
"profile_name": "Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated-Q4_K_M-Metal-arm64",
|
| 4 |
+
"model": {
|
| 5 |
+
"architecture": "Qwen3_5MoeForConditionalGeneration",
|
| 6 |
+
"model_type": "qwen3_5_moe",
|
| 7 |
+
"gguf_architecture": "qwen35moe",
|
| 8 |
+
"hidden_size": 2048,
|
| 9 |
+
"attention_heads": 16,
|
| 10 |
+
"key_value_heads": 2,
|
| 11 |
+
"layers": 40,
|
| 12 |
+
"full_attention_interval": 4,
|
| 13 |
+
"head_dim": 256,
|
| 14 |
+
"intermediate_size": 512,
|
| 15 |
+
"shared_expert_intermediate_size": 512,
|
| 16 |
+
"expert_count": 256,
|
| 17 |
+
"experts_per_token": 8,
|
| 18 |
+
"linear_key_head_dim": 128,
|
| 19 |
+
"linear_value_head_dim": 128,
|
| 20 |
+
"linear_num_key_heads": 16,
|
| 21 |
+
"linear_num_value_heads": 32,
|
| 22 |
+
"linear_conv_kernel_dim": 4,
|
| 23 |
+
"rope_theta": 10000000,
|
| 24 |
+
"partial_rotary_factor_millionths": 250000,
|
| 25 |
+
"vocabulary_size": 248320,
|
| 26 |
+
"maximum_position_embeddings": 262144,
|
| 27 |
+
"base_dtype": "bfloat16",
|
| 28 |
+
"runtime_quantization": "Q4_K_M"
|
| 29 |
+
},
|
| 30 |
+
"base_artifact": {
|
| 31 |
+
"repository": "huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated",
|
| 32 |
+
"revision": "ac18882735d037f6074a7630eb68d85db8234c25",
|
| 33 |
+
"download_scope": "metadata-only",
|
| 34 |
+
"files": [
|
| 35 |
+
{
|
| 36 |
+
"path": "README.md",
|
| 37 |
+
"sha256": "af5f5d80880bf4e84c3c9d079dc0cb7839be2c4c9c11de7b48045c4458212dc6"
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
"path": "chat_template.jinja",
|
| 41 |
+
"sha256": "55d4931433fe502b794226ee7f4d206a6bdd436ac9f80eb7d8ebb4c639f9ea0c"
|
| 42 |
+
},
|
| 43 |
+
{
|
| 44 |
+
"path": "config.json",
|
| 45 |
+
"sha256": "5e75e90b919ad0707bdb2bc609d25946a6ef27036dc2140620d0e6ea4d0d11ec"
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"path": "model.safetensors.index.json",
|
| 49 |
+
"sha256": "41b9356101ebf8e7519e150dc811f80c4226e727301fbb032b890f006ed0be83"
|
| 50 |
+
},
|
| 51 |
+
{
|
| 52 |
+
"path": "processor_config.json",
|
| 53 |
+
"sha256": "14932921ca485d458a04dafd8069fbb0a4505622a48208d19ed247115801385b"
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
"path": "tokenizer.json",
|
| 57 |
+
"sha256": "87a7830d63fcf43bf241c3c5242e96e62dd3fdc29224ca26fed8ea333db72de4"
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"path": "tokenizer_config.json",
|
| 61 |
+
"sha256": "a8fd45a0a19ff87cad15511ecb8c576a6907d697018e0f55decb3d1d075a4499"
|
| 62 |
+
}
|
| 63 |
+
]
|
| 64 |
+
},
|
| 65 |
+
"inference_artifact": {
|
| 66 |
+
"repository": "registry.ollama.ai/huihui_ai/Qwen3.6-abliterated",
|
| 67 |
+
"tag": "35b-Claude-4.7",
|
| 68 |
+
"revision": "1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b",
|
| 69 |
+
"path": "Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf",
|
| 70 |
+
"bytes": 23938321728,
|
| 71 |
+
"sha256": "1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b"
|
| 72 |
+
},
|
| 73 |
+
"runtime": {
|
| 74 |
+
"repository": "https://github.com/ggml-org/llama.cpp.git",
|
| 75 |
+
"commit": "12127defda4f41b7679cb2477a4b0d65ee6a0c8f",
|
| 76 |
+
"reported_version": "10015 (12127def)",
|
| 77 |
+
"supported_profile": "metal-arm64",
|
| 78 |
+
"build_directory": "vendor/llama.cpp/build-palw",
|
| 79 |
+
"targets": [
|
| 80 |
+
"llama-cli",
|
| 81 |
+
"llama-server",
|
| 82 |
+
"llama-tokenize",
|
| 83 |
+
"llama-palw-observer"
|
| 84 |
+
],
|
| 85 |
+
"cmake_cache": {
|
| 86 |
+
"CMAKE_BUILD_TYPE": "Release",
|
| 87 |
+
"CMAKE_OSX_ARCHITECTURES": "arm64",
|
| 88 |
+
"LLAMA_BUILD_NUMBER": "10015",
|
| 89 |
+
"LLAMA_BUILD_COMMIT": "12127def",
|
| 90 |
+
"GGML_NATIVE": "OFF",
|
| 91 |
+
"GGML_METAL": "ON",
|
| 92 |
+
"GGML_METAL_EMBED_LIBRARY": "ON",
|
| 93 |
+
"GGML_METAL_SHADER_DEBUG": "ON",
|
| 94 |
+
"GGML_CPU_KLEIDIAI": "OFF",
|
| 95 |
+
"GGML_LTO": "OFF",
|
| 96 |
+
"GGML_CUDA": "OFF",
|
| 97 |
+
"BUILD_SHARED_LIBS": "ON",
|
| 98 |
+
"GGML_CPU": "ON",
|
| 99 |
+
"GGML_ACCELERATE": "ON",
|
| 100 |
+
"GGML_BLAS": "ON",
|
| 101 |
+
"GGML_BLAS_VENDOR": "Apple",
|
| 102 |
+
"LLAMA_BUILD_TESTS": "OFF",
|
| 103 |
+
"LLAMA_BUILD_EXAMPLES": "OFF",
|
| 104 |
+
"LLAMA_BUILD_TOOLS": "ON",
|
| 105 |
+
"LLAMA_BUILD_SERVER": "ON",
|
| 106 |
+
"LLAMA_BUILD_APP": "OFF",
|
| 107 |
+
"LLAMA_BUILD_UI": "OFF",
|
| 108 |
+
"LLAMA_OPENSSL": "OFF",
|
| 109 |
+
"LLAMA_USE_PREBUILT_UI": "OFF"
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
}
|
config/runtime-pins.sh
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# shellcheck shell=bash
|
| 3 |
+
# shellcheck disable=SC2034
|
| 4 |
+
#
|
| 5 |
+
# Immutable upstream and build inputs for the supported PALW Metal profile.
|
| 6 |
+
# This file contains public identifiers only. Never add credentials here.
|
| 7 |
+
|
| 8 |
+
PALW_LLAMA_REPO_URL='https://github.com/ggml-org/llama.cpp.git'
|
| 9 |
+
PALW_LLAMA_COMMIT='12127defda4f41b7679cb2477a4b0d65ee6a0c8f'
|
| 10 |
+
PALW_LLAMA_COMMIT_SHORT='12127def'
|
| 11 |
+
PALW_LLAMA_VERSION='10015'
|
| 12 |
+
PALW_LLAMA_PATCH_REL='patches/llama.cpp-palw-observer.patch'
|
| 13 |
+
PALW_LLAMA_PATCH_SHA256='d155a88b7c11ee74f48011760cb1a37773a694c8cab28258ee108c85e2f9e02c'
|
| 14 |
+
|
| 15 |
+
# Inference artifact: the exact GGUF blob published by the Ollama registry
|
| 16 |
+
# model huihui_ai/Qwen3.6-abliterated, tag 35b-Claude-4.7. The registry blob
|
| 17 |
+
# digest is the SHA-256 of the GGUF itself, so revision == sha256 here.
|
| 18 |
+
PALW_GGUF_REGISTRY='registry.ollama.ai'
|
| 19 |
+
PALW_GGUF_REPO_ID='huihui_ai/Qwen3.6-abliterated'
|
| 20 |
+
PALW_GGUF_OLLAMA_TAG='35b-Claude-4.7'
|
| 21 |
+
PALW_GGUF_REVISION='1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b'
|
| 22 |
+
PALW_GGUF_FILENAME='Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf'
|
| 23 |
+
PALW_GGUF_SIZE='23938321728'
|
| 24 |
+
PALW_GGUF_SHA256='1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b'
|
| 25 |
+
|
| 26 |
+
PALW_BASE_REPO_ID='huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated'
|
| 27 |
+
PALW_BASE_REVISION='ac18882735d037f6074a7630eb68d85db8234c25'
|
| 28 |
+
|
| 29 |
+
PALW_LLAMA_DIR_REL='vendor/llama.cpp'
|
| 30 |
+
PALW_BUILD_DIR_REL='vendor/llama.cpp/build-palw'
|
| 31 |
+
PALW_GGUF_DIR_REL='models/Qwen3.6-abliterated-35b-Claude-4.7'
|
| 32 |
+
PALW_BASE_META_DIR_REL='models/Qwen3.6-35B-A3B-Claude-4.7-base-meta'
|
| 33 |
+
PALW_BASE_META_CHECKSUMS_REL='config/qwen3.6-35b-a3b-claude-4.7-base-metadata.sha256'
|
| 34 |
+
PALW_MODEL_PROFILE_REL='config/qwen3.6-35b-a3b-claude-4.7-profile.json'
|
| 35 |
+
|
| 36 |
+
PALW_BASE_METADATA_FILES=(
|
| 37 |
+
'README.md'
|
| 38 |
+
'chat_template.jinja'
|
| 39 |
+
'config.json'
|
| 40 |
+
'model.safetensors.index.json'
|
| 41 |
+
'processor_config.json'
|
| 42 |
+
'tokenizer.json'
|
| 43 |
+
'tokenizer_config.json'
|
| 44 |
+
)
|
| 45 |
+
|
| 46 |
+
# The first sixteen entries reproduce the successful build-palw configure
|
| 47 |
+
# command. The final five make the effective Apple/Metal defaults explicit and
|
| 48 |
+
# prevent this profile from silently becoming a CUDA build.
|
| 49 |
+
PALW_METAL_CMAKE_ARGS=(
|
| 50 |
+
'-DCMAKE_BUILD_TYPE=Release'
|
| 51 |
+
'-DCMAKE_OSX_ARCHITECTURES=arm64'
|
| 52 |
+
'-DLLAMA_BUILD_NUMBER=10015'
|
| 53 |
+
'-DLLAMA_BUILD_COMMIT=12127def'
|
| 54 |
+
'-DGGML_NATIVE=OFF'
|
| 55 |
+
'-DGGML_METAL=ON'
|
| 56 |
+
'-DGGML_METAL_EMBED_LIBRARY=ON'
|
| 57 |
+
'-DGGML_METAL_SHADER_DEBUG=ON'
|
| 58 |
+
'-DGGML_CPU_KLEIDIAI=OFF'
|
| 59 |
+
'-DGGML_LTO=OFF'
|
| 60 |
+
'-DLLAMA_BUILD_TESTS=OFF'
|
| 61 |
+
'-DLLAMA_BUILD_EXAMPLES=OFF'
|
| 62 |
+
'-DLLAMA_BUILD_TOOLS=ON'
|
| 63 |
+
'-DLLAMA_BUILD_SERVER=ON'
|
| 64 |
+
'-DLLAMA_BUILD_APP=OFF'
|
| 65 |
+
'-DLLAMA_BUILD_UI=OFF'
|
| 66 |
+
'-DLLAMA_OPENSSL=OFF'
|
| 67 |
+
'-DLLAMA_USE_PREBUILT_UI=OFF'
|
| 68 |
+
'-DGGML_CUDA=OFF'
|
| 69 |
+
'-DBUILD_SHARED_LIBS=ON'
|
| 70 |
+
'-DGGML_CPU=ON'
|
| 71 |
+
'-DGGML_ACCELERATE=ON'
|
| 72 |
+
'-DGGML_BLAS=ON'
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
PALW_METAL_CACHE_EXPECTATIONS=(
|
| 76 |
+
'CMAKE_BUILD_TYPE=Release'
|
| 77 |
+
'CMAKE_OSX_ARCHITECTURES=arm64'
|
| 78 |
+
'LLAMA_BUILD_NUMBER=10015'
|
| 79 |
+
'LLAMA_BUILD_COMMIT=12127def'
|
| 80 |
+
'GGML_NATIVE=OFF'
|
| 81 |
+
'GGML_METAL=ON'
|
| 82 |
+
'GGML_METAL_EMBED_LIBRARY=ON'
|
| 83 |
+
'GGML_METAL_SHADER_DEBUG=ON'
|
| 84 |
+
'GGML_CPU_KLEIDIAI=OFF'
|
| 85 |
+
'GGML_LTO=OFF'
|
| 86 |
+
'LLAMA_BUILD_TESTS=OFF'
|
| 87 |
+
'LLAMA_BUILD_EXAMPLES=OFF'
|
| 88 |
+
'LLAMA_BUILD_TOOLS=ON'
|
| 89 |
+
'LLAMA_BUILD_SERVER=ON'
|
| 90 |
+
'LLAMA_BUILD_APP=OFF'
|
| 91 |
+
'LLAMA_BUILD_UI=OFF'
|
| 92 |
+
'LLAMA_OPENSSL=OFF'
|
| 93 |
+
'LLAMA_USE_PREBUILT_UI=OFF'
|
| 94 |
+
'GGML_CUDA=OFF'
|
| 95 |
+
'BUILD_SHARED_LIBS=ON'
|
| 96 |
+
'GGML_CPU=ON'
|
| 97 |
+
'GGML_ACCELERATE=ON'
|
| 98 |
+
'GGML_BLAS=ON'
|
| 99 |
+
'GGML_BLAS_VENDOR=Apple'
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
PALW_BUILD_TARGETS=(
|
| 103 |
+
'llama-cli'
|
| 104 |
+
'llama-server'
|
| 105 |
+
'llama-tokenize'
|
| 106 |
+
'llama-palw-observer'
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
readonly PALW_LLAMA_REPO_URL PALW_LLAMA_COMMIT PALW_LLAMA_COMMIT_SHORT
|
| 110 |
+
readonly PALW_LLAMA_VERSION PALW_LLAMA_PATCH_REL PALW_LLAMA_PATCH_SHA256
|
| 111 |
+
readonly PALW_GGUF_REGISTRY PALW_GGUF_REPO_ID PALW_GGUF_OLLAMA_TAG
|
| 112 |
+
readonly PALW_GGUF_REVISION
|
| 113 |
+
readonly PALW_GGUF_FILENAME PALW_GGUF_SIZE PALW_GGUF_SHA256
|
| 114 |
+
readonly PALW_BASE_REPO_ID PALW_BASE_REVISION PALW_LLAMA_DIR_REL
|
| 115 |
+
readonly PALW_BUILD_DIR_REL PALW_GGUF_DIR_REL PALW_BASE_META_DIR_REL
|
| 116 |
+
readonly PALW_BASE_META_CHECKSUMS_REL PALW_MODEL_PROFILE_REL
|
| 117 |
+
readonly -a PALW_BASE_METADATA_FILES PALW_METAL_CMAKE_ARGS
|
| 118 |
+
readonly -a PALW_METAL_CACHE_EXPECTATIONS PALW_BUILD_TARGETS
|
docs/SETUP.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SETUP — リポジトリの再構築手順
|
| 2 |
+
|
| 3 |
+
このリポジトリは **ソース・ドキュメント・パッチ・検証証跡のみ** を追跡します。
|
| 4 |
+
以下は再現に必要だがサイズ・秘密の理由で追跡しない成果物と、その決定論的な再構築手順です。
|
| 5 |
+
|
| 6 |
+
| 追跡しないもの | 理由 | 再構築方法 |
|
| 7 |
+
|---|---|---|
|
| 8 |
+
| `vendor/llama.cpp/` | ネストした `.git`(~55MB)と大きな `.gguf` を含む | pinned commit + パッチ(下記 §1) |
|
| 9 |
+
| `models/**` (`*.gguf`, `*.safetensors`) | 数 GB のモデル重み | `scripts/hf_snapshot_download.py`(下記 §2) |
|
| 10 |
+
| `runtime-palw/target*/`, `build/`, `runtime-palw/cuda/build-host-*/` | ビルド生成物 | `cargo` / `cmake`(下記 §3) |
|
| 11 |
+
| `*.sqlite3`, `*.palw.bundle` | 実行時状態・暗号化された秘密素材(署名鍵・opening・registry snapshot) | ローカルにのみ保持。**公開しない** |
|
| 12 |
+
|
| 13 |
+
すべての固定値は [`../config/runtime-pins.sh`](../config/runtime-pins.sh)(公開識別子のみ、資格情報を含めない)が正本です。
|
| 14 |
+
|
| 15 |
+
---
|
| 16 |
+
|
| 17 |
+
## 1. llama.cpp(vendor)の再構築
|
| 18 |
+
|
| 19 |
+
```sh
|
| 20 |
+
# 固定リビジョンで clone
|
| 21 |
+
git clone https://github.com/ggml-org/llama.cpp.git vendor/llama.cpp
|
| 22 |
+
git -C vendor/llama.cpp checkout --detach 12127defda4f41b7679cb2477a4b0d65ee6a0c8f
|
| 23 |
+
|
| 24 |
+
# PALW の変更を適用
|
| 25 |
+
git -C vendor/llama.cpp apply ../../patches/llama.cpp-palw-full.patch
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
パッチは2種類あります。用途で選択してください。
|
| 29 |
+
|
| 30 |
+
| パッチ | 内容 | 用途 |
|
| 31 |
+
|---|---|---|
|
| 32 |
+
| `patches/llama.cpp-palw-observer.patch` | Metal read-only graph observer のみ(`scripts/install.sh` が SHA256 固定で自動適用) | サポート対象の Metal プロファイル再現 |
|
| 33 |
+
| `patches/llama.cpp-palw-full.patch` | 上記 observer に加え、**実験的 CUDA hooks**(`ggml-cuda/mmvq.cu`・`mmvf.cu`・`softmax.cu`・`ggml-cuda.cu`・`common.cuh` の trace hook、`tools/palw-mmvq-smoke/`、`llama-context` binder)を含む上位集合 | この repo の vendor 作業ツリー(CUDA 証跡採取に使用した状態)を完全再現 |
|
| 34 |
+
|
| 35 |
+
`llama.cpp-palw-full.patch` は、CUDA 証跡([`evidence/cuda-v3-full-hook-sm89-2026-07-16.md`](evidence/cuda-v3-full-hook-sm89-2026-07-16.md))を採取した際の vendor ローカル変更 21 ファイルをそのまま固めたものです。CUDA は実験的経路であり production Receipt を発行しません。
|
| 36 |
+
|
| 37 |
+
---
|
| 38 |
+
|
| 39 |
+
## 2. モデル重みの取得(固定リビジョン)
|
| 40 |
+
|
| 41 |
+
```sh
|
| 42 |
+
python scripts/hf_snapshot_download.py
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
固定値([`config/runtime-pins.sh`](../config/runtime-pins.sh)):
|
| 46 |
+
|
| 47 |
+
| Artifact | Repo | Revision | 検証 |
|
| 48 |
+
|---|---|---|---|
|
| 49 |
+
| GGUF ランタイム artifact | `huihui_ai/Qwen3.6-abliterated`(Ollama `registry.ollama.ai`, tag `35b-Claude-4.7`) | `1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b` | `Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf`, size `23938321728`, SHA256 `1dc494614bee…5a0a671b` |
|
| 50 |
+
| Base metadata | `huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated` | `ac18882735d037f6074a7630eb68d85db8234c25` | `config/qwen3.6-35b-a3b-claude-4.7-base-metadata.sha256` と照合 |
|
| 51 |
+
|
| 52 |
+
取得後、`scripts/verify_model_profile.py` がプロファイル定数と GGUF metadata を照合します。
|
| 53 |
+
|
| 54 |
+
---
|
| 55 |
+
|
| 56 |
+
## 3. ビルド & 検証
|
| 57 |
+
|
| 58 |
+
```sh
|
| 59 |
+
# Rust protocol core(MSRV 1.81 固定)
|
| 60 |
+
rustup toolchain install 1.81.0 --profile minimal --component rustfmt,clippy
|
| 61 |
+
cargo +1.81.0 fmt --manifest-path runtime-palw/Cargo.toml --all -- --check
|
| 62 |
+
cargo +1.81.0 clippy --manifest-path runtime-palw/Cargo.toml --locked --all-targets -- -D warnings
|
| 63 |
+
cargo +1.81.0 test --manifest-path runtime-palw/Cargo.toml --locked --all-targets
|
| 64 |
+
|
| 65 |
+
# llama.cpp(Metal observer)+ E2E ヘルパ
|
| 66 |
+
./scripts/install.sh
|
| 67 |
+
./scripts/verify-install.sh
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
CUDA 実験ゲート(NVIDIA 実機が必要)の詳細は [`requirements.md`](requirements.md) の R32/R35 と
|
| 71 |
+
[`evidence/`](evidence/) を参照してください。
|
| 72 |
+
|
| 73 |
+
---
|
| 74 |
+
|
| 75 |
+
## 4. 何が公開されているか(このリポジトリの範囲)
|
| 76 |
+
|
| 77 |
+
- **含む**: `runtime-palw/`(Rust protocol core + `cuda/` native ソース + tests)、`docs/`、`scripts/`、`config/`、`patches/`、`.github/`、README、`final-v5`/`final-v6` の canonical 証跡(`.palw` / `.json` / `.complete`)
|
| 78 |
+
- **含まない**: モデル重み、vendor チェックアウト、ビルド生成物、SQLite 状態、**暗号化 bundle(`.palw.bundle`)**
|
| 79 |
+
|
| 80 |
+
このスナップショットは repository-scope の設計・実装・evidence baseline を固定したものであり、
|
| 81 |
+
Production Network readiness を意味しません([`requirements.md`](requirements.md) 参照)。
|
docs/architecture.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# PALW Runtime Architecture
|
| 2 |
+
|
| 3 |
+
## 1. Scope
|
| 4 |
+
|
| 5 |
+
本実装は Qwen3.6-35B-A3B(hybrid MoE/SSM)の学習済み model artifact と PALW mining logic を分離する。
|
| 6 |
+
model artifact は読み取り専用で開き、Receipt に関係する request、assignment、nonce、
|
| 7 |
+
commitment、署名、永続状態はランタイム側が生成・検証する。model artifact へ書き戻す
|
| 8 |
+
処理は持たない。
|
| 9 |
+
|
| 10 |
+
現在、実 model からReceipt発行・検証まで接続しているのは Apple arm64 / Metal の Self Local
|
| 11 |
+
graph-fallback pathである。CUDAではWindows WSL2 Ubuntu 24.04上のRTX 4060 Ti(sm_89)へ固定Qwenを37/37 layer
|
| 12 |
+
offloadしたdiagnostic graph observerに加え、same-backend vendored MMVQ V3 1-token diagnostic E2Eも実行済みだが、
|
| 13 |
+
production Receipt issuance pathではない。
|
| 14 |
+
Metal pathもlocal issuance/verification pathであり、production scheduler、network
|
| 15 |
+
admission/transport、beacon delivery、auditor re-execution、payment rail を含む production service
|
| 16 |
+
全体が完成したという意味ではない。CUDA directory は実験 transport を実装するが、production
|
| 17 |
+
issuance gate は閉じている。
|
| 18 |
+
|
| 19 |
+
## 2. Trust and execution layers
|
| 20 |
+
|
| 21 |
+
### Layer 1 — Rust wrapper、manifest、Receipt
|
| 22 |
+
|
| 23 |
+
`palw-metal-receipt` は固定 artifact と host identity から完全な runtime manifest を作る。
|
| 24 |
+
manifest は GGUF と tokenizer artifact root、実際にロードする observer/dylib 群、llama.cpp
|
| 25 |
+
commit と local patch、CMake cache、OS/compiler/device/Metal identity、許可環境変数、固定
|
| 26 |
+
deterministic policy を binding する。
|
| 27 |
+
|
| 28 |
+
wrapper は必須の `--prompt-stdin` から最大 1 MiB の prompt を読み、argv で prompt を受ける
|
| 29 |
+
`--prompt TEXT` は実装しない。別途、output directory 外に置いた raw 32-byte key file を
|
| 30 |
+
`--audit-key-file` で必須指定する。scheduler key、署名済み `JobRequestV1` と `AssignmentV1`、
|
| 31 |
+
worker key、nonce、salt を OS CSPRNG から生成し、Qwen adapter を呼ぶ。現行 CLI が生成する
|
| 32 |
+
scheduler/worker registry は local fixture であり、production scheduler/governance registry ではない。
|
| 33 |
+
adapter が返したprompt/generated token IDsはprivate local opening、observer evidenceはverification witness
|
| 34 |
+
として保持する。どちらもcanonical Receiptには入れないが、evidenceはbundle public sectionへ含める。
|
| 35 |
+
Receipt 構築後は同じ manifest/evidence/opening で stateless verify、strict canonical round-trip、
|
| 36 |
+
secret scan を行い、成功時だけ canonical envelope、暗号化 verification bundle、公開 JSON、
|
| 37 |
+
durable DB を出力する。
|
| 38 |
+
|
| 39 |
+
worker Receipt、scheduler request/assignment、future beaconのEd25519 pathは`verify_strict`を使う。
|
| 40 |
+
worker signer、scheduler、beacon authorityのregistryはweak/small-order public keyを拒否し、opaqueな
|
| 41 |
+
verified/accepted typestateより前でkey identityとsignatureを確定する。
|
| 42 |
+
|
| 43 |
+
### Layer 2 — native graph observer と strict Qwen adapter
|
| 44 |
+
|
| 45 |
+
固定 commit の llama.cpp に `llama-palw-observer` target を加え、
|
| 46 |
+
`ggml_backend_sched_eval_callback` で実際に scheduler へ渡された graph node を順番に観測する。
|
| 47 |
+
graph mode は metadata だけを読み、sketch mode は `MUL_MAT`/`MUL_MAT_ID` の post-compute tensor
|
| 48 |
+
から固定 logical prefix を read-only copy して 256-bit の lossy graph sketch にする。raw tensor
|
| 49 |
+
値は出力しない。
|
| 50 |
+
|
| 51 |
+
adapter は shell を使わず observer を起動し、prompt を argv ではなく専用 stdin pipe へ渡す。
|
| 52 |
+
通常の Receipt 実行では `--emit-output-bytes` を指定せず、native JSONL の decoded output bytes
|
| 53 |
+
を空にする。stdout は versioned JSONL、stderr は bounded diagnostic channel として別々に読み、
|
| 54 |
+
prompt/output を error に埋め込まない。tokenizer、observer、host/source identity helper は inherited
|
| 55 |
+
environment を `env_clear` し、`LANG=C` と `LC_ALL=C` だけを復元する。host identity helper は
|
| 56 |
+
absolute executable path を使い、この完全な locale allowlist を manifest に bind する。
|
| 57 |
+
|
| 58 |
+
JSONL parser は header → event* → result の順序と一意性、schema/version、連続 event sequence、
|
| 59 |
+
Qwen3.6-35B-A3B shape/metadata、deterministic policy、41/41 full offload、prefill/decode step、token count、
|
| 60 |
+
tensor/GEMM shape、sketch width、graph-only trace claim を厳格に検査する。`MUL_MAT`、`RMS_NORM`、
|
| 61 |
+
`ROPE`、`SET_ROWS`、`SOFT_MAX`、`GLU`、`MUL`、`CONT`、`ADD`、`GET_ROWS` を versioned canonical
|
| 62 |
+
operation へ変換し、`VIEW`/`RESHAPE`/`PERMUTE` だけを layout metadata として除外する。GLU の
|
| 63 |
+
ような複合 node は複数 operation に展開する。未知 operation、未価格 operation、overflow、
|
| 64 |
+
欠落/重複 event、CUDA kernel trace を偽る claim は fail-closed である。
|
| 65 |
+
|
| 66 |
+
### Layer 3 — CUDA trace transport(R32 In progress・非発行)
|
| 67 |
+
|
| 68 |
+
CUDA directory のlegacy device observer は GEMM/attention final output の固定 tile を同一 stream 上で
|
| 69 |
+
sketch し、checked sequence、shape、tile index、V1 canonical 139-byte record、capacity/commit/copy、
|
| 70 |
+
sticky overflow、permanent poison を実装する。additive V2 transport は、declared origin、accumulator
|
| 71 |
+
stage/dtype、sketch scheme、reduction segment、producer dispatch digest を含むexact 184-byte wire
|
| 72 |
+
recordを定義し、native struct memoryやpaddingをwireとして扱わない。
|
| 73 |
+
|
| 74 |
+
これとは別にstandaloneの`palw_cuda_producer_capture_accumulator_f32`は、producerが渡すpre-epilogue
|
| 75 |
+
FP32 accumulatorを同じCUDA stream上でsketchする。exact function pointer/attribute、per-launch nonce、
|
| 76 |
+
record/mask/fault、全tile/segment coverageを検査するtrue-accumulator採取primitiveである。Windows WSL2
|
| 77 |
+
Ubuntu 24.04、
|
| 78 |
+
RTX 4060 Ti(sm_89)、CUDA Toolkit 13.3.1 / nvcc 13.3.73でstandalone/grouped CUDA CTest 8/8と
|
| 79 |
+
producer 20/20同一diagnostic fingerprintを確認した。さらにV3 captureはvendored Q4_K/Q6_K non-fused
|
| 80 |
+
MMVQ specializationのfull-K pre-epilogue位置と、FA-off QK-score/softmax/PV work直後へ接続済みである。
|
| 81 |
+
same-backend Qwen 1-token gateは253 MMVQと108 attention sublaunchの合計361/361 record、exact selected-
|
| 82 |
+
specialization attribute、3回同一diagnostic fingerprint、5 work classの選択launch拒否を確認した。
|
| 83 |
+
|
| 84 |
+
Rust側のV2 decoder/binderはunknown tagと不正なprovenance tupleを拒否し、attentionを含むunfiltered
|
| 85 |
+
全record streamを、連続launch sequence、狭義増加schedule index、canonical tile/segment order、exact
|
| 86 |
+
MMVQ/flash-attention dispatch、CUDA runtime manifestへbindする。raw recordから得る
|
| 87 |
+
`BoundCudaTranscriptV1`はdiagnostic typestateである。さらにauthority署名、network/job/execution/
|
| 88 |
+
assignment、runtime class/manifest、producer integration、operation scheduleとfull transcriptを検証した
|
| 89 |
+
場合だけ、public raw constructorを持たない`AuthorityBoundCudaTranscriptV2`からReceipt V2用
|
| 90 |
+
`AuthorityBoundCudaReceiptEvidenceV2`へproducer-accumulator GEMMを射影できる。attention recordはfull
|
| 91 |
+
transcript commitmentには残るが、GEMM evidenceには昇格しない。
|
| 92 |
+
|
| 93 |
+
現行`ComputeReceiptV1`にはauthority provenance commitmentがないため、V1 builderとverifierはCUDA
|
| 94 |
+
`KernelSketch`をともに拒否する。FlashAttention-onlyのV2 transportで表せなかった固定QwenのFA-off
|
| 95 |
+
eager attentionに対し、additive 452-byte V3 schema/binderはQK-score MMVF、masked/scaled softmax、
|
| 96 |
+
value-aggregation MMVFのcanonical 3-sublaunch bundleを実装済みであり、各実work直後の同一stream collectorと
|
| 97 |
+
typed graph associationもsourceへ統合済みである。361-launch実機E2E、exact symbol/runtime attributesを
|
| 98 |
+
DSO/fatbin/cubin/ELF sectionへ結ぶrelease manifest、complete expected tableを検証する
|
| 99 |
+
Receipt/RuntimeManifest/Request/Assignment V2、暗号化Bundle V2、SQLite V2は実装・検証済みである。
|
| 100 |
+
live C++ callbackはなおdiagnostic IDを使用するため、authority提供のcanonical operation/plan/
|
| 101 |
+
physical-layout IDからproduction署名Receiptを作る経路には接続していない。
|
| 102 |
+
|
| 103 |
+
固定Qwenは37/37 layerをCUDA offloadし、batch 1 graph observerの6/6同一diagnostic streamと、vendored
|
| 104 |
+
MMVQ/attention producerのsame-backend 361-record diagnostic E2Eを得た。これはhook coverageを証明するが、
|
| 105 |
+
production authority-connected proofではない。
|
| 106 |
+
`PALW_CUDA_TRACE_PRODUCTION_CAPABLE`、`PALW_CUDA_PRODUCER_VENDOR_RUNTIME_INTEGRATED`、
|
| 107 |
+
`PALW_CUDA_PRODUCER_RECEIPT_MAPPING_AVAILABLE`、`PALW_CUDA_PRODUCER_PRODUCTION_CAPABLE`はすべて0で、
|
| 108 |
+
`PALW_CUDA_PRODUCTION_KERNEL_TRACE=ON`はCMake configure errorのままである。したがってR32は
|
| 109 |
+
`In progress`であり、current CUDA evidenceをproduction Receiptへ昇格してはならない。
|
| 110 |
+
|
| 111 |
+
## 3. Metal execution data flow
|
| 112 |
+
|
| 113 |
+
1. model、tokenizer、observer/dylib、build/source/host identity から manifest を構築する。
|
| 114 |
+
2. pinned runtime tokenizer で prompt token IDs を確定し、nonce で salted prompt commitment を作る。
|
| 115 |
+
3. 署名済み job request と assignment を検証し、model/runtime/shape/evidence policy を固定する。
|
| 116 |
+
4. observer を fixed policy(`n_ctx=4096`、batch/ubatch/request batch/thread=1、greedy、repack/
|
| 117 |
+
Flash Attention/context shift/speculation/tensor parallel 無効)で実行する。
|
| 118 |
+
5. adapter が全 event を operation schedule hash chain、canonical CU counter、graph trace chain へ渡す。
|
| 119 |
+
6. native run 後に manifest を再構築し、実行中の model/runtime artifact 変更がないことを確認する。
|
| 120 |
+
7. token IDs、stop reason、scheduler-signed shared output nonce から output commitment を作る。
|
| 121 |
+
8. owner commitment と job/execution nullifier を作り、worker が canonical `ComputeReceiptV1` を署名する。
|
| 122 |
+
9. verifier が request/assignment/signer、manifest、policy、commitments、CU、schedule、trace、opening を検査する。
|
| 123 |
+
10. caller-owned audit key から domain-separated AEAD subkey を導出し、request/assignment、worker
|
| 124 |
+
signer record、prompt/output opening、owner salt を XChaCha20-Poly1305 bundle の private sectionへ
|
| 125 |
+
封入する。public sectionにはreceipt binding、verification epoch、scheduler key snapshot、manifest、
|
| 126 |
+
execution evidenceだけを置く。
|
| 127 |
+
11. SQLite transaction が receipt ID、execution nullifier、job/slot と original acceptance epoch を
|
| 128 |
+
一意に予約して `AcceptedReceipt` にする。
|
| 129 |
+
12. WALを`TRUNCATE` checkpointし、DB connectionをdropしてmain DBを`fsync`する。その後、Receipt、
|
| 130 |
+
bundle、公開JSONをそれぞれ`fsync`し、receipt ID、bundle ID、公開JSON SHA-256を記録するcompletion
|
| 131 |
+
markerを最後に書き、output directoryを`fsync`する。
|
| 132 |
+
13. Self Local はdurable future-audit transition、Self Replicated はtyped k=2 pair、External はauthority-
|
| 133 |
+
confirmed funded escrow settlementからだけopaque `MatureEvidence`を生成する。
|
| 134 |
+
14. bonded production pathではmaturity transactionがsourceに必要な1件または2件のassignment bondを
|
| 135 |
+
releaseし、release IDをsourceへlinkする。link数がjob classのrequired replica数と一致しなければ
|
| 136 |
+
Work Ticketを発行しない。
|
| 137 |
+
15. SQLite が証拠のnetwork/class/CU、`maturity_basis_id`、optional `weight_grant_id`、`mature_epoch`を
|
| 138 |
+
保存し、そのepoch以後にsourceを一度だけ`WorkTicketV2`へ変換する。
|
| 139 |
+
|
| 140 |
+
output directory はowned non-symlink directoryかつmode `0700`、既存ならemptyでなければならない。
|
| 141 |
+
canonical Receipt、公開JSON、completion markerは`0644`、暗号化bundleとDBは`0600`で`create_new`
|
| 142 |
+
する。cross-file write全体は単一transactionではないため、late failure時に未完成artifactが残る
|
| 143 |
+
可能性はあるが、marker-last ruleによりmarkerのないsetをverifierがcompleteとして受理しない。markerは
|
| 144 |
+
unkeyed plain textのcrash-completeness signalで、signature/AEAD authenticationではない。
|
| 145 |
+
|
| 146 |
+
## 4. Identities
|
| 147 |
+
|
| 148 |
+
`model_profile_id` は architecture、tokenizer、trained precision と runtime quantization、shape、
|
| 149 |
+
weight/tokenizer/chat-template artifact root を識別する。実際にロードした GGUF 全体の SHA-256、
|
| 150 |
+
PALW artifact root、bytes、配布 revision も manifest に含める。
|
| 151 |
+
|
| 152 |
+
`runtime_class_id` は backend、runtime commit/source patch、driver/library versions、device class、
|
| 153 |
+
quantization、context/batch/ubatch/thread、sampling、adapter mapping、trace capability を識別する。
|
| 154 |
+
|
| 155 |
+
`runtime_manifest_hash` は実行時の完全 manifest の canonical digest である。同じ class label でも
|
| 156 |
+
binary、dylib、model、source patch、CMake/host identity が違えば manifest 検証で拒否する。
|
| 157 |
+
|
| 158 |
+
`request_commitment` と `signed_assignment_id` は Receipt を scheduler authorization へ binding し、
|
| 159 |
+
`job_nullifier` と `execution_nullifier` は別 domain で replay を防ぐ。Receipt signer の public key
|
| 160 |
+
は registry で解決し、canonical body には key ID だけを置く。
|
| 161 |
+
|
| 162 |
+
`verification_bundle_id` はcomplete encrypted envelopeを識別する。bundle public sectionはworker
|
| 163 |
+
public keyやopeningを公開しない。completion marker v2はreceipt ID、bundle ID、公開JSON SHA-256を
|
| 164 |
+
記録するが、同じowner権限のwriterはJSONとmarkerを一緒に置換できる。authorityはstrict canonical
|
| 165 |
+
Receiptとauthenticated bundleにあり、markerを署名済みprotocol objectとして扱わない。
|
| 166 |
+
|
| 167 |
+
## 5. Determinism boundary
|
| 168 |
+
|
| 169 |
+
浮動小数点の bitwise determinism は runtime class 内だけで検証する。Metal/CUDA、異なる GPU、
|
| 170 |
+
driver、compiler、kernel class をまたいだ一致は要求しない。observer callback は read-only でも
|
| 171 |
+
synchronization と timing を変え得るため、observer mode/capability は runtime class の一部である。
|
| 172 |
+
|
| 173 |
+
現行 Metal Receipt の `graph_fallback` は順序・shape・logical-prefix sketch を commit するが、
|
| 174 |
+
kernel execution の暗号学的 proof ではない。Self Local の重みは future audit なしに確定しない。
|
| 175 |
+
|
| 176 |
+
## 6. Durable state and external jobs
|
| 177 |
+
|
| 178 |
+
SQLite registry は WAL、`synchronous=FULL`、foreign key、application ID、schema version 4 を検査する。
|
| 179 |
+
さらにtables/columns/foreign keys/indexだけでなく、全non-internal `sqlite_master`
|
| 180 |
+
`(type,name,tbl_name,sql)`をcanonical化したSHA3-256とcompiled goldenを照合し、同名objectのDDL mutation
|
| 181 |
+
もfail-closedにする。旧schema databaseの暗黙migrationは行わず、unclaimed nonempty DBも拒否する。
|
| 182 |
+
|
| 183 |
+
receipt、nullifier、job slot、replica pair、maturity source、Work Ticket v2、future-audit selection、signed
|
| 184 |
+
beacon provenance、audit replayに加え、authority-signed bond funding/appeal/decision、assignment bond、
|
| 185 |
+
release、slash/health、signed canary precommit、external escrow/payment command/terminalをtransactionで更新する。
|
| 186 |
+
receiptのoriginal `accepted_at_epoch`、pairの`matched_epoch`、signed beaconのepoch/provenance、audit
|
| 187 |
+
replayのaccepted epochをdurableに保持し、restart restore時にcurrent stateless verification epochと
|
| 188 |
+
区別する。
|
| 189 |
+
|
| 190 |
+
maturity source に caller-supplied raw marker を受け付ける public API はない。Self Localでは、
|
| 191 |
+
authority-verified signed future beaconを保存した後、selected replayの受理・typed projection比較・
|
| 192 |
+
terminal verdict・passing maturity sourceを一transactionで確定する。non-selected auditもwindow経過と
|
| 193 |
+
maturity sourceを一transactionで確定する。`restore_audit` は保存したsigned beaconをcaller-supplied
|
| 194 |
+
network authority registryで再検証し、selection/challengeを再計算する。selected pass/mismatch terminalは
|
| 195 |
+
beacon rowだけのrestoreを`AuditReplayRequired`で拒否し、`restore_selected_audit_with_replay`がdurable
|
| 196 |
+
audit state/challenge、canonical replay、全identity/epochを照合する。さらにprojection verdictを再計算し、
|
| 197 |
+
match bit、submission commitment、completed epochをstored terminal outcomeへ再照合する。
|
| 198 |
+
|
| 199 |
+
`MatureEvidence` のfieldと低水準constructorは非公開で、durable Self Local auditのexact mature
|
| 200 |
+
state、Self Replicated `MatchedReplicaPair`、authority-confirmed External settlementだけが生成経路である。
|
| 201 |
+
`WorkTicketV2`はsourceに加えてaudit/pair/settlementの`maturity_basis_id`と、Externalだけに必須の
|
| 202 |
+
authority-signed `weight_grant_id`をbindする。ticket発行epochの前倒しとsource再消費を拒否する。
|
| 203 |
+
|
| 204 |
+
bond authorityはnetwork-scoped Ed25519 key、validity/revocation、funding/appeal/decision capabilityを検査する。
|
| 205 |
+
verified fundingだけがdurable accountをcreditし、scheduler-signed assignmentだけがfundsをlockする。
|
| 206 |
+
bonded Receiptは`accept_bonded`でactive exact lockを要求する。auditによるpassing maturity(canaryが
|
| 207 |
+
ある場合はterminal completion以後へ遅延)とk=2 pair maturityは、必要なassignmentを同じtransactionで
|
| 208 |
+
release/linkし、ticket issuerはlink countを再検査する。
|
| 209 |
+
typed audit mismatch/timeoutとcanary mismatch/receipt timeoutはslash、pending appeal balance、worker healthを
|
| 210 |
+
同じtransactionで更新する。immutable targetを持つ複数claimのallocationはfinalized max-envelopeとpending
|
| 211 |
+
extensionへorder-independentに再計算し、v1 Equivocation追加penaltyは0である。authority-signed appealには
|
| 212 |
+
durable verification/acceptance epoch基準のdecision deadlineがあり、signed epochとaccepted epochの両方が
|
| 213 |
+
期限内のuphold/reverseか、期限経過後のdeterministic default-upholdでterminalになる。unappealed slashも
|
| 214 |
+
appeal deadline後だけfinalizeする。
|
| 215 |
+
|
| 216 |
+
canaryはscheduler-signed precommit、exact signed request/assignment、bond lockを先にdurable保存する。
|
| 217 |
+
`accept_canary`はnormal Receipt acceptanceと`ReceiptSubmitted`をatomicにし、valid openingのpassは
|
| 218 |
+
terminalだけをcommit、mismatchはworker slashへ接続する。receipt deadline欠落はworker fault/slash、
|
| 219 |
+
receipt受理後のopening deadline欠落はscheduler faultとしてworker bondをslashしない。passと
|
| 220 |
+
OpeningMissingではbondをmaturityまで保持し、pending canary中のmaturityを拒否する。terminal canaryが
|
| 221 |
+
あるsourceのmature epochはcanary completion以後へ遅延し、そのmaturity transactionだけがbondを
|
| 222 |
+
`Mature` release/linkする。External Replicatedをhidden canaryにすることはv1で禁止する。
|
| 223 |
+
|
| 224 |
+
External Replicatedはauthority-signed exact funding attestationとfunded demand-weight grantからdurable
|
| 225 |
+
escrowを作り、scheduler-signed requestとk=2 pairをbindする。local payment commandを準備した後、authority-
|
| 226 |
+
verified terminal confirmationだけがterminalを確定できる。`SettlementPrepared` transitionは両worker bondが
|
| 227 |
+
activeでpending/upheld/default-final slashなしとpreflightする。`SettlementPrepared`または
|
| 228 |
+
`RefundPrepared`以後のnon-replay slashをcut offする。
|
| 229 |
+
settlement pathはconfirmation、maturity source、
|
| 230 |
+
両worker bondのrelease/link、source consumption、`WorkTicketV2`を一つのSQLite transactionでcommitする。
|
| 231 |
+
refund pathはstate 1..3からexpiry後にpairの有無を問わず進め、terminalとeligible assignment bond releaseを
|
| 232 |
+
一つのSQLite transactionでcommitする。pending claimのbondは解決までreleaseせず、maturity/ticketを生成しない。
|
| 233 |
+
ただし実payment rail上の資金移動とSQLite transactionはdistributed atomicではない。external authorityのfinality claimとkey governanceが
|
| 234 |
+
crate外のtrust boundaryである。
|
| 235 |
+
|
| 236 |
+
## 7. Restart verification and trust scopes
|
| 237 |
+
|
| 238 |
+
verification bundle はXChaCha20-Poly1305(256-bit key、192-bit random nonce、128-bit tag)を使い、
|
| 239 |
+
canonical public section、receipt/public/nonceへbindしたAAD、encrypted private sectionを1つのstrict
|
| 240 |
+
envelopeにする。audit keyそのものとprivate signing-key seedはserializeしない。key fileはexact 32
|
| 241 |
+
bytes、nonzero、owner一致、single-link regular file、mode `0400`または`0600`を要求し、output/protected
|
| 242 |
+
artifactとのcolocation、symlink、inode alias、path raceを拒否する。
|
| 243 |
+
|
| 244 |
+
local restart APIはbundle内のembedded scheduler/worker snapshotでstateless verificationをやり直した
|
| 245 |
+
うえで、既存DB rowのcanonical Receipt、runtime instance、original acceptance epochへexact restore
|
| 246 |
+
する。CLIはReceipt/bundle/公開JSON/DBが同じowned `0700` directoryにexpected filename/modeで存在する
|
| 247 |
+
こと、marker v2とtyped公開JSON `misaka.palw.public-receipt.v2`全体がverified Receiptとauthenticated bundle manifest/evidenceへ一致
|
| 248 |
+
することも検査する。保持する`artifacts`と`observer_summary`を含む全fieldを照合し、unknown fieldは
|
| 249 |
+
objectの全階層で拒否する。DBにrowがなければinsertへfallbackしない。このmodeはlocal continuityの検証であり、
|
| 250 |
+
embedded snapshotをnetwork authorityとして第三者へ昇格しない。
|
| 251 |
+
|
| 252 |
+
default bundle restoreはoriginal acceptance時のhistorical verification epochを使う。future beacon後の
|
| 253 |
+
audit restoreには`verify_bundle_and_restore_at_epoch`を使い、caller-selected epochをhistorical値以上かつ
|
| 254 |
+
beacon以上へ進める。epoch rollbackは拒否し、durable original acceptance epochは上書きしない。このlocal
|
| 255 |
+
fresh pathはembedded key snapshotsを使い、bundle作成後のrevocationを学習できない。productionではcurrent
|
| 256 |
+
external trust rootsを必須にする`verify_bundle_and_restore_at_epoch_with_trust`を使う。現行
|
| 257 |
+
`palw-verify-bundle` CLIはdefault historical pathだけを呼び、fresh epochはlibrary/service APIで指定する。
|
| 258 |
+
|
| 259 |
+
第三者向けstateless APIはexpected network、外部scheduler registry、外部worker registry、独立に
|
| 260 |
+
approvedされたmanifest hashを必須にし、embedded snapshotとのexact一致も検査する。default APIは
|
| 261 |
+
historical epoch、`verify_bundle_stateless_at_epoch_with_trust`はrollbackしないcaller-selected fresh epochで
|
| 262 |
+
署名/validityを検証する。このstateless pathはDB acceptanceを行わない。既存DB continuityも同時に必要な
|
| 263 |
+
production restartは`verify_bundle_and_restore_at_epoch_with_trust`を使う。それでもnetwork admissionは
|
| 264 |
+
別のservice decisionである。
|
| 265 |
+
|
| 266 |
+
## 8. Build and CI boundary
|
| 267 |
+
|
| 268 |
+
Rust protocol core は edition 2021、MSRV 1.81 を宣言する。Cargo 1.81 が edition-2024 manifest を
|
| 269 |
+
読めない transitive-resolution drift を防ぐため、crypto graph の `zeroize 1.8.1` と
|
| 270 |
+
`base64ct 1.7.3` を exact pin し、Clippy/test/release build は lockfile を必須にする。
|
| 271 |
+
|
| 272 |
+
CI は push/PR の pinned llama.cpp clean-checkout patch apply/CPU target build gate、Rust 1.81 all-target
|
| 273 |
+
gate、Linux host ABI sanitizer gateと、手動self-hosted NVIDIA experimental gateに分離する。NVIDIA jobは
|
| 274 |
+
skip code 77をfailureとするが、production capabilityを無効のまま実験transportだけをtestする。
|
| 275 |
+
したがってCI successとR32 production acceptanceは別のstateであり、workflowやhost fixtureからCUDA
|
| 276 |
+
Receipt発行権限を推論しない。
|
| 277 |
+
|
| 278 |
+
現行sourceのRust all-target gateは224 passed / 2 ignored(226 discovered)である。WSL sm_89ではstandalone/grouped CUDA
|
| 279 |
+
suite 8/8とproducer device binary 20/20同一fingerprintに加え、vendored MMVQ/attention same-backend
|
| 280 |
+
Qwen diagnostic E2Eで361/361 record、3回同一fingerprint、5 work-class negativeを確認した。exact
|
| 281 |
+
release manifestも最終DSOに対してcreate/verify一致した。この実測はexperimental hook goalを完了するが、
|
| 282 |
+
production authority acceptanceではない。
|
| 283 |
+
|
| 284 |
+
production scheduler/network transport、governance-backed scheduler/worker/beacon/bond/external key
|
| 285 |
+
distribution、finalized beacon delivery、independent auditor execution/opening delivery、実payment railと
|
| 286 |
+
authority serviceはこのrepositoryに含まれない。durable coreへ自動接続済みのslash proofはaudit mismatch/
|
| 287 |
+
timeoutとcanary mismatch/receipt timeoutであり、invalid-manifest、equivocation、duplicate-executionの
|
| 288 |
+
production proof constructor/orchestrationは未統合である。CUDAのstandalone true-accumulator primitive、vendored
|
| 289 |
+
MMVQ/FA-off attention hook、same-backend 361-launch diagnostic E2E、release manifest、Receipt/Bundle/
|
| 290 |
+
SQLite V2は成立した。残るproduction範囲は、authority-derived canonical IDを使うlive callback、
|
| 291 |
+
deployed trust root、signed Receipt発行、独立restoreまでのfull-stream production E2Eである。
|
docs/cuda-receipt-v2-design.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CUDA Producer Transcript → Receipt V2 設計
|
| 2 |
+
|
| 3 |
+
## 現在の安全境界
|
| 4 |
+
|
| 5 |
+
CUDA transport V2 の `ProducerAccumulator` は自己申告tagであり、それ単体はproducer由来の証明ではない。
|
| 6 |
+
また `ComputeReceiptV1` にはauthority証跡をcommitするfieldがない。このためRust側でも次をhard gateとする。
|
| 7 |
+
|
| 8 |
+
- CUDA `KernelSketch` を `build_signed_receipt` へ渡してもV1 Receiptを発行しない。
|
| 9 |
+
- workerがV1 bodyを手組み・署名してもstateless verifierが拒否する。
|
| 10 |
+
- Metal/開発用 `GraphFallback` とCUDA production provenanceは別のまま維持する。
|
| 11 |
+
|
| 12 |
+
## 実装済みtypestate
|
| 13 |
+
|
| 14 |
+
```text
|
| 15 |
+
RawCudaTraceRecordV2
|
| 16 |
+
-> bind_cuda_trace_v2
|
| 17 |
+
BoundCudaTranscriptV1
|
| 18 |
+
-> authority署名 + registry/runtime/job/schedule/full-stream検証
|
| 19 |
+
AuthorityBoundCudaTranscriptV2
|
| 20 |
+
-> deterministic mapping v1
|
| 21 |
+
AuthorityBoundCudaReceiptEvidenceV2
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
`AuthorityBoundCudaTranscriptV2` と `AuthorityBoundCudaReceiptEvidenceV2` にはpublic raw constructorがない。
|
| 25 |
+
authority verificationは次を同時にbindする。
|
| 26 |
+
|
| 27 |
+
- network、job nullifier、execution nullifier
|
| 28 |
+
- signed assignment ID、runtime instance ID、assignment epoch範囲
|
| 29 |
+
- exact runtime class ID、complete runtime manifest hash
|
| 30 |
+
- operation schedule commitmentと全scheduled GEMM/attentionのexact coverage
|
| 31 |
+
- full unfiltered CUDA transcript commitment
|
| 32 |
+
- reviewed producer hook source/binary、entry-point table、accumulator extraction policyから成るintegration ID
|
| 33 |
+
- authority keyのnetwork、validity、revocation、exact integration/runtime approval
|
| 34 |
+
|
| 35 |
+
射影時はproducer-accumulator GEMMだけを `KernelSketch` eventへ変換する。attention final-output recordは
|
| 36 |
+
GEMM evidenceへ昇格させないが、signed full-transcript commitmentには残る。raw `u64` sketch laneはbit patternを
|
| 37 |
+
保ったまま既存のcanonical `i64` laneへ写像する。
|
| 38 |
+
|
| 39 |
+
vendored llama.cppのQ4_K/Q6_K MMVQ producerはV3 full-K pre-epilogue hookへ接続済みである。
|
| 40 |
+
same-backend Qwen 1-token diagnostic E2Eは253/253 record、3回同一fingerprintと選択launch拒否の
|
| 41 |
+
fail-closedを確認した。続いてFA-off QK/softmax/PVも接続し、253 MMVQ + 108 attention = 361 recordを
|
| 42 |
+
3回同一fingerprintで取得した。Q4/Q6/QK/softmax/PV各先頭の拒否もfail closedである。
|
| 43 |
+
|
| 44 |
+
## V2の非互換とV3 schemaの現状
|
| 45 |
+
|
| 46 |
+
現行PALW deterministic Qwen profileは `flash_attention=false` で、実scheduleはeager/decomposed
|
| 47 |
+
`Attention` を含む。一方、CUDA V2が表現できるattention dispatchは
|
| 48 |
+
`CudaDispatchV1::LlamaFlashAttention` だけである。`bind_cuda_trace_v2` はattention launchがあるのに
|
| 49 |
+
runtimeがFA-offなら拒否し、authority layerは全scheduled GEMM/attention indexのexact coverageを要求する。
|
| 50 |
+
|
| 51 |
+
したがって次のどちらも通らない。
|
| 52 |
+
|
| 53 |
+
- `LlamaFlashAttention` recordをFA-off runtimeへbindする。
|
| 54 |
+
- attention recordを省略してGEMMだけをauthority-bound transcriptにする。
|
| 55 |
+
|
| 56 |
+
これはlegacy V2の意図したfail-closed状態であり、現行V2 candidateをproduction Qwen Receiptに
|
| 57 |
+
使用可能とは扱わない。この非互換に対し、additive V3は452-byte record、eager/decomposed attentionの
|
| 58 |
+
exact shape/stage、1 scheduled `Attention`に対するQK-score MMVF、masked/scaled softmax、
|
| 59 |
+
value-aggregation MMVFのcanonical 3-sublaunch grouping、strict schedule/runtime binderを実装済みである。
|
| 60 |
+
|
| 61 |
+
実eager-attention 3 entry point直後のV3 collectorとtyped graph associationはsourceへ接続済みである。
|
| 62 |
+
361-launch実機E2E、strict expected table、actual runtime attributes、exact entry symbolとDSO/fatbin/cubinを
|
| 63 |
+
結ぶrelease-manifest照合、Receipt V2のstateless bindingは実装・検証済みである。ただしlive C++ smokeは
|
| 64 |
+
diagnostic IDを生成し、authority-derived canonical physical-layout IDを受け取るproduction callbackではない。
|
| 65 |
+
したがってcurrent smokeをproduction Qwen Receiptに使用可能とは扱わない。flash attentionをproduction
|
| 66 |
+
deterministic policyで明示的に有効化する
|
| 67 |
+
別案でも、再現性・algorithm identity・schedule/CU semanticsを別runtime classとして再承認する必要がある。
|
| 68 |
+
|
| 69 |
+
## 実装済みReceipt V2 schema
|
| 70 |
+
|
| 71 |
+
現行V1へauthority証跡を後付けすると、証跡を捨てても同じReceipt body/rootを作れてしまう。そこで次を
|
| 72 |
+
V1とtype-confusionしない新しいconsensus schemaとして実装した。
|
| 73 |
+
|
| 74 |
+
1. `ComputeReceiptV2.receipt_version = 2`
|
| 75 |
+
2. `trace_provenance_kind`(少なくとも `NoneOrGraph` / `CudaProducerAuthorityV1`)
|
| 76 |
+
3. `trace_provenance_commitment`
|
| 77 |
+
4. `RuntimeManifestV2` の `producer_integration_id` と `trace_provenance_policy_id`
|
| 78 |
+
5. scheduler request/assignmentが選ぶrequired provenance policy
|
| 79 |
+
6. `SignedReceiptV2` envelope discriminator(V1 bodyとのtype confusionを避ける)
|
| 80 |
+
7. FA-off用eager/decomposed attention dispatchとsublaunch grouping
|
| 81 |
+
|
| 82 |
+
`trace_provenance_commitment` は実装済みのdomain-separated valueで、次をcommitする。
|
| 83 |
+
|
| 84 |
+
- authority attestation ID / authority key ID
|
| 85 |
+
- producer integration ID
|
| 86 |
+
- full bound transcript commitment
|
| 87 |
+
- mapping version
|
| 88 |
+
- projected trace scheme ID / root / event count
|
| 89 |
+
|
| 90 |
+
verification bundle V2はsigned authority envelope、raw V3 stream、expected launch table、six-entry release
|
| 91 |
+
table、producer integration descriptorを含み、secret openingをXChaCha20-Poly1305で暗号化する。verifierは
|
| 92 |
+
current registryを外部trust rootとして解決し、公式`verify_stateless_v2`でtypestateを再構築する。
|
| 93 |
+
SQLite V2はcomplete proof bytes、provenance commitment、network epoch watermarkを原子的に保存し、restart時に
|
| 94 |
+
body-to-proof binding、replay、rollback、exact restore rowを再検査する。
|
| 95 |
+
|
| 96 |
+
matcher、audit、maturity、WorkTicketはV1/V2を暗黙に同一視せず、V2 production policyが要求されたjobでは
|
| 97 |
+
authority-bound provenanceのstateless/durable verification完了を必須にする。
|
| 98 |
+
|
| 99 |
+
## 実装済みadversarial gate
|
| 100 |
+
|
| 101 |
+
- missing / duplicate / reordered / metadata-mutated raw record拒否
|
| 102 |
+
- exact dispatch、SM、kernel binary/algorithm identity差分拒否
|
| 103 |
+
- forged authority signature、unknown/revoked/out-of-window key拒否
|
| 104 |
+
- cross-network / cross-job / cross-assignment / cross-runtime replay拒否
|
| 105 |
+
- runtime class、manifest、producer integration、schedule、transcript差分拒否
|
| 106 |
+
- scheduled GEMM/attentionの欠落拒否
|
| 107 |
+
- FA-off runtimeへの唯一のV2 attention dispatch (`LlamaFlashAttention`) binding拒否
|
| 108 |
+
- final-output GEMMのproducer evidence昇格拒否
|
| 109 |
+
- raw CUDA `KernelSketch` のV1 builder/verifier bypass拒否
|
| 110 |
+
|
| 111 |
+
## 残るproduction blocker
|
| 112 |
+
|
| 113 |
+
- authority registry/governance/KMSサービスとproduction key lifecycle
|
| 114 |
+
- authority-derived canonical operation/plan/physical-layout IDをlive C++ approval callbackへ渡すbridge
|
| 115 |
+
- live raw transcriptから署名Receipt V2を発行し、deployed trust rootで独立restoreするproduction E2E
|
| 116 |
+
- checked-in release manifestとpolicyを承認するgovernance lifecycle
|
| 117 |
+
- NVIDIA実機でのfull-stream fault injectionと認可済みrepeatability/reproducibility matrix
|
| 118 |
+
|
| 119 |
+
authority署名は「登録authorityがこのexact transcriptとintegrationを承認した」ことを証明するが、authority自身が
|
| 120 |
+
producer内部値を正しく観測したことを純粋なEd25519署名だけで暗号学的に証明するものではない。脅威モデルが
|
| 121 |
+
authority compromiseを含む場合は、GPU/host attestation、TEE、または独立再実行proofを追加する。
|
docs/evidence/cuda-v3-full-hook-sm89-2026-07-16.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CUDA V3 full Qwen hook and V2 receipt evidence — SM89 — 2026-07-16
|
| 2 |
+
|
| 3 |
+
## Scope and status
|
| 4 |
+
|
| 5 |
+
This is the repository evidence for the completed experimental CUDA goal on a
|
| 6 |
+
Windows/WSL2 RTX 4060 Ti host:
|
| 7 |
+
|
| 8 |
+
- a real pinned Qwen3-8B Q4_K_M model executes all 253 quantized MMVQ launches
|
| 9 |
+
for one evaluated token through the vendored V3 producer hook;
|
| 10 |
+
- the flash-attention-off path executes all 72 attention GEMMs (36 QK and 36
|
| 11 |
+
PV), plus 36 grouped softmax capture launches, through the vendored producer;
|
| 12 |
+
- the exact selected CUDA entry points, runtime function attributes, containing
|
| 13 |
+
cubins, fatbin, and loaded DSO are content-addressed by a strict release
|
| 14 |
+
manifest;
|
| 15 |
+
- Receipt, RuntimeManifest, Request/Assignment, encrypted Bundle, and atomic
|
| 16 |
+
SQLite persistence V2 bind and reverify the complete 361-launch profile; and
|
| 17 |
+
- production issuance remains deliberately unavailable. All capability macros
|
| 18 |
+
remain zero and the production CMake configuration fails closed.
|
| 19 |
+
|
| 20 |
+
This evidence does not claim a production CUDA Receipt. The live smoke result
|
| 21 |
+
explicitly reports `diagnostic_only=true` and `receipt_authority=false`. It also
|
| 22 |
+
does not claim multi-token/KV-continuation, FA-on, another GPU architecture, or
|
| 23 |
+
another model/weight profile.
|
| 24 |
+
|
| 25 |
+
No Tailscale address, SSH credential, GPU UUID, or signing secret is recorded in
|
| 26 |
+
this artifact.
|
| 27 |
+
|
| 28 |
+
## Fixed model, host, and build
|
| 29 |
+
|
| 30 |
+
| Item | Recorded value |
|
| 31 |
+
| --- | --- |
|
| 32 |
+
| Host | Windows 11 / WSL2 Ubuntu |
|
| 33 |
+
| GPU | NVIDIA GeForce RTX 4060 Ti |
|
| 34 |
+
| CUDA architecture | `sm_89` |
|
| 35 |
+
| CUDA compiler | NVCC 13.3.73 |
|
| 36 |
+
| Model | `Qwen3-8B-Q4_K_M.gguf` |
|
| 37 |
+
| Model SHA-256 | `d98cdcbd03e17ce47681435b5150e34c1417f50b5c0019dd560e4882c5745785` |
|
| 38 |
+
| Build type | Release |
|
| 39 |
+
| Build directory | `/root/qwen-8.0/build/llama-palw-full-sm89-v2` |
|
| 40 |
+
| Loaded CUDA DSO | `bin/libggml-cuda.so` |
|
| 41 |
+
| Loaded DSO SHA-256 | `389bda6116c50eea8aebb9e1fcca1cc0145ab7245cb01d688024856c947f8e6f` |
|
| 42 |
+
|
| 43 |
+
The final CMake cache fixes `CMAKE_CUDA_ARCHITECTURES=89`, `GGML_CUDA=ON`,
|
| 44 |
+
`GGML_CUDA_PALW_TRACE=ON`, `GGML_CUDA_FA=OFF`, `GGML_CUDA_GRAPHS=OFF`, and
|
| 45 |
+
`GGML_CUDA_NCCL=OFF`.
|
| 46 |
+
|
| 47 |
+
## Full real-model launch gate
|
| 48 |
+
|
| 49 |
+
The final smoke executable loaded the real 5,027,783,488-byte model, attached a
|
| 50 |
+
fresh request-local producer context, disabled flash attention, evaluated one
|
| 51 |
+
token at position zero, finalized the stream, and canonically encoded every V3
|
| 52 |
+
record.
|
| 53 |
+
|
| 54 |
+
Three independent positive invocations with the release-manifest cubin digests
|
| 55 |
+
all exited successfully with the following identical result:
|
| 56 |
+
|
| 57 |
+
| Field | Run 1 | Run 2 | Run 3 |
|
| 58 |
+
| --- | ---: | ---: | ---: |
|
| 59 |
+
| Total launches | 361 | 361 | 361 |
|
| 60 |
+
| Accepted | 361 | 361 | 361 |
|
| 61 |
+
| Records | 361 | 361 | 361 |
|
| 62 |
+
| Committed after finalize | 361 | 361 | 361 |
|
| 63 |
+
| Quantized MMVQ | 253 | 253 | 253 |
|
| 64 |
+
| Q4_K MMVQ | 216 | 216 | 216 |
|
| 65 |
+
| Q6_K MMVQ | 37 | 37 | 37 |
|
| 66 |
+
| Attention QK GEMM | 36 | 36 | 36 |
|
| 67 |
+
| Attention softmax | 36 | 36 | 36 |
|
| 68 |
+
| Attention PV GEMM | 36 | 36 | 36 |
|
| 69 |
+
| Canonical-record FNV-1a 64 | `22f3a57e3640a8c6` | `22f3a57e3640a8c6` | `22f3a57e3640a8c6` |
|
| 70 |
+
|
| 71 |
+
Thus the 72 FA-off attention GEMMs are exactly the 36 QK plus 36 PV launches.
|
| 72 |
+
The additional 36 softmax launches make the complete attention producer stream
|
| 73 |
+
108 records and the complete MMVQ-plus-attention stream 361 records.
|
| 74 |
+
|
| 75 |
+
The FNV-1a value is a compact same-stack diagnostic reproducibility check. The
|
| 76 |
+
cryptographic artifact identity is supplied separately by the SHA-256 release
|
| 77 |
+
manifest; FNV-1a is not used as receipt authority.
|
| 78 |
+
|
| 79 |
+
## Actual CUDA entry-point authority manifest
|
| 80 |
+
|
| 81 |
+
The release manifest was generated on the RTX host from the final loaded DSO
|
| 82 |
+
using CUDA 13.3 `cuobjdump`. The manifest parser independently extracts the
|
| 83 |
+
embedded cubins, requires an exact mangled-symbol match, parses the raw ELF
|
| 84 |
+
sections, and hashes the containing cubin plus symbol-scoped text and
|
| 85 |
+
`.nv.info` sections.
|
| 86 |
+
|
| 87 |
+
| Entry | Cubin SHA-256 | Registers | Max threads | Static shared bytes | Local bytes |
|
| 88 |
+
| --- | --- | ---: | ---: | ---: | ---: |
|
| 89 |
+
| Q4_K MMVQ | `3f9bfb88b5898b7d59b7fc39a01d7fda3b8ce4e270605b2d4cf29465907dfb64` | 40 | 128 | 384 | 0 |
|
| 90 |
+
| Q6_K MMVQ | `3f9bfb88b5898b7d59b7fc39a01d7fda3b8ce4e270605b2d4cf29465907dfb64` | 40 | 128 | 384 | 0 |
|
| 91 |
+
| Attention QK | `f04b5d1fb574c3558384bb37f261bc63be926cc0bef584b7a527977bd31b7237` | 40 | 1024 | 0 | 0 |
|
| 92 |
+
| Attention softmax | `31d368e4cffc8668bf678aebae93fd79d9b5a4fed626b2a1ce615efa77ce6903` | 22 | 1024 | 0 | 0 |
|
| 93 |
+
| Attention PV | `f04b5d1fb574c3558384bb37f261bc63be926cc0bef584b7a527977bd31b7237` | 34 | 1024 | 0 | 0 |
|
| 94 |
+
| Grouped collector | `09bb6b85776ba02de3b9e5aa457d090208ab25cb276ed63021020ebadc804435` | 44 | 1024 | 0 | 0 |
|
| 95 |
+
|
| 96 |
+
Every entry reported SM architecture, binary version, and PTX version 89. The
|
| 97 |
+
Q4/Q6 entries share one containing cubin, as do QK/PV; their exact symbols and
|
| 98 |
+
scoped ELF sections remain distinct.
|
| 99 |
+
|
| 100 |
+
The canonical artifacts are:
|
| 101 |
+
|
| 102 |
+
- [`cuda-v3-release-kernel-manifest-sm89-2026-07-16.json`](cuda-v3-release-kernel-manifest-sm89-2026-07-16.json)
|
| 103 |
+
- [`cuda-v3-runtime-entrypoint-info-sm89-2026-07-16.json`](cuda-v3-runtime-entrypoint-info-sm89-2026-07-16.json)
|
| 104 |
+
|
| 105 |
+
Recorded identities:
|
| 106 |
+
|
| 107 |
+
| Identity | Value |
|
| 108 |
+
| --- | --- |
|
| 109 |
+
| Release manifest ID (SHA3-256 protocol domain) | `4ededc7c257e13becbf74ebeecdff6c7bfe8ba84d550a6e07aa6cca52d9c7ce7` |
|
| 110 |
+
| DSO `.nv_fatbin` SHA-256 | `0654f8f423f059dccb94abf098fca2b47f106dcc6581f575756e6a985c6fa35c` |
|
| 111 |
+
| Loaded DSO SHA-256 | `389bda6116c50eea8aebb9e1fcca1cc0145ab7245cb01d688024856c947f8e6f` |
|
| 112 |
+
|
| 113 |
+
Creating and then independently verifying the manifest against the same final
|
| 114 |
+
DSO both returned the exact manifest ID above. The checked-in manifest bytes
|
| 115 |
+
have SHA-256
|
| 116 |
+
`849917d9def741ed7920661a57fbcdc16cb32e0c18836d1f454aa0c3e66133bf`,
|
| 117 |
+
identical to the file copied back from the RTX host.
|
| 118 |
+
|
| 119 |
+
The checked-in artifact is also a compile-time Rust integration fixture. The
|
| 120 |
+
strict `CudaReleaseKernelManifestV1` decoder validates its exact six-entry
|
| 121 |
+
authority requirement table, and the Receipt V2 end-to-end test uses that real
|
| 122 |
+
validated table to build, sign, and reverify the complete 361-launch receipt at
|
| 123 |
+
the next epoch. This gate also records the valid CUDA packaging case where an
|
| 124 |
+
extracted, uncompressed cubin is larger than the compressed `.nv_fatbin` bytes;
|
| 125 |
+
all cubins remain nonempty and every scoped section is bounded by its expanded
|
| 126 |
+
cubin size.
|
| 127 |
+
|
| 128 |
+
## Fail-closed launch gates
|
| 129 |
+
|
| 130 |
+
Five negative invocations rejected the first occurrence of each work class.
|
| 131 |
+
Every invocation stopped llama decoding with the expected failure status; no
|
| 132 |
+
rejected or later launch was accepted.
|
| 133 |
+
|
| 134 |
+
| Reject index | Expected class | Accepted before rejection | Records before rejection |
|
| 135 |
+
| ---: | --- | ---: | ---: |
|
| 136 |
+
| 0 | Q4_K | 0 | 0 |
|
| 137 |
+
| 1 | Q6_K | 1 | 1 |
|
| 138 |
+
| 3 | Attention QK | 3 | 3 |
|
| 139 |
+
| 4 | Attention softmax | 4 | 4 |
|
| 140 |
+
| 5 | Attention PV | 5 | 5 |
|
| 141 |
+
|
| 142 |
+
Each result reported `status=expected_failure` and the matching
|
| 143 |
+
`rejected_class`. This complements the standalone CUDA device fault tests and
|
| 144 |
+
proves that every vendored work path honors the request-local approval boundary.
|
| 145 |
+
|
| 146 |
+
## Receipt, manifest, bundle, and persistence V2
|
| 147 |
+
|
| 148 |
+
The Rust V2 flow is deliberately distinct from V1 and binds all of the
|
| 149 |
+
following before producing a verified typestate:
|
| 150 |
+
|
| 151 |
+
- signed RuntimeManifest, Request, Assignment, and Receipt V2 domains;
|
| 152 |
+
- network, epoch, authority lifetime, revocation, assignment, worker, job, and
|
| 153 |
+
execution identities;
|
| 154 |
+
- the approved six-entry release table, exact cubin digests, work/capture roles,
|
| 155 |
+
runtime CUDA attributes, and launch geometry;
|
| 156 |
+
- the exact ordered 361-launch transcript and its 216/37/36/36/36 class counts;
|
| 157 |
+
- Qwen3-8B, Q4_K_M, SM89, FA-off, batch-one, one-token policy;
|
| 158 |
+
- schedule, canonical compute units, output commitment, and stable projected
|
| 159 |
+
authority provenance.
|
| 160 |
+
|
| 161 |
+
Bundle V2 stores the full raw transcript and external trust material, encrypts
|
| 162 |
+
secret openings with XChaCha20-Poly1305, and reuses the official stateless V2
|
| 163 |
+
verifier as its only acceptance authority. SQLite V2 has a separate PAL2 schema
|
| 164 |
+
and application ID and atomically stores jobs, receipts, and bundles. It rejects
|
| 165 |
+
receipt, execution, assignment, and job-slot replay; stale network epochs;
|
| 166 |
+
rollback; torn transactions; schema mutation; and non-exact restore rows.
|
| 167 |
+
|
| 168 |
+
The integrated Rust gate discovered 226 tests and completed with 224 passed and
|
| 169 |
+
two ignored pre-existing Metal real-model tests. The CUDA V3, release-manifest,
|
| 170 |
+
protocol V2, receipt V2 flow, encrypted-bundle, restart, and SQLite V2 tests all
|
| 171 |
+
ran and passed. Additional gates passed:
|
| 172 |
+
|
| 173 |
+
- `cargo fmt --all -- --check`;
|
| 174 |
+
- `cargo clippy --locked --all-targets -- -D warnings`;
|
| 175 |
+
- rustdoc with `RUSTDOCFLAGS=-D warnings`;
|
| 176 |
+
- Rust 1.81 `cargo check --locked --all-targets`;
|
| 177 |
+
- Python release-manifest tests: 4/4;
|
| 178 |
+
- Apple host ABI/header/producer/bridge/closed-gate CTests: 5/5; and
|
| 179 |
+
- RTX SM89 ABI, device producer, grouped collector, manifest, and closed-gate
|
| 180 |
+
CTests: 8/8 with no skipped GPU test.
|
| 181 |
+
|
| 182 |
+
## Production issuance remains closed
|
| 183 |
+
|
| 184 |
+
The following public capability values remain exactly zero:
|
| 185 |
+
|
| 186 |
+
```text
|
| 187 |
+
PALW_CUDA_TRACE_PRODUCTION_CAPABLE=0
|
| 188 |
+
PALW_CUDA_PRODUCER_VENDOR_RUNTIME_INTEGRATED=0
|
| 189 |
+
PALW_CUDA_PRODUCER_RECEIPT_MAPPING_AVAILABLE=0
|
| 190 |
+
PALW_CUDA_PRODUCER_PRODUCTION_CAPABLE=0
|
| 191 |
+
PALW_CUDA_LLAMA_MMVQ_RECEIPT_MAPPING_AVAILABLE=0
|
| 192 |
+
PALW_CUDA_LLAMA_MMVQ_PRODUCTION_CAPABLE=0
|
| 193 |
+
```
|
| 194 |
+
|
| 195 |
+
Configuring `PALW_CUDA_PRODUCTION_KERNEL_TRACE=ON` still fails with
|
| 196 |
+
`PALW CUDA production kernel trace is unavailable`, and the closed-gate CTest
|
| 197 |
+
passes on both host and RTX builds.
|
| 198 |
+
|
| 199 |
+
Before a future production gate can open, the diagnostic C++ approval callback
|
| 200 |
+
must consume authority-provided canonical operation/plan/physical-layout IDs,
|
| 201 |
+
the live raw transcript must be passed into the Rust verifier and signed-receipt
|
| 202 |
+
flow, and the resulting bundle must be independently restored under deployed
|
| 203 |
+
trust roots. General multi-token/KV continuation and additional approved
|
| 204 |
+
hardware/model profiles require separate evidence.
|
docs/evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CUDA V3 vendored MMVQ hook SM89 diagnostic evidence — 2026-07-15
|
| 2 |
+
|
| 3 |
+
## Scope and status
|
| 4 |
+
|
| 5 |
+
This is the repository evidence for a one-token, flash-attention-off diagnostic
|
| 6 |
+
run through the vendored llama.cpp Q4_K/Q6_K MMVQ producer hook on an RTX 4060
|
| 7 |
+
Ti. It establishes all of the following on the recorded stack:
|
| 8 |
+
|
| 9 |
+
- the dense Qwen3-8B Q4_K_M graph exposes exactly 253 supported quantized MMVQ
|
| 10 |
+
launches for one evaluated token;
|
| 11 |
+
- the request-local bridge associates those launches in order with the exact
|
| 12 |
+
graph operation token, weight allocation, shape, and quantization;
|
| 13 |
+
- the selected Q4_K and Q6_K producer specializations execute the V3 full-K
|
| 14 |
+
pre-epilogue FP32 accumulator capture and finalize one canonical V3 record per
|
| 15 |
+
launch; and
|
| 16 |
+
- an injected association rejection stops the request at the selected launch
|
| 17 |
+
without accepting later work.
|
| 18 |
+
|
| 19 |
+
This evidence is deliberately **diagnostic only**. Both positive and negative
|
| 20 |
+
results report `diagnostic_only=true` and `receipt_authority=false`. It does not
|
| 21 |
+
establish a complete attention transcript, production kernel-binary authority,
|
| 22 |
+
or a production CUDA Receipt. R13, R32, and R35 therefore remain `In progress`.
|
| 23 |
+
|
| 24 |
+
The earlier layer-offload, graph-observer, and standalone-producer device gates
|
| 25 |
+
remain recorded separately in
|
| 26 |
+
[`cuda-wsl-sm89-2026-07-15.md`](cuda-wsl-sm89-2026-07-15.md).
|
| 27 |
+
No Tailscale address, SSH credential, or GPU UUID is recorded here.
|
| 28 |
+
|
| 29 |
+
## Fixed inputs and build
|
| 30 |
+
|
| 31 |
+
| Item | Recorded value |
|
| 32 |
+
| --- | --- |
|
| 33 |
+
| GPU | NVIDIA GeForce RTX 4060 Ti |
|
| 34 |
+
| Compute capability | 8.9 (`sm_89`) |
|
| 35 |
+
| CUDA compiler | NVCC 13.3.73 |
|
| 36 |
+
| Vendored llama.cpp base commit | `12127defda4f41b7679cb2477a4b0d65ee6a0c8f` |
|
| 37 |
+
| Model | `Qwen3-8B-Q4_K_M.gguf` |
|
| 38 |
+
| Remote build directory | `/root/qwen-8.0/build/llama-palw-hook-sm89-v1` |
|
| 39 |
+
| Loaded CUDA backend | `bin/libggml-cuda.so` |
|
| 40 |
+
| Loaded CUDA backend SHA-256 | `e8b357569b5845596775226b226eea77b2d3cd34eadc43207820e3c9f3fd6115` |
|
| 41 |
+
|
| 42 |
+
The executable was built with the experimental `GGML_CUDA_PALW_TRACE` path and
|
| 43 |
+
ran with all model layers assigned to the single CUDA backend, batch and ubatch
|
| 44 |
+
equal to one, and flash attention disabled. The relevant invocation was:
|
| 45 |
+
|
| 46 |
+
```sh
|
| 47 |
+
LD_LIBRARY_PATH=/root/qwen-8.0/build/llama-palw-hook-sm89-v1/bin \
|
| 48 |
+
/root/qwen-8.0/build/llama-palw-hook-sm89-v1/bin/llama-palw-mmvq-smoke \
|
| 49 |
+
--model /root/qwen-8.0/models/Qwen3-8B/Qwen3-8B-Q4_K_M.gguf \
|
| 50 |
+
--kernel-binary-sha256 \
|
| 51 |
+
e8b357569b5845596775226b226eea77b2d3cd34eadc43207820e3c9f3fd6115
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
The SHA-256 above is the whole loaded `libggml-cuda.so`, supplied explicitly to
|
| 55 |
+
the diagnostic tool. It is useful for identifying this build artifact, but it
|
| 56 |
+
is not an independently attested digest of the exact selected cubin/fatbin entry
|
| 57 |
+
point and is not a production manifest-authority assertion.
|
| 58 |
+
|
| 59 |
+
## Positive one-token gate
|
| 60 |
+
|
| 61 |
+
The tool first used an untraced discovery context and then attached a fresh V3
|
| 62 |
+
producer context to the exact CUDA backend used by the traced llama context. An
|
| 63 |
+
approval callback required the next preapproved weight pointer, shape, and
|
| 64 |
+
quantization and a unique non-null graph operation token. The backend queried
|
| 65 |
+
`cudaFuncGetAttributes` from the same Q4_K or Q6_K specialization passed to the
|
| 66 |
+
V3 exact launch wrapper. Finalization validated record coverage and identity,
|
| 67 |
+
then encoded each record with the 452-byte canonical V3 codec before computing
|
| 68 |
+
the diagnostic FNV-1a value.
|
| 69 |
+
|
| 70 |
+
Three independent positive invocations all exited successfully with the same
|
| 71 |
+
values:
|
| 72 |
+
|
| 73 |
+
| Field | Run 1 | Run 2 | Run 3 |
|
| 74 |
+
| --- | ---: | ---: | ---: |
|
| 75 |
+
| `discovered` | 253 | 253 | 253 |
|
| 76 |
+
| `q4_k` | 216 | 216 | 216 |
|
| 77 |
+
| `q6_k` | 37 | 37 | 37 |
|
| 78 |
+
| `approved` | 253 | 253 | 253 |
|
| 79 |
+
| `accepted` | 253 | 253 | 253 |
|
| 80 |
+
| `records` | 253 | 253 | 253 |
|
| 81 |
+
| `committed` after finalize | 253 | 253 | 253 |
|
| 82 |
+
| `producer_faults` | 0 | 0 | 0 |
|
| 83 |
+
| `poisoned` | false | false | false |
|
| 84 |
+
| canonical-record FNV-1a 64 | `6618cafb2d66fc5c` | `6618cafb2d66fc5c` | `6618cafb2d66fc5c` |
|
| 85 |
+
|
| 86 |
+
The 253 records decompose exactly into 216 Q4_K and 37 Q6_K MMVQ launches. This
|
| 87 |
+
is one record per approved MMVQ launch in the smoke profile; it is not a claim
|
| 88 |
+
that the uninstrumented attention sublaunches are represented.
|
| 89 |
+
|
| 90 |
+
The exact selected-specialization diagnostics were also identical for Q4_K and
|
| 91 |
+
Q6_K:
|
| 92 |
+
|
| 93 |
+
| Attribute | Q4_K | Q6_K |
|
| 94 |
+
| --- | ---: | ---: |
|
| 95 |
+
| SM architecture | 89 | 89 |
|
| 96 |
+
| CUDA binary version | 89 | 89 |
|
| 97 |
+
| PTX version | 89 | 89 |
|
| 98 |
+
| Registers per thread | 40 | 40 |
|
| 99 |
+
| Maximum threads per block | 128 | 128 |
|
| 100 |
+
| Static shared memory bytes | 384 | 384 |
|
| 101 |
+
| Local memory bytes | 0 | 0 |
|
| 102 |
+
|
| 103 |
+
The bridge additionally checked nonzero, exact producer-variant, work-entry,
|
| 104 |
+
and capture-implementation identities against every finalized record. Those
|
| 105 |
+
source/dispatch-derived identifiers and the runtime attributes constrain this
|
| 106 |
+
diagnostic execution, but only a reviewed release manifest and authority can
|
| 107 |
+
turn them into an approved production identity.
|
| 108 |
+
|
| 109 |
+
The repeated `6618cafb2d66fc5c` value demonstrates same-stack diagnostic
|
| 110 |
+
repeatability for these three invocations. FNV-1a is only a compact diagnostic
|
| 111 |
+
fingerprint; it is not a cryptographic transcript commitment and does not prove
|
| 112 |
+
cross-driver, cross-GPU, or independently reproduced equality.
|
| 113 |
+
|
| 114 |
+
## Negative association gate
|
| 115 |
+
|
| 116 |
+
The same executable was run with zero-based `--reject-index 17`. The approval
|
| 117 |
+
callback deliberately returned `PALW_CUDA_TRACE_IDENTITY_MISMATCH` for that
|
| 118 |
+
association. Indices 0 through 16 were accepted; index 17 and every later launch
|
| 119 |
+
were not. The process exited zero only because all fail-closed oracle conditions
|
| 120 |
+
matched:
|
| 121 |
+
|
| 122 |
+
| Field | Observed value |
|
| 123 |
+
| --- | ---: |
|
| 124 |
+
| `status` | `expected_failure` |
|
| 125 |
+
| `reject_index` | 17 |
|
| 126 |
+
| llama decode status | -3 |
|
| 127 |
+
| producer unbind status | 8 (`PALW_CUDA_TRACE_IDENTITY_MISMATCH`) |
|
| 128 |
+
| `accepted` | 17 |
|
| 129 |
+
| `records` | 17 |
|
| 130 |
+
| committed records | 0 |
|
| 131 |
+
| fault callbacks | 1 |
|
| 132 |
+
| producer device faults | 0 |
|
| 133 |
+
| producer poisoned | false |
|
| 134 |
+
|
| 135 |
+
This is specifically a scheduler/backend association failure. The single fault
|
| 136 |
+
callback reported an association mismatch, no rejected launch was enqueued, and
|
| 137 |
+
the producer remained unpoisoned because no asynchronous CUDA or device-view
|
| 138 |
+
fault occurred. The result proves ordered fail-closed cancellation at this
|
| 139 |
+
boundary; it does not substitute for separate device-fault and asynchronous
|
| 140 |
+
error-injection gates.
|
| 141 |
+
|
| 142 |
+
## Complementary final verification gates
|
| 143 |
+
|
| 144 |
+
The source state used for this evidence also passed the following non-smoke
|
| 145 |
+
gates:
|
| 146 |
+
|
| 147 |
+
- Rust/Cargo 1.81.0 with `--locked`: 182 passed and 2 real-model tests ignored
|
| 148 |
+
(184 discovered). The passed tests were library 131, adversarial 12, bonded
|
| 149 |
+
maturity 3, canary durability 2, core flow 3, CUDA V2 contract 13, CUDA V3
|
| 150 |
+
contract 7, external bonded settlement 2, and restart/bundle 9.
|
| 151 |
+
- `cargo fmt --check`, Clippy with warnings denied, and rustdoc with warnings
|
| 152 |
+
denied all passed.
|
| 153 |
+
- The normal host CUDA-contract build passed 5/5 CTests.
|
| 154 |
+
- The AppleClang ASan+UBSan host build passed the same 5/5 CTests with no
|
| 155 |
+
sanitizer report.
|
| 156 |
+
- The RTX 4060 Ti SM89 build passed 7/7 CTests with no skipped device test.
|
| 157 |
+
|
| 158 |
+
These gates validate the codecs, bridge ABI, host failure contracts, standalone
|
| 159 |
+
device primitives, and Rust binding rules around the smoke run. They do not add
|
| 160 |
+
the missing attention or production-authority coverage listed below.
|
| 161 |
+
|
| 162 |
+
## What remains before production completion
|
| 163 |
+
|
| 164 |
+
This gate closes the experimental vendored MMVQ-hook diagnostic item only. It
|
| 165 |
+
does not close any of the following:
|
| 166 |
+
|
| 167 |
+
1. Wire the V3 FA-off eager-attention decomposition into the actual QK GEMM,
|
| 168 |
+
masked/scaled softmax, and PV GEMM producer launches and
|
| 169 |
+
prove complete ordered coverage.
|
| 170 |
+
2. Build the live expected-sublaunch table from the authoritative Qwen schedule
|
| 171 |
+
and bind the complete MMVQ-plus-attention V3 stream through the Rust authority
|
| 172 |
+
typestate. The smoke tool's discovery callback is diagnostic scaffolding.
|
| 173 |
+
3. Content-address and independently attest the actual release cubin/fatbin and
|
| 174 |
+
reviewed entry-point table, then bind them to the runtime manifest, authority
|
| 175 |
+
registry, governance, and key lifecycle. The whole-DSO hash above is not that
|
| 176 |
+
proof.
|
| 177 |
+
4. Implement and independently verify the CUDA Receipt/Manifest/Request/Bundle/
|
| 178 |
+
SQLite V2 mapping and persistence path. CUDA evidence remains forbidden in a
|
| 179 |
+
`ComputeReceiptV1` issuance path.
|
| 180 |
+
5. Pass full-stream fault injection plus approved replica, clean-rebuild,
|
| 181 |
+
cross-driver, and supported-hardware reproducibility matrices.
|
| 182 |
+
|
| 183 |
+
Until those gates close, `PALW_CUDA_LLAMA_MMVQ_RECEIPT_MAPPING_AVAILABLE`,
|
| 184 |
+
`PALW_CUDA_LLAMA_MMVQ_PRODUCTION_CAPABLE`,
|
| 185 |
+
`PALW_CUDA_PRODUCER_RECEIPT_MAPPING_AVAILABLE`,
|
| 186 |
+
`PALW_CUDA_PRODUCER_PRODUCTION_CAPABLE`, and
|
| 187 |
+
`PALW_CUDA_TRACE_PRODUCTION_CAPABLE` remain zero. Production Receipt issuance
|
| 188 |
+
must remain fail-closed.
|
docs/evidence/cuda-v3-release-kernel-manifest-sm89-2026-07-16.json
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"authority_payload": {
|
| 3 |
+
"entries": [
|
| 4 |
+
{
|
| 5 |
+
"cubin": {
|
| 6 |
+
"elf_flags": 100686084,
|
| 7 |
+
"sha256": "f04b5d1fb574c3558384bb37f261bc63be926cc0bef584b7a527977bd31b7237",
|
| 8 |
+
"size": 4229392,
|
| 9 |
+
"target_arch": "sm_89"
|
| 10 |
+
},
|
| 11 |
+
"label": "attention_pv",
|
| 12 |
+
"runtime_attributes": {
|
| 13 |
+
"binary_version": 89,
|
| 14 |
+
"local_memory_bytes": 0,
|
| 15 |
+
"max_threads_per_block": 1024,
|
| 16 |
+
"num_regs": 34,
|
| 17 |
+
"ptx_version": 89,
|
| 18 |
+
"sm_arch": 89,
|
| 19 |
+
"static_shared_memory_bytes": 0
|
| 20 |
+
},
|
| 21 |
+
"scoped_sections": [
|
| 22 |
+
{
|
| 23 |
+
"alignment": 4,
|
| 24 |
+
"flags": 66,
|
| 25 |
+
"name": ".nv.constant0._Z13mul_mat_vec_fI6__halfS0_Li1ELi128ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii",
|
| 26 |
+
"sha256": "076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560",
|
| 27 |
+
"size": 512,
|
| 28 |
+
"storage": "raw",
|
| 29 |
+
"type": 1
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"alignment": 4,
|
| 33 |
+
"flags": 64,
|
| 34 |
+
"name": ".nv.info._Z13mul_mat_vec_fI6__halfS0_Li1ELi128ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii",
|
| 35 |
+
"sha256": "06f0e251abee94e479087c5853edcb658b1237de93ed1f561d755774e3c2e5ab",
|
| 36 |
+
"size": 500,
|
| 37 |
+
"storage": "raw",
|
| 38 |
+
"type": 1879048192
|
| 39 |
+
},
|
| 40 |
+
{
|
| 41 |
+
"alignment": 16,
|
| 42 |
+
"flags": 67,
|
| 43 |
+
"name": ".nv.shared._Z13mul_mat_vec_fI6__halfS0_Li1ELi128ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii",
|
| 44 |
+
"size": 0,
|
| 45 |
+
"storage": "nobits",
|
| 46 |
+
"type": 8
|
| 47 |
+
},
|
| 48 |
+
{
|
| 49 |
+
"alignment": 128,
|
| 50 |
+
"flags": 6,
|
| 51 |
+
"name": ".text._Z13mul_mat_vec_fI6__halfS0_Li1ELi128ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii",
|
| 52 |
+
"sha256": "1f6a2a6fc1112e02fdec8773ac7bd1055c41e85ae3254e02e12ab487237d4c62",
|
| 53 |
+
"size": 3584,
|
| 54 |
+
"storage": "raw",
|
| 55 |
+
"type": 1
|
| 56 |
+
}
|
| 57 |
+
],
|
| 58 |
+
"semantic_binding": {
|
| 59 |
+
"capture_implementation_id": "c0a50513fee0ef0470636bf28a61c2f2b901c9cff650bdd2f58bd2fdc2921542",
|
| 60 |
+
"kernel_binary_digest_sha256": "f04b5d1fb574c3558384bb37f261bc63be926cc0bef584b7a527977bd31b7237",
|
| 61 |
+
"producer_variant_id": "e028f4560714ce35de86dc9346f7a23322951bffaa6d96d0f38ccbe6761f6a61",
|
| 62 |
+
"role": "work",
|
| 63 |
+
"work_entry_point_id": "e9d7c24faf7167a4ace7ec61bf721d8eb02e1f368a0293c798fcf12596c12d72"
|
| 64 |
+
},
|
| 65 |
+
"symbol": "_Z13mul_mat_vec_fI6__halfS0_Li1ELi128ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii"
|
| 66 |
+
},
|
| 67 |
+
{
|
| 68 |
+
"cubin": {
|
| 69 |
+
"elf_flags": 100686084,
|
| 70 |
+
"sha256": "f04b5d1fb574c3558384bb37f261bc63be926cc0bef584b7a527977bd31b7237",
|
| 71 |
+
"size": 4229392,
|
| 72 |
+
"target_arch": "sm_89"
|
| 73 |
+
},
|
| 74 |
+
"label": "attention_qk",
|
| 75 |
+
"runtime_attributes": {
|
| 76 |
+
"binary_version": 89,
|
| 77 |
+
"local_memory_bytes": 0,
|
| 78 |
+
"max_threads_per_block": 1024,
|
| 79 |
+
"num_regs": 40,
|
| 80 |
+
"ptx_version": 89,
|
| 81 |
+
"sm_arch": 89,
|
| 82 |
+
"static_shared_memory_bytes": 0
|
| 83 |
+
},
|
| 84 |
+
"scoped_sections": [
|
| 85 |
+
{
|
| 86 |
+
"alignment": 4,
|
| 87 |
+
"flags": 66,
|
| 88 |
+
"name": ".nv.constant0._Z13mul_mat_vec_fI6__halffLi1ELi64ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii",
|
| 89 |
+
"sha256": "076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560",
|
| 90 |
+
"size": 512,
|
| 91 |
+
"storage": "raw",
|
| 92 |
+
"type": 1
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"alignment": 4,
|
| 96 |
+
"flags": 64,
|
| 97 |
+
"name": ".nv.info._Z13mul_mat_vec_fI6__halffLi1ELi64ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii",
|
| 98 |
+
"sha256": "569beed4bcfdfde971aa30c94dcd9739ad8fd1a3cc1197041a59d400dc7dfe1b",
|
| 99 |
+
"size": 500,
|
| 100 |
+
"storage": "raw",
|
| 101 |
+
"type": 1879048192
|
| 102 |
+
},
|
| 103 |
+
{
|
| 104 |
+
"alignment": 16,
|
| 105 |
+
"flags": 67,
|
| 106 |
+
"name": ".nv.shared._Z13mul_mat_vec_fI6__halffLi1ELi64ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii",
|
| 107 |
+
"size": 0,
|
| 108 |
+
"storage": "nobits",
|
| 109 |
+
"type": 8
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"alignment": 128,
|
| 113 |
+
"flags": 6,
|
| 114 |
+
"name": ".text._Z13mul_mat_vec_fI6__halffLi1ELi64ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii",
|
| 115 |
+
"sha256": "e50f5e46cc7fc13848b9fe520014bed2a52e79745c5c7204a3236a0e5f707a8c",
|
| 116 |
+
"size": 6400,
|
| 117 |
+
"storage": "raw",
|
| 118 |
+
"type": 1
|
| 119 |
+
}
|
| 120 |
+
],
|
| 121 |
+
"semantic_binding": {
|
| 122 |
+
"capture_implementation_id": "c0a50513fee0ef0470636bf28a61c2f2b901c9cff650bdd2f58bd2fdc2921542",
|
| 123 |
+
"kernel_binary_digest_sha256": "f04b5d1fb574c3558384bb37f261bc63be926cc0bef584b7a527977bd31b7237",
|
| 124 |
+
"producer_variant_id": "0a299134085c7b67bfee9351427fa45a409c684b6533a70d9f41eacdcf805bb4",
|
| 125 |
+
"role": "work",
|
| 126 |
+
"work_entry_point_id": "f1112882f6d45fe2975c0012269229bbb3f5e21cdedfd0c085ccf3f53694b183"
|
| 127 |
+
},
|
| 128 |
+
"symbol": "_Z13mul_mat_vec_fI6__halffLi1ELi64ELb0ELb0EEvPKT_PKfPKi31ggml_cuda_mm_fusion_args_devicePfi5uint3iiiSA_iiiSA_iiii"
|
| 129 |
+
},
|
| 130 |
+
{
|
| 131 |
+
"cubin": {
|
| 132 |
+
"elf_flags": 100686084,
|
| 133 |
+
"sha256": "31d368e4cffc8668bf678aebae93fd79d9b5a4fed626b2a1ce615efa77ce6903",
|
| 134 |
+
"size": 195152,
|
| 135 |
+
"target_arch": "sm_89"
|
| 136 |
+
},
|
| 137 |
+
"label": "attention_softmax",
|
| 138 |
+
"runtime_attributes": {
|
| 139 |
+
"binary_version": 89,
|
| 140 |
+
"local_memory_bytes": 0,
|
| 141 |
+
"max_threads_per_block": 1024,
|
| 142 |
+
"num_regs": 22,
|
| 143 |
+
"ptx_version": 89,
|
| 144 |
+
"sm_arch": 89,
|
| 145 |
+
"static_shared_memory_bytes": 0
|
| 146 |
+
},
|
| 147 |
+
"scoped_sections": [
|
| 148 |
+
{
|
| 149 |
+
"alignment": 4,
|
| 150 |
+
"flags": 66,
|
| 151 |
+
"name": ".nv.constant0._Z12soft_max_f32ILb1ELi256ELi256EfEvPKfPKT2_S1_Pf15soft_max_params",
|
| 152 |
+
"sha256": "076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560",
|
| 153 |
+
"size": 512,
|
| 154 |
+
"storage": "raw",
|
| 155 |
+
"type": 1
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"alignment": 4,
|
| 159 |
+
"flags": 64,
|
| 160 |
+
"name": ".nv.info._Z12soft_max_f32ILb1ELi256ELi256EfEvPKfPKT2_S1_Pf15soft_max_params",
|
| 161 |
+
"sha256": "282f4482caa1aa8436716905e3ceaaf3e730f51e7daa48514f20788bc2032a37",
|
| 162 |
+
"size": 312,
|
| 163 |
+
"storage": "raw",
|
| 164 |
+
"type": 1879048192
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"alignment": 16,
|
| 168 |
+
"flags": 67,
|
| 169 |
+
"name": ".nv.shared._Z12soft_max_f32ILb1ELi256ELi256EfEvPKfPKT2_S1_Pf15soft_max_params",
|
| 170 |
+
"size": 0,
|
| 171 |
+
"storage": "nobits",
|
| 172 |
+
"type": 8
|
| 173 |
+
},
|
| 174 |
+
{
|
| 175 |
+
"alignment": 128,
|
| 176 |
+
"flags": 6,
|
| 177 |
+
"name": ".text._Z12soft_max_f32ILb1ELi256ELi256EfEvPKfPKT2_S1_Pf15soft_max_params",
|
| 178 |
+
"sha256": "c63ad88792a49ace599f83e605d084cac913a598beca77e4c49540fdf3a598aa",
|
| 179 |
+
"size": 4480,
|
| 180 |
+
"storage": "raw",
|
| 181 |
+
"type": 1
|
| 182 |
+
}
|
| 183 |
+
],
|
| 184 |
+
"semantic_binding": {
|
| 185 |
+
"capture_implementation_id": "c0a50513fee0ef0470636bf28a61c2f2b901c9cff650bdd2f58bd2fdc2921542",
|
| 186 |
+
"kernel_binary_digest_sha256": "31d368e4cffc8668bf678aebae93fd79d9b5a4fed626b2a1ce615efa77ce6903",
|
| 187 |
+
"producer_variant_id": "e74e46185a1164792446404386c2cf2ed3ae7f6c6726d72e26b1009d7e89c0cc",
|
| 188 |
+
"role": "work",
|
| 189 |
+
"work_entry_point_id": "eb58357f1b039704e68c9c71d9fda49f356b69bc234d18a64914f597caf4cffb"
|
| 190 |
+
},
|
| 191 |
+
"symbol": "_Z12soft_max_f32ILb1ELi256ELi256EfEvPKfPKT2_S1_Pf15soft_max_params"
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
"cubin": {
|
| 195 |
+
"elf_flags": 100686084,
|
| 196 |
+
"sha256": "09bb6b85776ba02de3b9e5aa457d090208ab25cb276ed63021020ebadc804435",
|
| 197 |
+
"size": 103016,
|
| 198 |
+
"target_arch": "sm_89"
|
| 199 |
+
},
|
| 200 |
+
"label": "grouped_collector",
|
| 201 |
+
"runtime_attributes": {
|
| 202 |
+
"binary_version": 89,
|
| 203 |
+
"local_memory_bytes": 0,
|
| 204 |
+
"max_threads_per_block": 1024,
|
| 205 |
+
"num_regs": 44,
|
| 206 |
+
"ptx_version": 89,
|
| 207 |
+
"sm_arch": 89,
|
| 208 |
+
"static_shared_memory_bytes": 0
|
| 209 |
+
},
|
| 210 |
+
"scoped_sections": [
|
| 211 |
+
{
|
| 212 |
+
"alignment": 4,
|
| 213 |
+
"flags": 66,
|
| 214 |
+
"name": ".nv.constant0._ZN56_GLOBAL__N__26eae2a6_23_producer_accumulator_cu_094d79ac35collect_grouped_final_output_f32_v3EPKfm33palw_cuda_producer_device_view_v337palw_cuda_producer_actual_identity_v3",
|
| 215 |
+
"sha256": "f4bd841308415de6ed2727462cd66a7333ac8155b4e8e95de0220355189c785c",
|
| 216 |
+
"size": 648,
|
| 217 |
+
"storage": "raw",
|
| 218 |
+
"type": 1
|
| 219 |
+
},
|
| 220 |
+
{
|
| 221 |
+
"alignment": 4,
|
| 222 |
+
"flags": 66,
|
| 223 |
+
"name": ".nv.constant2._ZN56_GLOBAL__N__26eae2a6_23_producer_accumulator_cu_094d79ac35collect_grouped_final_output_f32_v3EPKfm33palw_cuda_producer_device_view_v337palw_cuda_producer_actual_identity_v3",
|
| 224 |
+
"sha256": "106f52bc7d694dadb285f10109d0ce66a4ed1b6751fbc72c1752fec69980f796",
|
| 225 |
+
"size": 128,
|
| 226 |
+
"storage": "raw",
|
| 227 |
+
"type": 1
|
| 228 |
+
},
|
| 229 |
+
{
|
| 230 |
+
"alignment": 4,
|
| 231 |
+
"flags": 64,
|
| 232 |
+
"name": ".nv.info._ZN56_GLOBAL__N__26eae2a6_23_producer_accumulator_cu_094d79ac35collect_grouped_final_output_f32_v3EPKfm33palw_cuda_producer_device_view_v337palw_cuda_producer_actual_identity_v3",
|
| 233 |
+
"sha256": "2a4fe8a0afa52783b1bd49ce5a830a5079112ff9dfa79652195829fa16ea182c",
|
| 234 |
+
"size": 204,
|
| 235 |
+
"storage": "raw",
|
| 236 |
+
"type": 1879048192
|
| 237 |
+
},
|
| 238 |
+
{
|
| 239 |
+
"alignment": 128,
|
| 240 |
+
"flags": 6,
|
| 241 |
+
"name": ".text._ZN56_GLOBAL__N__26eae2a6_23_producer_accumulator_cu_094d79ac35collect_grouped_final_output_f32_v3EPKfm33palw_cuda_producer_device_view_v337palw_cuda_producer_actual_identity_v3",
|
| 242 |
+
"sha256": "37a0bca9a5e01be7a1595146e6b92938499be614bd8ca155ff9781b70121eb4b",
|
| 243 |
+
"size": 75008,
|
| 244 |
+
"storage": "raw",
|
| 245 |
+
"type": 1
|
| 246 |
+
}
|
| 247 |
+
],
|
| 248 |
+
"semantic_binding": {
|
| 249 |
+
"capture_implementation_id": "c0a50513fee0ef0470636bf28a61c2f2b901c9cff650bdd2f58bd2fdc2921542",
|
| 250 |
+
"kernel_binary_digest_sha256": "09bb6b85776ba02de3b9e5aa457d090208ab25cb276ed63021020ebadc804435",
|
| 251 |
+
"producer_variant_id": null,
|
| 252 |
+
"role": "capture",
|
| 253 |
+
"work_entry_point_id": null
|
| 254 |
+
},
|
| 255 |
+
"symbol": "_ZN56_GLOBAL__N__26eae2a6_23_producer_accumulator_cu_094d79ac35collect_grouped_final_output_f32_v3EPKfm33palw_cuda_producer_device_view_v337palw_cuda_producer_actual_identity_v3"
|
| 256 |
+
},
|
| 257 |
+
{
|
| 258 |
+
"cubin": {
|
| 259 |
+
"elf_flags": 100686084,
|
| 260 |
+
"sha256": "3f9bfb88b5898b7d59b7fc39a01d7fda3b8ce4e270605b2d4cf29465907dfb64",
|
| 261 |
+
"size": 97838152,
|
| 262 |
+
"target_arch": "sm_89"
|
| 263 |
+
},
|
| 264 |
+
"label": "q4_k",
|
| 265 |
+
"runtime_attributes": {
|
| 266 |
+
"binary_version": 89,
|
| 267 |
+
"local_memory_bytes": 0,
|
| 268 |
+
"max_threads_per_block": 128,
|
| 269 |
+
"num_regs": 40,
|
| 270 |
+
"ptx_version": 89,
|
| 271 |
+
"sm_arch": 89,
|
| 272 |
+
"static_shared_memory_bytes": 384
|
| 273 |
+
},
|
| 274 |
+
"scoped_sections": [
|
| 275 |
+
{
|
| 276 |
+
"alignment": 4,
|
| 277 |
+
"flags": 66,
|
| 278 |
+
"name": ".nv.constant0._Z13mul_mat_vec_qIL9ggml_type12ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 279 |
+
"sha256": "030dd256c2a1dda892b0e57157ec52f9ae5fd1e054d0c66380fae1cb6c09c477",
|
| 280 |
+
"size": 696,
|
| 281 |
+
"storage": "raw",
|
| 282 |
+
"type": 1
|
| 283 |
+
},
|
| 284 |
+
{
|
| 285 |
+
"alignment": 4,
|
| 286 |
+
"flags": 66,
|
| 287 |
+
"name": ".nv.constant2._Z13mul_mat_vec_qIL9ggml_type12ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 288 |
+
"sha256": "27ecd0a598e76f8a2fd264d427df0a119903e8eae384e478902541756f089dd1",
|
| 289 |
+
"size": 4,
|
| 290 |
+
"storage": "raw",
|
| 291 |
+
"type": 1
|
| 292 |
+
},
|
| 293 |
+
{
|
| 294 |
+
"alignment": 4,
|
| 295 |
+
"flags": 64,
|
| 296 |
+
"name": ".nv.info._Z13mul_mat_vec_qIL9ggml_type12ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 297 |
+
"sha256": "3898ea58f7ecc3b16c1f753686bd08c3d24fdd296e7bb8ec0be6fd1ec87d08fa",
|
| 298 |
+
"size": 456,
|
| 299 |
+
"storage": "raw",
|
| 300 |
+
"type": 1879048192
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"alignment": 4,
|
| 304 |
+
"flags": 67,
|
| 305 |
+
"name": ".nv.shared._Z13mul_mat_vec_qIL9ggml_type12ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 306 |
+
"size": 384,
|
| 307 |
+
"storage": "nobits",
|
| 308 |
+
"type": 8
|
| 309 |
+
},
|
| 310 |
+
{
|
| 311 |
+
"alignment": 128,
|
| 312 |
+
"flags": 6,
|
| 313 |
+
"name": ".text._Z13mul_mat_vec_qIL9ggml_type12ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 314 |
+
"sha256": "6a2373c1b75fc5baf98f68bddcbf8cb5de0b25044b78076044c2c86cf579fbd0",
|
| 315 |
+
"size": 55680,
|
| 316 |
+
"storage": "raw",
|
| 317 |
+
"type": 1
|
| 318 |
+
}
|
| 319 |
+
],
|
| 320 |
+
"semantic_binding": {
|
| 321 |
+
"capture_implementation_id": "b9d5fdda45db7cec8c8652fc60ee97a02bb09e83dfee57f2fc2ec52c51abdeb7",
|
| 322 |
+
"kernel_binary_digest_sha256": "3f9bfb88b5898b7d59b7fc39a01d7fda3b8ce4e270605b2d4cf29465907dfb64",
|
| 323 |
+
"producer_variant_id": "bb8334a8f131c5e9bad2902ad4d2e48bbcd2ee6a622feef4b5bb1bb24784e8cb",
|
| 324 |
+
"role": "work",
|
| 325 |
+
"work_entry_point_id": "e67572587d81ebab610881fd51059998702fab2fbd1f5102812be46181fb79b5"
|
| 326 |
+
},
|
| 327 |
+
"symbol": "_Z13mul_mat_vec_qIL9ggml_type12ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3"
|
| 328 |
+
},
|
| 329 |
+
{
|
| 330 |
+
"cubin": {
|
| 331 |
+
"elf_flags": 100686084,
|
| 332 |
+
"sha256": "3f9bfb88b5898b7d59b7fc39a01d7fda3b8ce4e270605b2d4cf29465907dfb64",
|
| 333 |
+
"size": 97838152,
|
| 334 |
+
"target_arch": "sm_89"
|
| 335 |
+
},
|
| 336 |
+
"label": "q6_k",
|
| 337 |
+
"runtime_attributes": {
|
| 338 |
+
"binary_version": 89,
|
| 339 |
+
"local_memory_bytes": 0,
|
| 340 |
+
"max_threads_per_block": 128,
|
| 341 |
+
"num_regs": 40,
|
| 342 |
+
"ptx_version": 89,
|
| 343 |
+
"sm_arch": 89,
|
| 344 |
+
"static_shared_memory_bytes": 384
|
| 345 |
+
},
|
| 346 |
+
"scoped_sections": [
|
| 347 |
+
{
|
| 348 |
+
"alignment": 4,
|
| 349 |
+
"flags": 66,
|
| 350 |
+
"name": ".nv.constant0._Z13mul_mat_vec_qIL9ggml_type14ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 351 |
+
"sha256": "030dd256c2a1dda892b0e57157ec52f9ae5fd1e054d0c66380fae1cb6c09c477",
|
| 352 |
+
"size": 696,
|
| 353 |
+
"storage": "raw",
|
| 354 |
+
"type": 1
|
| 355 |
+
},
|
| 356 |
+
{
|
| 357 |
+
"alignment": 4,
|
| 358 |
+
"flags": 66,
|
| 359 |
+
"name": ".nv.constant2._Z13mul_mat_vec_qIL9ggml_type14ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 360 |
+
"sha256": "b1b0bee5378188f5250138bcce25855f2617f9c55b20b9628e13d367c47404a9",
|
| 361 |
+
"size": 8,
|
| 362 |
+
"storage": "raw",
|
| 363 |
+
"type": 1
|
| 364 |
+
},
|
| 365 |
+
{
|
| 366 |
+
"alignment": 4,
|
| 367 |
+
"flags": 64,
|
| 368 |
+
"name": ".nv.info._Z13mul_mat_vec_qIL9ggml_type14ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 369 |
+
"sha256": "4459a5f5a9d38602c300a8aae11b4f61928cf9613f7520ad41fbf7c3332f5ed6",
|
| 370 |
+
"size": 456,
|
| 371 |
+
"storage": "raw",
|
| 372 |
+
"type": 1879048192
|
| 373 |
+
},
|
| 374 |
+
{
|
| 375 |
+
"alignment": 4,
|
| 376 |
+
"flags": 67,
|
| 377 |
+
"name": ".nv.shared._Z13mul_mat_vec_qIL9ggml_type14ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 378 |
+
"size": 384,
|
| 379 |
+
"storage": "nobits",
|
| 380 |
+
"type": 8
|
| 381 |
+
},
|
| 382 |
+
{
|
| 383 |
+
"alignment": 128,
|
| 384 |
+
"flags": 6,
|
| 385 |
+
"name": ".text._Z13mul_mat_vec_qIL9ggml_type14ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3",
|
| 386 |
+
"sha256": "726ad5b5ce0788fdf358ee8840ae9eb57950ff9b54be15bb1ca3939ea034cd28",
|
| 387 |
+
"size": 55808,
|
| 388 |
+
"storage": "raw",
|
| 389 |
+
"type": 1
|
| 390 |
+
}
|
| 391 |
+
],
|
| 392 |
+
"semantic_binding": {
|
| 393 |
+
"capture_implementation_id": "b9d5fdda45db7cec8c8652fc60ee97a02bb09e83dfee57f2fc2ec52c51abdeb7",
|
| 394 |
+
"kernel_binary_digest_sha256": "3f9bfb88b5898b7d59b7fc39a01d7fda3b8ce4e270605b2d4cf29465907dfb64",
|
| 395 |
+
"producer_variant_id": "855c0d09acbf494b388b172d67026ea35760d37bfbce7e60725943850f847040",
|
| 396 |
+
"role": "work",
|
| 397 |
+
"work_entry_point_id": "f7c95ceb945af4fc2c510ce2b9e879362fa4fc2effae66b1b7d0f3b3272c3250"
|
| 398 |
+
},
|
| 399 |
+
"symbol": "_Z13mul_mat_vec_qIL9ggml_type14ELi1ELb0ELb0EEvPKvS2_PKi31ggml_cuda_mm_fusion_args_devicePfj5uint3jjjS7_jjjS7_jjjj33palw_cuda_producer_device_view_v3"
|
| 400 |
+
}
|
| 401 |
+
],
|
| 402 |
+
"hash_algorithm": "sha256",
|
| 403 |
+
"library": {
|
| 404 |
+
"filename": "libggml-cuda.so.0.16.0",
|
| 405 |
+
"nv_fatbin": {
|
| 406 |
+
"sha256": "0654f8f423f059dccb94abf098fca2b47f106dcc6581f575756e6a985c6fa35c",
|
| 407 |
+
"size": 35595224
|
| 408 |
+
},
|
| 409 |
+
"sha256": "389bda6116c50eea8aebb9e1fcca1cc0145ab7245cb01d688024856c947f8e6f",
|
| 410 |
+
"size": 64330104
|
| 411 |
+
},
|
| 412 |
+
"schema": "misaka.palw.cuda-release-kernel-manifest.v1",
|
| 413 |
+
"schema_version": 1,
|
| 414 |
+
"target_arch": "sm_89"
|
| 415 |
+
},
|
| 416 |
+
"manifest_id_sha3_256": "4ededc7c257e13becbf74ebeecdff6c7bfe8ba84d550a6e07aa6cca52d9c7ce7",
|
| 417 |
+
"provenance": {
|
| 418 |
+
"cuobjdump_version": "cuobjdump: NVIDIA (R) fat binary listing tool\nCopyright (c) 2005-2026 NVIDIA Corporation\nBuilt on Tue_Jun_09_02:43:40_PM_PDT_2026\nCuda compilation tools, release 13.3, V13.3.73\nBuild cuda_13.3.r13.3/compiler.38244171_0"
|
| 419 |
+
}
|
| 420 |
+
}
|
docs/evidence/cuda-v3-runtime-entrypoint-info-sm89-2026-07-16.json
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"entries": [
|
| 3 |
+
{
|
| 4 |
+
"binary_version": 89,
|
| 5 |
+
"capture_implementation_id": "b9d5fdda45db7cec8c8652fc60ee97a02bb09e83dfee57f2fc2ec52c51abdeb7",
|
| 6 |
+
"label": "q4_k",
|
| 7 |
+
"local_memory_bytes": 0,
|
| 8 |
+
"max_threads_per_block": 128,
|
| 9 |
+
"num_regs": 40,
|
| 10 |
+
"producer_variant_id": "bb8334a8f131c5e9bad2902ad4d2e48bbcd2ee6a622feef4b5bb1bb24784e8cb",
|
| 11 |
+
"ptx_version": 89,
|
| 12 |
+
"role": "work",
|
| 13 |
+
"sm_arch": 89,
|
| 14 |
+
"static_shared_memory_bytes": 384,
|
| 15 |
+
"work_entry_point_id": "e67572587d81ebab610881fd51059998702fab2fbd1f5102812be46181fb79b5"
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"binary_version": 89,
|
| 19 |
+
"capture_implementation_id": "b9d5fdda45db7cec8c8652fc60ee97a02bb09e83dfee57f2fc2ec52c51abdeb7",
|
| 20 |
+
"label": "q6_k",
|
| 21 |
+
"local_memory_bytes": 0,
|
| 22 |
+
"max_threads_per_block": 128,
|
| 23 |
+
"num_regs": 40,
|
| 24 |
+
"producer_variant_id": "855c0d09acbf494b388b172d67026ea35760d37bfbce7e60725943850f847040",
|
| 25 |
+
"ptx_version": 89,
|
| 26 |
+
"role": "work",
|
| 27 |
+
"sm_arch": 89,
|
| 28 |
+
"static_shared_memory_bytes": 384,
|
| 29 |
+
"work_entry_point_id": "f7c95ceb945af4fc2c510ce2b9e879362fa4fc2effae66b1b7d0f3b3272c3250"
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"binary_version": 89,
|
| 33 |
+
"capture_implementation_id": "c0a50513fee0ef0470636bf28a61c2f2b901c9cff650bdd2f58bd2fdc2921542",
|
| 34 |
+
"label": "attention_qk",
|
| 35 |
+
"local_memory_bytes": 0,
|
| 36 |
+
"max_threads_per_block": 1024,
|
| 37 |
+
"num_regs": 40,
|
| 38 |
+
"producer_variant_id": "0a299134085c7b67bfee9351427fa45a409c684b6533a70d9f41eacdcf805bb4",
|
| 39 |
+
"ptx_version": 89,
|
| 40 |
+
"role": "work",
|
| 41 |
+
"sm_arch": 89,
|
| 42 |
+
"static_shared_memory_bytes": 0,
|
| 43 |
+
"work_entry_point_id": "f1112882f6d45fe2975c0012269229bbb3f5e21cdedfd0c085ccf3f53694b183"
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"binary_version": 89,
|
| 47 |
+
"capture_implementation_id": "c0a50513fee0ef0470636bf28a61c2f2b901c9cff650bdd2f58bd2fdc2921542",
|
| 48 |
+
"label": "attention_softmax",
|
| 49 |
+
"local_memory_bytes": 0,
|
| 50 |
+
"max_threads_per_block": 1024,
|
| 51 |
+
"num_regs": 22,
|
| 52 |
+
"producer_variant_id": "e74e46185a1164792446404386c2cf2ed3ae7f6c6726d72e26b1009d7e89c0cc",
|
| 53 |
+
"ptx_version": 89,
|
| 54 |
+
"role": "work",
|
| 55 |
+
"sm_arch": 89,
|
| 56 |
+
"static_shared_memory_bytes": 0,
|
| 57 |
+
"work_entry_point_id": "eb58357f1b039704e68c9c71d9fda49f356b69bc234d18a64914f597caf4cffb"
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"binary_version": 89,
|
| 61 |
+
"capture_implementation_id": "c0a50513fee0ef0470636bf28a61c2f2b901c9cff650bdd2f58bd2fdc2921542",
|
| 62 |
+
"label": "attention_pv",
|
| 63 |
+
"local_memory_bytes": 0,
|
| 64 |
+
"max_threads_per_block": 1024,
|
| 65 |
+
"num_regs": 34,
|
| 66 |
+
"producer_variant_id": "e028f4560714ce35de86dc9346f7a23322951bffaa6d96d0f38ccbe6761f6a61",
|
| 67 |
+
"ptx_version": 89,
|
| 68 |
+
"role": "work",
|
| 69 |
+
"sm_arch": 89,
|
| 70 |
+
"static_shared_memory_bytes": 0,
|
| 71 |
+
"work_entry_point_id": "e9d7c24faf7167a4ace7ec61bf721d8eb02e1f368a0293c798fcf12596c12d72"
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
"binary_version": 89,
|
| 75 |
+
"capture_implementation_id": "c0a50513fee0ef0470636bf28a61c2f2b901c9cff650bdd2f58bd2fdc2921542",
|
| 76 |
+
"label": "grouped_collector",
|
| 77 |
+
"local_memory_bytes": 0,
|
| 78 |
+
"max_threads_per_block": 1024,
|
| 79 |
+
"num_regs": 44,
|
| 80 |
+
"producer_variant_id": null,
|
| 81 |
+
"ptx_version": 89,
|
| 82 |
+
"role": "capture",
|
| 83 |
+
"sm_arch": 89,
|
| 84 |
+
"static_shared_memory_bytes": 0,
|
| 85 |
+
"work_entry_point_id": null
|
| 86 |
+
}
|
| 87 |
+
],
|
| 88 |
+
"schema": "misaka.palw.cuda-runtime-entrypoint-info.v1",
|
| 89 |
+
"target_arch": "sm_89"
|
| 90 |
+
}
|
docs/evidence/cuda-wsl-sm89-2026-07-15.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CUDA WSL2 SM89 Experimental Evidence — 2026-07-15
|
| 2 |
+
|
| 3 |
+
## Scope and status
|
| 4 |
+
|
| 5 |
+
This is the canonical repository evidence for the experimental CUDA gate run on
|
| 6 |
+
a Windows/WSL2 RTX 4060 Ti host. It establishes that the pinned Qwen artifact
|
| 7 |
+
runs with full CUDA layer offload, that the diagnostic graph observer is exactly
|
| 8 |
+
repeatable on this stack, and that the standalone producer primitive captures a
|
| 9 |
+
real pre-epilogue FP32 accumulator on an SM89 device.
|
| 10 |
+
|
| 11 |
+
It is **not** a production CUDA Receipt. The vendored llama.cpp Qwen producer is
|
| 12 |
+
not instrumented, the deterministic FA-off attention path is not representable
|
| 13 |
+
by the current V2 dispatch schema, and all production capability macros and the
|
| 14 |
+
production CMake gate remain closed. R32 therefore moves from `Blocked` to
|
| 15 |
+
`In progress`, not to `Complete`.
|
| 16 |
+
|
| 17 |
+
No Tailscale address, SSH credential, or GPU UUID is recorded in this artifact.
|
| 18 |
+
|
| 19 |
+
## Fixed host and toolchain
|
| 20 |
+
|
| 21 |
+
| Item | Observed value |
|
| 22 |
+
| --- | --- |
|
| 23 |
+
| Host path | Windows 11 + WSL2 Ubuntu 24.04.4 LTS |
|
| 24 |
+
| WSL kernel | 6.18.33.2 |
|
| 25 |
+
| GPU | NVIDIA GeForce RTX 4060 Ti, 8,188 MiB |
|
| 26 |
+
| Compute capability | 8.9 (`sm_89`) |
|
| 27 |
+
| NVIDIA driver | 610.62 |
|
| 28 |
+
| CUDA toolkit package | 13.3.1 |
|
| 29 |
+
| NVCC | 13.3.73 |
|
| 30 |
+
| CUDA architecture gate | exactly `89-real` |
|
| 31 |
+
| llama.cpp commit | `12127defda4f41b7679cb2477a4b0d65ee6a0c8f` |
|
| 32 |
+
| llama.cpp version | `10015 (12127def)` |
|
| 33 |
+
|
| 34 |
+
The build used `/usr/local/cuda/bin/nvcc` and did not rely on a compiler-default
|
| 35 |
+
or multi-architecture fatbin selection. `cuobjdump --list-elf` reported only
|
| 36 |
+
`sm_89.cubin` entries for both device-test executables.
|
| 37 |
+
|
| 38 |
+
## Pinned model artifact
|
| 39 |
+
|
| 40 |
+
| Item | Value |
|
| 41 |
+
| --- | --- |
|
| 42 |
+
| Repository | `Qwen/Qwen3-8B-GGUF` |
|
| 43 |
+
| Revision | `7c41481f57cb95916b40956ab2f0b139b296d974` |
|
| 44 |
+
| File | `Qwen3-8B-Q4_K_M.gguf` |
|
| 45 |
+
| Size | 5,027,783,488 bytes |
|
| 46 |
+
| SHA-256 | `d98cdcbd03e17ce47681435b5150e34c1417f50b5c0019dd560e4882c5745785` |
|
| 47 |
+
|
| 48 |
+
llama.cpp identified 399 tensors: 145 F32, 217 Q4_K, and 37 Q6_K.
|
| 49 |
+
All 37/37 model layers were offloaded to the RTX GPU. The CUDA model buffer was
|
| 50 |
+
4,455.34 MiB and the CUDA KV buffer was 576 MiB in the recorded probe.
|
| 51 |
+
|
| 52 |
+
## Deterministic diagnostic Qwen observer
|
| 53 |
+
|
| 54 |
+
The dedicated observer was invoked with a public `PALW` stdin prompt, two
|
| 55 |
+
predicted tokens, all GPU layers, and `observer=sketch`. Its enforced header
|
| 56 |
+
reported greedy sampling (`temperature=0`, `top_p=1`, `top_k=0`), request batch,
|
| 57 |
+
`n_batch`, and `n_ubatch` all equal to one, parallel/tensor parallel equal to one,
|
| 58 |
+
one CPU thread, context 4096, no context shift, no speculation, no tensor repack,
|
| 59 |
+
and flash attention disabled. CUDA graphs, graph fusion, and graph optimization
|
| 60 |
+
were also disabled for this diagnostic run.
|
| 61 |
+
|
| 62 |
+
Observed result:
|
| 63 |
+
|
| 64 |
+
- 4,338 total observer events: 2,892 prefill and 1,446 decode;
|
| 65 |
+
- 975 graph GEMM events across three evaluated tokens;
|
| 66 |
+
- six independent runs produced exactly the same event stream and result line;
|
| 67 |
+
- event-stream SHA-256:
|
| 68 |
+
`e8ec2574076a46d29a83d2016e657cadb12600ccca0246320d6f32a16c7b0ba3`;
|
| 69 |
+
- result-line SHA-256:
|
| 70 |
+
`6a22c1547efa9d5ba8b0478d11d82b2b817455eee35a7d4eeb2f66c5af9444cd`;
|
| 71 |
+
- retained observer JSONL SHA-256:
|
| 72 |
+
`8884b72be183e704b7238da9734d675bde764fe11b60a17038a69aefd0251ac3`;
|
| 73 |
+
- observer executable SHA-256:
|
| 74 |
+
`f84b67ea4ee5a36a2bd2b04823bbf0ee9abdd47329704457ffa3e5d96e79c38a`;
|
| 75 |
+
- loaded `libggml-cuda` SHA-256:
|
| 76 |
+
`680dc8a64ffc1a35658f6fcc71809d3e0afb11de968abf0d4ba7931c14d8b49a`.
|
| 77 |
+
|
| 78 |
+
This observer still reports `cuda_kernel_trace=false`: its 975 GEMM records are
|
| 79 |
+
graph-level diagnostic fallback evidence, not true producer-accumulator records.
|
| 80 |
+
|
| 81 |
+
The exact measured composition explains the remaining coverage gap:
|
| 82 |
+
|
| 83 |
+
| Operation path | Three-token count | Per token |
|
| 84 |
+
| --- | ---: | ---: |
|
| 85 |
+
| Q4_K quantized linear MMVQ candidate | 648 | 216 |
|
| 86 |
+
| Q6_K quantized linear MMVQ candidate | 111 | 37 |
|
| 87 |
+
| All quantized linear MMVQ | 759 | 253 |
|
| 88 |
+
| FA-off eager-attention F16 `MUL_MAT` | 216 | 72 |
|
| 89 |
+
| Total | 975 | 325 |
|
| 90 |
+
|
| 91 |
+
An MMVQ producer hook can cover the 253 quantized linear GEMMs per token, but it
|
| 92 |
+
cannot claim the 72 eager-attention GEMMs per token.
|
| 93 |
+
|
| 94 |
+
## Standalone true producer-accumulator primitive
|
| 95 |
+
|
| 96 |
+
The standalone test producer computes segmented dot-product accumulators in
|
| 97 |
+
CUDA registers, calls `palw_cuda_producer_capture_accumulator_f32` before an
|
| 98 |
+
independently variable epilogue/final store, and directly emits canonical V2
|
| 99 |
+
tile-by-K-segment evidence. It validates exact function pointer and
|
| 100 |
+
`cudaFuncGetAttributes`, immutable injected device view, per-launch nonce,
|
| 101 |
+
compiled entry-point/variant identity, 32 exactly-once samples, duplicate/missing
|
| 102 |
+
masks, host-retained metadata, stream/device binding, and codec grid limits.
|
| 103 |
+
|
| 104 |
+
The final CUDA source-tree aggregate is:
|
| 105 |
+
|
| 106 |
+
```text
|
| 107 |
+
2fda921624a095687e45aab9afb5ea32c48ca648727c6c5c6f1a923abbd9dc4f
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
It is calculated by hashing every regular file under `runtime-palw/cuda` in
|
| 111 |
+
byte-sorted pathname order, then SHA-256 hashing the resulting `shasum -a 256`
|
| 112 |
+
lines.
|
| 113 |
+
|
| 114 |
+
An independent clean build in `build/palw-cuda-device-root-final` produced:
|
| 115 |
+
|
| 116 |
+
- CTest: 6/6 passed, zero skipped (host 4, V1 device 1, producer device 1);
|
| 117 |
+
- standalone producer executable: 20/20 independent executions passed;
|
| 118 |
+
- all 20 logs had SHA-256
|
| 119 |
+
`bd5c1f458c7b4f81a1bd76414896de253f61d6b6f99426eefc3b51d9491673e6`;
|
| 120 |
+
- all 20 runs reported diagnostic fingerprint `c1a38ed138200874`;
|
| 121 |
+
- V1 device-test executable SHA-256:
|
| 122 |
+
`401241589d908a92e4bc1f83b90346eb896096e65bcae9b4102f1153ee99bc04`;
|
| 123 |
+
- producer device-test executable SHA-256:
|
| 124 |
+
`e9bb2ad7beb104bdba82a013bbfe9dd4271f36c79d09b10f380c840ced695a8e`;
|
| 125 |
+
- `libpalw_cuda_trace.a` SHA-256:
|
| 126 |
+
`8aef058ce12b746a683d037d70c72c3401940aa7136e46b8340f88229b0c5b9e`.
|
| 127 |
+
|
| 128 |
+
A separate build directory from the same source aggregate produced different
|
| 129 |
+
whole-binary/library SHA-256 values while passing the same 6/6 and 20/20 gates.
|
| 130 |
+
Consequently this evidence does **not** claim byte-for-byte build reproducibility;
|
| 131 |
+
the build-directory/toolchain provenance difference remains to be isolated and
|
| 132 |
+
the approved release artifact must be content-addressed explicitly.
|
| 133 |
+
|
| 134 |
+
The final adversarial review found and closed two pre-release defects: a caller
|
| 135 |
+
could previously change the injected-view argument position at launch, and a
|
| 136 |
+
codec-invalid grid-Y value could be accepted until finalization. The launch now
|
| 137 |
+
uses only the ABI position/count retained at `prepare`, and pure descriptor
|
| 138 |
+
validation shares the codec limits (`grid_x <= 2,147,483,647`,
|
| 139 |
+
`grid_y <= 65,535`). The review found no remaining P1/P2 issue within the stated
|
| 140 |
+
experimental trusted-ABI boundary.
|
| 141 |
+
|
| 142 |
+
## Host and Rust gates
|
| 143 |
+
|
| 144 |
+
- AppleClang warning-as-error host CTests: 4/4 passed.
|
| 145 |
+
- AppleClang ASan+UBSan host CTests: 4/4 passed with no report.
|
| 146 |
+
- Rust 1.81.0: 173 passed, 2 ignored (175 discovered).
|
| 147 |
+
- Rust CUDA trace contract: 13/13 passed.
|
| 148 |
+
- `cargo fmt --check`, Clippy `-D warnings`, and rustdoc `-D warnings` passed.
|
| 149 |
+
- `ComputeReceiptV1` builder and verifier both reject CUDA `KernelSketch`.
|
| 150 |
+
- Authority verification binds network/job/execution/assignment, runtime,
|
| 151 |
+
producer integration, complete schedule/transcript, validity and revocation;
|
| 152 |
+
its projection is candidate evidence for a future Receipt V2 only.
|
| 153 |
+
|
| 154 |
+
## Remaining completion gates
|
| 155 |
+
|
| 156 |
+
1. Instrument the pinned llama.cpp Q4_K and Q6_K unfused MMVQ specializations at
|
| 157 |
+
the true full-K pre-epilogue accumulator point and report the actual selected
|
| 158 |
+
dispatch from request-local state.
|
| 159 |
+
2. Version the transport/dispatch contract for FA-off eager/decomposed attention
|
| 160 |
+
sublaunch grouping, or approve and revalidate a separate deterministic FA-on
|
| 161 |
+
runtime class.
|
| 162 |
+
3. Bind reviewed hook source, compiled hook/entry-point table, actual loaded
|
| 163 |
+
cubin, extraction policy, and runtime manifest through production authority
|
| 164 |
+
governance and key lifecycle.
|
| 165 |
+
4. Implement Receipt/Manifest/Request/Bundle/SQLite V2 and an independent
|
| 166 |
+
verifier that retains the authority provenance commitment.
|
| 167 |
+
5. Run vendored-Qwen full-stream fault injection and approved replica/cross-driver
|
| 168 |
+
reproducibility matrices.
|
| 169 |
+
|
| 170 |
+
Until all five are complete,
|
| 171 |
+
`PALW_CUDA_PRODUCER_VENDOR_RUNTIME_INTEGRATED`,
|
| 172 |
+
`PALW_CUDA_PRODUCER_RECEIPT_MAPPING_AVAILABLE`,
|
| 173 |
+
`PALW_CUDA_PRODUCER_PRODUCTION_CAPABLE`, and
|
| 174 |
+
`PALW_CUDA_TRACE_PRODUCTION_CAPABLE` remain zero, and
|
| 175 |
+
`PALW_CUDA_PRODUCTION_KERNEL_TRACE=ON` must fail at CMake configure time.
|
docs/evidence/metal-hybrid-qwen36-2026-07-19.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Metal E2E evidence — Qwen3.6-35B-A3B (Claude-4.7, abliterated), 2026-07-19
|
| 2 |
+
|
| 3 |
+
このメモは、dense Qwen3-8B から hybrid Qwen3.6-35B-A3B へ移行した後の Metal arm64 実機
|
| 4 |
+
E2E(Receipt 発行 → 別 process 検証)の一次証跡である。
|
| 5 |
+
|
| 6 |
+
## Host / runtime
|
| 7 |
+
|
| 8 |
+
- Apple M1 Max、macOS(Metal 4)、`uname -m = arm64`
|
| 9 |
+
- pinned llama.cpp `12127defda4f41b7679cb2477a4b0d65ee6a0c8f` + PALW observer patch
|
| 10 |
+
(`patches/llama.cpp-palw-observer.patch`、SHA-256
|
| 11 |
+
`d155a88b7c11ee74f48011760cb1a37773a694c8cab28258ee108c85e2f9e02c`)
|
| 12 |
+
- `llama-palw-observer` は model load 時に `qwen35moe` / 40 layer / 2048 hidden / 248320
|
| 13 |
+
vocab を検証。`load_tensors: offloaded 41/41 layers to GPU` を確認。
|
| 14 |
+
|
| 15 |
+
## Model artifact
|
| 16 |
+
|
| 17 |
+
- GGUF: Ollama `huihui_ai/Qwen3.6-abliterated:35b-Claude-4.7`、blob/SHA-256
|
| 18 |
+
`1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b`、23,938,321,728 bytes(`Q4_K_M`)
|
| 19 |
+
- Base metadata(7 files): HF `huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated`
|
| 20 |
+
rev `ac18882735d037f6074a7630eb68d85db8234c25`
|
| 21 |
+
|
| 22 |
+
## 出力健全性(off-mode 差分)
|
| 23 |
+
|
| 24 |
+
prompt `The capital of France is`(token `[760, 6511, 314, 9338, 369]`)→ 生成
|
| 25 |
+
` Paris, a city renowned for its iconic`(8 token)。全 41 layer GPU offload。
|
| 26 |
+
|
| 27 |
+
## 発行 Receipt(sketch-mode、Metal kernel-bound)
|
| 28 |
+
|
| 29 |
+
- output dir: `receipts/final-v7/`
|
| 30 |
+
- Receipt ID: `8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9`
|
| 31 |
+
- Verification bundle ID: `f5b8a2968c4ea266b2cbbabf351a171e0fa2581984eff63362de2640fcdcf9db`
|
| 32 |
+
- public JSON schema: `misaka.palw.public-receipt.v2`、observer JSONL schema **v2**
|
| 33 |
+
- CU ruleset: **v3 semantic**、`43a5feef177b389f976361b22ac9d57da65815261282005bc78d1666a37870ce`
|
| 34 |
+
- `job_class=self_local`、`evidence_level=gemm_traced`、**`trace_evidence=metal_kernel`**
|
| 35 |
+
(M5 で graph-fallback から昇格。各 GEMM を実 Metal compute pipeline + launch geometry へ束縛)
|
| 36 |
+
- `mint`: `eligible=false`、`weight=0`、`class=local_self_consistent_v0_1`
|
| 37 |
+
- `mint.ineligible_reasons`: **「Metal kernel-launch-bound sketch, not an intra-kernel accumulator
|
| 38 |
+
proof」/ 非 network-anchored / 非 bonded の 3 件**(M3 で generic、M5 で graph-fallback の失格理由は
|
| 39 |
+
解消。Metal trace は launch-geometry 束縛で CUDA V3 相当の accumulator proof ではないため mint 不適格の
|
| 40 |
+
まま — honest labeling)。`mint.mainnet_ready=false`
|
| 41 |
+
- `prefill_tokens=5`、`decode_tokens=2`、`prefill_graph_steps=5`、`decode_graph_steps=1`
|
| 42 |
+
- `schedule_event_count=13770`(commitment-only)、`gemm_events=trace_event_count=2466`
|
| 43 |
+
- **`canonical_compute_units=41692`(v3 semantic、署名 commit)** = `semantic_compute_units_v3`。
|
| 44 |
+
graph 非依存 / fragmentation-proof、verifier が `prefill/decode` から再計算・照合。
|
| 45 |
+
- `semantic_schedule`: commitment `e6fc731e…`、`expert_route_ops=80`、`attention_ops=20`
|
| 46 |
+
(verifier が pinned architecture から独立再生成して照合)
|
| 47 |
+
- **`expert_route`: root `5e4ea70b…`、`route_event_count=240`**(observer が `ffn_moe_topk` を
|
| 48 |
+
post-compute で読み戻した実 MoE routing。封緘 bundle へ commit し公開 JSON へ再構成)
|
| 49 |
+
- 公開 artifact SHA-256:
|
| 50 |
+
- `<id>.palw`: `b602203cc781c67d8c45c915b29edcef30a1aca22f52a7482693f2551f493dca`
|
| 51 |
+
- `<id>.json`: `2bc670c2de4147fa150126cc36a5f35b5c0600f0835b334e3d36de58ccbf5154`
|
| 52 |
+
- prompt / prompt token IDs / generated token IDs / opening / signing key / owner salt は
|
| 53 |
+
公開 `.palw` / `.json` に含まれない(secret-leakage scan 済み)。
|
| 54 |
+
|
| 55 |
+
## 別 process 検証
|
| 56 |
+
|
| 57 |
+
`palw-verify-bundle` が `.palw` / `.palw.bundle` / `.json` / `palw-state.sqlite3` を復元・再検証し、
|
| 58 |
+
`status=local_restored`、`trust_scope=embedded_local_snapshot`、`receipt_id` / `bundle_id`
|
| 59 |
+
一致(exit 0)。
|
| 60 |
+
|
| 61 |
+
## Hybrid 対応の要点
|
| 62 |
+
|
| 63 |
+
- pinned llama.cpp の qwen35moe loader/graph は 3-section mrope、`ssm_dt` naming、
|
| 64 |
+
per-layer KV-head(layer 0 は linear-attention で `n_head_kv=0`)、bundled vision/MTP
|
| 65 |
+
tensor、full-attention reshape の per-layer head 数を扱うよう修正。
|
| 66 |
+
- Rust adapter(`AdapterProfile::HybridQwen36A3B`): 全演算を**忠実な canonical operation**へ写像
|
| 67 |
+
— `MUL_MAT_ID→ExpertGemm`、`ARGSORT→ExpertRoute{top_k=8}`、`SSM_CONV→SsmConv`、
|
| 68 |
+
`GATED_DELTA_NET→GatedDeltaNet`、`L2_NORM→L2Norm`、`SUM_ROWS→Reduction`、
|
| 69 |
+
`CONCAT/CONT/CPY→TensorCopy`、`UNARY/SCALE/DIV/CLAMP→Elementwise`、`VIEW`/`RESHAPE`/`PERMUTE`/
|
| 70 |
+
`TRANSPOSE` は layout-only。**`Generic` は不使用**。未列挙 op は fail-closed。plain `MUL_MAT` のみ
|
| 71 |
+
accumulator sketch を採取。
|
| 72 |
+
- observer(schema v2)は `ffn_moe_topk`(I32)を post-compute で読み戻し、per-token 選択 expert を
|
| 73 |
+
"route" record として emit。adapter が commitment chain へ fold し `expert_route_root` を封緘。
|
| 74 |
+
- **ggml-metal 計装(M5)**: `ggml_metal_palw_set_dispatch_hook` が全 Metal dispatch を pipeline 名 +
|
| 75 |
+
launch geometry で報告。observer は各 GEMM を ASK→POST window 内の最後���非 `_id` matmul dispatch
|
| 76 |
+
(`kernel_mul_mv_*`)へ束縛(実機で 200/200 window・411/411 GEMM を確認、0 anomaly)。adapter は
|
| 77 |
+
kernel 名 + threads-per-threadgroup を `kernel_id`、threadgroup grid を tile へ束ね
|
| 78 |
+
`TraceEvidenceKind::MetalKernel` を commit。verifier が `TraceCapability::MetalKernel` と照合。
|
| 79 |
+
- 0-element の recurrent state cache tensor は observer が no-compute として skip。
|
| 80 |
+
- 観測 patch: `patches/llama.cpp-palw-observer.patch`、SHA-256
|
| 81 |
+
`d155a88b7c11ee74f48011760cb1a37773a694c8cab28258ee108c85e2f9e02c`。
|
| 82 |
+
|
| 83 |
+
## 限界
|
| 84 |
+
|
| 85 |
+
Metal の kernel-level trace(`trace_evidence=metal_kernel`)は **launch-geometry 束縛**であり、
|
| 86 |
+
CUDA V3 の intra-kernel accumulator sketch とは異なる(より弱い)。そのため `MetalKernel` は
|
| 87 |
+
`KernelSketch` とは**別の evidence kind**として commit し、CUDA 相当を主張しない(honest labeling)。
|
| 88 |
+
mint は依然不適格(「kernel-launch-bound, not accumulator proof」)。単独ノードの Receipt はそれだけで
|
| 89 |
+
ゼロ知識の計算証明ではない。network/hardware/model-Genesis 依存の未達 gate
|
| 90 |
+
R13/R21/R23/R24/R26/R27/R32/R35 は [`../requirements.md`](../requirements.md) の通り。
|
docs/evidence/metal-smoke-2026-07-15.md
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Metal Smoke / Receipt Evidence — 2026-07-15
|
| 2 |
+
|
| 3 |
+
> **Historical schema-v3 evidence.** This page records the `final-v5` run and its historical
|
| 4 |
+
> test counts; it is not the current schema-v4 acceptance baseline. See
|
| 5 |
+
> [`metal-smoke-schema-v4-2026-07-15.md`](metal-smoke-schema-v4-2026-07-15.md) for current evidence.
|
| 6 |
+
|
| 7 |
+
Host: Mac Studio `Mac13,1`, Apple M1 Max (24 GPU cores), 32 GiB unified memory,
|
| 8 |
+
macOS 26.5 arm64 build `25F71`, Metal 4.
|
| 9 |
+
|
| 10 |
+
## Pinned artifacts
|
| 11 |
+
|
| 12 |
+
- llama.cpp commit: `12127defda4f41b7679cb2477a4b0d65ee6a0c8f`
|
| 13 |
+
- llama.cpp version: `10015 (12127def)`
|
| 14 |
+
- model repo/revision: `Qwen/Qwen3-8B-GGUF@7c41481f57cb95916b40956ab2f0b139b296d974`
|
| 15 |
+
- base metadata revision: `Qwen/Qwen3-8B@b968826d9c46dd6066d109eabc6255188de91218`
|
| 16 |
+
- model file: `Qwen3-8B-Q4_K_M.gguf`
|
| 17 |
+
- model bytes: `5,027,783,488`
|
| 18 |
+
- model SHA-256: `d98cdcbd03e17ce47681435b5150e34c1417f50b5c0019dd560e4882c5745785`
|
| 19 |
+
- Hub LFS SHA-256/size、local digest/size、revision sidecar は一致した。
|
| 20 |
+
- official base metadata 8ファイルの SHA-256 と profile shape/dtype は固定値と一致した。
|
| 21 |
+
|
| 22 |
+
Binary SHA-256:
|
| 23 |
+
|
| 24 |
+
- `llama-cli`: `98d1680585d450e25a9a4352b33defd04447e9b344e9251ab3e7935e4bf0f57d`
|
| 25 |
+
- `llama-server`: `ad2946371ae4abe62115dc514dee11f4655ed117d718b714b338b00d82e039e0`
|
| 26 |
+
- `llama-tokenize`: `8caaa7f2fb7c74344169cfdec40d6d5f83ee924320534d877128e8cf84a4ef23`
|
| 27 |
+
- `llama-palw-observer`: `c35ee95d261bbb7689199338fa9444b58d03f057cc164e97c4bd6698d456a166`
|
| 28 |
+
(114,720 bytes; fixed upstream commit と local PALW observer patch を含む)
|
| 29 |
+
|
| 30 |
+
`./scripts/verify-install.sh` は origin/commit、model/base metadata、profile、CMake cache、上記4
|
| 31 |
+
target の version/hash、Metal device、37/37 offload、one-token probe を通過した。
|
| 32 |
+
|
| 33 |
+
## Basic Metal runtime result
|
| 34 |
+
|
| 35 |
+
- Metal device は `MTL0: Apple M1 Max` として検出された。
|
| 36 |
+
- 37/37 model layers が GPU へ offload された。
|
| 37 |
+
- CLI one-token inference は exit 0。測定された prompt processing は 80.5 token/s だった。
|
| 38 |
+
- HTTP server `/health` は `{"status":"ok"}` を返した。
|
| 39 |
+
- `/tokenize` で test text `PALW deterministic receipt` は
|
| 40 |
+
`[73342, 54, 72349, 22567]` になった。
|
| 41 |
+
|
| 42 |
+
同一 request を cache 無効、temperature 0、top-k 0、top-p 1、seed 0、prediction bound 16 で
|
| 43 |
+
2回実行した。両方が同じ stop type `limit` と token IDs を返した。
|
| 44 |
+
|
| 45 |
+
```text
|
| 46 |
+
[271, 73342, 54, 8375, 271, 32313, 11, 358,
|
| 47 |
+
1184, 311, 7071, 700, 1246, 311, 5486, 419]
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
これはこの prompt/runtime instance の repeatability evidence であり、cross-driver、cross-device、
|
| 51 |
+
Metal/CUDA 間の bitwise determinism を証明しない。
|
| 52 |
+
|
| 53 |
+
## Native observer fixed policy
|
| 54 |
+
|
| 55 |
+
現行 binary の header で次を確認した。
|
| 56 |
+
|
| 57 |
+
```text
|
| 58 |
+
n_ctx=4096
|
| 59 |
+
n_batch=1
|
| 60 |
+
n_ubatch=1
|
| 61 |
+
request_batch=1
|
| 62 |
+
parallel_sequences=1
|
| 63 |
+
threads=1
|
| 64 |
+
threads_batch=1
|
| 65 |
+
tensor_repack=false
|
| 66 |
+
flash_attention=false
|
| 67 |
+
context_shift=false
|
| 68 |
+
speculation=false
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
prompt は `--prompt-stdin` で専用 pipe から渡した。通常の Receipt path は
|
| 72 |
+
`--emit-output-bytes` を指定せず、result の `output_bytes=[]` / `output_n_bytes=0` を要求する。
|
| 73 |
+
以下の非干渉比較だけは token IDs に加えて decoded bytes を比較する QA gate のため、明示的な
|
| 74 |
+
output-byte retention を使った。
|
| 75 |
+
|
| 76 |
+
## Current observer non-interference matrix
|
| 77 |
+
|
| 78 |
+
### Short prompt
|
| 79 |
+
|
| 80 |
+
test prompt `PALW`、`n_predict=2` を `off`、`graph`、`sketch` の各 mode で実行した。
|
| 81 |
+
全 process が exit 0 で、次が完全一致した。
|
| 82 |
+
|
| 83 |
+
- prompt token IDs: `[73342, 54]`
|
| 84 |
+
- generated token IDs: `[19114, 374]`
|
| 85 |
+
- decoded output bytes: `[69, 76, 76, 32, 105, 115]`
|
| 86 |
+
- stop reason: `n_predict`
|
| 87 |
+
|
| 88 |
+
| Mode | Native events | Post-compute sketches |
|
| 89 |
+
|---|---:|---:|
|
| 90 |
+
| `off` | 0 | 0 |
|
| 91 |
+
| `graph` | 4,338 | 0 |
|
| 92 |
+
| `sketch` | 4,338 | 975 |
|
| 93 |
+
|
| 94 |
+
同じ short prompt を再度全 mode で実行し、同じ token IDs、bytes、stop reason を得た。
|
| 95 |
+
|
| 96 |
+
### Longer prompt
|
| 97 |
+
|
| 98 |
+
test prompt `PALW deterministic receipt observer non interference`、`n_predict=4` でも全 mode が一致した。
|
| 99 |
+
|
| 100 |
+
- prompt token IDs: `[73342, 54, 72349, 22567, 22067, 2477, 31217]`
|
| 101 |
+
- generated token IDs: `[271, 785, 7286, 498]`
|
| 102 |
+
- decoded output bytes: `[10, 10, 84, 104, 101, 32, 99, 111, 110, 99, 101, 112, 116, 32, 121, 111, 117]`
|
| 103 |
+
- events: off `0`、graph/sketch `14,460`
|
| 104 |
+
- sketches: off/graph `0`、sketch `3,250`
|
| 105 |
+
|
| 106 |
+
short 975件と longer 3,250件の全 sketch は `bits=256`、64桁 hexadecimal だった。header の
|
| 107 |
+
`cuda_kernel_trace` は false で、全 event の `kernel_trace.available=true` は0件、
|
| 108 |
+
`backend=cuda` も0件だった。この matrix は現行 Metal runtime class で callback の output
|
| 109 |
+
non-interference を示す。graph fallback を CUDA kernel trace や暗号学的 proof へ昇格させる
|
| 110 |
+
証拠ではなく、callback synchronization が timing を変え得る点も残る。
|
| 111 |
+
|
| 112 |
+
final publication 前の追加 QA は prompt `PALW observer non interference`、`n_predict=2` を使い、
|
| 113 |
+
親 process に GPU/thread/library/token 関連の誤誘導 environment を設定したまま実行した。child は
|
| 114 |
+
allowlist 以外を消去し、off/graph/sketch の token IDs、decoded bytes、stop reason は完全一致した。
|
| 115 |
+
native event は off `0`、graph `8,676`、sketch `8,676` だった。sketch sample count はこの追加 run
|
| 116 |
+
では保存していないため主張しない。
|
| 117 |
+
|
| 118 |
+
## Signed Self Local Receipt E2E
|
| 119 |
+
|
| 120 |
+
release `palw-metal-receipt` は pinned tokenizer と current observer を実行し、実行前後 manifest
|
| 121 |
+
一致、strict adapter、全 operation pricing、署名済み request/assignment、Receipt build、stateless
|
| 122 |
+
verification、canonical round-trip、secret scan、SQLite acceptance を一度の fail-closed path で完了した。
|
| 123 |
+
その後の CLI hardening で `--prompt-stdin`、`--audit-key-file`、`--output-dir` を必須とし、
|
| 124 |
+
prompt の非空 UTF-8 / 1 MiB 上限を inference 前に検査するようにした。argv で prompt を受ける
|
| 125 |
+
互換 option はない。tokenizer/native observer へも専用 stdin pipe で渡す。
|
| 126 |
+
|
| 127 |
+
現行 publication contract は署名済み `.palw`、公開 JSON、XChaCha20-Poly1305 で認証付き暗号化した
|
| 128 |
+
`.palw.bundle`、schema-v3 `palw-state.sqlite3`、最後に fsync する
|
| 129 |
+
`misaka.palw.receipt-set.v2` completion marker の一式である。audit key は output directory 外の exact
|
| 130 |
+
32-byte raw file(owner-only `0400` / `0600`)、output directory は `0700`、bundle/DB は `0600`、
|
| 131 |
+
公開 `.palw` / JSON / marker は `0644` を要求する。公開 JSON schema は strict
|
| 132 |
+
`misaka.palw.public-receipt.v2` である。
|
| 133 |
+
|
| 134 |
+
正本 artifact:
|
| 135 |
+
|
| 136 |
+
- output directory: `../../receipts/final-v5`(absolute:
|
| 137 |
+
`<REPO>/receipts/final-v5`)、mode `0700`、uid `<UID>`
|
| 138 |
+
- Receipt ID: `ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68`
|
| 139 |
+
- verification bundle ID: `6fd4e57a6cbcd6fc1d9138989960b627c9ee4817bc3ac4ce889a1a1b41d7d63b`
|
| 140 |
+
- canonical envelope:
|
| 141 |
+
[`../../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw`](../../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw)
|
| 142 |
+
— 713 bytes、mode `0644`、SHA-256
|
| 143 |
+
`b43cf66c6fe4803e03355a4c1658a3466d1efacc0121759b01b5a9c431251f38`
|
| 144 |
+
- encrypted verification bundle:
|
| 145 |
+
[`../../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw.bundle`](../../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw.bundle)
|
| 146 |
+
— 337,257 bytes、mode `0600`、SHA-256
|
| 147 |
+
`4b40cefba773142f83cd04f047e952732c5f087b09a6ee8511a9eda99ca1acf2`
|
| 148 |
+
- public metrics:
|
| 149 |
+
[`../../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.json`](../../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.json)
|
| 150 |
+
— 3,427 bytes、mode `0644`、SHA-256
|
| 151 |
+
`3aa158cacd9c790a85f550e232e1b5b3a5c3f1d81aaa0c5b56b57bb08f1dca22`
|
| 152 |
+
- completion marker:
|
| 153 |
+
[`../../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.complete`](../../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.complete)
|
| 154 |
+
— 262 bytes、mode `0644`、SHA-256
|
| 155 |
+
`58d43673f80fa29cd9cab8837d5156ecd4ba42a1d6ab1aacb43365145ea16e39`
|
| 156 |
+
- durable state:
|
| 157 |
+
[`../../receipts/final-v5/palw-state.sqlite3`](../../receipts/final-v5/palw-state.sqlite3)
|
| 158 |
+
— 126,976 bytes、mode `0600`、SHA-256
|
| 159 |
+
`0b1774f89d8fbcd2f0f88771477a173bbae5135b71b5439a090d31f167528702`
|
| 160 |
+
|
| 161 |
+
全5 artifact は uid `<UID>`、link count `1` で、相互に異なる inode だった。audit key は
|
| 162 |
+
`$HOME/.config/misaka-palw/audit-keys/qwen3-8b-final-20260715.key` の exact 32 bytes、mode
|
| 163 |
+
`0600`、uid `<UID>`、link count `1` を検査した。key bytes は publication set に含めない。
|
| 164 |
+
|
| 165 |
+
Public E2E metrics:
|
| 166 |
+
|
| 167 |
+
| Field | Value |
|
| 168 |
+
|---|---:|
|
| 169 |
+
| prompt/prefill tokens | 4 |
|
| 170 |
+
| generated/decode tokens | 2 |
|
| 171 |
+
| prefill graph steps | 4 |
|
| 172 |
+
| decode graph steps | 1 |
|
| 173 |
+
| canonical scheduled operations | 4,890 |
|
| 174 |
+
| authenticated GEMM groups | 1,625 |
|
| 175 |
+
| graph-trace events | 1,625 |
|
| 176 |
+
| canonical compute units | 12,135 |
|
| 177 |
+
|
| 178 |
+
Identity/root evidence:
|
| 179 |
+
|
| 180 |
+
- runtime manifest hash: `2b9c3cd05942f16b36ab348bc71033c33e8f7aa6872ce4c0c0fcac3ba0212bc1`
|
| 181 |
+
- model profile ID: `0c58c66b03bb471a248cb36be954b42945c6694c148370e6852f674ff98e64d4`
|
| 182 |
+
- runtime class ID: `5b2fd7a56d73aa9757e516f92cbc7b4d43995ebe9ed27e445b9b7ab4cd8c7bc9`
|
| 183 |
+
- shape profile ID: `c4f8ae70ab6fda2707d841a64d79d36cff58509ea7f228eb4c93b693e630d674`
|
| 184 |
+
- schedule commitment: `6ee6163863df1a9a715bb42dc89d7431c13e0cb2538d022d074ca07c11aabab7`
|
| 185 |
+
- graph trace root: `ebfd5d143ee57b1db20751ae4d241479fa9447cd5fcc7052fccce129604b78bc`
|
| 186 |
+
- model PALW root: `ad7d0e950531195bc2cf84f112fee6487777f78120c9a809cf9306c7a7a8684f`
|
| 187 |
+
- tokenizer PALW root: `63839f0ab58084bbaa108a877e52bebd685b2c0616fcfab684a08354dee713dd`
|
| 188 |
+
- trace evidence: `graph_fallback`; required evidence level: `gemm_traced`
|
| 189 |
+
|
| 190 |
+
strict parser が受理した evidence から layout-only metadata を除く 4,890 canonical operation を
|
| 191 |
+
versioned CU table で価格付けした。global LM head の optional layer representation も受理対象を
|
| 192 |
+
狭めた���示 rule として検証され、unknown/unsupported/unpriced operation はない。公開 JSON parser は
|
| 193 |
+
unknown field を拒否し、retained `artifacts` / `observer_summary` を含む全 field を authenticated
|
| 194 |
+
receipt、bundle manifest/evidence、固定 privacy policy と一致させる。
|
| 195 |
+
|
| 196 |
+
canonical envelope と encrypted bundle の pre-write scan は prompt text、prompt/generated token
|
| 197 |
+
sequence、output nonce、owner salt、scheduler/worker private key bytes の平文出現を検査し、いずれも
|
| 198 |
+
検出しない。private request/assignment、opening、owner salt、検証用 signer record は bundle の
|
| 199 |
+
authenticated ciphertext に封入する。公開 JSON は prompt/generated tokens、output bytes、nonce、
|
| 200 |
+
salt、private keys を serialized=false と記録し、その全 field を verifier が authenticated receipt、
|
| 201 |
+
bundle manifest/evidence、固定 privacy policy と照合する。提出 prompt に対する published artifact
|
| 202 |
+
directory の fixed-string search も必須である。
|
| 203 |
+
|
| 204 |
+
SQLite verification result:
|
| 205 |
+
|
| 206 |
+
```text
|
| 207 |
+
PRAGMA application_id -> 1346456663 (PALW)
|
| 208 |
+
PRAGMA user_version -> 3
|
| 209 |
+
PRAGMA integrity_check -> ok
|
| 210 |
+
PRAGMA foreign_key_check -> no rows
|
| 211 |
+
receipts -> 1
|
| 212 |
+
jobs -> 1
|
| 213 |
+
pairs / pair_members -> 0 / 0
|
| 214 |
+
future_audits -> 0
|
| 215 |
+
audit_replays -> 0
|
| 216 |
+
mature_sources -> 0
|
| 217 |
+
work_tickets -> 0
|
| 218 |
+
slash_records -> 0
|
| 219 |
+
external_escrows -> 0
|
| 220 |
+
```
|
| 221 |
+
|
| 222 |
+
現行 state contract は `PRAGMA user_version=3`、full `sqlite_master` DDL fingerprint、foreign keys、
|
| 223 |
+
`synchronous=FULL`、WAL checkpoint/truncate を要求する。completion marker 作成前に main DB と全
|
| 224 |
+
artifact/directory entry を fsync するため、portable publication は残存 `-wal` / `-shm` に依存しない。
|
| 225 |
+
legacy schema v1 は暗黙 migrate せず fail-closed に拒否する。
|
| 226 |
+
|
| 227 |
+
別 process の verifier は exit 0 で次を返した。checkpoint 後に `-wal` / `-shm` は残っていない。
|
| 228 |
+
|
| 229 |
+
```text
|
| 230 |
+
status=local_restored
|
| 231 |
+
trust_scope=embedded_local_snapshot
|
| 232 |
+
receipt_id=ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68
|
| 233 |
+
bundle_id=6fd4e57a6cbcd6fc1d9138989960b627c9ee4817bc3ac4ce889a1a1b41d7d63b
|
| 234 |
+
```
|
| 235 |
+
|
| 236 |
+
v2 marker は receipt ID、bundle ID、公開 JSON byte 列の SHA-256 を bind する crash-completion signal
|
| 237 |
+
である。keyed MAC や network authority の署名ではなく、directory を変更できる同一 user は再計算
|
| 238 |
+
できるため、marker 単独では authenticity、authorization、maturity を証明しない。separate verifier
|
| 239 |
+
は exact filenames、same private directory、owner/mode/link/inode、bounded read、marker、bundle AEAD、
|
| 240 |
+
公開 JSON、durable acceptance をまとめて検査する。CLI の local restore は encrypted embedded
|
| 241 |
+
registry snapshot との continuity であり、production network trust root の代替ではない。
|
| 242 |
+
|
| 243 |
+
`pairs=0`、`future_audits=0`、`work_tickets=0` は Self Local Receipt が発行・受理済みでも、
|
| 244 |
+
replication や future audit/challenge maturity をまだ通していないことと整合する。
|
| 245 |
+
|
| 246 |
+
## Rust and adversarial gates
|
| 247 |
+
|
| 248 |
+
crate の宣言 MSRV は Rust 1.81 である。実際に toolchain 1.81.0 を install して最初に locked
|
| 249 |
+
dependency graph を検査したところ、open transitive range が `zeroize 1.9` と `base64ct 1.8.3`
|
| 250 |
+
を選び、その edition-2024 Cargo manifest を Cargo 1.81 が parse できない不一致を発見した。
|
| 251 |
+
`Cargo.toml` に `zeroize = "=1.8.1"` と `base64ct = "=1.7.3"` を exact pin し、lockfile を
|
| 252 |
+
downgrade した後、次を current tree で実行した。
|
| 253 |
+
|
| 254 |
+
```sh
|
| 255 |
+
rustup toolchain install 1.81.0 --profile minimal --component rustfmt,clippy
|
| 256 |
+
cd runtime-palw
|
| 257 |
+
cargo +1.81.0 fmt --all -- --check
|
| 258 |
+
cargo +1.81.0 clippy --locked --all-targets -- -D warnings
|
| 259 |
+
cargo +1.81.0 test --locked --all-targets
|
| 260 |
+
```
|
| 261 |
+
|
| 262 |
+
- library unit tests: 104 passed、2 ignored real-model tests
|
| 263 |
+
- `tests/adversarial.rs`: 11 passed
|
| 264 |
+
- `tests/core_flow.rs`: 3 passed
|
| 265 |
+
- `tests/restart_bundle.rs`: 9 passed
|
| 266 |
+
- total: **127 passed, 2 ignored**(129 discovered)
|
| 267 |
+
- fmt: passed
|
| 268 |
+
- locked all-target Clippy with warnings denied: passed
|
| 269 |
+
|
| 270 |
+
strict public JSON v2 hygiene change と final-v5 発行後に上記 Rust gate をすべて再実行し、同じ結果を得た。
|
| 271 |
+
ignored 2件は pinned Qwen model/Metal observer を必要とする実モデル test である。release build を
|
| 272 |
+
使い、親 process の GPU/thread/Hugging Face/dynamic-loader environment を意図的に汚染した手動 gate
|
| 273 |
+
では child environment isolation を含めて 2/2 passed した。Clippy pedantic の
|
| 274 |
+
`module_name_repetitions` は versioned public protocol API 名を module 外でも自己記述的にする
|
| 275 |
+
意図的な naming policy としてだけ allow し、それ以外の warning は `-D warnings` で拒否した。
|
| 276 |
+
|
| 277 |
+
adversarial suite は全 consensus Receipt field、全 request/assignment field、signature/envelope、
|
| 278 |
+
nonce/prompt/output/runtime/network binding、schedule reorder/insert/delete、CU/evidence mismatch、dummy
|
| 279 |
+
signer/assignment、fork/credential/runtime instance、k=2 self/duplicate/reuse、serialized secret leakage、
|
| 280 |
+
replay cardinality を mutation し、fail-closed rejection を確認した。
|
| 281 |
+
|
| 282 |
+
Work Ticket regression gate は `MatureEvidence` の field/low-level constructor が非公開であることに
|
| 283 |
+
加え、Self Local audit の typed `Mature` state、Self Replicated pair、External escrow settlement だけを
|
| 284 |
+
public 生成経路とする。各 evidence は audit eligible epoch、pair matched epoch、settlement epoch を
|
| 285 |
+
封入する。durable registration は accepted receipt/pair の network/class/CU と照合し、ticket issue は
|
| 286 |
+
その exact epoch より前を拒否する。raw maturity marker と caller-supplied epoch の public bypass はない。
|
| 287 |
+
|
| 288 |
+
これは core protocol/state-machine の test evidence であり、production service の完了証跡ではない。
|
| 289 |
+
External escrow は payment rail、durable monetary balance/authority、settlement/refund/slash との原子的
|
| 290 |
+
連携を持たない。future audit は production beacon delivery、auditor、re-execution executor を持たず、
|
| 291 |
+
canary/bond は in-memory state を中心とし、durable balance、health bridge、automatic slash、appeal、
|
| 292 |
+
atomic debit を持たない。demand bonus も整数 weight/cap/terms の core 演算までで、funded demand
|
| 293 |
+
authority と payment settlement は未接続である。ローカル CLI が生成する scheduler/worker key、
|
| 294 |
+
network/job ID を production network 登録 identity と解釈しない。
|
| 295 |
+
|
| 296 |
+
## CUDA host-only sanitizer evidence
|
| 297 |
+
|
| 298 |
+
この Apple host には `nvcc` と NVIDIA device がないため、CUDA implementation/device CTest は
|
| 299 |
+
compile/run していない。host-only build の CTest は 3/3 passed した。さらに
|
| 300 |
+
`build/palw-cuda-sanitize` を AppleClang 21、Debug、
|
| 301 |
+
`-Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer` で構成した。
|
| 302 |
+
|
| 303 |
+
macOS のこの ASan runtime は leak detection を support せず、`detect_leaks=1` 試行は環境理由で
|
| 304 |
+
abort した。`ASAN_OPTIONS=detect_leaks=0:abort_on_error=1` と
|
| 305 |
+
`UBSAN_OPTIONS=halt_on_error=1` で host CTest を再実行し、同じ3/3 が sanitizer report なしで通過した。
|
| 306 |
+
|
| 307 |
+
1. C++ ABI / canonical codec contract
|
| 308 |
+
2. C header contract
|
| 309 |
+
3. production non-issuance nested CMake gate
|
| 310 |
+
|
| 311 |
+
production gate は `PALW_CUDA_PRODUCTION_KERNEL_TRACE=ON` を意図どおり reject した。現在の CUDA
|
| 312 |
+
transport は final-output sketch であり、true partial accumulator、exact kernel identity、NVIDIA
|
| 313 |
+
実機 evidence がない。よってこの host-only result を R32 completion または CUDA Receipt 発行の
|
| 314 |
+
根拠には使用しない。
|
| 315 |
+
|
| 316 |
+
## CI definitions
|
| 317 |
+
|
| 318 |
+
[`../../.github/workflows/palw-ci.yml`](../../.github/workflows/palw-ci.yml) は YAML parse gate を通過し、
|
| 319 |
+
次を定義する。remote Actions run はこの host では実行していない。
|
| 320 |
+
|
| 321 |
+
- push/pull request: Ubuntu 24.04 へ Rust 1.81.0 を install し、上記 fmt、locked all-target
|
| 322 |
+
Clippy/test を再実行する MSRV job。
|
| 323 |
+
- push/pull request: Linux で host-only CUDA ABI/codec/closed-production-gate を ASan+UBSan、
|
| 324 |
+
leak detection、warning-as-error 付きで実行する job。
|
| 325 |
+
- manual dispatch only: `self-hosted, linux, x64, nvidia` runner と exact real SM architecture で
|
| 326 |
+
experimental CUDA device transport を build/test する job。device 0 の実 compute capability と
|
| 327 |
+
selected `*-real` architecture の一致も configure 前に要求する。
|
| 328 |
+
|
| 329 |
+
manual NVIDIA job は device executable を直接実行するため、return code 77 は CTest skip ではなく
|
| 330 |
+
failure になる。一方で `PALW_CUDA_PRODUCTION_KERNEL_TRACE=OFF` かつ job 名が `not R32` であり、
|
| 331 |
+
成功しても final-output transport の実験 test にすぎない。CI definition 自体の追加も remote run
|
| 332 |
+
成功を示さないため、この evidence は R32/R35 completion を主張しない。
|
| 333 |
+
|
| 334 |
+
全 checkout は action SHA を固定し credential persistence を無効化する。automatic run は同じ
|
| 335 |
+
event/ref で cancel 可能だが、manual NVIDIA run は event 名で別 concurrency group に置き、push に
|
| 336 |
+
よる途中 cancel を受けない。
|
docs/evidence/metal-smoke-schema-v4-2026-07-15.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Metal Schema-v4 Receipt Evidence — 2026-07-15
|
| 2 |
+
|
| 3 |
+
この文書は current source から Apple M1 Max で生成した schema-v4 Self Local Receipt set と、
|
| 4 |
+
同じ tree に対する検証 gate の記録である。current canonical set は
|
| 5 |
+
[`../../receipts/final-v6/`](../../receipts/final-v6/) に置く。以前の schema-v3 実行は
|
| 6 |
+
[`metal-smoke-2026-07-15.md`](metal-smoke-2026-07-15.md) に historical evidence として残す。
|
| 7 |
+
|
| 8 |
+
## Install / device gate
|
| 9 |
+
|
| 10 |
+
`scripts/install.sh` と `scripts/verify-install.sh` の full device gate は、固定した Qwen3-8B GGUF、
|
| 11 |
+
official base metadata、llama.cpp commit `12127defda4f41b7679cb2477a4b0d65ee6a0c8f`、4 build target の
|
| 12 |
+
revision/hash を照合した。Metal device は Apple M1 Max、Qwen3-8B の 37/37 layers を GPU へ offloadし、
|
| 13 |
+
one-token probe まで通過した。
|
| 14 |
+
|
| 15 |
+
## Current canonical Receipt set
|
| 16 |
+
|
| 17 |
+
- Receipt ID: `eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131`
|
| 18 |
+
- verification bundle ID: `359f1bedaeefc1e140bf8c0dbba11582cb5cc0be428dcd95bc6077721f8096e9`
|
| 19 |
+
|
| 20 |
+
| Artifact | Bytes | SHA-256 |
|
| 21 |
+
|---|---:|---|
|
| 22 |
+
| [`eb51…8131.palw`](../../receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.palw) | 713 | `85ecb4281a1cb4abf26d6e3e70c84bfb3cc2a6dad80e2022ea4a356165345a75` |
|
| 23 |
+
| [`eb51…8131.json`](../../receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.json) | 3,427 | `03bee886144a2c64dd5f4d2207f86c748f5a3e7891b43f82f077f051342c3d0b` |
|
| 24 |
+
| [`eb51…8131.palw.bundle`](../../receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.palw.bundle) | 403,066 | `b475193fcfe1aea3189066790f925cc3682d2ff5a48cdfa061d62db85d0cff78` |
|
| 25 |
+
| [`eb51…8131.complete`](../../receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.complete) | 262 | `f3dc4e142eb602977c1ac065d51297418c8dca3967b6cdb53eb0dfb447d5c77b` |
|
| 26 |
+
| [`palw-state.sqlite3`](../../receipts/final-v6/palw-state.sqlite3) | 282,624 | `8a740c342a12c83ae211edfa8776b93a14ea9369e3d7bd19a1e780e0724c471e` |
|
| 27 |
+
|
| 28 |
+
公開 JSON は strict `misaka.palw.public-receipt.v2` で、prefill 5 tokens、decode 2 tokens、
|
| 29 |
+
5,868 canonical operations、1,950 GEMM events、14,562 canonical CUを記録する。主要 binding は次のとおり。
|
| 30 |
+
|
| 31 |
+
- operation schedule commitment: `ad5b7b98c81354be64a9021cb7a20838ccf9d555576fc0743c79286ea29681f6`
|
| 32 |
+
- GEMM trace root: `53c906957957aa34cd5c66fc9ad8c863e541732ead6728e3125d78dff6c133f1`
|
| 33 |
+
- runtime manifest hash: `5920accc3a0a0529c5f0c0a4050d6bf00d4d8fdf2b9772b64af2b4fdac2b84dd`
|
| 34 |
+
- model profile ID: `0c58c66b03bb471a248cb36be954b42945c6694c148370e6852f674ff98e64d4`
|
| 35 |
+
- runtime class ID: `c38307d57c847f3c276247411c563daf50fc7576cf1f6488ab29fe9a56970c5c`
|
| 36 |
+
- shape profile ID: `c4f8ae70ab6fda2707d841a64d79d36cff58509ea7f228eb4c93b693e630d674`
|
| 37 |
+
|
| 38 |
+
## Separate verification and durable state
|
| 39 |
+
|
| 40 |
+
`palw-verify-bundle` を別 process で実行し、exit 0、`status=local_restored`、
|
| 41 |
+
`trust_scope=embedded_local_snapshot` を得た。これは暗号化 bundle 内の発行時 registry snapshot との
|
| 42 |
+
local continuity であり、外部 network authority や後日の revocation を独立に証明しない。
|
| 43 |
+
|
| 44 |
+
SQLite は application ID `PALW` (`1346456663`)、schema version 4、`integrity_check=ok`、
|
| 45 |
+
foreign-key violationなしだった。receipt/job は1/1、pair、audit、WorkTicket、slash、external settlement
|
| 46 |
+
関連 state はすべて0である。portable set は最終検証後に `-wal` / `-shm` sidecarを持たない。
|
| 47 |
+
|
| 48 |
+
## Rust / CUDA gates
|
| 49 |
+
|
| 50 |
+
Rust/Cargo 1.81.0 で `fmt --check`、`check --locked --all-targets`、
|
| 51 |
+
`clippy --locked --all-targets -D warnings`、`test --locked --all-targets` を通過した。通常 suite は
|
| 52 |
+
**166 passed, 2 ignored**(168 discovered)。pinned model と Metal observer を要求する ignored 2件は、
|
| 53 |
+
release build と親環境汚染 gate を有効にした手動実モデル実行で **2/2 passed** した。したがって実行済み
|
| 54 |
+
test は合計168件だが、通常 gate の表記は166 passed / 2 ignoredのままとする。
|
| 55 |
+
|
| 56 |
+
CUDA host-only gate は通常 build 3/3、AppleClang ASan+UBSan 3/3を通過し、production enable configure は
|
| 57 |
+
意図どおり拒否された。この host に `nvcc` / NVIDIA device はないため device E2E は未実施であり、
|
| 58 |
+
これらはR32 completion evidenceではない。現行 CUDA observerはtrue producer accumulatorとproduction
|
| 59 |
+
exact kernel identityを証明せず、CUDA production Receipt発行はfail-closedのままである。
|
| 60 |
+
|
| 61 |
+
上記はこのMetal Receiptを固定した時点のgateである。その後のRTX 4060 Ti/SM89
|
| 62 |
+
実験 gate、standalone true-accumulator primitive、現行Rust test数は
|
| 63 |
+
[`cuda-wsl-sm89-2026-07-15.md`](cuda-wsl-sm89-2026-07-15.md) が正本である。Metal Receiptの
|
| 64 |
+
canonical ID/bytesはこの追加検証で変更しない。
|
| 65 |
+
|
| 66 |
+
## Scope
|
| 67 |
+
|
| 68 |
+
この証跡は current schema-v4 local Receipt publication、復元、durable acceptance と、Metal runtime classの
|
| 69 |
+
local E2Eを示す。graph fallbackをCUDA kernel traceと同一��せず、local ephemeral signer/embedded snapshotを
|
| 70 |
+
production network authority、maturity、payment railの証明として扱わない。scheduler、beacon、auditor、bond、
|
| 71 |
+
external authority/paymentのproduction service未実装範囲は
|
| 72 |
+
[`../requirements.md`](../requirements.md) の `In progress` / `Blocked` を維持する。repository-scope の
|
| 73 |
+
baselineを固定したことはProduction Network readinessを意味せず、R13/R21/R23/R24/R26/R27/R35の未達gateは
|
| 74 |
+
内部統合と外部境界をrequirementsで分離する。R32はこの証跡固定時にはhard `Blocked`
|
| 75 |
+
だったが、後続SM89 gateで外部hardware blockerが解消したため現行statusは `In progress`である。
|
docs/protocol-v1.md
ADDED
|
@@ -0,0 +1,954 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MISAKA PALW Receipt Protocol V1
|
| 2 |
+
|
| 3 |
+
本書は `runtime-palw` の現行 Rust 実装を wire protocol の正本として記述する。ここにない
|
| 4 |
+
production 承認、決済連携、attestation を Receipt から推論してはならない。実装と本書が
|
| 5 |
+
一致しない場合は Receipt を発行しない。
|
| 6 |
+
|
| 7 |
+
## 1. Primitive types
|
| 8 |
+
|
| 9 |
+
- `Hash32`、commitment、ID、`NetworkId`: 固定 32 byte
|
| 10 |
+
- `u16` / `u32` / `u64` / `i64`: big endian。`i64` は two's-complement
|
| 11 |
+
- `bool`: `u8(0)` または `u8(1)`
|
| 12 |
+
- enum: variant tag `u8` の後に variant 固有 payload
|
| 13 |
+
- Ed25519 public key: 32 byte、signature: 64 byte、algorithm tag: `0`
|
| 14 |
+
- `Option<T>`: `u8(0)`、または `u8(1) || encode(T)`
|
| 15 |
+
|
| 16 |
+
`NetworkId` は UTF-8 名ではなく `Hash32` である。consensus encoding へ `usize`、float、map、
|
| 17 |
+
JSON text、platform enum、暗黙の default を直接入れない。
|
| 18 |
+
|
| 19 |
+
Receipt、scheduler message、future beacon、canary precommit、bond/external authority evidenceのEd25519
|
| 20 |
+
verificationは`verify_strict`を使う。small-order/weak public keyはworker signer、scheduler、beacon、bond、
|
| 21 |
+
external authorityのregistry recordとして拒否し、key IDが一致してもauthorization identityとして扱わない。
|
| 22 |
+
|
| 23 |
+
## 2. Canonical encoding
|
| 24 |
+
|
| 25 |
+
```text
|
| 26 |
+
LP(x) = u64be(len(x)) || x
|
| 27 |
+
bytes(x) = LP(x)
|
| 28 |
+
string(s) = LP(utf8(s))
|
| 29 |
+
vector(xs) = u64be(count(xs)) || encode(xs[0]) || ...
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
固定長 hash は LP を付けず 32 byte を直接書く。struct は本書に記した順で field を連結する。
|
| 33 |
+
decoder は未知の version/tag、truncated/trailing bytes、invalid UTF-8、非canonical bool/option、
|
| 34 |
+
上限超過を拒否し、decode 後の再encodeが入力と一致しなければ拒否する。現行 reader の blob
|
| 35 |
+
上限は 64 MiB、item count 上限は 16,777,216 である。
|
| 36 |
+
|
| 37 |
+
## 3. Domain-separated hash
|
| 38 |
+
|
| 39 |
+
```text
|
| 40 |
+
H(tag, part_0, ..., part_n) = SHA3-256(
|
| 41 |
+
LP("MISAKA/PALW") ||
|
| 42 |
+
LP(utf8(tag)) ||
|
| 43 |
+
u16be(schema_version) ||
|
| 44 |
+
LP(part_0) || ... || LP(part_n)
|
| 45 |
+
)
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
part count 自体は入らないが、すべての part が LP されるため partition は曖昧にならない。
|
| 49 |
+
raw concatenation と domain の流用は禁止する。core V1 が使用する domain は次のとおり。
|
| 50 |
+
|
| 51 |
+
```text
|
| 52 |
+
model-artifact-leaf/v1 model-artifact-node/v1
|
| 53 |
+
model-profile/v1 runtime-class/v1 runtime-manifest/v1
|
| 54 |
+
shape-profile/v1 cu-ruleset/v1
|
| 55 |
+
job-request/v1 assignment/v1 signer-key/v1
|
| 56 |
+
prompt/v1 output/v1 owner/v1
|
| 57 |
+
job-nullifier/v1 execution-nullifier/v1
|
| 58 |
+
schedule-init/v1 schedule-step/v1 schedule-final/v1
|
| 59 |
+
gemm-trace-scheme/v1 gemm-trace-init/v1 gemm-trace-step/v1
|
| 60 |
+
gemm-trace-final/v1
|
| 61 |
+
receipt-body/v1 receipt-id/v1 receipt-signature/v1
|
| 62 |
+
replica-match/v1 pair-id/v1
|
| 63 |
+
future-beacon/v1 audit-policy/v1
|
| 64 |
+
audit-selection/v1 audit-challenge/v1
|
| 65 |
+
audit-replay-result/v1 audit-replay-submission/v1
|
| 66 |
+
work-ticket/v2 local-maturity-basis/v2 canary/v1
|
| 67 |
+
canary-precommit/v1 durable-slash-offense/v2 bond-release/v1
|
| 68 |
+
bond-funding-attestation/v1 slash-appeal/v1 slash-decision/v1
|
| 69 |
+
slash-default-uphold/v1 external-escrow/v1 external-payment-command/v1
|
| 70 |
+
external-funding-attestation/v1 external-demand-weight-grant/v1
|
| 71 |
+
external-terminal-confirmation/v1
|
| 72 |
+
llama-cuda-dispatch/v1 cuda-kernel-entry/v1
|
| 73 |
+
verification-bundle-receipt/v1 verification-bundle-public/v1
|
| 74 |
+
verification-bundle-aad/v1 verification-bundle-aead-key/v1
|
| 75 |
+
verification-bundle-id/v1
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
`request/v1` は generic helper `commit_request` に残るが、署名済み `JobRequestV1` の ID には
|
| 79 |
+
使用しない。job request の唯一の domain は `job-request/v1` である。deterministic policy と
|
| 80 |
+
Qwen Metal profile はさらに `lora-set/v1`、`control-vector-set/v1`、
|
| 81 |
+
`thinking-policy/v1`、`workspace-policy/v1`、`thread-policy/v1`、
|
| 82 |
+
`qwen-native-observer-mapping/v1` 等の artifact domain を runtime identity の内側で使う。
|
| 83 |
+
|
| 84 |
+
## 4. Artifact and model identity
|
| 85 |
+
|
| 86 |
+
artifact は slash-separated relative path の辞書順で処理する。空、absolute、末尾 `/`、空要素、
|
| 87 |
+
`.`、`..`、backslash、非UTF-8、重複、symlink、非regular file は拒否する。
|
| 88 |
+
|
| 89 |
+
```text
|
| 90 |
+
leaf_i = H(
|
| 91 |
+
"model-artifact-leaf/v1",
|
| 92 |
+
utf8(relative_path_i),
|
| 93 |
+
u64be(file_size_i),
|
| 94 |
+
file_bytes_i
|
| 95 |
+
)
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
file は streaming hash するが上式と同じ framing である。各 level の leaf/node が奇数なら
|
| 99 |
+
末尾を複製し、`H("model-artifact-node/v1", left, right)` で二分木を作る。artifact は空に
|
| 100 |
+
できない。
|
| 101 |
+
|
| 102 |
+
`ModelProfile` canonical order:
|
| 103 |
+
|
| 104 |
+
1. `architecture: string`
|
| 105 |
+
2. `base_repository: string`
|
| 106 |
+
3. `immutable_revision: string`
|
| 107 |
+
4. `topology: u8` (`0=Dense`, `1=MixtureOfExperts`)
|
| 108 |
+
5. `tokenizer: string`
|
| 109 |
+
6. `weight_artifact_root: Hash32`
|
| 110 |
+
7. `tokenizer_artifact_root: Hash32`
|
| 111 |
+
8. `chat_template_digest: Hash32`
|
| 112 |
+
9. `special_tokens_digest: Hash32`
|
| 113 |
+
10. `hidden_size: u32`
|
| 114 |
+
11. `attention_heads: u32`
|
| 115 |
+
12. `kv_heads: u32`
|
| 116 |
+
13. `head_dim: u32`
|
| 117 |
+
14. `layer_count: u32`
|
| 118 |
+
15. `intermediate_size: u32`
|
| 119 |
+
16. `rope: string`
|
| 120 |
+
17. `rope_theta: u64`
|
| 121 |
+
18. `rope_scaling_millionths: u64`
|
| 122 |
+
19. `native_context_tokens: u32`
|
| 123 |
+
20. `vocabulary: u32`
|
| 124 |
+
21. `precision: string`
|
| 125 |
+
|
| 126 |
+
```text
|
| 127 |
+
model_profile_id = H("model-profile/v1", encode(ModelProfile))
|
| 128 |
+
```
|
| 129 |
+
|
| 130 |
+
全 string、artifact hash、次元、RoPE integer parameter は nonzero/nonempty でなければならない。
|
| 131 |
+
`hidden_size / attention_heads == head_dim`、`attention_heads % kv_heads == 0` も検査する。
|
| 132 |
+
Q4 GGUF は fixed inference artifact であり、学習済み base revision と量子化 artifact の双方を
|
| 133 |
+
profile に bind する。
|
| 134 |
+
|
| 135 |
+
## 5. Runtime class, deterministic policy, and manifest
|
| 136 |
+
|
| 137 |
+
`BackendKind` canonical encoding:
|
| 138 |
+
|
| 139 |
+
- `0=CUDA`: `cuda_version, driver_version, cublas_version, sm_architecture`(各 string)、
|
| 140 |
+
`cublas_policy_digest: Hash32`
|
| 141 |
+
- `1=Metal`: `metal_version, driver_build, gpu_family, language_version`(各 string)、
|
| 142 |
+
`metallib_digest: Hash32`
|
| 143 |
+
- `2=CPU`: `isa_class, blas_version`(各 string)、`affinity_policy_digest: Hash32`
|
| 144 |
+
|
| 145 |
+
`TraceCapability`: `0=None`, `1=GraphFallback`, `2=KernelSketch`。
|
| 146 |
+
|
| 147 |
+
`RuntimeClass` canonical order:
|
| 148 |
+
|
| 149 |
+
1. `backend: BackendKind`
|
| 150 |
+
2. `runtime_version: string`
|
| 151 |
+
3. `runtime_source_repository: string`
|
| 152 |
+
4. `runtime_source_commit: string`
|
| 153 |
+
5. `runtime_binary_digest: Hash32`
|
| 154 |
+
6. `dirty_patch_digest: Hash32`
|
| 155 |
+
7. `operating_system: string`
|
| 156 |
+
8. `host_architecture: string`
|
| 157 |
+
9. `device_class: string`
|
| 158 |
+
10. `accelerator_api: string`
|
| 159 |
+
11. `compiler_version: string`
|
| 160 |
+
12. `build_flags_digest: Hash32`
|
| 161 |
+
13. `kernel_binary_digest: Hash32`
|
| 162 |
+
14. `kernel_algorithm_digest: Hash32`
|
| 163 |
+
15. `accelerator_count: u32`
|
| 164 |
+
16. `tensor_parallel: u32`
|
| 165 |
+
17. `split_policy: string`
|
| 166 |
+
18. `quantization: string`
|
| 167 |
+
19. `kv_cache_precision: string`
|
| 168 |
+
20. `flash_attention: bool`
|
| 169 |
+
21. `tensor_repack: bool`
|
| 170 |
+
22. `context_size: u32`
|
| 171 |
+
23. `batch_size: u32`
|
| 172 |
+
24. `micro_batch_size: u32`
|
| 173 |
+
25. `thread_count: u32`
|
| 174 |
+
26. `trace_capability: TraceCapability`
|
| 175 |
+
27. `deterministic_policy: DeterministicPolicy`
|
| 176 |
+
|
| 177 |
+
`DeterministicPolicy` の nested canonical order は
|
| 178 |
+
`temperature_millionths:u32, top_p_millionths:u32, top_k:u32, batch_size:u32,
|
| 179 |
+
tensor_parallel:u32, parallel_sequences:u32, context_shift_enabled:bool,
|
| 180 |
+
speculative_decoding_enabled:bool, dynamic_fit_enabled:bool, random_seed:u64,
|
| 181 |
+
kernel_graph_id:Hash32, quantization_artifact_id:Hash32, lora_adapters_digest:Hash32,
|
| 182 |
+
control_vectors_digest:Hash32, thinking_policy_digest:Hash32, workspace_policy_digest:Hash32,
|
| 183 |
+
thread_policy_digest:Hash32` である。
|
| 184 |
+
|
| 185 |
+
V1 strict policy は temperature 0、top-p 1,000,000、top-k 0、batch/tensor-parallel/
|
| 186 |
+
parallel-sequences各1、context shift/speculative/dynamic fit無効を要求する。
|
| 187 |
+
|
| 188 |
+
```text
|
| 189 |
+
runtime_class_id = H("runtime-class/v1", encode(RuntimeClass))
|
| 190 |
+
```
|
| 191 |
+
|
| 192 |
+
Qwen Metal profile の `kernel_graph_id` は pinned llama.cpp commit、
|
| 193 |
+
`qwen_adapter_mapping_id_v1()`、native graph variant、prefill/decode serialization policyを
|
| 194 |
+
まとめて hash する。したがって graph-to-CU mapping の変更も runtime class を変更する。
|
| 195 |
+
|
| 196 |
+
`ShapeProfile` canonical order は `batch_size:u32, max_context_tokens:u32,
|
| 197 |
+
max_decode_tokens:u32, max_prefill_tokens:u32`。batch は1、各上限は nonzero、prefill/decode
|
| 198 |
+
各上限は context 以下とする。
|
| 199 |
+
|
| 200 |
+
`RuntimeManifest` canonical order:
|
| 201 |
+
|
| 202 |
+
1. `manifest_version: u16` (=1)
|
| 203 |
+
2. `model_profile: ModelProfile`
|
| 204 |
+
3. `runtime_class: RuntimeClass`
|
| 205 |
+
4. `shape_profile: ShapeProfile`
|
| 206 |
+
5. `model_artifact_digest: Hash32`
|
| 207 |
+
6. `model_artifact_size: u64`
|
| 208 |
+
7. `runtime_device_digest: Hash32`
|
| 209 |
+
8. `loaded_libraries_digest: Hash32`
|
| 210 |
+
9. `environment_allowlist_digest: Hash32`
|
| 211 |
+
10. `build_provenance_digest: Hash32`
|
| 212 |
+
11. `schedule_schema_version: u16` (=1)
|
| 213 |
+
12. `trace_schema_version: u16` (=1)
|
| 214 |
+
13. `cu_ruleset_id: Hash32`
|
| 215 |
+
14. `trace_scheme_id: Hash32`
|
| 216 |
+
|
| 217 |
+
`model_artifact_digest == model_profile.weight_artifact_root`、batch/context、CU ruleset を相互検査し、
|
| 218 |
+
`runtime_manifest_hash = H("runtime-manifest/v1", encode(RuntimeManifest))` とする。
|
| 219 |
+
|
| 220 |
+
現行Qwen Metal issuanceはtokenizer、observer、host/source identity childのinherited environmentを消去し、
|
| 221 |
+
`LANG=C`、`LC_ALL=C`だけを設定する。host/source identity helperはabsolute executable pathを使い、この
|
| 222 |
+
exact mapを`environment_allowlist_digest`へbindする。親processの追加environmentはcompute childへ継承しない。
|
| 223 |
+
|
| 224 |
+
## 6. Scheduler-signed request and assignment
|
| 225 |
+
|
| 226 |
+
`JobClass`: `0=SelfLocal`, `1=SelfReplicated`, `2=ExternalReplicated`。
|
| 227 |
+
`EvidenceLevel`: `0=Wrapper`, `1=RuntimeObserved`, `2=GemmTraced`。replicated class は
|
| 228 |
+
`GemmTraced` を要求する。
|
| 229 |
+
|
| 230 |
+
`ExecutionConstraintsV1` order:
|
| 231 |
+
|
| 232 |
+
1. `model_profile_id: Hash32`
|
| 233 |
+
2. `runtime_class_id: Hash32`
|
| 234 |
+
3. `shape_profile_id: Hash32`
|
| 235 |
+
|
| 236 |
+
`JobRequestV1` canonical order:
|
| 237 |
+
|
| 238 |
+
1. `version: u16` (=1)
|
| 239 |
+
2. `network_id: Hash32`
|
| 240 |
+
3. `scheduler_job_id: Hash32`
|
| 241 |
+
4. `job_class: JobClass`
|
| 242 |
+
5. `prompt_commitment: Hash32`
|
| 243 |
+
6. `shared_output_nonce: Hash32`
|
| 244 |
+
7. `constraints: ExecutionConstraintsV1`
|
| 245 |
+
8. `required_evidence_level: EvidenceLevel`
|
| 246 |
+
9. `issued_epoch: u64`
|
| 247 |
+
10. `expires_epoch: u64`
|
| 248 |
+
11. `external_escrow_reference: Option<Hash32>`
|
| 249 |
+
|
| 250 |
+
`ExternalReplicated` は nonzero escrow reference が必須、それ以外は `None` が必須。
|
| 251 |
+
|
| 252 |
+
```text
|
| 253 |
+
request_commitment = H("job-request/v1", encode(JobRequestV1))
|
| 254 |
+
```
|
| 255 |
+
|
| 256 |
+
`AssignmentV1` canonical order:
|
| 257 |
+
|
| 258 |
+
1. `version: u16` (=1)
|
| 259 |
+
2. `network_id: Hash32`
|
| 260 |
+
3. `request_commitment: Hash32`
|
| 261 |
+
4. `scheduler_job_id: Hash32`
|
| 262 |
+
5. `job_class: JobClass`
|
| 263 |
+
6. `replica_slot: u8`
|
| 264 |
+
7. `worker_credential_id: Hash32`
|
| 265 |
+
8. `runtime_instance_id: Hash32`
|
| 266 |
+
9. `assignment_id: Hash32`
|
| 267 |
+
10. `issued_epoch: u64`
|
| 268 |
+
11. `expires_epoch: u64`
|
| 269 |
+
|
| 270 |
+
```text
|
| 271 |
+
assignment_commitment = H("assignment/v1", encode(AssignmentV1))
|
| 272 |
+
```
|
| 273 |
+
|
| 274 |
+
assignment は network/request/job/class を request と一致させ、validity interval を request 内へ
|
| 275 |
+
包含させる。Self Local は slot 0、replicated は slot 0/1 のみ。
|
| 276 |
+
|
| 277 |
+
request/assignment envelope は同じ orderを使う。
|
| 278 |
+
|
| 279 |
+
```text
|
| 280 |
+
u16be(envelope_version=1) ||
|
| 281 |
+
LP(canonical_body) ||
|
| 282 |
+
scheduler_key_id:Hash32 ||
|
| 283 |
+
u8(signature_algorithm=0) ||
|
| 284 |
+
signature:64-byte
|
| 285 |
+
```
|
| 286 |
+
|
| 287 |
+
signature message はそれぞれ `request_commitment` / `assignment_commitment` そのもの。
|
| 288 |
+
`scheduler_key_id = H("signer-key/v1", scheduler_public_key)`。network-scoped registry は key の
|
| 289 |
+
valid-from/through、revocation、message epoch、weak-key rejectionを検査し、signatureはstrict Ed25519で
|
| 290 |
+
検証する。miner が job ID、nonce、slot、assignment IDを自己生成したものは authorization record に
|
| 291 |
+
ならない。現行local Receipt CLIが自己生成するscheduler key/snapshotはfixture boundaryであり、
|
| 292 |
+
production scheduler/governance authorizationを表さない。
|
| 293 |
+
|
| 294 |
+
## 7. Prompt, output, owner, and nullifiers
|
| 295 |
+
|
| 296 |
+
prompt text は commit しない。tokenizerの正確な prompt token列を次で commit する。
|
| 297 |
+
|
| 298 |
+
```text
|
| 299 |
+
PromptTokens = u64be(count) || concat(u32be(token_id_i))
|
| 300 |
+
prompt_commitment = H(
|
| 301 |
+
"prompt/v1", network_id, scheduler_job_id,
|
| 302 |
+
shared_output_nonce, PromptTokens
|
| 303 |
+
)
|
| 304 |
+
```
|
| 305 |
+
|
| 306 |
+
`StopReason`:
|
| 307 |
+
|
| 308 |
+
- `0=EndOfSequence(u32 eos_token_id)`
|
| 309 |
+
- `1=LengthLimit`
|
| 310 |
+
- `2=ContextLimit`
|
| 311 |
+
- `3=StopSequence(Hash32 stop_sequence_digest)`
|
| 312 |
+
|
| 313 |
+
`Cancelled` variant は存在しない。cancelled execution から Receipt を発行しない。現行request
|
| 314 |
+
schemaにはstop-sequence list fieldがないため、`StopSequence` digestが特定requestの設定へbindして
|
| 315 |
+
いるかをverifierが別途検査する実装もまだない。
|
| 316 |
+
|
| 317 |
+
```text
|
| 318 |
+
CanonicalOutput =
|
| 319 |
+
u64be(token_count) || concat(u32be(generated_token_id_i)) || encode(stop_reason)
|
| 320 |
+
|
| 321 |
+
output_commitment = H(
|
| 322 |
+
"output/v1", network_id, job_nullifier,
|
| 323 |
+
shared_output_nonce, CanonicalOutput
|
| 324 |
+
)
|
| 325 |
+
```
|
| 326 |
+
|
| 327 |
+
k=2 の両slotは signed request の同じ nonceを使う。nonce、prompt IDs、output IDs、owner salt は
|
| 328 |
+
Receipt bodyへ載せず、stateless verifier への private opening とする。
|
| 329 |
+
|
| 330 |
+
```text
|
| 331 |
+
owner_commitment = H(
|
| 332 |
+
"owner/v1", network_id, owner_salt, owner_ed25519_public_key
|
| 333 |
+
)
|
| 334 |
+
|
| 335 |
+
signer_key_id = H("signer-key/v1", owner_ed25519_public_key)
|
| 336 |
+
|
| 337 |
+
job_nullifier = H(
|
| 338 |
+
"job-nullifier/v1", network_id, scheduler_job_id,
|
| 339 |
+
request_commitment, u8(job_class)
|
| 340 |
+
)
|
| 341 |
+
|
| 342 |
+
execution_nullifier = H(
|
| 343 |
+
"execution-nullifier/v1", job_nullifier, assignment_id,
|
| 344 |
+
u8(replica_slot), worker_credential_id, runtime_instance_id
|
| 345 |
+
)
|
| 346 |
+
```
|
| 347 |
+
|
| 348 |
+
owner commitment に worker credential は含めない。registry の `SignerRecord` が public key、
|
| 349 |
+
owner commitment、worker credential の対応を供給する。owner salt は registry recordにも含めない。
|
| 350 |
+
|
| 351 |
+
## 8. Canonical operations and CU
|
| 352 |
+
|
| 353 |
+
`DType`: `0=Fp32`, `1=Fp16`, `2=Bf16`, `3=Int8`, `4=Int4`。
|
| 354 |
+
`QuantizationClass`: `0=None`, `1=Q4K`, `2=Q4KM`, `3=Q5KM`, `4=Q8_0`,
|
| 355 |
+
`5=Iq4Xs`, `255=Artifact(Hash32)`。
|
| 356 |
+
|
| 357 |
+
`GemmShape` order は `m:u32, n:u32, k:u32, batch:u32, dtype:DType,
|
| 358 |
+
quantization:QuantizationClass`。
|
| 359 |
+
|
| 360 |
+
`ComputeOperation` wire tags と payload:
|
| 361 |
+
|
| 362 |
+
| Tag | Variant | Canonical payload order |
|
| 363 |
+
|---:|---|---|
|
| 364 |
+
| 0 | `Gemm` | `GemmShape` |
|
| 365 |
+
| 1 | `Attention` | `query_tokens:u32, key_value_tokens:u32, heads:u32, head_dim:u32, batch:u32, causal:bool` |
|
| 366 |
+
| 2 | `LayerNorm` | `elements:u32, batch:u32` |
|
| 367 |
+
| 3 | `RmsNorm` | `elements:u32, batch:u32` |
|
| 368 |
+
| 4 | `Rotary` | `tokens:u32, heads:u32, head_dim:u32` |
|
| 369 |
+
| 5 | `ExpertRoute` | `tokens:u32, experts:u32, top_k:u32` |
|
| 370 |
+
| 6 | `KvCacheRead` | `bytes:u64` |
|
| 371 |
+
| 7 | `KvCacheWrite` | `bytes:u64` |
|
| 372 |
+
| 8 | `Silu` | `elements:u64` |
|
| 373 |
+
| 9 | `ElementwiseMultiply` | `elements:u64` |
|
| 374 |
+
| 10 | `Softmax` | `elements:u64` |
|
| 375 |
+
| 11 | `ElementwiseAdd` | `elements:u64` |
|
| 376 |
+
| 12 | `TensorCopy` | `bytes:u64` |
|
| 377 |
+
| 13 | `EmbeddingLookup` | `elements:u64` |
|
| 378 |
+
|
| 379 |
+
Dense modelでは `ExpertRoute` を拒否する。Qwen adapter mapping V1 は `MUL_MAT`、`RMS_NORM`、
|
| 380 |
+
`ROPE`、`SET_ROWS`、`SOFT_MAX`、`GLU`、`MUL`、`CONT`、`ADD`、`GET_ROWS` を上記 operationへ
|
| 381 |
+
変換し、`VIEW/RESHAPE/PERMUTE`だけを layout metadata として除外する。その他は fail-closed。
|
| 382 |
+
|
| 383 |
+
`ComputeUnitRules::v1()` は全variantを integer-only、checked `u128`、明示ceil、minimum 1で
|
| 384 |
+
再計算する。ruleset descriptor の hash が `cu_ruleset_id`。observer申告の cost は受け取らない。
|
| 385 |
+
|
| 386 |
+
## 9. Ordered operation schedule
|
| 387 |
+
|
| 388 |
+
`ExecutionPhase`: `0=Prefill`、`1=Decode(u32 step)`。
|
| 389 |
+
`ScheduledOperation` canonical order:
|
| 390 |
+
|
| 391 |
+
1. `index: u64`(0から連続)
|
| 392 |
+
2. `phase: ExecutionPhase`
|
| 393 |
+
3. `layer_id: Option<u32>`(`None` は global LM head 等)
|
| 394 |
+
4. `operation: ComputeOperation`
|
| 395 |
+
|
| 396 |
+
```text
|
| 397 |
+
s0 = H("schedule-init/v1", job_nullifier, shape_profile_id, cu_ruleset_id)
|
| 398 |
+
si = H("schedule-step/v1", s(i-1), u64be(i), encode(event_i))
|
| 399 |
+
schedule_root = H("schedule-final/v1", sn, u64be(event_count))
|
| 400 |
+
```
|
| 401 |
+
|
| 402 |
+
index、chain、decode stepの単調性、model layer range、Dense/MoE制約を verifier が再検査する。
|
| 403 |
+
挿入、削除、並べ替えはCU合計が同じでもrootを変える。
|
| 404 |
+
|
| 405 |
+
## 10. GEMM trace
|
| 406 |
+
|
| 407 |
+
`TraceEvidenceKind` の wire tag は `0=Absent`, `1=GraphFallback`, `2=KernelSketch`。
|
| 408 |
+
`trace_scheme_id_v1` は
|
| 409 |
+
`H("gemm-trace-scheme/v1", fixed_scheme_descriptor)` である。
|
| 410 |
+
|
| 411 |
+
`AccumulatorSketch` は `i64be lane[4]`。`TileIndex` は `m:u32, n:u32, k:u32`。
|
| 412 |
+
`GemmTraceEvent` canonical order:
|
| 413 |
+
|
| 414 |
+
1. `index: u64`
|
| 415 |
+
2. `schedule_index: u64`
|
| 416 |
+
3. `kernel_sequence: u64`
|
| 417 |
+
4. `tile_linear_index: u32`
|
| 418 |
+
5. `tile_count: u32`
|
| 419 |
+
6. `evidence_kind: TraceEvidenceKind`
|
| 420 |
+
7. `phase: ExecutionPhase`
|
| 421 |
+
8. `layer_id: Option<u32>`(`None` は global LM head)
|
| 422 |
+
9. `kernel_id: Hash32`
|
| 423 |
+
10. `shape: GemmShape`
|
| 424 |
+
11. `tile: TileIndex`
|
| 425 |
+
12. `accumulator_sketch: [i64;4]`
|
| 426 |
+
|
| 427 |
+
```text
|
| 428 |
+
t0 = H("gemm-trace-init/v1", job_nullifier, trace_scheme_id)
|
| 429 |
+
ti = H("gemm-trace-step/v1", t(i-1), u64be(i), encode(trace_event_i))
|
| 430 |
+
trace_root = H(
|
| 431 |
+
"gemm-trace-final/v1", tn,
|
| 432 |
+
u64be(trace_event_count), u64be(gemm_group_count)
|
| 433 |
+
)
|
| 434 |
+
```
|
| 435 |
+
|
| 436 |
+
各scheduled GEMMは1つのcontiguous groupとなる。groupのschedule indexは狭義増加、全event index/
|
| 437 |
+
kernel sequenceは0から連続、group内metadataは一致、kernel IDはnonzero、全groupで evidence kindを
|
| 438 |
+
混在させない。`GraphFallback` は各GEMM exactly 1 synthetic tile、`KernelSketch` は1個以上の
|
| 439 |
+
native tileを許す。trace group数はschedule内GEMM数と一致し、各eventのschedule index、phase、
|
| 440 |
+
optional layer、shapeを元scheduleと照合する。
|
| 441 |
+
|
| 442 |
+
現行 Qwen Metal adapter が発行できる trace は `GraphFallback` だけであり、CUDA claimへ昇格しない。
|
| 443 |
+
CUDA C ABIは既存final-output V1 recordに加え、declared origin、accumulator stage/dtype、sketch scheme、
|
| 444 |
+
reduction segment、producer variant IDを持つexact 184-byte V2 wire recordを定義する。Rustのstrict
|
| 445 |
+
decoder/binderは全unfiltered record streamをexpected launch sequence、schedule、tile/segment order、exact
|
| 446 |
+
MMVQ/flash-attention dispatch、CUDA runtime manifestへbindする。raw `ProducerAccumulator`はtransport上の
|
| 447 |
+
declared tagにすぎず、`BoundCudaTranscriptV1`はdiagnostic typestateである。
|
| 448 |
+
さらにadditive V3は452-byte recordと、FA-off attentionのQK-score MMVF、masked/scaled softmax、
|
| 449 |
+
value-aggregation MMVFからなるcanonical 3-sublaunch grouping、strict schedule/runtime binderを実装する。
|
| 450 |
+
|
| 451 |
+
別のauthority layerはsigned attestationをnetwork/job/execution/assignment、runtime class/manifest、
|
| 452 |
+
producer integration、operation schedule、full unfiltered transcriptへexact bindし、public raw constructorを
|
| 453 |
+
持たない`AuthorityBoundCudaTranscriptV2`を作る。そこからproducer-accumulator GEMMだけを
|
| 454 |
+
`AuthorityBoundCudaReceiptEvidenceV2`へdeterministically射影する。attention
|
| 455 |
+
final-output recordはsigned full-transcript commitmentに残すがGEMM evidenceへは昇格しない。
|
| 456 |
+
|
| 457 |
+
`ComputeReceiptV1`にはauthority provenance commitmentがないため、V1 builderはCUDA
|
| 458 |
+
`KernelSketch`の発行を拒否し、workerがV1 bodyを手組み・署名してもverifierが拒否する。standaloneの
|
| 459 |
+
true FP32 producer-accumulator採取primitiveはRTX 4060 Ti sm_89でdevice suite 7/7と20/20同一
|
| 460 |
+
diagnostic fingerprintを確認した。最終grouped suiteは8/8である。vendored llama.cppのQ4_K/Q6_K MMVQと
|
| 461 |
+
FA-off QK/softmax/PV producerも接続済みで、same-backend Qwen 1-token diagnostic E2Eは361/361 record、
|
| 462 |
+
3回同一fingerprint、5 work-class rejectionを確認した。ただしproduction Receipt authorityではない。
|
| 463 |
+
|
| 464 |
+
現行deterministic profileはFA-offで、legacy V2が表すattention dispatchは
|
| 465 |
+
`LlamaFlashAttention`だけである。この非互換に対するV3 sublaunch/grouping schema/binderは実装済みだが、
|
| 466 |
+
実eager-attention 3-stage hook、361-launch実機E2E、release manifest、Receipt/Bundle/SQLite V2も
|
| 467 |
+
実装・検証済みである。live callbackへのauthority-derived canonical expected table接続は未完了である。public headerは
|
| 468 |
+
`PALW_CUDA_TRACE_PRODUCTION_CAPABLE=0`、`PALW_CUDA_PRODUCER_VENDOR_RUNTIME_INTEGRATED=0`、
|
| 469 |
+
`PALW_CUDA_PRODUCER_RECEIPT_MAPPING_AVAILABLE=0`、`PALW_CUDA_PRODUCER_PRODUCTION_CAPABLE=0`で、production
|
| 470 |
+
CMake optionもfailするため、R32は`In progress`でもproduction CUDA `KernelSketch` Receiptを発行してはならない。
|
| 471 |
+
|
| 472 |
+
## 11. Compute Receipt and signature
|
| 473 |
+
|
| 474 |
+
`ComputeReceiptV1` は正確に30 fieldで、canonical orderは次のとおり。
|
| 475 |
+
|
| 476 |
+
1. `receipt_version: u16` (=1)
|
| 477 |
+
2. `network_id: Hash32`
|
| 478 |
+
3. `request_commitment: Hash32`
|
| 479 |
+
4. `scheduler_job_id: Hash32`
|
| 480 |
+
5. `signed_assignment_id: Hash32`(assignment body の `assignment_id`)
|
| 481 |
+
6. `replica_slot: u8`
|
| 482 |
+
7. `model_profile_id: Hash32`
|
| 483 |
+
8. `runtime_class_id: Hash32`
|
| 484 |
+
9. `runtime_manifest_hash: Hash32`
|
| 485 |
+
10. `shape_profile_id: Hash32`
|
| 486 |
+
11. `cu_ruleset_id: Hash32`
|
| 487 |
+
12. `trace_scheme_id: Hash32`
|
| 488 |
+
13. `trace_evidence: TraceEvidenceKind`
|
| 489 |
+
14. `operation_schedule_commitment: Hash32`
|
| 490 |
+
15. `schedule_event_count: u64`
|
| 491 |
+
16. `canonical_compute_units: u64`
|
| 492 |
+
17. `prefill_tokens: u32`
|
| 493 |
+
18. `decode_tokens: u32`
|
| 494 |
+
19. `output_commitment: Hash32`
|
| 495 |
+
20. `gemm_trace_root: Hash32`
|
| 496 |
+
21. `trace_event_count: u64`
|
| 497 |
+
22. `owner_commitment: Hash32`
|
| 498 |
+
23. `worker_credential_id: Hash32`
|
| 499 |
+
24. `job_nullifier: Hash32`
|
| 500 |
+
25. `execution_nullifier: Hash32`
|
| 501 |
+
26. `job_class: JobClass`
|
| 502 |
+
27. `evidence_level: EvidenceLevel`
|
| 503 |
+
28. `timestamp: u64`(informational only)
|
| 504 |
+
29. `issued_epoch: u64`
|
| 505 |
+
30. `expires_epoch: u64`
|
| 506 |
+
|
| 507 |
+
body-local evidence invariants:
|
| 508 |
+
|
| 509 |
+
- `Wrapper`: schedule count、trace count、CUは0、trace kindはAbsent
|
| 510 |
+
- `RuntimeObserved`: schedule countとCUはnonzero、trace countは0、trace kindはAbsent
|
| 511 |
+
- `GemmTraced`: schedule count、trace count、CUはnonzero、trace kindはnon-Absent
|
| 512 |
+
- replicated class: evidence levelはGemmTraced
|
| 513 |
+
|
| 514 |
+
trace無しでも `gemm_trace_root` は zero ではなく、同jobで初期化した empty trace root である。
|
| 515 |
+
|
| 516 |
+
```text
|
| 517 |
+
body_id = H("receipt-body/v1", network_id, encode(body))
|
| 518 |
+
receipt_id = H("receipt-id/v1", network_id, encode(body))
|
| 519 |
+
signature_message = H("receipt-signature/v1", network_id, encode(body))
|
| 520 |
+
```
|
| 521 |
+
|
| 522 |
+
`SignedReceiptV1` canonical order:
|
| 523 |
+
|
| 524 |
+
```text
|
| 525 |
+
u16be(envelope_version=1) ||
|
| 526 |
+
LP(encode(body)) ||
|
| 527 |
+
signer_key_id:Hash32 ||
|
| 528 |
+
u8(signature_algorithm=0) ||
|
| 529 |
+
ed25519_signature:64-byte
|
| 530 |
+
```
|
| 531 |
+
|
| 532 |
+
現行 `receipt_id` は署名byteを含まず、同じbodyなら同じIDである。signature は worker keyで上記
|
| 533 |
+
messageを署名する。verifier は signer registry、scheduler-derived assignment authorization、
|
| 534 |
+
manifest、private prompt/output opening、schedule/CU/traceをすべて照合する。signer registryはnonzero
|
| 535 |
+
owner/credentialとnon-weak keyだけを受け、Receipt signatureはstrict Ed25519で検証する。
|
| 536 |
+
|
| 537 |
+
## 12. Stateless verification and durable acceptance
|
| 538 |
+
|
| 539 |
+
stateless path:
|
| 540 |
+
|
| 541 |
+
1. signed envelope と body をstrict canonical decode
|
| 542 |
+
2. body structure、network、assignment epoch
|
| 543 |
+
3. scheduler署名検証済み authorization recordとの全binding
|
| 544 |
+
4. worker signer key、owner commitment、credential、Receipt signature
|
| 545 |
+
5. model/runtime/manifest/shape/CU/trace identity
|
| 546 |
+
6. job/execution nullifier再導出
|
| 547 |
+
7. token shape bounds
|
| 548 |
+
8. schedule、CU、traceをwitnessから再計算
|
| 549 |
+
9. prompt/output private openingとtoken countを再計算
|
| 550 |
+
|
| 551 |
+
型は `UnverifiedReceipt -> StatelesslyVerifiedReceipt`。その後 `StateStore::accept` が SQLite
|
| 552 |
+
transactionで replay/cardinality keyを予約した場合だけ `AcceptedReceipt` になる。Matcher と
|
| 553 |
+
canary submission は `AcceptedReceipt` を要求する。first acceptance時のstateless
|
| 554 |
+
`verified_at_epoch`をdurable `accepted_at_epoch`として保存する。restart後の`restore_accepted`は新しい
|
| 555 |
+
stateless verification epochとoriginal acceptance epochを区別し、canonical signed Receiptとauthorized
|
| 556 |
+
runtime instanceがstored rowとexact一致するときだけtypestateを復元する。stored acceptanceはbody
|
| 557 |
+
issued/expiry内かつcurrent `verified_at_epoch`以下でなければならず、rollbackを拒否する。
|
| 558 |
+
|
| 559 |
+
durable storeはapplication ID `PALW`、schema version 4、foreign keys、WAL、`synchronous=FULL`を要求する。
|
| 560 |
+
exact table set/column order/foreign-key count/indexに加え、non-internal `sqlite_master`の全
|
| 561 |
+
`(type,name,tbl_name,sql)`をcanonical encodeしたSHA3-256 fingerprintをcompiled goldenと照合する。
|
| 562 |
+
旧schemaのsilent migrationとobjectを持つunclaimed DBは拒否する。receiptのaccepted epoch、pairのmatched
|
| 563 |
+
epoch、signed future beaconのclaimed epoch、audit replayのissued/accepted epochは8-byte big-endian
|
| 564 |
+
BLOBとして保存する。beacon verification時のcaller current epochは別columnへ固定せず、restore時の
|
| 565 |
+
current `AcceptedReceipt.verified_at_epoch`でregistry validity/revocationとともに再検証する。
|
| 566 |
+
|
| 567 |
+
## 13. Replica matching
|
| 568 |
+
|
| 569 |
+
`MatchProjectionV1` canonical order:
|
| 570 |
+
|
| 571 |
+
1. `job_nullifier`
|
| 572 |
+
2. `request_commitment`
|
| 573 |
+
3. `job_class`
|
| 574 |
+
4. `model_profile_id`
|
| 575 |
+
5. `runtime_class_id`
|
| 576 |
+
6. `runtime_manifest_hash`
|
| 577 |
+
7. `shape_profile_id`
|
| 578 |
+
8. `cu_ruleset_id`
|
| 579 |
+
9. `canonical_compute_units`
|
| 580 |
+
10. `prefill_tokens`
|
| 581 |
+
11. `decode_tokens`
|
| 582 |
+
12. `operation_schedule_commitment`
|
| 583 |
+
13. `schedule_event_count`
|
| 584 |
+
14. `output_commitment`
|
| 585 |
+
15. `trace_scheme_id`
|
| 586 |
+
16. `trace_evidence`
|
| 587 |
+
17. `gemm_trace_root`
|
| 588 |
+
18. `trace_event_count`
|
| 589 |
+
|
| 590 |
+
network、scheduler job ID、assignment/slot、owner/credential/runtime instance/execution nullifier、
|
| 591 |
+
evidence level、timestamp/epoch、signature はprojectionに入らない。ただしjob nullifierとrequest
|
| 592 |
+
commitmentはnetwork-boundであり、durable pair保存時には両memberのnetworkをexplicitに照合する。
|
| 593 |
+
2 Receipt は未失効、slot集合`{0,1}`、異なるexecution、signer key、credential、owner、assignment、
|
| 594 |
+
runtime instanceでなければならない。pairing `current_epoch`は両bodyのissued epoch、両receiptのoriginal
|
| 595 |
+
accepted epochとcurrent stateless verified epoch以上、両expiry以下でなければならない。
|
| 596 |
+
|
| 597 |
+
```text
|
| 598 |
+
match_commitment = H("replica-match/v1", encode(projection))
|
| 599 |
+
pair_id = H(
|
| 600 |
+
"pair-id/v1", network_id,
|
| 601 |
+
min(execution_nullifier_a, execution_nullifier_b),
|
| 602 |
+
max(execution_nullifier_a, execution_nullifier_b),
|
| 603 |
+
match_commitment
|
| 604 |
+
)
|
| 605 |
+
```
|
| 606 |
+
|
| 607 |
+
`MatchedReplicaPair` はpairing呼出し時の`current_epoch`をprivate `matched_epoch`として保持する。
|
| 608 |
+
このepochはprojection/pair IDには入らないが、Self Replicated用のpublic maturity constructorが
|
| 609 |
+
`MatureEvidence.mature_epoch`へ封入する。durable pair recordのcanonical bytesには`matched_epoch`を
|
| 610 |
+
含め、memberのstored issued/accepted/expiry epochと再照合する。
|
| 611 |
+
|
| 612 |
+
## 14. Audit, Work Ticket, canary, bond, and external identities
|
| 613 |
+
|
| 614 |
+
`FutureBeaconV1` canonical orderは`version:u16 (=1), network_id:Hash32, epoch:u64,
|
| 615 |
+
value:Hash32`。`beacon_id = H("future-beacon/v1", encode(body))`。signed envelopeは次のorderである。
|
| 616 |
+
|
| 617 |
+
```text
|
| 618 |
+
u16be(envelope_version=1) ||
|
| 619 |
+
LP(encode(FutureBeaconV1)) ||
|
| 620 |
+
authority_key_id:Hash32 ||
|
| 621 |
+
u8(signature_algorithm=0) ||
|
| 622 |
+
ed25519_signature:64-byte
|
| 623 |
+
```
|
| 624 |
+
|
| 625 |
+
signature messageは`beacon_id`。network-scoped authority registryはbeacon epochのvalidity、verification
|
| 626 |
+
epoch時点のrevocation、key ID、weak keyを検査し、strict Ed25519成功後だけraw constructorを持たない
|
| 627 |
+
`VerifiedFutureBeacon`へ昇格する。claimed beacon epochはverification epoch以下でなければならない。
|
| 628 |
+
|
| 629 |
+
future audit selection:
|
| 630 |
+
|
| 631 |
+
```text
|
| 632 |
+
sample = H(
|
| 633 |
+
"audit-selection/v1", network_id, receipt_id,
|
| 634 |
+
u64be(beacon_epoch), beacon
|
| 635 |
+
)
|
| 636 |
+
selected iff sample_as_big_endian_u256 < selection_threshold:Hash32
|
| 637 |
+
|
| 638 |
+
challenge_id = H(
|
| 639 |
+
"audit-challenge/v1", network_id, receipt_id, sample
|
| 640 |
+
)
|
| 641 |
+
```
|
| 642 |
+
|
| 643 |
+
`AuditRecord::new`はexact `AcceptedReceipt`を受け、network、receipt ID、body issued epoch、durable
|
| 644 |
+
accepted epoch、scheduler job、job nullifier、request commitmentをbindする。beacon epochはissued epochと
|
| 645 |
+
accepted epochの両方より後でなければならない。v1 policyはselection threshold `2^252`(一様digestの
|
| 646 |
+
1/16)、response window 2 epoch、challenge window 5 epochの固定値で、全値を`audit-policy/v1` IDへ
|
| 647 |
+
commitする。
|
| 648 |
+
|
| 649 |
+
`StateStore::store_audit_selection`はpolicy ID、original issued/accepted epoch、canonical signed beacon、
|
| 650 |
+
beacon ID/value/authority key ID、challenge/deadlineまたはnon-selected mature epochを保存する。restore時は
|
| 651 |
+
current authority registryでsigned beaconを再検証し、sample/challenge/deadlineを再計算する。
|
| 652 |
+
|
| 653 |
+
selected replayはdistinctな`StatelesslyVerifiedReceipt`をaudit専用にacceptする。same network/job/requestを
|
| 654 |
+
要求し、receipt/execution/assignment/runtime instance/signer key/worker credential/owner commitmentはoriginal
|
| 655 |
+
と異ならなければならない。replay issued epochはbeaconより後、durable replay accepted epochはissued/
|
| 656 |
+
current stateless verified epoch以上かつdeadline以下である。`VerifiedReplayVerdict`が両
|
| 657 |
+
`MatchProjectionV1`を比較してresult commitmentとmatch outcomeを作るため、callerはraw
|
| 658 |
+
`projection_matches:bool`を注入できない。
|
| 659 |
+
|
| 660 |
+
selected pathはaudit replay identityの一回予約、terminal mismatchまたはpass、pass時のSelf Local
|
| 661 |
+
maturity sourceを1 SQLite transactionで確定する。non-selected pathもwindow maturityとsourceを1
|
| 662 |
+
transactionで確定する。beacon delivery/finality、auditor assignment、model re-execution、opening配送は
|
| 663 |
+
このwire/state coreの外部service boundaryである。
|
| 664 |
+
|
| 665 |
+
`restore_audit`はnon-replay state/terminalをrestoreするが、selected pass/mismatch terminalは
|
| 666 |
+
`AuditReplayRequired`で拒否する。この場合は`restore_selected_audit_with_replay`を使い、durable audit
|
| 667 |
+
state/challenge、stored canonical replay、全identity/epochを照合する。さらにprojection verdictを再計算し、
|
| 668 |
+
match bit、submission commitment、completed epochをstored terminal outcomeへexact比較する。
|
| 669 |
+
|
| 670 |
+
`WorkTicketV2` のIDを除くcanonical body orderは次のとおり。
|
| 671 |
+
|
| 672 |
+
1. `version:u16 (=2)`
|
| 673 |
+
2. `network_id:Hash32`
|
| 674 |
+
3. `source_id:Hash32`
|
| 675 |
+
4. `maturity_basis_id:Hash32`
|
| 676 |
+
5. `weight_grant_id:Option<Hash32>`
|
| 677 |
+
6. `job_class:JobClass`
|
| 678 |
+
7. `weight_policy_version:u32`
|
| 679 |
+
8. `canonical_compute_units:u64`
|
| 680 |
+
9. `weight_bps:u32`
|
| 681 |
+
10. `weighted_compute_units:u64`
|
| 682 |
+
11. `issued_epoch:u64`
|
| 683 |
+
|
| 684 |
+
```text
|
| 685 |
+
weighted_CU = ceil(CU * weight_bps / 10_000)
|
| 686 |
+
ticket_id = H("work-ticket/v2", network_id, encode(ticket_body_without_ticket_id))
|
| 687 |
+
```
|
| 688 |
+
|
| 689 |
+
V1 default weight は Self Local challenge 2,500、audit pass 5,000、replicated 10,000、external
|
| 690 |
+
demand bonus最大5,000 bps。これは算術/型変換の実装値であり、production network admission の
|
| 691 |
+
証明ではない。
|
| 692 |
+
|
| 693 |
+
`MatureEvidence` はwire objectではなく、fieldと低水準constructorを非公開にしたtyped gateである。
|
| 694 |
+
生成経路、`maturity_basis_id`、`mature_epoch`は次の3つだけ。
|
| 695 |
+
|
| 696 |
+
- Self Local: exact `AcceptedReceipt + AuditRecord::Mature`。domain `local-maturity-basis/v2`で
|
| 697 |
+
audit basis/epochをbindし、audit stateが保持するmature epochを使う
|
| 698 |
+
- Self Replicated: `MatchedReplicaPair`。pair IDをmaturity basis、pairのmatched epochを使う
|
| 699 |
+
- External Replicated: authority-verified terminal settlement。confirmation IDをmaturity basis、authority-
|
| 700 |
+
signed grant IDを必須weight grant、confirmation epochをmature epochとして使う
|
| 701 |
+
|
| 702 |
+
`StateStore::register_mature_evidence(&MatureEvidence)` はstored receipt/pairのnetwork、class、CUとopaque
|
| 703 |
+
evidenceを照合し、Self Localではstored durable auditのstate/basis/epochも照合する。External evidenceは
|
| 704 |
+
このAPIから拒否し、後述のsettlement transactionだけが登録できる。primary Self Local audit pathと
|
| 705 |
+
Self Replicated pathは、source登録と同じtransactionで必要な1件/2件のactive assignment bondを`Mature`
|
| 706 |
+
releaseし、`mature_source_assignments`へrelease IDをlinkする。unbonded/不足/terminal lockならtransactionを
|
| 707 |
+
rollbackする。ticket issuerもjob classのrequired replica数とlink数を再検査する。
|
| 708 |
+
`issue_work_ticket` は `issued_epoch >= mature_epoch` を要求し、SQLite ticket pathも保存epochに対して
|
| 709 |
+
同じ条件を検査してから1 sourceをatomicに消費する。既消費sourceの通常pathは`SourceAlreadyConsumed`、
|
| 710 |
+
External settlementのexact replayはstored ticketを返す。
|
| 711 |
+
|
| 712 |
+
canary expected projection commitment:
|
| 713 |
+
|
| 714 |
+
```text
|
| 715 |
+
H("canary/v1", network_id, canary_id, request_commitment,
|
| 716 |
+
u64be(opening_epoch), canary_salt, encode(expected_match_projection))
|
| 717 |
+
```
|
| 718 |
+
|
| 719 |
+
`CanaryPrecommitBodyV1`は `version, network_id, canary_id, scheduler_job_id, request_commitment,
|
| 720 |
+
signed_assignment_id, worker_credential_id, expected_commitment, created_epoch, receipt_deadline_epoch,
|
| 721 |
+
opening_epoch, opening_deadline_epoch` をcanonical encodeし、
|
| 722 |
+
`precommit_id = H("canary-precommit/v1", encode(body))`をschedulerがEd25519署名する。strict envelopeは
|
| 723 |
+
body、scheduler key ID、algorithm、signatureを持つ。scheduler registryのnetwork、key validity/revocation、
|
| 724 |
+
strict signatureと、exact signed request/assignment/worker bindingを検査した後だけ
|
| 725 |
+
`VerifiedCanaryPrecommit`になる。External Replicated canaryはv1で禁止する。
|
| 726 |
+
|
| 727 |
+
windowは `assignment.issued <= created <= receipt_deadline <= assignment.expires < opening_epoch <=
|
| 728 |
+
opening_deadline`。canary markerはReceiptにない。verified precommitはactive bonded assignmentとcanonical
|
| 729 |
+
signed envelopeをschema-v4 DBへ保存する。`accept_canary`はbonded normal Receipt acceptanceと
|
| 730 |
+
`ReceiptSubmitted`を同じtransactionでcommitする。valid opening passはterminalだけをcommitし、valid
|
| 731 |
+
commitmentのprojection mismatchはtyped `CanaryFailure` slashをatomicに適用する。receipt deadline経過は
|
| 732 |
+
worker faultでslashし、receipt受理後のopening deadline経過はscheduler faultとしてworkerをslashしない。
|
| 733 |
+
passとOpeningMissingではassignment bondをactiveのまま保持する。pending canaryがあるsourceのmaturityは
|
| 734 |
+
拒否し、terminal後はmature epochをcanary completion epoch以上へ遅延する。Self Localでは遅延後のepochで
|
| 735 |
+
`local-maturity-basis/v2`も再計算する。その後のmaturity transactionがbondを`Mature` releaseしてsourceへ
|
| 736 |
+
linkするため、canary terminal単独ではWork Ticketを発行できない。
|
| 737 |
+
|
| 738 |
+
in-memory helperのslash offense:
|
| 739 |
+
|
| 740 |
+
```text
|
| 741 |
+
Evidence = u64be(unique_sorted_count) || concat(sorted_unique_evidence_id)
|
| 742 |
+
offense_id = H(
|
| 743 |
+
"slash-offense/v1", network_id, worker_credential_id,
|
| 744 |
+
assignment_id, u8(reason), u32be(policy_version), Evidence
|
| 745 |
+
)
|
| 746 |
+
```
|
| 747 |
+
|
| 748 |
+
reason tagは `1=InvalidManifest`, `2=AuditMismatch`, `3=Equivocation`,
|
| 749 |
+
`4=DuplicateExecution`, `5=CanaryFailure`, `6=AuditTimeout`。
|
| 750 |
+
|
| 751 |
+
durable slashはcaller-selected attachment集合ではなくcrate-private `TypedSlashEvidence`のprimary proofを
|
| 752 |
+
authority identityに使う。
|
| 753 |
+
|
| 754 |
+
```text
|
| 755 |
+
offense_id = H(
|
| 756 |
+
"durable-slash-offense/v2", network_id, worker_credential_id,
|
| 757 |
+
assignment_id, u8(reason), primary_proof_id, u32be(policy_version)
|
| 758 |
+
)
|
| 759 |
+
```
|
| 760 |
+
|
| 761 |
+
audit mismatch/timeoutとcanary mismatch/receipt timeoutはproof IDをstate transition自身から導出して、
|
| 762 |
+
slash claim、derived allocation、assignment remainder、pending appeal bucket、health eventを同じtransactionで
|
| 763 |
+
更新する。claimはinitial assignment amountからreason別bpsをceilしたimmutable targetを持つ。v1の
|
| 764 |
+
Equivocation追加penaltyは0である。複数claimを単純���算せず、finalized(signed/default uphold)targetの
|
| 765 |
+
max-envelopeを先に割り当て、pending claimはそのenvelopeを超えるextensionだけを受ける。同じassignmentへの
|
| 766 |
+
late equal/weaker claimのallocationは既存envelopeに覆われるなら0、stronger claimはdeltaだけとなる。
|
| 767 |
+
reverse後も全claimから再計算するため、ingestion順序でslash総額は変わらない。standard policyのappeal
|
| 768 |
+
windowはdurable `applied_epoch`から100 epoch。nonappealed slashはinclusive deadlineの後だけfinalizeする。
|
| 769 |
+
typed proofが示す`fault_event_epoch`とstoreがclaimを受理する`applied_epoch`は別で、
|
| 770 |
+
`locked_epoch <= fault_event_epoch <= applied_epoch`とaccount transition epochの単調性を要求する。
|
| 771 |
+
|
| 772 |
+
partial claimのremainderはactive lockとして残る。pendingまたはuphold/default-final claimを持つassignmentは
|
| 773 |
+
maturity/Work Ticketの根拠にならない。全claim解決後、audit mismatch/
|
| 774 |
+
timeout terminalはclaimがreverseされても残額を`SlashResolved` releaseする。canary mismatch/receipt-timeout
|
| 775 |
+
terminalはmatching `CanaryFailure` claimがuphold/default-finalの場合だけ同releaseを許し、External refundも
|
| 776 |
+
release terminalになる。reversed canary claimだけではreleaseしない。未使用または
|
| 777 |
+
acceptedだがunpairedのSelf Replicated assignmentだけは、pending canary/slashがなくsigned expiryを過ぎた
|
| 778 |
+
場合に`Expired` releaseできる。paired、Self Local、その他used assignmentはこのexpiry bypassを持たない。
|
| 779 |
+
pendingで全targetをallocateしたstate 2にもdistinct late claimを保存できるが、fully finalized/exhaustedの
|
| 780 |
+
state 3は新claimを拒否する。terminal epoch/proofは全immutable claimをoffense ID順に並べ、各effective epochの
|
| 781 |
+
maxと完全なterminal fact setから導出する。audit/canary terminalとExternal prepared/terminal stateは
|
| 782 |
+
後出しclaimのcutoffであり、特にExternal `SettlementPrepared`または`RefundPrepared`以後は新しい
|
| 783 |
+
non-replay slashを受けない。
|
| 784 |
+
|
| 785 |
+
bond funding、slash appeal、slash decisionはそれぞれversion 1 canonical bodyとsigned envelopeを持つ。
|
| 786 |
+
funding bodyはnetwork/worker/funding event/asset/exact amount/finalized epoch、appeal bodyはnetwork/worker/
|
| 787 |
+
offense/assignment/appeal ID/submitted epoch、decision bodyはnetwork/appeal/offense/outcome/decided epochを
|
| 788 |
+
bindする。network-scoped bond authority registryはkey validity/revocation、funding/appeal/decision capability、
|
| 789 |
+
weak key、strict Ed25519を検査し、raw constructorを持たないverified typestateだけをstoreへ渡す。
|
| 790 |
+
|
| 791 |
+
appeal submissionはstored pending slashとinclusive appeal deadlineを照合する。signed `submitted_epoch`と
|
| 792 |
+
registry verification epochの両方が`applied_epoch..=appeal_deadline`内でなければならず、後者をdurable
|
| 793 |
+
`accepted_epoch`として保存する。decision deadlineは`accepted_epoch + 100`である。authority-signed
|
| 794 |
+
`Uphold`/`Reverse`はsigned `decided_epoch`とdecision verification/acceptance epochの両方がdeadline以下で
|
| 795 |
+
だけ受理し、claim statusを更新してassignment全claimのallocationをatomicに再計算する。期限を過ぎても
|
| 796 |
+
decisionがなければ`finalize_stale_slash_appeal(current_epoch > decision_deadline)`がdomain-separated
|
| 797 |
+
default decisionを作ってdeterministically upholdする。offenseごとのappealは1件だけで、first stored
|
| 798 |
+
signed/default decisionが勝つ。stored canonical appeal/decisionのexact replayは期限後もidempotent、distinct
|
| 799 |
+
second appealやconflicting later decisionはfatalである。
|
| 800 |
+
|
| 801 |
+
`ExternalEscrowTermsV1` canonical order は `version:u16, network_id, escrow_nonce,
|
| 802 |
+
funding_authorization_id, prompt_commitment, ExecutionConstraintsV1, required_reward:u64,
|
| 803 |
+
demand_bonus_amount:u64, demand_bonus_bps:u32, protocol_fee:u64, failure_reserve:u64,
|
| 804 |
+
issued_epoch:u64, expires_epoch:u64`。
|
| 805 |
+
|
| 806 |
+
```text
|
| 807 |
+
escrow_reference = H("external-escrow/v1", encode(terms))
|
| 808 |
+
```
|
| 809 |
+
|
| 810 |
+
external authorityはnetwork-scoped Ed25519 keyにfunding、demand-weight、terminal capabilityを分離する。
|
| 811 |
+
key validity/revocation、weak key、strict signatureを検査し、次のraw constructorを持たないtypestateを作る。
|
| 812 |
+
|
| 813 |
+
- `VerifiedFundingAttestation`: escrow reference、funding authorization ID、asset、exact finalized amount/epoch
|
| 814 |
+
- `VerifiedDemandWeightGrant`: escrow/funding attestation、grant/policy/asset、funded bonus amount/bps、
|
| 815 |
+
issued/expiry interval(v1 bonus上限5,000 bps)
|
| 816 |
+
- `VerifiedTerminalConfirmation`: escrow、payment command、rail confirmation、asset、exact settlement/refund
|
| 817 |
+
distribution、confirmed epoch
|
| 818 |
+
|
| 819 |
+
schema-v4 durable external pathはexact funding+grantから`Funded` escrowを作り、scheduler-signed
|
| 820 |
+
External request、typed k=2 pair、stable payment commandへ進む。settlement confirmationはcommand/distribution/
|
| 821 |
+
pair/asset/epochを照合し、terminal state、maturity source、両worker assignment bondのrelease/link、
|
| 822 |
+
`WorkTicketV2` insert、source consumptionを一SQLite transactionでcommitする。refund commandはstate 1..3
|
| 823 |
+
(`Funded|Assigned|EvidenceReady`)からterms expiry後に作成でき、pairの有無を問わない。refund confirmationは
|
| 824 |
+
terminalとeligible assignment bond releaseを一SQLite transactionでcommitし、maturity/ticketを作らない。
|
| 825 |
+
pending slash claimを持つbondは解決までreleaseせず、解決後に残額だけをreleaseできる。exact confirmation replayは
|
| 826 |
+
idempotentで、逆terminal、amount、identityのconflictを拒否する。
|
| 827 |
+
|
| 828 |
+
settlement commandを`SettlementPrepared`へcommitする同じ`BEGIN IMMEDIATE` transactionで、pair両assignmentが
|
| 829 |
+
active state 0かつpending/upheld/default-final slash claimなしであることをpreflightする。
|
| 830 |
+
`SettlementPrepared`と`RefundPrepared`(state 4/5)はどちらもnon-replayのlate slashを拒否するため、
|
| 831 |
+
terminal準備とslashの順序で結果が変わらない。
|
| 832 |
+
|
| 833 |
+
これはexternal authorityが「rail上のfinality」を正しく署名するというtrust boundaryである。crateは
|
| 834 |
+
payment railを操作せず、rail transactionとSQLite commitのdistributed atomicityを主張しない。
|
| 835 |
+
|
| 836 |
+
## 15. Encrypted verification bundle and restart restoration
|
| 837 |
+
|
| 838 |
+
`VerificationBundleV1`はcanonical Receiptのprivate openingをrestart後もstrict verifyするためのartifactで、
|
| 839 |
+
Receipt wire format自体は変更しない。audit keyはcaller-owned raw 32 bytes、nonzeroで、bundleには含めない。
|
| 840 |
+
|
| 841 |
+
public sectionのcanonical order:
|
| 842 |
+
|
| 843 |
+
1. `version:u16 (=1)`
|
| 844 |
+
2. `receipt_binding:Hash32`
|
| 845 |
+
3. `receipt_id:Hash32`
|
| 846 |
+
4. `verification_epoch:u64`
|
| 847 |
+
5. scheduler key snapshot: `network_id, verifying_key, valid_from_epoch, valid_through_epoch,
|
| 848 |
+
revoked_at_epoch:Option<u64>`
|
| 849 |
+
6. `LP(RuntimeManifest canonical bytes)`
|
| 850 |
+
7. `LP(portable ExecutionEvidence canonical bytes)`(schedule/CU/trace witness)
|
| 851 |
+
|
| 852 |
+
worker public keyはpublic sectionへ置かない。private sectionのcanonical order:
|
| 853 |
+
|
| 854 |
+
1. `LP("MISAKA/PALW/PRIVATE-OPENING")`, `version:u16 (=1)`, `public_digest:Hash32`
|
| 855 |
+
2. `LP(SignedJobRequestV1)`, `LP(SignedAssignmentV1)`
|
| 856 |
+
3. worker `verifying_key`, `owner_commitment`, `worker_credential_id`
|
| 857 |
+
4. `output_nonce`, `u64be(prompt_token_count)`, `u32be(prompt_token_id_i)*`
|
| 858 |
+
5. `LP(CanonicalOutput)`(generated token IDsとstop reason)
|
| 859 |
+
6. `owner_salt`
|
| 860 |
+
|
| 861 |
+
private signing-key seedはどのsectionにもserializeしない。
|
| 862 |
+
|
| 863 |
+
```text
|
| 864 |
+
receipt_binding = H("verification-bundle-receipt/v1", canonical_signed_receipt)
|
| 865 |
+
public_digest = H("verification-bundle-public/v1", canonical_public_section)
|
| 866 |
+
aead_key = H("verification-bundle-aead-key/v1", raw_audit_key)
|
| 867 |
+
aad = H(
|
| 868 |
+
"verification-bundle-aad/v1",
|
| 869 |
+
"XCHACHA20-POLY1305;KEY=256;NONCE=192;TAG=128",
|
| 870 |
+
receipt_binding, public_digest, nonce, canonical_public_section
|
| 871 |
+
)
|
| 872 |
+
```
|
| 873 |
+
|
| 874 |
+
envelope canonical order:
|
| 875 |
+
|
| 876 |
+
```text
|
| 877 |
+
LP("MISAKA/PALW/VERIFICATION-BUNDLE") ||
|
| 878 |
+
u16be(version=1) || u16be(cipher=1) ||
|
| 879 |
+
receipt_binding || public_digest || nonce:24-byte ||
|
| 880 |
+
LP(canonical_public_section) || LP(XChaCha20-Poly1305 ciphertext_and_tag)
|
| 881 |
+
```
|
| 882 |
+
|
| 883 |
+
nonceはOS CSPRNGのnonzero 192-bit値、AEAD keyは256 bit、tagは128 bit。envelopeは64 MiB、public
|
| 884 |
+
sectionは48 MiB、private plaintextは16 MiBを上限とし、strict decode/re-encode、receipt/public binding、
|
| 885 |
+
AEAD authenticationを検査する。
|
| 886 |
+
|
| 887 |
+
```text
|
| 888 |
+
bundle_id = H("verification-bundle-id/v1", canonical_complete_envelope)
|
| 889 |
+
```
|
| 890 |
+
|
| 891 |
+
local restart pathはembedded scheduler/worker snapshotsを使ってcomplete stateless verificationを再実行し、
|
| 892 |
+
既存schema-v4 DB rowのcanonical Receipt/runtime instance/original acceptance epochへexact restoreする。
|
| 893 |
+
missing DB rowを新規acceptしない。これはlocal continuity modeであり、embedded snapshotはthird-party
|
| 894 |
+
network authorityではない。
|
| 895 |
+
|
| 896 |
+
bundle public sectionのhistorical `verification_epoch`はoriginal acceptance時点をbindする。
|
| 897 |
+
`verify_bundle_and_restore_at_epoch`はcaller-selected current epochがhistorical値以上であることを要求し、
|
| 898 |
+
同じbundle/openingをfresh epochで再検証したうえでoriginal durable acceptance epochを保持してrestoreする。
|
| 899 |
+
ただし、このlocal APIはembedded snapshotsを使うためbundle作成後のrevocationを学習できない。future audit
|
| 900 |
+
restoreではcurrent epochをbeacon以上にする。rollbackは拒否する。現行
|
| 901 |
+
`palw-verify-bundle` CLIはhistorical default pathで、fresh epoch overrideはlibrary APIだけが公開する。
|
| 902 |
+
|
| 903 |
+
external stateless pathはexpected network、independent scheduler registry、independent signer registry、
|
| 904 |
+
approved manifest hashを必須にし、embedded snapshotとのexact equalityも検査する。default APIはhistorical
|
| 905 |
+
epoch、`verify_bundle_stateless_at_epoch_with_trust`はrollbackしないcaller-selected fresh epochで検証する。
|
| 906 |
+
DB reservationを行わず、network acceptanceを主張しない。production restartではcurrent external trust rootsと
|
| 907 |
+
既存DB continuityを同時に検査する`verify_bundle_and_restore_at_epoch_with_trust`を使う。
|
| 908 |
+
|
| 909 |
+
Receipt CLIは`--prompt-stdin --audit-key-file RAW_32_BYTE_KEY`を必須とし、`--prompt TEXT`を受けない。
|
| 910 |
+
key fileはoutput directory外のowner-owned single-link regular file、mode `0400`/`0600`、exact 32 bytesで
|
| 911 |
+
なければならない。issuance output directoryは`0700`、Receipt/公開JSON/completion markerは`0644`、
|
| 912 |
+
bundle/DBは`0600`。DB WALを`TRUNCATE` checkpointしてmain DBを`fsync`し、各artifactを`fsync`した後、
|
| 913 |
+
`misaka.palw.receipt-set.v2` markerへ`receipt_id`、`bundle_id`、公開JSON bytesのSHA-256を記録して最後に
|
| 914 |
+
書き、directoryを`fsync`する。local verifier CLIは`--public-json`も必須とし、protected artifactsが同じ
|
| 915 |
+
owned `0700` directoryにexpected filename/modeで存在すること、marker、typed公開JSON
|
| 916 |
+
`misaka.palw.public-receipt.v2`全体を検査する。
|
| 917 |
+
保持する`artifacts`と`observer_summary`はauthenticated bundle manifest/evidenceから再構成してexact照合し、
|
| 918 |
+
extra JSON fieldはobjectの全階層で拒否する。
|
| 919 |
+
marker-lastはpartial setをcompleteとして受理しないためのgateであり、cross-file atomic transactionでも
|
| 920 |
+
authenticity proofでもない。markerはunkeyed plain textなのでsame-owner writerはJSONとmarkerを一緒に
|
| 921 |
+
置換できるが、改変JSONはReceipt/bundleとの照合に失敗する。canonical Receipt/authenticated bundleだけが
|
| 922 |
+
protocol authorityである。
|
| 923 |
+
|
| 924 |
+
## 16. Security and issuance boundary
|
| 925 |
+
|
| 926 |
+
trace root は approved observer が報告したeventへのcommitmentであり、単独のproof of executionでは
|
| 927 |
+
ない。intended production safety modelはpinned build、signed assignment、independent replica、future
|
| 928 |
+
audit、bond/slashing、durable uniquenessを組み合わせるが、個別primitive/state machineの存在はそれらが
|
| 929 |
+
operationally統合済みであることを意味しない。
|
| 930 |
+
|
| 931 |
+
schema-v4 coreはscheduler-signed canary precommit、authority-signed bond funding/appeal/decision、durable
|
| 932 |
+
assignment lock/release/slash/health、authority-signed external funding/grant/terminalを実装する。bonded receipt
|
| 933 |
+
acceptance、audit/canaryのtyped slash、maturity時bond release/link、WorkTicketV2 gate、External terminalから
|
| 934 |
+
maturity/ticketまでのlocal atomic transactionも実装済みである。
|
| 935 |
+
|
| 936 |
+
ただしproduction scheduler/network transport、governance-backed scheduler/worker/beacon/bond/external key
|
| 937 |
+
distribution、finalized beacon delivery、independent auditor execution/opening delivery、実payment railと
|
| 938 |
+
authority serviceはこのrepositoryにない。署名済みfunding/terminalは外部factのauthenticated statementで
|
| 939 |
+
あり、crate単体が実collateralやrail movementを独立証明するものではない。railとSQLiteはdistributed
|
| 940 |
+
atomic transactionではない。durable slashへ自動接続済みのproofはaudit mismatch/timeoutとcanary
|
| 941 |
+
mismatch/receipt timeoutで、invalid-manifest、equivocation、duplicate-executionのproduction proof
|
| 942 |
+
constructor/orchestrationは未統合である。legacy in-memory `BondLedger`/`CanaryRecord`/`ExternalEscrow` helperの
|
| 943 |
+
raw mutation APIをproduction authority pathとして使ってはならない。
|
| 944 |
+
|
| 945 |
+
現時点で実モデルReceiptを発行できるのはApple Metal `GraphFallback` runtime classである。CUDAは
|
| 946 |
+
RTX 4060 Ti sm_89 / CUDA Toolkit 13.3.1 / nvcc 13.3.73で固定Qwen 37/37 layer offload、graph observer
|
| 947 |
+
6/6、standalone true-accumulator primitiveの最終grouped device suite 8/8とproducer 20/20同一fingerprintに
|
| 948 |
+
加え、vendored MMVQ/FA-off attention same-backend 1-token diagnostic E2Eで361/361 recordと3回同一
|
| 949 |
+
fingerprintを実測済みである。exact entry/cubin/DSO release manifest、Receipt/RuntimeManifest/Request/
|
| 950 |
+
Assignment V2、暗号化Bundle V2、SQLite V2も実装・検証済みである。これはproduction `KernelSketch`
|
| 951 |
+
acceptanceではなく、authority-derived canonical IDを使うlive callbackとauthority governanceは未完了である。
|
| 952 |
+
V1 builder/verifierとproduction macro/CMake gateはfail closedを維持するため、
|
| 953 |
+
これらが完了するまでproduction CUDA Receipt/Work Ticketを発行しない。TEE attestationやZK/VCは
|
| 954 |
+
実装範囲外である。
|
docs/receipt-implementation-qwen36.md
ADDED
|
@@ -0,0 +1,656 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MISAKA PALW Receipt 実装仕様 — Qwen3.6-35B-A3B (hybrid MoE)
|
| 2 |
+
|
| 3 |
+
本書は、対象モデルを dense Qwen3-8B から hybrid **Qwen3.6-35B-A3B**
|
| 4 |
+
(`huihui_ai/Qwen3.6-abliterated:35b-Claude-4.7`、abliterated) へ移行した後の
|
| 5 |
+
`ComputeReceiptV1` 発行・検証パイプラインの実装仕様である。記述は現行 Rust/C++
|
| 6 |
+
ソースを正本とし、実装と本書が一致しない場合は Receipt を発行しない
|
| 7 |
+
([`protocol-v1.md`](protocol-v1.md) と同じ原則)。本書に無い production 承認・決済連携・
|
| 8 |
+
attestation を Receipt から推論してはならない。
|
| 9 |
+
|
| 10 |
+
対象モデルは linear-attention(state-space / gated-delta-net)層と mixture-of-experts
|
| 11 |
+
層を組み合わせた hybrid 構成であり、dense Qwen3-8B 用の厳格な canonical operation
|
| 12 |
+
mapping では表現できない演算を含む。そのため本移行では **(1)** pinned llama.cpp への
|
| 13 |
+
qwen35moe loader/graph 互換修正、**(2)** dense vocabulary に対応の無い演算を output-element
|
| 14 |
+
数で committ する generic operation と CU ルールセット v2、**(3)** profile 駆動の hybrid
|
| 15 |
+
adapter/manifest、を追加した。移行完了後、dense Qwen3-8B 経路(profile / manifest builder /
|
| 16 |
+
constants / tests)は撤去され、Qwen3.6-35B-A3B が唯一の対象モデルとなった。
|
| 17 |
+
|
| 18 |
+
行番号 anchor は執筆時点のものであり、正本はソースである。
|
| 19 |
+
|
| 20 |
+
> **compute-gate track 更新(2026-07-19、実機検証済み)。** 上記 (2) の「generic operation + CU
|
| 21 |
+
> ルールセット v2」は**後続の compute-gate track で置換された**。現行 receipt は **(M1)** CU を
|
| 22 |
+
> semantic ルールセット v3 で canonical commit(`canonical_compute_units = 41692`)、**(M3)** generic
|
| 23 |
+
> 演算を廃止し全 MoE/SSM op を忠実な canonical 演算(`ExpertGemm`/`ExpertRoute`/`SsmConv`/
|
| 24 |
+
> `GatedDeltaNet`/`L2Norm`/`Reduction`/`Elementwise`)へ写像、**(M2)** canonical semantic schedule を
|
| 25 |
+
> 再生成・commit、**(M4/#6)** observer が実 MoE routing(`ffn_moe_topk`)を捕捉し `expert_route_root`
|
| 26 |
+
> を封緘 bundle へ commit(observer schema v2)、**(M5/#5)** ggml-metal を計装して各 GEMM を実 Metal
|
| 27 |
+
> kernel dispatch + launch geometry へ束縛し `trace_evidence=metal_kernel` を commit(graph-fallback
|
| 28 |
+
> から昇格、実機で 200/200・411/411 検証)。§0–§2 の一部記述(CU v2 / generic / SCHEMA_VERSION 1 /
|
| 29 |
+
> MUL_MAT_ID=metadata / graph_fallback)は旧版で、現行の正確な値は §10・§11 と
|
| 30 |
+
> [`receipt-review-remediation.md`](receipt-review-remediation.md) を参照。**6 つの compute gate は
|
| 31 |
+
> 全て実機検証済み。** Metal の kernel-level trace は launch-geometry 束縛であり CUDA V3 相当の
|
| 32 |
+
> intra-kernel accumulator proof ではない(honest labeling、mint は依然不適格)。
|
| 33 |
+
|
| 34 |
+
---
|
| 35 |
+
|
| 36 |
+
## 0. 全体アーキテクチャとデータフロー
|
| 37 |
+
|
| 38 |
+
三層構成:
|
| 39 |
+
|
| 40 |
+
1. `vendor/llama.cpp/`(commit 固定 + PALW patch): 推論ランタイムと read-only graph observer
|
| 41 |
+
`llama-palw-observer`。
|
| 42 |
+
2. `runtime-palw/`(Rust): adapter、canonical CU、schedule、commitment、manifest、receipt
|
| 43 |
+
builder/verifier、verification bundle、schema-v4 SQLite。
|
| 44 |
+
3. `config/` / `patches/`: 固定 artifact pin、model profile pin、llama.cpp patch。
|
| 45 |
+
|
| 46 |
+
Receipt 発行(`palw-metal-receipt`)のデータフロー:
|
| 47 |
+
|
| 48 |
+
```
|
| 49 |
+
prompt(stdin)
|
| 50 |
+
│
|
| 51 |
+
├─ build_qwen36_35b_metal_manifest ─────────► RuntimeManifest(MoE topology, CU v3 semantic)
|
| 52 |
+
│
|
| 53 |
+
├─ llama-tokenize ──────────────────────────► prompt_token_ids
|
| 54 |
+
│
|
| 55 |
+
├─ llama-palw-observer --observer sketch ───► JSONL(header/event*/result)
|
| 56 |
+
│ │(read-only graph callback、sketch)
|
| 57 |
+
│ ▼
|
| 58 |
+
│ qwen_adapter(HybridQwen36A3B)
|
| 59 |
+
│ │ header 検証 + op→ComputeOperation 写像 + GEMM sketch
|
| 60 |
+
│ ▼
|
| 61 |
+
│ RuntimeObserver → ExecutionEvidence(schedule + GEMM trace + CU total, ruleset=v3 semantic)
|
| 62 |
+
│
|
| 63 |
+
├─ build_signed_receipt ────────────────────► ComputeReceiptV1(署名)
|
| 64 |
+
├─ verify_stateless(cu_rules=v3) ───────────► 自己検証
|
| 65 |
+
├─ seal_verification_bundle(XChaCha20) ─────► <id>.palw.bundle
|
| 66 |
+
├─ StateStore(schema v4).accept ────────────► palw-state.sqlite3
|
| 67 |
+
└─ 書き出し: <id>.palw / <id>.json / <id>.palw.bundle / <id>.complete
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
別 process 検証(`palw-verify-bundle`)は artifact set・完了 marker を検査し、bundle を復号・
|
| 71 |
+
再検証(`verify_bundle_and_restore`)して `status=local_restored` /
|
| 72 |
+
`trust_scope=embedded_local_snapshot` を出力する。
|
| 73 |
+
|
| 74 |
+
---
|
| 75 |
+
|
| 76 |
+
## 1. 対象モデルと固定 artifact
|
| 77 |
+
|
| 78 |
+
正本: [`config/runtime-pins.sh`](../config/runtime-pins.sh)(公開識別子のみ、末尾で全て `readonly`)。
|
| 79 |
+
|
| 80 |
+
### 1.1 推論 GGUF(Ollama registry blob)
|
| 81 |
+
|
| 82 |
+
| 変数 | 値 |
|
| 83 |
+
|---|---|
|
| 84 |
+
| `PALW_GGUF_REGISTRY` | `registry.ollama.ai` |
|
| 85 |
+
| `PALW_GGUF_REPO_ID` | `huihui_ai/Qwen3.6-abliterated` |
|
| 86 |
+
| `PALW_GGUF_OLLAMA_TAG` | `35b-Claude-4.7` |
|
| 87 |
+
| `PALW_GGUF_REVISION` = `PALW_GGUF_SHA256` | `1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b` |
|
| 88 |
+
| `PALW_GGUF_FILENAME` | `Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf` |
|
| 89 |
+
| `PALW_GGUF_SIZE` | `23938321728`(bytes) |
|
| 90 |
+
|
| 91 |
+
Ollama registry の blob digest は GGUF 本体の SHA-256 に等しいため `revision == sha256`。
|
| 92 |
+
content 検証だけで pin 全体の照合になる。
|
| 93 |
+
|
| 94 |
+
### 1.2 base metadata(Hugging Face、7 files)
|
| 95 |
+
|
| 96 |
+
`PALW_BASE_REPO_ID = huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated`、
|
| 97 |
+
`PALW_BASE_REVISION = ac18882735d037f6074a7630eb68d85db8234c25`。
|
| 98 |
+
files: `README.md`、`chat_template.jinja`、`config.json`、`model.safetensors.index.json`、
|
| 99 |
+
`processor_config.json`、`tokenizer.json`、`tokenizer_config.json`。
|
| 100 |
+
sha256 は [`config/qwen3.6-35b-a3b-claude-4.7-base-metadata.sha256`](../config/qwen3.6-35b-a3b-claude-4.7-base-metadata.sha256)
|
| 101 |
+
および profile pin の `base_artifact.files[]` と一致する。
|
| 102 |
+
|
| 103 |
+
### 1.3 llama.cpp
|
| 104 |
+
|
| 105 |
+
`PALW_LLAMA_COMMIT = 12127defda4f41b7679cb2477a4b0d65ee6a0c8f`(build 10015)、
|
| 106 |
+
patch = [`patches/llama.cpp-palw-observer.patch`](../patches/llama.cpp-palw-observer.patch)、
|
| 107 |
+
`PALW_LLAMA_PATCH_SHA256 = d155a88b7c11ee74f48011760cb1a37773a694c8cab28258ee108c85e2f9e02c`。
|
| 108 |
+
Metal build は `-DGGML_METAL=ON -DGGML_CUDA=OFF`、`arm64`、target
|
| 109 |
+
`llama-cli/llama-server/llama-tokenize/llama-palw-observer`。
|
| 110 |
+
|
| 111 |
+
### 1.4 Ollama download 経路(`install.sh :: download_gguf_if_needed`)
|
| 112 |
+
|
| 113 |
+
1. `gguf_content_matches`(存在 + size + sha256)が成立すれば再利用。
|
| 114 |
+
2. mismatch する既存 file は上書きせず die。
|
| 115 |
+
3. URL = `https://$PALW_GGUF_REGISTRY/v2/$PALW_GGUF_REPO_ID/blobs/sha256:$PALW_GGUF_REVISION`
|
| 116 |
+
(OCI/Docker registry の blob-by-digest endpoint)。
|
| 117 |
+
4. `curl -fSL -C -`(再開可能)で `.partial` に取得。
|
| 118 |
+
5. size と sha256 を照合してから `mv` で atomic に確定。
|
| 119 |
+
6. base metadata は従来通り HF(`hf_snapshot_download.py`、token を strip し Xet を無効化)。
|
| 120 |
+
|
| 121 |
+
---
|
| 122 |
+
|
| 123 |
+
## 2. 決定論的実行と native observer
|
| 124 |
+
|
| 125 |
+
正本: `vendor/llama.cpp/tools/palw-observer/palw-observer.cpp`(以下 OBS)。単一リクエストの
|
| 126 |
+
非対話 runner で、public な `llama`/`ggml` API のみ使用。versioned JSONL を stdout に、
|
| 127 |
+
llama/ggml のログを stderr に書く。
|
| 128 |
+
|
| 129 |
+
### 2.1 強制される決定論的実行ポリシー
|
| 130 |
+
|
| 131 |
+
`n_ctx = PALW_CONTEXT_TOKENS = 4096`、`n_batch = n_ubatch = 1`、`n_seq_max = 1`、
|
| 132 |
+
`n_threads = n_threads_batch = 1`、greedy sampler、`flash_attn = DISABLED`、
|
| 133 |
+
`type_k = type_v = F16`、`split_mode = NONE`、`use_mmap = true`。context 初期化後に
|
| 134 |
+
実 context を読み直し、この不変条件を満たさなければ exit 3。prompt は `--prompt-stdin`
|
| 135 |
+
専用 pipe で渡し(argv に置かない)、prefill/decode とも 1 token ずつ `llama_batch_get_one`
|
| 136 |
+
で評価する。`prompt_tokens + n_predict > 4096` は context-shift せず失敗。
|
| 137 |
+
|
| 138 |
+
### 2.2 model profile gate(`validate_qwen36_35b_a3b_profile`)
|
| 139 |
+
|
| 140 |
+
model load 直後に、`general.architecture == "qwen35moe"`、`n_layer == 40`、`n_embd == 2048`、
|
| 141 |
+
`n_vocab == 248320`、decoder-only(encoder 無し)のみ受理。不一致は header/result を一切
|
| 142 |
+
emit せず exit 3。
|
| 143 |
+
|
| 144 |
+
### 2.3 JSONL プロトコル
|
| 145 |
+
|
| 146 |
+
`SCHEMA_NAME = "misaka.palw.runtime_observer"`、`SCHEMA_VERSION = 2`(route record 追加)。1 実行は
|
| 147 |
+
**header 1** → **event 0..N** → **result 1**。各行は個別に flush。
|
| 148 |
+
|
| 149 |
+
- **header**: `observer`(off/graph/sketch)、`trace_variant`、`cuda_kernel_trace:false`、
|
| 150 |
+
`model{path,description,tensor_size_bytes,parameter_count,file_type,n_ctx_train,n_embd,
|
| 151 |
+
n_layer,n_head,n_head_kv,n_vocab,rope_type,rope_freq_scale_train,metadata[]}`、
|
| 152 |
+
`runtime{ggml_version,ggml_commit,system_info,supports_gpu_offload,requested_gpu_layers,
|
| 153 |
+
devices[]}`、`execution_policy{...上記決定論ポリシー...}`、
|
| 154 |
+
`observation_policy{read_only:true, graph_metadata_stage:"ask", sketch_bits:256,
|
| 155 |
+
sketch_probe:"gemm_output_contiguous_prefix_64", raw_activation_values_published:false,
|
| 156 |
+
tile_variant:"graph_fallback_logical_prefix_v1", kernel_trace_claim:"none"}`。
|
| 157 |
+
- **event**: `event_seq`(単調増加、最終値 = result の `event_count`)、`phase`
|
| 158 |
+
(prefill/decode)、`phase_step`、`stage`(ask_metadata / post_compute_sketch)、`layer`
|
| 159 |
+
(名前から導出、無ければ null)、`categories[]`、`tensor{name,op,type,shape[4],n_bytes}`、
|
| 160 |
+
`sources[]`。MUL_MAT には `gemm{variant:"ggml_graph_op_v1",m,n,k,batch_shape}`。sketch
|
| 161 |
+
時のみ `sketch{}`/`tile{}`/`kernel_trace{}`。
|
| 162 |
+
- **result**: `status`、`stop_reason`(n_predict/eog/…)、`prompt_token_ids[]`、
|
| 163 |
+
`generated_token_ids[]`、`output_bytes[]`(`--emit-output-bytes` 時のみ非空)、
|
| 164 |
+
`output_n_bytes`、`event_count`。
|
| 165 |
+
|
| 166 |
+
### 2.4 observer モードと sketch scheme
|
| 167 |
+
|
| 168 |
+
- `off`: callback 無し、event 0。
|
| 169 |
+
- `graph`: 各非空 valid node に対し `ask_metadata` を 1 件 emit。tensor data は一切読まない。
|
| 170 |
+
- `sketch`: 非 MUL_MAT node は `ask_metadata`。`MUL_MAT` node のみ post-compute で
|
| 171 |
+
`ggml_backend_tensor_get` により先頭最大 64 要素を読み、**sign/bucket sketch** を採取して
|
| 172 |
+
`post_compute_sketch` を emit。
|
| 173 |
+
|
| 174 |
+
sketch(`sign_bucket_256_v1`): 各要素を 1 nibble(bit3 = 符号、bit0..2 = 3-bit 絶対値
|
| 175 |
+
bucket)にし、64 nibble = **256 bit**。bucket 境界は `0, 2⁻⁸, 2⁻⁴, 2⁻², 1, 4, 16, ∞`。生の
|
| 176 |
+
活性値は決して serialize しない。`kernel_trace{available:false, backend:"none",
|
| 177 |
+
claim:"not_a_cuda_kernel_trace"}` を常に付し、graph 観測を CUDA kernel 証拠へ昇格しない。
|
| 178 |
+
|
| 179 |
+
### 2.5 observer 側の hybrid 対応(3 点)
|
| 180 |
+
|
| 181 |
+
1. **`is_gemm` を `GGML_OP_MUL_MAT` のみに限定**。`GGML_OP_MUL_MAT_ID`(indirect expert
|
| 182 |
+
GEMM)は sketch せず通常の metadata node として emit する。
|
| 183 |
+
2. **0-element(recurrent state cache)tensor を skip**。gated-delta-net / SSM 層は初期状態が
|
| 184 |
+
空の state cache を gather し、合法な 0-element node を生む。これは compute を伴わないため
|
| 185 |
+
error にせず skip。
|
| 186 |
+
3. **`validate_tensor` が空 tensor を許容**(name/type/op の範囲検査後に短絡)。
|
| 187 |
+
|
| 188 |
+
### 2.6 qwen35moe.cpp loader/graph 修正(5 点)
|
| 189 |
+
|
| 190 |
+
pinned commit `12127def` の `src/models/qwen35moe.cpp` は本モデルを load/run できないため、
|
| 191 |
+
PALW comment 付きで以下を修正(observer patch に同梱):
|
| 192 |
+
|
| 193 |
+
1. **3-section mrope zero-pad**: `rope.dimension_sections` を可変配列として読み、size 3 or 4 を
|
| 194 |
+
許容して zero-fill+copy。新しい HF→GGUF 変換の `[t,h,w]`(末尾 0 省略)を受理。
|
| 195 |
+
2. **`ssm_dt` bias の suffix 両対応**: `blk.N.ssm_dt.bias` を `TENSOR_NOT_REQUIRED` で試し、
|
| 196 |
+
無ければ suffix 無し `blk.N.ssm_dt` を required で load。
|
| 197 |
+
3. **KV 射影幅に `n_embd_k_gqa_max()`**: `LLAMA_LOAD_LOCALS` は layer 0 から `n_embd_k/v_gqa`
|
| 198 |
+
を導出するが、layer 0 は linear-attention 層で `n_head_kv==0`。full-attention trunk 層と
|
| 199 |
+
MTP 層の tensor 生成で per-layer 最大値を使う。
|
| 200 |
+
4. **sibling tensor(`v.*` / `mtp.*`)の計上**: Ollama 同梱 GGUF は vision tower と(MTP 未
|
| 201 |
+
有効時)MTP sub-model を同梱する。text runtime はこれらを構築しないため、該当 prefix の
|
| 202 |
+
tensor 分だけ `n_created`/`size_data` を調整し `done_getting_tensors` を通す。存在する
|
| 203 |
+
tensor のみ 1 回ずつ計上するため、text tensor の欠落は依然として検出される。
|
| 204 |
+
5. **`build_layer_attn` の per-layer `n_head(il)`/`n_head_kv(il)`**: graph base は layer 0 から
|
| 205 |
+
head 数を初期化するため、full-attention の Q/K/V reshape と RoPE を per-layer 値で shadow。
|
| 206 |
+
|
| 207 |
+
---
|
| 208 |
+
|
| 209 |
+
## 3. Rust adapter — hybrid 経路
|
| 210 |
+
|
| 211 |
+
正本: `runtime-palw/src/qwen_adapter.rs`。`AdapterProfile { HybridQwen36A3B }`(唯一の profile)
|
| 212 |
+
を `NativeParseConfig`/`NativeRunConfig` の `profile` field で選択し、
|
| 213 |
+
`parse_native_jsonl_with_stderr` が header 検証 / event 変換 / vocab 上限を hybrid 経路で処理する。
|
| 214 |
+
旧 dense 経路は撤去済み。
|
| 215 |
+
|
| 216 |
+
### 3.1 hybrid 定数と識別子
|
| 217 |
+
|
| 218 |
+
`QWEN36_35B_LAYERS=40`、`QWEN36_35B_VOCAB=248320`、`QWEN36_35B_EMBED=2048`、
|
| 219 |
+
`QWEN36_35B_CONTEXT=262144`、`QWEN36_35B_PARAMETERS=35_951_822_704`、
|
| 220 |
+
`QWEN36_ARCHITECTURE="qwen35moe"`、共有の `Q4_K_M_FILE_TYPE=15`、`QWEN_RUNTIME_CONTEXT=4096`。
|
| 221 |
+
|
| 222 |
+
`qwen36_adapter_mapping_id_v1()` は domain `"qwen36-native-observer-mapping/v1"` の
|
| 223 |
+
`domain_hash`。payload は各 op の写像を列挙し `cu-ruleset=v2;graph-fallback-only` を含む。dense
|
| 224 |
+
の `"qwen-native-observer-mapping/v1"`(`soft_max=attention`)とは別 hash。
|
| 225 |
+
|
| 226 |
+
### 3.2 header 検証(`validate_header_hybrid`)
|
| 227 |
+
|
| 228 |
+
deterministic execution policy と observation policy は **dense と同一**の厳格さで検証する。
|
| 229 |
+
model-shape だけを MoE 向けに一般化する:
|
| 230 |
+
|
| 231 |
+
- `parameter_count == 35_951_822_704`、`file_type == 15`、`n_ctx_train == 262144`、
|
| 232 |
+
`n_embd == 2048`、`n_layer == 40`、`n_vocab == 248320`、`rope_freq_scale_train == 1.0`。
|
| 233 |
+
- **dense と違い `n_head`/`n_head_kv`/`rope_type` は pin しない**(MoE は per-layer で可変、
|
| 234 |
+
layer-0 KV-head を制約しない)。
|
| 235 |
+
- 必須 metadata: `general.architecture=qwen35moe`、`general.file_type=15`、
|
| 236 |
+
`general.quantization_version=2`、`qwen35moe.context_length=262144`、
|
| 237 |
+
`qwen35moe.embedding_length=2048`、`qwen35moe.block_count=40`、
|
| 238 |
+
`qwen35moe.expert_count=256`、`qwen35moe.expert_used_count=8`。dense と逆に **expert
|
| 239 |
+
metadata を要求**する(dense は expert metadata を拒否)。
|
| 240 |
+
- graph/sketch 時は `supports_gpu_offload && requested_gpu_layers==999 && GPU device 存在`。
|
| 241 |
+
|
| 242 |
+
### 3.3 op → canonical operation 写像(`convert_event_hybrid`)
|
| 243 |
+
|
| 244 |
+
各 ggml op を canonical `ComputeOperation` へ写像する。dense と異なり、正確な canonical
|
| 245 |
+
対応がある演算はそれへ、対応の無い演算は `Generic{op_class, elements}` へ写す。fail-closed。
|
| 246 |
+
|
| 247 |
+
| ggml op | canonical operation |
|
| 248 |
+
|---|---|
|
| 249 |
+
| `MUL_MAT` | `Gemm`(`convert_gemm_hybrid`、sketch 採取) |
|
| 250 |
+
| `RMS_NORM` | `RmsNorm { elements=shape[0], batch=Πshape[1..] }` |
|
| 251 |
+
| `ROPE` | `Rotary { head_dim=shape[0], heads=shape[1], tokens=Πshape[2..] }` |
|
| 252 |
+
| `SOFT_MAX` | `Softmax { elements=Πshape }`(dense は Attention 再構成) |
|
| 253 |
+
| `GLU` | `Silu{elements}` + `ElementwiseMultiply{elements}` |
|
| 254 |
+
| `MUL` | `ElementwiseMultiply { elements }` |
|
| 255 |
+
| `ADD` | `ElementwiseAdd { elements }` |
|
| 256 |
+
| `GET_ROWS` | `EmbeddingLookup { elements }` |
|
| 257 |
+
| `SET_ROWS` | `KvCacheWrite { bytes = tensor.n_bytes }` |
|
| 258 |
+
| `CONT` \| `CPY` | `TensorCopy { bytes = tensor.n_bytes }` |
|
| 259 |
+
| `VIEW` \| `RESHAPE` \| `PERMUTE` \| `TRANSPOSE` | layout-only(schedule に載せない) |
|
| 260 |
+
| その他 | `Generic { op_class=hybrid_generic_op_class(op), elements=Πshape }`。未列挙は拒否 |
|
| 261 |
+
|
| 262 |
+
`hybrid_generic_op_class`(不変な op→u32 表): `MUL_MAT_ID=1`、`UNARY=2`、`SCALE=3`、
|
| 263 |
+
`L2_NORM=4`、`SUM_ROWS=5`、`DIV=6`、`CLAMP=7`、`ARGSORT=8`、`SSM_CONV=9`、
|
| 264 |
+
`GATED_DELTA_NET=10`、`CONCAT=11`。これ以外は `None` → `InvalidEvent`(fail-closed)。
|
| 265 |
+
|
| 266 |
+
### 3.4 GEMM 変換(`convert_gemm_hybrid`)
|
| 267 |
+
|
| 268 |
+
`gemm{}` metadata の相互整合(`m==left.shape[1]`、`n==right.shape[1]`、`k==left.shape[0]`、
|
| 269 |
+
`left.shape[0]==right.shape[0]`、output shape 一致)を検証する。dense と異なり **固定 geometry
|
| 270 |
+
や dtype allowlist は課さない**。quantization は `left.kind` から `q4_K→Q4KM`、`q6_K→Q6K`、
|
| 271 |
+
その他→`None`。sketch 時は `validate_graph_fallback_sketch`(sketch/tile/kernel_trace の値を
|
| 272 |
+
厳格検証)後、64 hex を 4 lane の big-endian `i64` へ復元し `on_gemm_group` で trace に記録。
|
| 273 |
+
kernel_id domain は `"qwen36-graph-fallback-probe/v1"`。
|
| 274 |
+
|
| 275 |
+
### 3.5 GPU offload marker とプライバシ
|
| 276 |
+
|
| 277 |
+
`scan_stderr_markers` は `"offloaded N/N layers to gpu"` を **N が正で左右一致なら任意の N** で
|
| 278 |
+
検出する(dense 37/37、hybrid 41/41 を model 非依存で受理)。不一致は
|
| 279 |
+
`IncompleteGpuOffload`。prompt は `OsStr` の stdin のみ、error payload は `&'static str`/数値
|
| 280 |
+
のみ、`QwenObserverOutput` は `Debug` 未実装、`zeroize_private_material` が prompt/生成
|
| 281 |
+
token/QA bytes を zeroize。
|
| 282 |
+
|
| 283 |
+
---
|
| 284 |
+
|
| 285 |
+
## 4. 正準演算語彙と CU ルールセット
|
| 286 |
+
|
| 287 |
+
正本: `runtime-palw/src/compute_units.rs`。
|
| 288 |
+
|
| 289 |
+
### 4.1 `ComputeOperation`(canonical serialize discriminant)
|
| 290 |
+
|
| 291 |
+
`0 Gemm(GemmShape)`、`1 Attention`、`2 LayerNorm`、`3 RmsNorm`、`4 Rotary`、`5 ExpertRoute`、
|
| 292 |
+
`6 KvCacheRead`、`7 KvCacheWrite`、`8 Silu`、`9 ElementwiseMultiply`、`10 Softmax`、
|
| 293 |
+
`11 ElementwiseAdd`、`12 TensorCopy`、`13 EmbeddingLookup`、**`14 Generic{op_class:u32,
|
| 294 |
+
elements:u64}`**(本移行で追加)。0..5 は `u32` 次元、6..13 は単一 `u64`。追加は additive で
|
| 295 |
+
既存 variant の byte は不変。
|
| 296 |
+
|
| 297 |
+
`Generic` は「dense に cost 規則の無い演算(gated-delta-net、SSM conv、MoE routing 等)を
|
| 298 |
+
意味を歪めず、output 要素数で忠実に committ する」ための variant。`op_class` は演算種別の
|
| 299 |
+
安定 ID、cost は output 要素数のみに依存する。**v2 のみが pricing し、v1 は拒否する**ため
|
| 300 |
+
既存 dense receipt と ruleset identity は不変。
|
| 301 |
+
|
| 302 |
+
### 4.2 CU ルールセット v1/v2
|
| 303 |
+
|
| 304 |
+
`CU_RULESET_VERSION_V1=1`、`CU_RULESET_VERSION_V2=2`。`ruleset_id()` は
|
| 305 |
+
`domain_hash("cu-ruleset/vX", X, [payload])`。payload の唯一の差分は v2 が `ceil;min1` の前に
|
| 306 |
+
**`generic=2/4096;`** を挿入する点(domain も `/v2`)。よって
|
| 307 |
+
`v1().ruleset_id() != v2().ruleset_id()`。`matching_ruleset_id(&Hash32)` は `[v1(),v2()]` から
|
| 308 |
+
一致する ruleset を返す(本移行で追加、bundle 経路が使用)。
|
| 309 |
+
|
| 310 |
+
cost 式(`cost()`、`scaled_cost = max(1, ceil(work·units/reference))`、全て checked):
|
| 311 |
+
|
| 312 |
+
| op | work | reference | units |
|
| 313 |
+
|---|---|---|---|
|
| 314 |
+
| `Gemm` | m·n·k·batch | 4096³ | 120 |
|
| 315 |
+
| `Attention` | q·kv·heads·head_dim·batch | 4096·4096·32·128 | 80 |
|
| 316 |
+
| `LayerNorm`/`RmsNorm` | elements·batch | 4096 | 8 |
|
| 317 |
+
| `Rotary` | tokens·heads·head_dim | 4096 | 4 |
|
| 318 |
+
| `ExpertRoute` | tokens·experts·top_k | 4096 | 16 |
|
| 319 |
+
| `KvCacheRead`/`Write`/`TensorCopy` | bytes | 1 MiB | 1 |
|
| 320 |
+
| `Silu`/`ElementwiseMultiply`/`ElementwiseAdd` | elements | 4096 | 2 |
|
| 321 |
+
| `Softmax` | elements | 4096 | 4 |
|
| 322 |
+
| `EmbeddingLookup` | elements | 4096 | 1 |
|
| 323 |
+
| **`Generic`** | elements | 4096 | 2 (**v2 限定**、v1 は `UnsupportedOperation`) |
|
| 324 |
+
|
| 325 |
+
`ComputeUnitCounter.record` は cost を checked-add し、overflow 時は state を変えず
|
| 326 |
+
`CostError::Overflow`(fail-closed)。
|
| 327 |
+
|
| 328 |
+
---
|
| 329 |
+
|
| 330 |
+
## 5. Model profile pin と RuntimeManifest 構築
|
| 331 |
+
|
| 332 |
+
正本: `runtime-palw/src/qwen_profile.rs`、`runtime-palw/src/manifest.rs`、
|
| 333 |
+
[`config/qwen3.6-35b-a3b-claude-4.7-profile.json`](../config/qwen3.6-35b-a3b-claude-4.7-profile.json)。
|
| 334 |
+
|
| 335 |
+
### 5.1 profile pin(schema v2)
|
| 336 |
+
|
| 337 |
+
`schema = "misaka.palw.model-profile-pin.v2"`、
|
| 338 |
+
`profile_name = "Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated-Q4_K_M-Metal-arm64"`。
|
| 339 |
+
`model{}` は MoE の全 shape(architecture `Qwen3_5MoeForConditionalGeneration`、model_type
|
| 340 |
+
`qwen3_5_moe`、gguf_architecture `qwen35moe`、hidden 2048、heads 16、kv 2、layers 40、
|
| 341 |
+
head_dim 256、intermediate 512、expert_count 256、experts_per_token 8、rope_theta 10000000、
|
| 342 |
+
vocab 248320、max_pos 262144、bfloat16、Q4_K_M、ほか linear_* 等)を持つ。`base_artifact`
|
| 343 |
+
は 7 files(各 sha256)、`inference_artifact` は Ollama repo/tag/**64-hex blob revision**/bytes/
|
| 344 |
+
sha256、`runtime` は commit と cmake_cache。deserialize struct は serde `deny_unknown_fields`
|
| 345 |
+
(`HybridProfilePin`/`HybridModelPin`/`HybridInferenceArtifactPin`。dense との差は `tag` field)。
|
| 346 |
+
|
| 347 |
+
### 5.2 `validate_hybrid_pin`
|
| 348 |
+
|
| 349 |
+
schema/profile_name 一致、model 全 shape 一致、`download_scope=="metadata-only"`、
|
| 350 |
+
`supported_profile=="metal-arm64"`、`targets` に `llama-palw-observer`、`commit.len()==40`、
|
| 351 |
+
`base.revision.len()==40`、**`inference.revision.len()==64`**(Ollama blob digest)、
|
| 352 |
+
`inference.bytes!=0`。metadata files は 7 件で各 sha256 を streaming 照合
|
| 353 |
+
(`verify_base_metadata_hybrid`)。
|
| 354 |
+
|
| 355 |
+
### 5.3 `build_qwen36_35b_metal_manifest`
|
| 356 |
+
|
| 357 |
+
host(arm64、8 field 非空)と environment(`LANG`/`LC_ALL` のみ)を検証し、GGUF の size/sha256、
|
| 358 |
+
tokenizer(`tokenizer.json`+`tokenizer_config.json` の 2 件)を artifact 化する。以下の digest を
|
| 359 |
+
`domain_hash` で計算し RuntimeManifest に committ する(dense と domain string が異なる主要点):
|
| 360 |
+
|
| 361 |
+
- `chat_template_digest`(`chat-template/v1`): **`chat_template.jinja` file bytes**
|
| 362 |
+
(dense は tokenizer_config 内の文字列)。
|
| 363 |
+
- `special_tokens_digest`(`special-token-semantics/v1`): tokenizer_config + config.json
|
| 364 |
+
(generation は `Value::Null`)。
|
| 365 |
+
- `kernel_graph_id`(`qwen36-35b-llama-graph/v1`): commit + `qwen36_adapter_mapping_id_v1()`
|
| 366 |
+
+ `ggml_sched_ask_metadata_v1` + prefill/decode 直列。
|
| 367 |
+
- `kernel_algorithm_digest`(`kernel-algorithm-policy/v1`): 末尾に `;moe-hybrid;cu-ruleset=v2`。
|
| 368 |
+
- ほか `loaded_libraries_digest`、`build_flags_digest`、`dirty_patch_digest`、
|
| 369 |
+
`environment_allowlist_digest`、`runtime_device_digest`、`runtime_program_digest`、
|
| 370 |
+
`build_provenance_digest`。
|
| 371 |
+
|
| 372 |
+
`ModelProfile` は **topology = MixtureOfExperts**、`kv_heads=2`、**`head_dim=256`(hidden/heads
|
| 373 |
+
= 2048/16 = 128 とは decouple)**、`rope="Qwen3.5-iMRoPE"`、`native_context_tokens=262144`、
|
| 374 |
+
`vocabulary=248320`。`RuntimeClass` は Q4_K_M、flash-attn off、`context_size=4096`、batch=1。
|
| 375 |
+
`RuntimeManifest.cu_ruleset_id = ComputeUnitRules::v2().ruleset_id()`。
|
| 376 |
+
|
| 377 |
+
### 5.4 manifest validator の緩和(hybrid を受理する 2 点)
|
| 378 |
+
|
| 379 |
+
- `ModelProfile::validate` は旧来の `head_dim == hidden/heads` 検査を**削除**した。head_dim を
|
| 380 |
+
独立 field として committ し cross-check しないため、`head_dim=256` と `2048/16=128` が
|
| 381 |
+
共存できる。`hidden % heads == 0`(2048%16)、`heads % kv == 0`(16%2)は維持。
|
| 382 |
+
- `RuntimeManifest::validate` は `cu_ruleset_id` が **v1 または v2** の ruleset_id なら受理する。
|
| 383 |
+
|
| 384 |
+
---
|
| 385 |
+
|
| 386 |
+
## 6. Receipt body・commitment・署名
|
| 387 |
+
|
| 388 |
+
正本: `runtime-palw/src/receipt.rs`、`runtime-palw/src/builder.rs`、`runtime-palw/src/observer.rs`。
|
| 389 |
+
|
| 390 |
+
### 6.1 `ComputeReceiptV1`(署名される canonical wire 順)
|
| 391 |
+
|
| 392 |
+
30 field を固定順で encode し、その byte 列が全 digest(`signing_digest`/`body_id`/
|
| 393 |
+
`receipt_id`)の入力になる。主要 field: `receipt_version(=1)`、`network_id`、
|
| 394 |
+
`request_commitment`、`scheduler_job_id`、`signed_assignment_id`、`replica_slot`、
|
| 395 |
+
`model_profile_id`、`runtime_class_id`、`runtime_manifest_hash`、`shape_profile_id`、
|
| 396 |
+
**`cu_ruleset_id = evidence.cu_ruleset_id()`**、`trace_scheme_id`、`trace_evidence`、
|
| 397 |
+
`operation_schedule_commitment`、`schedule_event_count`、`canonical_compute_units`、
|
| 398 |
+
`prefill_tokens`、`decode_tokens`、`output_commitment`、`gemm_trace_root`、`trace_event_count`、
|
| 399 |
+
`owner_commitment`、`worker_credential_id`、`job_nullifier`、`execution_nullifier`、`job_class`、
|
| 400 |
+
`evidence_level`、`timestamp`、`issued_epoch`、`expires_epoch`。
|
| 401 |
+
|
| 402 |
+
`validate_structure` は署名前後で 17 digest の非零、`prefill_tokens!=0`、
|
| 403 |
+
`issued<=expires`、job_class ごとの replica_slot 範囲、evidence_level ごとの count 整合
|
| 404 |
+
(GemmTraced は schedule/trace/CU が全て非零かつ `trace_evidence!=Absent`)を検査する。
|
| 405 |
+
|
| 406 |
+
### 6.2 `build_signed_receipt`
|
| 407 |
+
|
| 408 |
+
`manifest.validate`、CUDA KernelSketch 拒否、scheduler 署名(request+assignment)検証、worker
|
| 409 |
+
credential binding、request constraints と manifest ID の一致、evidence↔shape/job binding、
|
| 410 |
+
prompt opening と `prefill_tokens` 一致、output count 一致、を検査後に commitment
|
| 411 |
+
(`commit_prompt_tokens`/`commit_output`/`commit_owner`/`derive_job_nullifier`/
|
| 412 |
+
`derive_execution_nullifier`)を計算し、body を Ed25519 署名(`signing_digest` は network-id
|
| 413 |
+
salt 付き canonical bytes)。builder は `cu_ruleset_id` を **evidence の値そのまま** committ する
|
| 414 |
+
(独自に ruleset を再導出しない)。
|
| 415 |
+
|
| 416 |
+
### 6.3 evidence 生成(`RuntimeObserver` → `ExecutionEvidence`)
|
| 417 |
+
|
| 418 |
+
observer は `job_nullifier`/`shape_profile_id`/`ComputeUnitRules`/`EvidenceLevel` に束縛される。
|
| 419 |
+
`schedule = OperationSchedule::new(..., rules.ruleset_id())`、trace は GemmTraced 時のみ生成。
|
| 420 |
+
状態機械は `AwaitingPrefill→Prefill→Decode{step}`、decode step は厳密連番、任意の event error で
|
| 421 |
+
恒久 poison。`finalize_with_generated_tokens` は `generated == decode_tokens+1`(先頭 token は
|
| 422 |
+
prefill logits から sample)を要求。GemmTraced 不変条件として **schedule の GEMM 数 ==
|
| 423 |
+
trace group 数**。`ExecutionEvidence.cu_ruleset_id = counter.rules().ruleset_id()`(本移行では
|
| 424 |
+
v2)がそのまま receipt へ流れる。
|
| 425 |
+
|
| 426 |
+
---
|
| 427 |
+
|
| 428 |
+
## 7. Stateless 検証(`verify_stateless`)
|
| 429 |
+
|
| 430 |
+
正本: `runtime-palw/src/verifier.rs`。`VerificationContext { network_id, current_epoch,
|
| 431 |
+
manifest, cu_rules, signer_registry, assignment_authorizations }` を取り、順に:
|
| 432 |
+
|
| 433 |
+
1. `validate_structure`、network/epoch。
|
| 434 |
+
2. assignment 解決と全 field binding、assignment policy(`required_evidence_level==evidence_level`)。
|
| 435 |
+
3. signer 解決、owner/worker commitment、**Ed25519 署名**(weak-key 拒否 + `verify_strict`)。
|
| 436 |
+
4. `manifest.validate`、CUDA KernelSketch 拒否。
|
| 437 |
+
5. `model_profile_id`/`runtime_class_id`/`runtime_manifest_hash`/`shape_profile_id` を manifest
|
| 438 |
+
から独立再計算して照合。
|
| 439 |
+
6. **CU-ruleset triple-bind**: `body.cu_ruleset_id == context.cu_rules.ruleset_id()` **かつ**
|
| 440 |
+
`== manifest.cu_ruleset_id`(不一致は `CuRulesetMismatch`)。本移行では三者とも v2。
|
| 441 |
+
7. `trace_scheme_id` bind、`job_nullifier`/`execution_nullifier` の再導出照合、`verify_shape`。
|
| 442 |
+
8. `verify_execution_evidence`: evidence metadata・schedule integrity/commitment 照合後、
|
| 443 |
+
**`context.cu_rules` で schedule を最初から再 pricing** し `canonical_compute_units` を
|
| 444 |
+
照合(claim を信用しない)。per-entry で layer 範囲、dense topology の expert-route 拒否、
|
| 445 |
+
decode phase 順序を検査。GemmTraced は `verify_trace`(trace binding、capability 一致、
|
| 446 |
+
GEMM 数 == trace group 数、per-event の schedule 対応)。
|
| 447 |
+
9. output nonce / prompt opening / output opening / output count。
|
| 448 |
+
|
| 449 |
+
hybrid では topology が MixtureOfExperts のため expert-route の dense 拒否は発火しない(なお
|
| 450 |
+
本 adapter は `MUL_MAT_ID` を `Generic` に写すので ExpertRoute op 自体を生成しない)。
|
| 451 |
+
|
| 452 |
+
---
|
| 453 |
+
|
| 454 |
+
## 8. Verification bundle と ruleset 選択の 3 修正
|
| 455 |
+
|
| 456 |
+
正本: `runtime-palw/src/verification_bundle.rs`。
|
| 457 |
+
|
| 458 |
+
### 8.1 `seal_verification_bundle`
|
| 459 |
+
|
| 460 |
+
owner opening を照合し、**封印前に receipt を完全に再 stateless 検証**する(state-store は
|
| 461 |
+
変更しない)。公開部 `BundlePublicV1`(receipt_binding、receipt_id、verification_epoch、
|
| 462 |
+
scheduler-key record、`manifest.canonical_bytes()`、`PortableEvidenceV1`)は認証済み cleartext。
|
| 463 |
+
秘密部 `BundlePrivateV1`(署名済み request/assignment、signer record、output opening =
|
| 464 |
+
output_nonce + prompt/output token IDs、owner salt)は **XChaCha20-Poly1305** で AEAD 暗号化
|
| 465 |
+
(AAD で receipt_binding/public_digest/nonce/public_bytes を束縛、AEAD 鍵は audit key の
|
| 466 |
+
`domain_hash` 派生で raw key を直接使わない)。`bundle_id` は完全な暗号化 envelope 全体の
|
| 467 |
+
`domain_hash`。
|
| 468 |
+
|
| 469 |
+
### 8.2 CU ルールセット選択の 3 修正(v2 対応)
|
| 470 |
+
|
| 471 |
+
| # | 位置 | 修正 |
|
| 472 |
+
|---|---|---|
|
| 473 |
+
| 1 | seal 経路 | `cu_rules = ComputeUnitRules::matching_ruleset_id(&context.manifest.cu_ruleset_id)`(旧: v1 固定) |
|
| 474 |
+
| 2 | `verify_bundle_stateless_inner` | `matching_ruleset_id(&bundle.public.manifest.cu_ruleset_id)`(旧: v1 固定) |
|
| 475 |
+
| 3 | `PortableEvidenceV1::encode_canonical` | ruleset **version** を evidence に合わせて書く(`matching_ruleset_id(evidence.cu_ruleset_id()).map_or(0, version)`。旧: v1 固定)。decode は `for_version` で読む |
|
| 476 |
+
|
| 477 |
+
これらが無いと、v2 evidence が bundle 内で v1 として round-trip し `CuRulesetMismatch` になる。
|
| 478 |
+
併せて `manifest.rs` の validate が v1|v2 を受理し、`matching_ruleset_id` を追加した。producing CLI
|
| 479 |
+
は `ComputeUnitRules::v2()` を bind する。
|
| 480 |
+
|
| 481 |
+
### 8.3 portable evidence の round-trip
|
| 482 |
+
|
| 483 |
+
encode は version・level・prefill/decode・**ruleset version**・job_nullifier・shape_profile_id・
|
| 484 |
+
schedule entries・trace groups・claimed CU・claimed ruleset を書く。decode は `RuntimeObserver`
|
| 485 |
+
で schedule/trace/CU を **再導出**(serialize 済み total を信用しない)し、再構成 evidence の
|
| 486 |
+
`canonical_compute_units`/`cu_ruleset_id` が claimed と一致することを要求する。bounds:
|
| 487 |
+
`MAX_EVIDENCE_EVENTS=250000`、`MAX_BUNDLE_BYTES=64MiB`。
|
| 488 |
+
|
| 489 |
+
---
|
| 490 |
+
|
| 491 |
+
## 9. 永続化(SQLite schema v4)と CLI 契約
|
| 492 |
+
|
| 493 |
+
### 9.1 StateStore(schema v4)
|
| 494 |
+
|
| 495 |
+
`APPLICATION_ID="PALW"`、`SCHEMA_VERSION=4`。`open` は parent dir 解決 + `SQLITE_OPEN_NOFOLLOW`、
|
| 496 |
+
`foreign_keys=ON`、`synchronous=FULL`、`journal_mode=WAL`、application/schema 照合、および
|
| 497 |
+
`sqlite_master` の **DDL fingerprint**(SHA3-256 golden 照合)。`accept` は `BEGIN IMMEDIATE` で
|
| 498 |
+
duplicate receipt / duplicate execution_nullifier / job-class 整合 / slot 充填を強制し、
|
| 499 |
+
`jobs`(PK `(network_id,job_nullifier)`、WITHOUT ROWID)と `receipts`(PK `receipt_id`、
|
| 500 |
+
`execution_nullifier` UNIQUE、`UNIQUE(network_id,job_nullifier,replica_slot)`、FK RESTRICT)へ
|
| 501 |
+
transaction で insert する。復元経路 `restore_accepted` は read-only で既存 row を byte 照合する。
|
| 502 |
+
|
| 503 |
+
### 9.2 `palw-metal-receipt`(発行 CLI)
|
| 504 |
+
|
| 505 |
+
必須: `--prompt-stdin`、`--audit-key-file`(**exact 32 raw bytes**、owner-only single-link
|
| 506 |
+
`0400`/`0600`、output dir 外)、`--output-dir`(新規/空、owner-only `0700`)。任意: `--n-predict`
|
| 507 |
+
(`1..=1024`、default 2)。prompt は UTF-8 非空 ≤1 MiB。run flow は §0 の通り。`canonical_source_patch`
|
| 508 |
+
は `tools/CMakeLists.txt` と `src/models/qwen35moe.cpp` の modified、`tools/palw-observer/` の
|
| 509 |
+
untracked のみを許容する(他は拒否 = fail-closed)。出力 artifact:
|
| 510 |
+
|
| 511 |
+
| file | mode | 内容 |
|
| 512 |
+
|---|---|---|
|
| 513 |
+
| `<id>.palw` | 0644 | 署名済み canonical receipt |
|
| 514 |
+
| `<id>.json` | 0644 | 公開 metadata(`misaka.palw.public-receipt.v2`、strict field) |
|
| 515 |
+
| `<id>.palw.bundle` | 0600 | XChaCha20 暗号化 bundle |
|
| 516 |
+
| `palw-state.sqlite3` | 0600 | schema v4 state |
|
| 517 |
+
| `<id>.complete` | 0644 | `misaka.palw.receipt-set.v2` 完了 marker(**最後**に fsync 付きで作成) |
|
| 518 |
+
|
| 519 |
+
### 9.3 `palw-verify-bundle`(検証 CLI)
|
| 520 |
+
|
| 521 |
+
必須: `--receipt`/`--bundle`/`--public-json`/`--audit-key-file`/`--state-db`。artifact set の
|
| 522 |
+
mode/owner/single-link/同一 private dir、完了 marker の binding、bounded read、`decode_strict`、
|
| 523 |
+
`validate_artifact_names`(receipt_id は bundle 由来)、`verify_bundle_and_restore`(§8 の復号・
|
| 524 |
+
再検証・schema-v4 復元)、`verify_public_metadata`(公開 JSON を authenticated 値と field 単位で
|
| 525 |
+
照合)。正常時 `status=local_restored` / `trust_scope=embedded_local_snapshot`。この trust scope
|
| 526 |
+
は bundle 内 registry snapshot による continuity を示すのみで、network authority の代替ではない。
|
| 527 |
+
|
| 528 |
+
---
|
| 529 |
+
|
| 530 |
+
## 10. E2E 実測(reference receipt)
|
| 531 |
+
|
| 532 |
+
Apple M1 Max(macOS Metal 4、arm64)。observer は load 時に qwen35moe/40/2048/248320 を検証し
|
| 533 |
+
`offloaded 41/41 layers to GPU`。出力健全性: `The capital of France is`
|
| 534 |
+
(`[760,6511,314,9338,369]`)→ ` Paris, a city renowned for its iconic`。
|
| 535 |
+
|
| 536 |
+
reference artifact は [`receipts/final-v7/`](../receipts/final-v7)、evidence 詳細は
|
| 537 |
+
[`docs/evidence/metal-hybrid-qwen36-2026-07-19.md`](evidence/metal-hybrid-qwen36-2026-07-19.md)。
|
| 538 |
+
公開 receipt(`misaka.palw.public-receipt.v2`)の主要値:
|
| 539 |
+
|
| 540 |
+
| field | 値 |
|
| 541 |
+
|---|---|
|
| 542 |
+
| `receipt_id` | `8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9` |
|
| 543 |
+
| `verification_bundle_id` | `f5b8a2968c4ea266b2cbbabf351a171e0fa2581984eff63362de2640fcdcf9db` |
|
| 544 |
+
| `cu_ruleset_id`(**v3 semantic**) | `43a5feef177b389f976361b22ac9d57da65815261282005bc78d1666a37870ce` |
|
| 545 |
+
| `job_class` / `evidence_level` / `trace_evidence` | `self_local` / `gemm_traced` / **`metal_kernel`** |
|
| 546 |
+
| `prefill_tokens` / `decode_tokens` | `5` / `2` |
|
| 547 |
+
| `prefill_graph_steps` / `decode_graph_steps` | `5` / `1` |
|
| 548 |
+
| `schedule_event_count`(= canonical_operations、commitment-only) | `13770` |
|
| 549 |
+
| `trace_event_count`(= gemm_events) | `2466` |
|
| 550 |
+
| `canonical_compute_units`(**v3 semantic、署名 commit**) | `41692` |
|
| 551 |
+
| `semantic_compute_units_v3`(= canonical_compute_units) | `41692` |
|
| 552 |
+
| `semantic_schedule.commitment` / `.expert_route_ops` | `e6fc731e…` / `80` |
|
| 553 |
+
| `expert_route.root` / `.route_event_count`(実捕捉) | `5e4ea70b…` / `240` |
|
| 554 |
+
| `mint.eligible` / `mint.weight` / `mint.mainnet_ready` | `false` / `0` / `false` |
|
| 555 |
+
| `mint.ineligible_reasons` | Metal kernel-launch-bound / 非 network-anchored / 非 bonded の 3 件(generic+graph-fallback は解消) |
|
| 556 |
+
| `model_profile_id` | `b6b83a274a889fc5dfa2044b9158111b3849f880a05eb7ebcf560d036515d472` |
|
| 557 |
+
| `runtime_class_id` | `8f6f536118a72be70dab2028535c3bb95e3de9a3bac0e9b81cf78677ae902a9c` |
|
| 558 |
+
| `artifacts.llama_commit` / `model_bytes` | `12127def…` / `23938321728` |
|
| 559 |
+
|
| 560 |
+
privacy: prompt / prompt token IDs / 生成 token IDs / opening / signing key / owner salt は公開
|
| 561 |
+
`.palw` / `.json` に**含まれない**(全 9 flag が非公開/暗号化)。別 process の `palw-verify-bundle`
|
| 562 |
+
が `status=local_restored`、`trust_scope=embedded_local_snapshot`、receipt_id/bundle_id 一致、
|
| 563 |
+
exit 0 で再検証済み。発行は実行ごとに OS CSPRNG で identity を生成するため receipt_id は再現しない。
|
| 564 |
+
|
| 565 |
+
---
|
| 566 |
+
|
| 567 |
+
## 11. セキュリティ境界・正直な限界
|
| 568 |
+
|
| 569 |
+
- **この Receipt は mint-grade ではない。** 現行の `evidence_level=gemm_traced` /
|
| 570 |
+
`trace_evidence=graph_fallback` は**強い計算証明ではない**。`runtime-palw/src/mint.rs` の
|
| 571 |
+
`assess_mint_eligibility` が現行 runtime の全 receipt を `eligible=false, weight=0,
|
| 572 |
+
class="local_self_consistent_v0_1"` と判定し、公開 JSON の `mint` ブロックに失格理由と共に
|
| 573 |
+
自己申告する(`palw-verify-bundle` が再構成して照合)。用途は「ローカル自己整合 receipt /
|
| 574 |
+
testnet 計測 / Self-Local 非報酬」に限られる。mint-grade 化の是正計画は
|
| 575 |
+
[`receipt-review-remediation.md`](receipt-review-remediation.md) を参照���
|
| 576 |
+
- Metal の graph-fallback sketch は **CUDA kernel trace ではない**。
|
| 577 |
+
- 単独ノードが発行する Receipt は、それだけでゼロ知識の計算証明ではない。PALW の不正耐性は
|
| 578 |
+
runtime/model digest、署名、k=2 replica、future audit、canary、bond/slashing の組み合わせで
|
| 579 |
+
成立する。
|
| 580 |
+
- **`Generic` 演算は廃止済み(M3)。** hybrid の全 MoE/SSM op を忠実な canonical 演算へ写像
|
| 581 |
+
(`MUL_MAT_ID→ExpertGemm`、`ARGSORT→ExpertRoute`、`SSM_CONV→SsmConv`、`GATED_DELTA_NET→GatedDeltaNet`、
|
| 582 |
+
`L2_NORM→L2Norm`、`SUM_ROWS→Reduction`、`CONCAT→TensorCopy`、`UNARY/SCALE/DIV/CLAMP→Elementwise`)。
|
| 583 |
+
実機 receipt の schedule は `contains_generic_operation()==false`。
|
| 584 |
+
- **Semantic CU v3 は canonical commitment(M1、mainnet compute measure)。** `semantic_cu.rs` の
|
| 585 |
+
`qwen36_semantic_compute_units(prefill, generated)` は CU を **observed graph からではなく pinned
|
| 586 |
+
model 構造 + token 数**から算出(active-parameter FLOPs + causal attention 項、丸めは最後に 1 回)。
|
| 587 |
+
現行 receipt の `canonical_compute_units` は **この semantic 値(41692)を `cu_ruleset_id=v3` で署名
|
| 588 |
+
commit** する(v2 の graph 値ではない)。fragmentation-proof / backend 非依存で、verifier は
|
| 589 |
+
`prefill_tokens`/`decode_tokens` から同値を再計算・照合。
|
| 590 |
+
- **canonical semantic schedule(M2、#7 構造半分)。** `semantic_schedule.rs` が pinned architecture +
|
| 591 |
+
token 数から canonical op schedule と commitment を決定的に再生成し、公開 JSON `semantic_schedule`
|
| 592 |
+
に束縛。verifier が独立再生成して照合。
|
| 593 |
+
- **実 MoE routing の捕捉(M4/#6)。** observer が `ffn_moe_topk`(I32)を post-compute で読み戻し、
|
| 594 |
+
per-token 選択 expert を封緘 bundle の `expert_route_root` へ commit、公開 JSON `expert_route` として
|
| 595 |
+
発行・再構成。実機で 240 route record を捕捉。
|
| 596 |
+
- **kernel-level trace(#5、M5、完了・実機検証済み)。** ggml-metal を計装して各 GEMM を実 Metal
|
| 597 |
+
kernel dispatch + launch geometry へ束縛(200/200・411/411、0 anomaly)。`trace_evidence=metal_kernel`
|
| 598 |
+
(graph-fallback から昇格)、`TraceEvidenceKind/TraceCapability::MetalKernel` を新設し verifier が照合。
|
| 599 |
+
**launch-geometry 束縛であり CUDA V3 相当の intra-kernel accumulator proof ではない**ため
|
| 600 |
+
`KernelSketch` とは別 kind で commit(over-claim しない)。mint 失格理由は「Metal kernel-launch-bound
|
| 601 |
+
sketch, not an intra-kernel accumulator proof」に置換(mint 不適格のまま)。accumulator-level は
|
| 602 |
+
Metal shader 計装が残件。
|
| 603 |
+
- **mainnet-readiness。** `assess_mainnet_readiness` が compute / network / hardware / model-Genesis の
|
| 604 |
+
全 gate を列挙し、外部 gate を Met と偽らない。現状 `mint.mainnet_ready=false`。mainnet 報酬適格性は
|
| 605 |
+
deployed network authority / global nullifier / epoch beacon / bond authority / 複数世代実機 /
|
| 606 |
+
公式モデル Genesis を要し、この repository の完了範囲外である(remediation の外部ブロック項参照)。
|
| 607 |
+
- 未達 gate R13/R21/R23/R24/R26/R27/R32/R35 は [`requirements.md`](requirements.md) の通り
|
| 608 |
+
`In progress`。本移行はこれらの production 完了を意味しない。
|
| 609 |
+
|
| 610 |
+
### 既知の drift とテスト網羅(2026-07-19 時点)
|
| 611 |
+
|
| 612 |
+
- **hybrid adapter の専用 unit test** は fixture test を追加済み(`hybrid_generic_op_class` 表、
|
| 613 |
+
mapping id 識別、MoE/SSM op 写像、unknown op fail-closed、q6_K trace、dense header 拒否)。
|
| 614 |
+
CU fragmentation invariant や公式 Transformers との differential 等の残りは
|
| 615 |
+
[`receipt-review-remediation.md`](receipt-review-remediation.md) の follow-up。
|
| 616 |
+
- `validate_hybrid_pin` は dense と異なり `base_artifact`/`inference_artifact` の repository
|
| 617 |
+
文字列を pin せず、deserialize する MoE/linear-attention の追加 dim(`linear_*`、
|
| 618 |
+
`shared_expert_intermediate_size`、`full_attention_interval`、`partial_rotary_factor_millionths`)
|
| 619 |
+
を committ manifest には使わない(`deny_unknown_fields` 受理のためだけに存在)。
|
| 620 |
+
|
| 621 |
+
---
|
| 622 |
+
|
| 623 |
+
## 12. 再現手順
|
| 624 |
+
|
| 625 |
+
```sh
|
| 626 |
+
# 1. 導入(GGUF は Ollama registry、base metadata は HF)
|
| 627 |
+
./scripts/install.sh
|
| 628 |
+
|
| 629 |
+
# 2. Rust gate(MSRV 1.81)
|
| 630 |
+
cd runtime-palw
|
| 631 |
+
cargo +1.81.0 fmt --all -- --check
|
| 632 |
+
cargo +1.81.0 clippy --locked --all-targets -- -D warnings
|
| 633 |
+
cargo +1.81.0 test --locked --all-targets
|
| 634 |
+
cargo +1.81.0 build --release --locked --bin palw-metal-receipt --bin palw-verify-bundle
|
| 635 |
+
cd ..
|
| 636 |
+
|
| 637 |
+
# 3. Receipt 発行(audit key は 32-byte raw、output dir 外に一度だけ作成)
|
| 638 |
+
OUT="receipts/manual-$(date +%Y%m%d-%H%M%S)"
|
| 639 |
+
AUDIT_KEY="$HOME/.config/misaka-palw/audit-keys/local-audit.key"
|
| 640 |
+
install -d -m 700 "$(dirname "$AUDIT_KEY")"; test ! -e "$AUDIT_KEY"
|
| 641 |
+
(umask 077 && /usr/bin/openssl rand 32 > "$AUDIT_KEY"); chmod 600 "$AUDIT_KEY"
|
| 642 |
+
runtime-palw/target/release/palw-metal-receipt \
|
| 643 |
+
--prompt-stdin --audit-key-file "$AUDIT_KEY" --output-dir "$OUT" --n-predict 2 \
|
| 644 |
+
< /path/to/private-prompt.txt
|
| 645 |
+
|
| 646 |
+
# 4. 別 process 検���
|
| 647 |
+
RECEIPT="$(find "$OUT" -maxdepth 1 -type f -name '*.palw' -print)"; ID="$(basename "$RECEIPT" .palw)"
|
| 648 |
+
runtime-palw/target/release/palw-verify-bundle \
|
| 649 |
+
--receipt "$OUT/$ID.palw" --bundle "$OUT/$ID.palw.bundle" \
|
| 650 |
+
--public-json "$OUT/$ID.json" --audit-key-file "$AUDIT_KEY" \
|
| 651 |
+
--state-db "$OUT/palw-state.sqlite3"
|
| 652 |
+
# 期待: status=local_restored / trust_scope=embedded_local_snapshot / exit 0
|
| 653 |
+
```
|
| 654 |
+
|
| 655 |
+
GGUF の SHA-256 を発行前後に 4 回計算するため、1 回の発行は約 5 分要する(24GB × 4)。
|
| 656 |
+
これは hang ではない。
|
docs/receipt-review-remediation.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Receipt security review — remediation plan
|
| 2 |
+
|
| 3 |
+
本書は、Qwen3.6-35B-A3B hybrid receipt 実装に対する外部レビュー(16 項目)への対応方針を
|
| 4 |
+
正直に記録する。レビューの結論は妥当であり、本書もそれを採用する。
|
| 5 |
+
|
| 6 |
+
> **ローカル Receipt v0.1 として freeze 可。PALW mint-grade Receipt としては freeze 不可。**
|
| 7 |
+
|
| 8 |
+
`trace_evidence = graph_fallback` は依然 **kernel trace ではない**(#5、下記 external/remaining)。
|
| 9 |
+
ただし後述の compute-gate track により、CU は graph-independent な semantic commitment になり、
|
| 10 |
+
`Generic` 演算は廃止され、MoE expert routing は実捕捉されるようになった。
|
| 11 |
+
|
| 12 |
+
## compute-gate track — 実機検証済み(2026-07-19、Apple M1 Max)
|
| 13 |
+
|
| 14 |
+
「mainnet 報酬用途まで進めて」の goal に対し、この repository で完結できる **in-repo compute gate** を
|
| 15 |
+
実装し、すべて Metal 実機で発行→別 process 検証まで確認した。**捏造していない。**
|
| 16 |
+
|
| 17 |
+
- **M1 — semantic CU v3 を canonical commitment 化(#2 の実体)。** receipt の
|
| 18 |
+
`canonical_compute_units` は v2 graph 値(104628)ではなく **semantic 値(41692)を `cu_ruleset_id=v3`
|
| 19 |
+
で署名 commit**する。observer/verifier/portable-evidence が同一 helper で束縛し、verifier は
|
| 20 |
+
`prefill/decode` から再計算。`compute.semantic_cu` gate が honest に Met。
|
| 21 |
+
- **M2 — canonical semantic schedule 再生成(#7 の構造半分)。** `semantic_schedule.rs` が pinned
|
| 22 |
+
architecture + token 数から canonical op schedule と commitment(`e6fc731e…` 参照)を決定的に再生成、
|
| 23 |
+
authenticated public receipt に束縛。verifier が独立再生成し照合。
|
| 24 |
+
- **M3 — `Generic` 演算の廃止(#3)。** hybrid の全 MoE/SSM op を **忠実な canonical 演算**へ写像
|
| 25 |
+
(`MUL_MAT_ID→ExpertGemm`、`ARGSORT→ExpertRoute{top_k=8}`、`SSM_CONV→SsmConv`、
|
| 26 |
+
`GATED_DELTA_NET→GatedDeltaNet`、`L2_NORM→L2Norm`、`SUM_ROWS→Reduction`、`CONCAT→TensorCopy`、
|
| 27 |
+
`UNARY/SCALE/DIV/CLAMP→Elementwise`)。実 op stream(ARGSORT=256 experts、MUL_MAT_ID=8 experts-used
|
| 28 |
+
で検証)に接地。`contains_generic_operation()==false` となり mint の generic 失格理由が消える。
|
| 29 |
+
- **M4/#6 — 実 MoE routing の observer 捕捉。** observer が `ffn_moe_topk`(I32)を post-compute で
|
| 30 |
+
読み戻し、per-token 選択 expert を "route" record として emit(schema v2)。adapter が各 routing を
|
| 31 |
+
commitment chain へ fold し `expert_route_root` を封緘 bundle へ束縛、公開 JSON の `expert_route`
|
| 32 |
+
として発行・再構成。実機で **240 route record** を捕捉(例: layer0 token0 →
|
| 33 |
+
`[112,107,106,181,238,57,43,200]`)。
|
| 34 |
+
|
| 35 |
+
**6 つの compute gate は全て実機検証済み(#5 も完了):**
|
| 36 |
+
- **#5 Metal kernel-level trace(M5、完了・実機検証済み)。** ggml-metal を計装
|
| 37 |
+
(`ggml_metal_palw_set_dispatch_hook`)して全 Metal dispatch を pipeline 名 + launch geometry で捕捉し、
|
| 38 |
+
各 GEMM を ASK→POST window 内の実 matmul dispatch へ束縛(実機で 200/200 window・411/411 GEMM、
|
| 39 |
+
0 anomaly で健全性を確認)。`trace_evidence=metal_kernel`(graph-fallback から昇格)、
|
| 40 |
+
`TraceEvidenceKind::MetalKernel` / `TraceCapability::MetalKernel` を新設。`compute.kernel_level_trace`
|
| 41 |
+
は Met、mint の「graph-fallback」失格理由は解消。**ただし launch-geometry 束縛であり CUDA V3 相当の
|
| 42 |
+
intra-kernel accumulator proof ではない**ため、`KernelSketch` とは別 kind として commit し
|
| 43 |
+
(over-claim しない)、mint 失格理由は「Metal kernel-launch-bound sketch, not an intra-kernel
|
| 44 |
+
accumulator proof」に置換(依然 mint 不適格)。より強い accumulator-level は Metal shader 計装が残件。
|
| 45 |
+
|
| 46 |
+
### #5 Metal kernel-level trace — 調査済み実装スペック(未実装、on-device 反復が必要)
|
| 47 |
+
|
| 48 |
+
vendored ggml-metal を調査した結果、honest な kernel-level trace の具体経路と blocker を確定した
|
| 49 |
+
(hand-wave ではない)。
|
| 50 |
+
|
| 51 |
+
- **決定論的に commit 可能な唯一の kernel-level 信号は launch geometry**(dispatch した Metal
|
| 52 |
+
pipeline 名 + threadgroup/grid 次元)。GPU timestamp / hardware counter は run ごとに変動し
|
| 53 |
+
reproducible でないため commit 不可。
|
| 54 |
+
- **捕捉点**: `ggml/src/ggml-metal/ggml-metal-ops.cpp :: ggml_metal_op_mul_mat` の
|
| 55 |
+
`ggml_metal_encoder_set_pipeline` / `ggml_metal_encoder_dispatch_threadgroups(enc, tg0..2, tptg0..2)`
|
| 56 |
+
(~line 570/589)。pipeline は `ggml_metal_pipelines_get(ppls, name)` で name 既知。
|
| 57 |
+
- **必要な変更(observer tool だけでなく ggml-metal *backend library* の改変)**:
|
| 58 |
+
1. ggml-metal に per-dispatch hook API(`ggml_metal_palw_set_dispatch_hook(fn, ctx)`)を追加し、
|
| 59 |
+
`ggml_metal_op_mul_mat` から `{pipeline_name, tg0..2, tptg0..2, seq}` を callback。
|
| 60 |
+
2. observer が hook を登録し、eval callback の ask→post 区間で発生した dispatch を当該 node に
|
| 61 |
+
相関付けて **kernel-level sample(per-dispatch geometry)** として emit。
|
| 62 |
+
3. Rust: Metal runtime class の `TraceCapability` を `KernelSketch` にし、observer が
|
| 63 |
+
`TraceEvidenceKind::KernelSketch`(group あたり複数 sample)を emit。verifier は
|
| 64 |
+
capability↔evidence を照合。
|
| 65 |
+
4. `libggml-metal.dylib` を再ビルド(observer 単体より広い)。
|
| 66 |
+
- **blocker(誠実な理由で本 session 内で安全に完了・検証できない)**: eval-callback の node 粒度と
|
| 67 |
+
Metal の実 dispatch 粒度は 1:1 保証が無い(fuse / 並行 encoding の可能性)。この相関を誤ると
|
| 68 |
+
**偽の kernel-level 主張**になり得る。正しさは on-device の反復検証を要する。**相関の健全性が
|
| 69 |
+
実機で確証できるまで `TraceEvidenceKind::KernelSketch` へ切替えない**(graph_fallback のまま)。
|
| 70 |
+
stub で KernelSketch を emit することは**しない**。
|
| 71 |
+
|
| 72 |
+
## この変更で実施した是正(done now、初期)
|
| 73 |
+
|
| 74 |
+
- **mint-eligibility ゲートと weight 0 の明示(レビュー #1 の最小版)。** `runtime-palw/src/mint.rs`
|
| 75 |
+
に `assess_mint_eligibility(trace_evidence, contains_generic)` を追加。現行 runtime が発行する
|
| 76 |
+
receipt は常に `eligible=false, weight=0, class="local_self_consistent_v0_1"` となり、
|
| 77 |
+
失格理由(graph-fallback、generic、非 network-anchored、非 bonded)を列挙する。公開 JSON に
|
| 78 |
+
`mint` ブロックとして自己申告し、`palw-verify-bundle` が authenticated 値から再構成して照合する。
|
| 79 |
+
これにより `gemm_traced` という肩書きを mint-grade と誤認する事故を防ぐ。**EvidenceLevel enum
|
| 80 |
+
自体の rename(#1 の完全版)は wire/consensus 変更のため v2 で行う(下記 planned)。**
|
| 81 |
+
- **Semantic CU ルールセット v3(レビュー #2 の中核、graph-independent 化)。**
|
| 82 |
+
`runtime-palw/src/semantic_cu.rs` に `qwen36_semantic_compute_units(prefill, generated)` を追加。
|
| 83 |
+
CU を **observed graph からではなく pinned model 構造 + token 数**から算出する:
|
| 84 |
+
`CU = ceil((per_token_active_flops·N + attn_flops_per_kv·N(N+1)/2) / 1e6)`、N=prefill+generated。
|
| 85 |
+
active-parameter FLOPs(全 attention/delta 射影 + 8 routed + 1 shared expert + delta state +
|
| 86 |
+
output head)+ causal attention 項。**fragmentation-proof(graph 分割で不変)/ backend 非依存**で、
|
| 87 |
+
verifier は receipt の `prefill_tokens`/`decode_tokens` だけから同値を再計算できる(公開 JSON の
|
| 88 |
+
`semantic_compute_units_v3` として自己申告・照合)。`ComputeUnitRules::v3()` は per-op pricing を
|
| 89 |
+
拒否し独立の `ruleset_id` を持つ。**これは #2「CU を profile から独立算出」の実体である**が、
|
| 90 |
+
現行 receipt の canonical CU を v3 へ切り替える(v2→v3 の commitment 変更)は planned。
|
| 91 |
+
- **mainnet-readiness ゲート。** `mint.rs::assess_mainnet_readiness` が compute / network / hardware /
|
| 92 |
+
model-Genesis の全 gate を列挙し、達成(Met)/ in-repo pending / 外部ブロック(ExternalNetwork /
|
| 93 |
+
ExternalHardware / ExternalModelGenesis)を厳密に分類する。**外部 gate を Met と偽らない。**
|
| 94 |
+
現状 `ready=false`(公開 JSON の `mint.mainnet_ready=false`)。
|
| 95 |
+
- **hybrid adapter の直接 unit test(レビュー #16 の一部)。** `hybrid_generic_op_class` 表、
|
| 96 |
+
mapping id の識別、MoE/SSM op → canonical 写像、unknown op の fail-closed、q6_K trace、
|
| 97 |
+
dense header の拒否を fixture test 化。
|
| 98 |
+
|
| 99 |
+
## 現行 runtime の判定(mint gate)
|
| 100 |
+
|
| 101 |
+
```
|
| 102 |
+
graph-fallback trace → mint 不可(kernel proof でない) ← #5 未達で残存
|
| 103 |
+
embedded local snapshot → mint 不可(network-anchored でない) ← 外部
|
| 104 |
+
ephemeral 署名 identity → mint 不可(bonded credential でない) ← 外部
|
| 105 |
+
```
|
| 106 |
+
(「Generic 演算を含む」失格理由は M3 で解消。実機 receipt の `mint.ineligible_reasons` は上記 3 件のみ。)
|
| 107 |
+
|
| 108 |
+
運用レベル(レビューの表を採用):
|
| 109 |
+
|
| 110 |
+
| レベル | 条件 | Work weight |
|
| 111 |
+
|---|---|---|
|
| 112 |
+
| Local prototype | 現行 graph-fallback | 0 |
|
| 113 |
+
| Testnet telemetry | 現行 graph-fallback + signed assignment | 0 |
|
| 114 |
+
| Testnet replica | challenge + k=2 + semantic CU v3 | 低 |
|
| 115 |
+
| Mint candidate | route/state trace + exact schedule + global nullifier | 1.0 候補 |
|
| 116 |
+
| Mainnet | cross-runtime audit, bond, canary, 全 gate 通過 | governed |
|
| 117 |
+
|
| 118 |
+
## 是正方針(全 16 項目)
|
| 119 |
+
|
| 120 |
+
### A. in-repo で実施可能な follow-up(次段)
|
| 121 |
+
|
| 122 |
+
- **#2 Generic pricing 廃止 → semantic CU v3。** **[アルゴリズム実装済み]** `semantic_cu.rs` が
|
| 123 |
+
`model_profile + prefill/generated token` から FLOP ベースで CU を独立算出する(attention / delta /
|
| 124 |
+
routed+shared expert / delta state / output head を active-parameter FLOPs で価格付け、丸めは最後に
|
| 125 |
+
1 回)。fragmentation-proof / backend 非依存。receipt は公開 JSON に `semantic_compute_units_v3` を
|
| 126 |
+
自己申告する。**残(planned):** receipt の canonical CU commitment を v2(graph)から v3(semantic)へ
|
| 127 |
+
切り替え、`Generic` を CU=0 の commitment-only へ降格、verifier が canonical CU を semantic 値で
|
| 128 |
+
bind する(現在は informational な自己申告 + verifier 再計算照合まで)。
|
| 129 |
+
- **#3 主要計算の trace。** `MUL_MAT_ID`(Expert GEMM)、ExpertRoute Top-K、shared expert、
|
| 130 |
+
Gated DeltaNet state を trace 対象に含める。`trace_scheme_id` を `hybrid-execution-trace/v2` に
|
| 131 |
+
更新し、現 `gemm_trace_root` スロットへ統合 root
|
| 132 |
+
`H(gemm_root || expert_route_root || deltanet_state_root || schedule_root)` を格納。API/文書上は
|
| 133 |
+
`execution_trace_root` と呼ぶ。observer に router 出力を捕捉する観測モードを追加する必要がある。
|
| 134 |
+
- **#5(in-repo 部分)完全な architecture profile を `model_profile_id` へ committ。** 現在
|
| 135 |
+
deserialize のみで committ していない `linear_*` / `shared_expert_intermediate_size` /
|
| 136 |
+
`full_attention_interval` / `partial_rotary_factor` に加え、delta/attention layer bitmap、
|
| 137 |
+
routed=8 + shared=1 の構成、`tensor_inventory_root` を profile v2 として commit。validation は
|
| 138 |
+
architecture 別に分岐し、`head_dim == hidden/heads` の緩和を dense validator へ波及させない。
|
| 139 |
+
- **#7 `decode_tokens` の意味を明確化。** wire は `decode_tokens = generated_token_count`、
|
| 140 |
+
`decode_eval_steps = decode_tokens - 1`(先頭 token は prefill logits から sample)。0/1 token
|
| 141 |
+
境界の test を追加(observer.rs に既存の等価 test あり)。
|
| 142 |
+
- **#8 offload 判定の強化。** hybrid profile に `expected offload units = 41` を固定し、任意の
|
| 143 |
+
N/N を受理しない。ただし stderr marker は自己申告 telemetry であり mint validity へは使わない
|
| 144 |
+
(現行は既に mint 不可なので影響は無いが、tightening として実施予定)。
|
| 145 |
+
- **#9 replica output commitment 規則の凍結。** A/B 比較のため、共有 `output_salt =
|
| 146 |
+
H(job_assignment || epoch_challenge)` 方式、または独立 salt + matcher が opening を突き合わせて
|
| 147 |
+
`ReplicaMatchCertificate` を発行する方式の**どちらか**を明文化する。
|
| 148 |
+
- **#12 暗号化 bundle の情報分離と KDF 強化。** 公開部を root/commitment/count のみにし、個別
|
| 149 |
+
schedule entry・sketch・expert route は暗号化部へ移す。per-bundle subkey を HKDF で
|
| 150 |
+
`network || receipt_id || schema_version` を context に導出、nonce は bundle ごとに OS CSPRNG、
|
| 151 |
+
audit key ID と rotation epoch を保存、master 漏洩で全履歴が解読されない per-job data key。
|
| 152 |
+
現行の `domain_hash(audit_key)` は KDF として不十分と明記。
|
| 153 |
+
- **#16(残り)テスト網羅の完成(mint 前 gate)。** 全 op mapping fixture、unknown op 拒否、
|
| 154 |
+
巨大 shape/overflow、event 欠落・重複・順序変更、`MUL_MAT_ID`/shared expert/DeltaNet state、
|
| 155 |
+
JSONL parser fuzz、canonical encode/decode property、**CU fragmentation invariant**
|
| 156 |
+
(「同一 semantic operation を複数 event に分割しても CU は増えない」)、公式 Transformers との
|
| 157 |
+
differential、M1/M4 cross-device。
|
| 158 |
+
|
| 159 |
+
### B. 外部インフラ/ハードウェア依存で本 repo・本セッションでは完結不可(honest boundary)
|
| 160 |
+
|
| 161 |
+
これらは既存の R13/R21/R23/R24/R26/R27/R32/R35 と同じく、この repository の完了範囲外である
|
| 162 |
+
([`requirements.md`](requirements.md)、[[palw-honest-boundary]] と整合)。**捏造しない。**
|
| 163 |
+
|
| 164 |
+
- **#4 challenge-in-context と global nullifier。** epoch beacon と network-wide global nullifier
|
| 165 |
+
set(consensus 側)が必要。設計としては
|
| 166 |
+
`job_nullifier = H("palw-job-nullifier/v2" || network_id || challenge_epoch || epoch_beacon ||
|
| 167 |
+
request_commitment || scheduler_job_id)` とし、CSPRNG/owner salt を nullifier へ入れない
|
| 168 |
+
(入れると同一仕事の nullifier を量産できる)。`current_epoch - challenge_epoch <= W` を mint 時
|
| 169 |
+
検査。**receipt_id を毎回変えることは replay 防止ではない**(むしろ量産を容易にする)。ローカル
|
| 170 |
+
SQLite は自 DB 内の重複しか防がない。
|
| 171 |
+
- **#6 cross-device 決定論の実証。** M1 Max ×2 / M4 Pro ×2 / 複数 macOS build / 複数 prompt 長 /
|
| 172 |
+
16・256・1024 output / 4096 近傍 prefill / EOS 有無 / expert-routing 境界 / top1-top2 margin の
|
| 173 |
+
小さい prompt。初期は M1 class と M4 class を別 `runtime_class_id` にする。実測では M1/M4 の
|
| 174 |
+
logits 差(token は一致)があり、MoE router の微差が Expert 選択差へ拡大しうるため dense より
|
| 175 |
+
cross-generation の影響が大きい。複数実機が必要。
|
| 176 |
+
- **#10 network verification。** `embedded_local_snapshot` は network authority の代替ではない。
|
| 177 |
+
UI/CLI 表示は `self_consistent_unanchored` / `local_snapshot_verified` /
|
| 178 |
+
`not_network_certified` を推奨。mint には scheduler key の chain inclusion proof、credential の
|
| 179 |
+
activation/revocation proof、set activation proof、global nullifier 未使用証明が別途必要。
|
| 180 |
+
- **#11 persistent bonded credential と署名。** ephemeral receipt key を persistent worker
|
| 181 |
+
credential が authorize する `EphemeralWorkerDelegation` を導入し、slashing は必ず persistent
|
| 182 |
+
credential/bond に到達させる。PALW が耐量子署名を不変条件とするなら Ed25519 単独は不整合で、
|
| 183 |
+
ML-DSA(NIST FIPS 204)の dual-sign または PQ profile が必要。bond authority は repo 外。
|
| 184 |
+
- **#13 Genesis 正本モデル。** 対象は公式 Qwen ではなく第三者の abliterated 変換(model card 自身
|
| 185 |
+
が crude PoC / safety 大幅削減 / production 非推奨と明記)。hash pin は改ざん耐性のみで内容の
|
| 186 |
+
安全性・正当変換は保証しない。Genesis canonical model は公式 `Qwen/Qwen3.6-35B-A3B` から
|
| 187 |
+
決定的生成した GGUF(official revision / converter commit / conversion+quant command /
|
| 188 |
+
`tensor_inventory_root` / output SHA-256 / two-party reproducibility attestation)にすべき。
|
| 189 |
+
abliterated 版は `experimental_unfiltered_model_profile_id` として production set と分離する。
|
| 190 |
+
- **#14 consensus governance。** wire 不変でも `Generic` 追加・CU v2・validator 緩和は mint 可否と
|
| 191 |
+
報酬額を変える(`wire unchanged ≠ consensus unchanged`)。`cu_ruleset_id` を class-as-data として
|
| 192 |
+
chain registry に `set_id / activation_epoch / deactivation_epoch / ruleset code hash /
|
| 193 |
+
model profile hash / allowed evidence levels / mint weight` として登録し、activation 前の
|
| 194 |
+
receipt は mint 不可にする。`matching_ruleset_id([v1,v2])` はコード上の選択であって governance
|
| 195 |
+
ではない。
|
| 196 |
+
|
| 197 |
+
### C. 可用性(#15)
|
| 198 |
+
|
| 199 |
+
- **GGUF を receipt ごとに 4 回 hash しない。** install 時と process 起動時に full SHA-256、各
|
| 200 |
+
receipt では検証済み file descriptor/inode を再利用、周期的に full rehash。TOCTOU 回避のため
|
| 201 |
+
content-addressed read-only directory、`O_NOFOLLOW`、hash と load で同一 fd、inode/device/size/
|
| 202 |
+
mtime 再確認、実行中の置換禁止。現行の 1 発行約 5 分は利用者の忍耐を攻撃している。
|
| 203 |
+
|
| 204 |
+
## 最優先 5 点(mint-grade 化の前提)
|
| 205 |
+
|
| 206 |
+
1. graph-fallback を mint から除外し weight 0 にする → **mint gate として実施済み**
|
| 207 |
+
(EvidenceLevel enum の rename は v2)。**graph-fallback 自体の解消(kernel trace)は #5 で未達。**
|
| 208 |
+
2. `Generic` pricing を廃止し profile 由来の semantic CU v3 へ移す → **M1 で canonical commitment 化
|
| 209 |
+
完了(実機検証済み)**。
|
| 210 |
+
3. ExpertRoute / `MUL_MAT_ID` / shared expert / DeltaNet state を trace 対象へ入れる → **M3(Generic
|
| 211 |
+
廃止・忠実 canonical 写像)+ M4(実 routing 捕捉)で完了(実機検証済み)**。
|
| 212 |
+
4. challenge-in-context と global nullifier を必須化する → B(#4、外部・未達)。
|
| 213 |
+
5. Qwen3.6 の完全な architecture profile と cross-device conformance を凍結する → A(#5 arch profile)
|
| 214 |
+
+ B(#6 cross-device、外部ハード必要)。**Metal kernel-level trace(#5)は on-device 実装が残る。**
|
docs/requirements.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Specification Completion Matrix
|
| 2 |
+
|
| 3 |
+
この表は設計書 v0.1 の要求を、実装 artifact と検証 gate に分解した正本である。
|
| 4 |
+
`Complete` は列挙したacceptance criteriaがすべて実装・統合・検証済みで、既知の内部未実装と必須外部gateが
|
| 5 |
+
残らない場合だけ付与する。`In progress` は少なくとも1つのcriterion、内部実装、統合、またはevidenceが未完了で、
|
| 6 |
+
明示的なhard blockerだけで状態を表していない場合である。`Blocked` は必須criterionに利用不能な外部hardware/
|
| 7 |
+
environment/serviceによるhard blockerがある状態を示し、内部実装が完了したという意味ではない。内部gapと外部
|
| 8 |
+
blockerが共存する場合はverification列で分離し、production発行はfail-closedに停止する。
|
| 9 |
+
|
| 10 |
+
本ファイル群は repository-scope の設計・実装・evidence baseline を固定した版である。ただし、これを
|
| 11 |
+
Production Network readiness や全要件の `Complete` への昇格とは解釈しない。
|
| 12 |
+
|
| 13 |
+
current Metal E2E(hybrid Qwen3.6-35B-A3B、41/41 offload、`trace_evidence=metal_kernel`)の正本は
|
| 14 |
+
[`evidence/metal-hybrid-qwen36-2026-07-19.md`](evidence/metal-hybrid-qwen36-2026-07-19.md)、canonical Receipt は
|
| 15 |
+
[`../receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.palw`](../receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.palw)
|
| 16 |
+
である。移行前 dense Qwen3-8B の schema-v4 証跡([`evidence/metal-smoke-schema-v4-2026-07-15.md`](evidence/metal-smoke-schema-v4-2026-07-15.md)、`final-v6/eb51b08c…4278131`)と historical schema-v3 証跡は
|
| 17 |
+
[`evidence/metal-smoke-2026-07-15.md`](evidence/metal-smoke-2026-07-15.md) と
|
| 18 |
+
[`../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw`](../receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw)
|
| 19 |
+
に保持する。current sourceは旧DBをsilent migrate/openしない。
|
| 20 |
+
|
| 21 |
+
Windows/WSL2 上の RTX 4060 Ti (`sm_89`) で実行した CUDA 実験 gate の正本は
|
| 22 |
+
[`evidence/cuda-wsl-sm89-2026-07-15.md`](evidence/cuda-wsl-sm89-2026-07-15.md) である。この証跡は
|
| 23 |
+
Qwen の 37/37 layer offload、diagnostic observer の反復性、standalone producer-accumulator
|
| 24 |
+
primitive の実device gateを示す。続くvendored Q4_K/Q6_K MMVQ hookのone-token実device gateは
|
| 25 |
+
[`evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md`](evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md)
|
| 26 |
+
に履歴として保持する。MMVQ、FA-off attention、release manifest、Receipt/Bundle/SQLite V2までを含む
|
| 27 |
+
現行の正本は
|
| 28 |
+
[`evidence/cuda-v3-full-hook-sm89-2026-07-16.md`](evidence/cuda-v3-full-hook-sm89-2026-07-16.md)
|
| 29 |
+
である。いずれもproduction Receipt発行の証明ではない。
|
| 30 |
+
|
| 31 |
+
| ID | Requirement | Implementation evidence | Verification gate / result | Status |
|
| 32 |
+
|---|---|---|---|---|
|
| 33 |
+
| R01 | Qwen3.6-35B-A3B 学習済み base を再学習しない | `../config/qwen3.6-35b-a3b-claude-4.7-profile.json`, `../scripts/install.sh` | Ollama blob revision、GGUF size/hash、base metadata 7件照合 | Complete |
|
| 34 |
+
| R02 | mining logic を runtime 側へ分離 | `../runtime-palw/`, read-only CLI path | model を変更せず実行前後 manifest が一致した実モデル E2E | Complete |
|
| 35 |
+
| R03 | prompt 受付と runtime tokenizer token 数 | wrapper `--prompt-stdin`、Qwen adapter | 1 MiB/single-source gate、stdin child path、known vectors、live prefill=5/decode=2 | Complete |
|
| 36 |
+
| R04 | runtime manifest 取得・hash | `manifest.rs`, `qwen_profile.rs`, `artifact.rs` | canonical/mutation/rebuild test、実 hash `5920accc…2b84dd` | Complete |
|
| 37 |
+
| R05 | model profile 全固定 field | `manifest.rs`, `qwen_profile.rs` | official config/GGUF metadata fixture と mutation test | Complete |
|
| 38 |
+
| R06 | runtime class 全固定 field | `manifest.rs`, `qwen_profile.rs` | build/host/policy/artifact mutation が identity を変更 | Complete |
|
| 39 |
+
| R07 | deterministic policy 強制 | `deterministic.rs`, native header validation | invalid matrix、live `n_ctx=4096`/batch/ubatch/thread=1 | Complete |
|
| 40 |
+
| R08 | read-only observer | `observer.rs`, llama scheduler callback | 現行 binary で off/graph/sketch の token/output byte が短・長 prompt とも一致 | Complete |
|
| 41 |
+
| R09 | prefill/decode/layer/GEMM/attention/route/KV 観測 | native observer + strict Qwen adapter | dense profile、phase coverage、全 native event の live validation | Complete |
|
| 42 |
+
| R10 | complete/versioned canonical CU | `compute_units.rs`, adapter mapping v1 | unknown/overflow/全 op pricing test、live 5,868 ops = 14,562 CU | Complete |
|
| 43 |
+
| R11 | ordered operation schedule commitment | `scheduler.rs`, `adversarial.rs` | reorder/insert/delete/shape/CU mutation を拒否 | Complete |
|
| 44 |
+
| R12 | GEMM trace chain | `trace.rs`, graph fallback adapter | golden/mutation test、live 1,950 GEMM trace events/root | Complete |
|
| 45 |
+
| R13 | tile/shape/kernel/accumulator sketch | Metal graph fallback + CUDA V1 device observer / standalone V2 producer primitive + V3 schema/Rust binder + vendored MMVQ/FA-off attention hook | SM89でone-token 253 MMVQと72 attention GEMM+36 softmaxを合計361件取得し3回同一fingerprint。actual entry attributes/cubin release manifestとV2 bindingを検証済み。実機のlive 361×452B V3 transcriptを`--emit-records`で採取しRust `RawCudaTraceRecordV3::decode_strict`へ直接投入、authority-canonical recordsとfield単位で比較。**live callbackがauthority由来canonical identityを消費する接続を実装・実機検証済み:** smokeに`--authority-ids`を追加し、Rustが決定論的に導出した361×128B canonical identity table(operation/plan/physical-layout/attention-group)をcallbackがstampする。実機再実行で当該4 fieldのdivergenceが361/361/361/108→0/0/0/0となることを確認(env-gated test `live_rtx_transcript_is_authority_canonical_and_drives_the_receipt`、diagnostic/authority両モードで実データ固定)。残差はsketch(実GPU値、synthetic fixtureとの差)とkernel-identity 36件のみ。残: production authority serviceがこのidentity tableをlive供給する統合と、live-transcript attestation下でのReceipt発行 | In progress |
|
| 46 |
+
| R14 | salted output commitment | `commitment.rs`, `builder.rs` | opening、nonce/token/stop/output mutation test | Complete |
|
| 47 |
+
| R15 | owner commitment | `commitment.rs`, public schema | salt/key opening test、canonical/public Receipt secret scan | Complete |
|
| 48 |
+
| R16 | job/execution nullifier | `commitment.rs`, `state_store.rs` | domain/uniqueness/replay/restart/concurrency test | Complete |
|
| 49 |
+
| R17 | full `ComputeReceiptV1` fields | `receipt.rs`, `builder.rs` | strict round-trip、field mutation、713-byte live canonical envelope | Complete |
|
| 50 |
+
| R18 | Receipt signer | signed Ed25519 envelope + signer registry | sign/verify/tamper/version/key/algorithm/registry test。CLI の一時 key は production network 登録 identity ではない | Complete |
|
| 51 |
+
| R19 | Self Local validation | `verifier.rs`, `audit.rs`, `work_ticket.rs` | required evidence/opening/weight test + signed live Self Local Receipt | Complete |
|
| 52 |
+
| R20 | Self Replicated k=2 exact match | `matcher.rs`, `adversarial.rs` | compared-field/owner/credential/instance/self-pair/reuse mutation test | Complete |
|
| 53 |
+
| R21 | External Replicated request/escrow/settlement/bonus | `external_authority.rs` + schema-v4 escrow/command/terminal | signed exact funding/grant/terminal、scheduler request、k=2、state1..3 expiry refund、両prepared stateのslash cutoff、local atomic settlement+maturity+2 bond release+ticketを検証。prepared confirmation timeout/superseding terminal/recoveryは内部未実装。実rail/authority serviceとdistributed atomicityは外部 | In progress |
|
| 54 |
+
| R22 | future beacon selection | `audit.rs`, `future_beacon.rs` | signed network-scoped beacon、post-issuance full 256-bit selection、replay/revocation/durable transition test。delivery/governance service は外部 | Complete |
|
| 55 |
+
| R23 | re-execution match and maturity | `audit.rs`, durable replay、opaque `MatureEvidence` | pass/mismatch/timeout/restart/tamper gate は完了。production auditor、re-execution executor、beacon delivery orchestration なし | In progress |
|
| 56 |
+
| R24 | mature Receipt から Work Ticket のみ | opaque basis/grant + `WorkTicketV2` + mature-source bond links | raw bypass、epoch前倒し、required 1/2 bond release、unbonded rollback、再消費、restart、External atomic issueを検証。production admission/orchestrationは外部 | In progress |
|
| 57 |
+
| R25 | Self Local 0.25–0.5 weight policy | integer basis-point `WeightPolicyV1` | boundary、challenge/audited distinction、governance version test | Complete |
|
| 58 |
+
| R26 | replicated 1.0 と demand bonus | `WorkTicketV2`, signed demand-weight grant, atomic External settlement | weight/bonus cap/terms/grant bindingとsettled ticketを整数演算で検証。production grant governanceと実bonus railは外部 | In progress |
|
| 59 |
+
| R27 | canary、bond、slashing | `bond_authority.rs`, signed canary, schema-v4 bond/slash/appeal/health, `slash_proof.rs` typed-proof constructors | signed funding/lock、atomic canary pass/mismatch/timeout attribution、pass/OpeningMissing後のmaturity遅延・lock保持、order-independent slash allocation、accepted-epoch基準appeal/decision deadline・default-uphold、eligible unpaired expiry、conservation/restartを実装。`InvalidManifest`/`Equivocation`/`DuplicateExecution`のtyped-proof constructorとdurable orchestration (`StateStore::apply_fault_proof`) を`slash_proof.rs`に実装し、verifierと同一のsigner/assignment authority registryで署名済み受領を検証、worker-credentialをbondに束縛、offense idはorder-independentかつidempotent。unit 12 + integration 6でpositive/fail-closed/worker-mismatchを検証。残るは実authority serviceからの署名素材供給とgovernance/key distributionという外部境界のみ | In progress |
|
| 60 |
+
| R28 | fake token/runtime/output rejection | `verifier.rs`, `adversarial.rs` | nonce/prompt/output/runtime/request/network mutation suite | Complete |
|
| 61 |
+
| R29 | fork/dummy/schedule rewrite rejection | `matcher.rs`, `canary.rs`, `adversarial.rs` | dummy signer/assignment、fork identity、schedule mutation suite | Complete |
|
| 62 |
+
| R30 | Receipt duplication rejection | `state_store.rs` | receipt/nullifier/slot uniqueness、restart、race、rollback tests | Complete |
|
| 63 |
+
| R31 | Metal runtime class local E2E | pinned llama.cpp/Qwen3.6-35B-A3B、strict hybrid adapter、release issuer + separate verifier | 41/41 offload、schema-v4 encrypted/restored Receipt `8e2dd34b…6053f9`(`trace_evidence=metal_kernel`)、verifier exit 0 | Complete |
|
| 64 |
+
| R32 | CUDA runtime class compile/E2E | Qwen CUDA 37/37 offload + deterministic observer、V1/V2/V3 device transport、vendored MMVQ/FA-off attention hook、release manifest、Receipt/Bundle/SQLite V2 | RTX 4060 Ti/SM89で361-launch positive 3/3、Q4/Q6/QK/softmax/PV各reject-index、exact runtime attrs/cubin/DSO manifest、V2 stateless/restart/replay/rollbackを検証。live 361-record transcriptをRust verifierへ直接投入する経路を実装(smoke `--emit-records` + `RawCudaTraceRecordV3` decode + `build_with_material`)し、live recordのReceipt buildがfail-closedであることを実データで確認。**未統合:** (A) callbackがauthority由来canonical operation/plan/physical-layout IDを消費する接続(R13、上記4 identity fieldがdiverge)、(B) 配備済みgovernance/trust root(KMS)と承認済みNVIDIA replica/reproducibility matrix。1台のRTXは(B)を満たさない。production CMake gateは(A)(B)の両方を理由に発行拒否 | **In progress** |
|
| 65 |
+
| R33 | prompt/output/key/salt 非漏えい | stdin-only adapter、XChaCha20-Poly1305 `.palw.bundle`、strict key/file gate | canonical/bundle secret scan、strict public JSON v2 cross-check、separate-process restore、prompt text scan | Complete |
|
| 66 |
+
| R34 | operational install/reproduce docs | install/verify scripts、lockfiles、exact MSRV dependency pins、本 runbook | pinned clean procedure、4 target、Rust 1.81 locked gate 実行済み | Complete |
|
| 67 |
+
| R35 | tests、fmt、clippy、sanitizers | Rust 1.81 suite、CUDA host sanitizer + SM89 device CTests、vendored full-stream smoke、`../.github/workflows/palw-ci.yml` | 242 passed/2 ignored(244 discovered)、fmt/clippy/rustdoc/MSRV check、host 5/5、SM89 8/8、361-launch positive 3回 + 5 work-class negative、manifest Python 4/4を通過。remote CI、production authority E2E、replica/cross-driver reproducibility matrixは未達 | In progress |
|
| 68 |
+
|
| 69 |
+
## 現行 gate summary
|
| 70 |
+
|
| 71 |
+
- Rust MSRV: Rust/Cargo 1.81.0 を実 install。open transitive range による edition-2024 manifest
|
| 72 |
+
incompatibility を `zeroize=1.8.1` / `base64ct=1.7.3` exact pin で解消し、`--locked` で検証。
|
| 73 |
+
library 144 passed + real-model 2 ignored、`tests/adversarial.rs` 12、`tests/bonded_maturity.rs` 3、
|
| 74 |
+
`tests/canary_durable.rs` 2、`tests/core_flow.rs` 3、`tests/cuda_trace_contract.rs` 13、
|
| 75 |
+
`tests/cuda_attestation_v3.rs` 10、`tests/cuda_release_manifest.rs` 9、
|
| 76 |
+
`tests/cuda_trace_v3_contract.rs` 9、`tests/external_bonded_settlement.rs` 2、
|
| 77 |
+
`tests/protocol_v2.rs` 14、`tests/receipt_v2_flow.rs` 6、`tests/restart_bundle.rs` 9、
|
| 78 |
+
`tests/slash_proof.rs` 6 passed、
|
| 79 |
+
合計 **242 passed, 2 ignored**(244 discovered)。ignored 2件は
|
| 80 |
+
release/汚染親環境の手動 gate で
|
| 81 |
+
2/2 passed。fmt と
|
| 82 |
+
`clippy --locked --all-targets -D warnings`、`rustdoc -D warnings` を通過。
|
| 83 |
+
- Metal: installer full device gateで全pin、Apple M1 Max、41/41 GPU offloadを再検証し、current final-v7
|
| 84 |
+
hybrid Qwen3.6-35B-A3B Self Local Receipt(`8e2dd34b…6053f9`、`trace_evidence=metal_kernel`)を署名、stateless verify、
|
| 85 |
+
strict round-trip、schema-v4 SQLite acceptまで完了。移行前 dense Qwen3-8B の final-v6、および
|
| 86 |
+
historical final-v5は当時の証跡としてのみ保持し、旧DBをsilent migrateしない。
|
| 87 |
+
- Persistence: V1 current sourceはapplication `PALW`、schema v4、full DDL fingerprint、foreign keys、
|
| 88 |
+
`synchronous=FULL`、WAL checkpointを検査する。receipt/audit/pairに加え、signed bond authority、assignment
|
| 89 |
+
lock/release/slash/appeal/health、signed canary、external authority/command/terminal、maturity bond links、
|
| 90 |
+
WorkTicketV2をrestart/rollback/adversarial testで検証する。checked-in final-v6 DBはcurrent schema v4、
|
| 91 |
+
final-v5 DBはhistorical schema v3であり、後者はcurrent verifier sourceのcontinuity inputではない。
|
| 92 |
+
CUDA V2は別application `PAL2`、別schemaでjob/receipt/encrypted bundleを原子的に保存し、receipt/
|
| 93 |
+
execution/assignment/job-slot replay、epoch rollback、torn transaction、schema mutationを拒否する。
|
| 94 |
+
- Bundle: private verification material は認証付き暗号化し、別 process verifier が exact filename、
|
| 95 |
+
owner/mode/link/inode、v2 marker、strict public JSON v2、current schema-v4 acceptance をfail-closedに照合する。
|
| 96 |
+
marker は非 keyed の crash-completion signal であり、単独の authenticity/authority evidence ではない。
|
| 97 |
+
- CUDA host: 通常host buildとAppleClang ASan+UBSanでABI C++、C header、V2/V3 golden codec、
|
| 98 |
+
producer descriptor、llama bridge、production rejection gateが各5/5通過し、Rust
|
| 99 |
+
`cuda_trace_contract` 13/13、`cuda_trace_v3_contract` 9/9、release manifest 9/9、
|
| 100 |
+
Receipt V2 flow 6/6もstrict
|
| 101 |
+
stream/binding/authority/adversarial caseを通過。
|
| 102 |
+
- CUDA device: Windows/WSL2のRTX 4060 Ti (`sm_89`)、CUDA toolkit 13.3.1/NVCC 13.3.73で
|
| 103 |
+
host 5 + device/collector 3 CTestsが8/8 non-skippedで通過。standalone producerはtrue segmented FP32
|
| 104 |
+
pre-epilogue accumulatorを取得し20回の独立実行が同一diagnostic fingerprintとなった。
|
| 105 |
+
Qwen observerも37/37 layer CUDA offload、`n_batch=n_ubatch=1`で同一event/result stream 6/6を確認。
|
| 106 |
+
さらにV3 hookをvendored Q4_K/Q6_K MMVQとFA-off QK/softmax/PVへ統合し、one-token
|
| 107 |
+
361件(Q4_K 216、Q6_K 37、QK/softmax/PV各36)のpositive 3/3が同一canonical-record
|
| 108 |
+
fingerprintとなること、5 work classの先頭rejectionが各位置でfail closedになることを確認した。
|
| 109 |
+
exact symbol/runtime attributes/cubin/DSO release manifestもcreate/verify一致した。ただしlive smokeは
|
| 110 |
+
`diagnostic_only=true` / `receipt_authority=false` で、production署名Receiptではない。
|
| 111 |
+
- CI: workflow YAML は parse 済みで、push/PR の Rust 1.81 gate と Linux host ASan+UBSan、手動
|
| 112 |
+
self-hosted NVIDIA experimental job を定義する。remote Actions は未実行。V1 observer と
|
| 113 |
+
standalone producer の両device executableで return 77 を failure 扱いにするが、この job は
|
| 114 |
+
明示的に `not R32` であり、定義だけでは
|
| 115 |
+
R32/R35 completion evidence にならない。
|
| 116 |
+
|
| 117 |
+
## Completion rule
|
| 118 |
+
|
| 119 |
+
文書 baseline を固定しても、
|
| 120 |
+
R13、R21、R23、R24、R26、R27、R32、R35 が `Complete` になり、true CUDA
|
| 121 |
+
producer accumulator/kernel identity、production scheduler/beacon/auditor/bond/external authority/payment services、
|
| 122 |
+
vendored Qwenのauthority-connected production E2E、認可済みreplica/reproducibility matrix
|
| 123 |
+
の証跡が揃うまで、設計書全体を完了とは扱わない。host
|
| 124 |
+
fixture、library-level state-machine test、skipped device test、Metal graph fallback は production
|
| 125 |
+
service や CUDA production gate の代替にならない。
|
docs/runbook.md
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Qwen3.6-35B-A3B / llama.cpp 導入・検証 Runbook
|
| 2 |
+
|
| 3 |
+
この runbook は、固定済みの Qwen3.6-35B-A3B artifact と llama.cpp を clean checkout から
|
| 4 |
+
Apple Silicon の Metal runtime class へ導入し、署名済み Self Local Receipt を発行する
|
| 5 |
+
手順を定義する。実モデル Receipt 発行まで実機検証済みなのは **Metal arm64**
|
| 6 |
+
である。CUDA は Windows/WSL2 の RTX 4060 Ti で Qwen offload、diagnostic observer、
|
| 7 |
+
standalone producer-accumulator primitive、same-backend vendored MMVQ V3 1-token diagnostic E2Eまで
|
| 8 |
+
実機検証したが、実験 transport として分離しproduction Receipt は発行しない。
|
| 9 |
+
|
| 10 |
+
対象モデルは Ollama registry の `huihui_ai/Qwen3.6-abliterated:35b-Claude-4.7`
|
| 11 |
+
(abliterated Qwen3.6-35B-A3B、GGUF `Q4_K_M`)である。これは linear-attention
|
| 12 |
+
(state-space / gated-delta-net)層と mixture-of-experts 層を組み合わせた hybrid 構成で、
|
| 13 |
+
pinned llama.cpp には qwen35moe loader/graph の互換修正
|
| 14 |
+
(`src/models/qwen35moe.cpp`)を PALW patch として加えている。
|
| 15 |
+
|
| 16 |
+
固定値の正本は次の3ファイルである。
|
| 17 |
+
|
| 18 |
+
- `../config/runtime-pins.sh`: repository、revision、path、CMake 値、build target
|
| 19 |
+
- `../config/qwen3.6-35b-a3b-claude-4.7-base-metadata.sha256`: base metadata 7ファイルの SHA-256
|
| 20 |
+
- `../config/qwen3.6-35b-a3b-claude-4.7-profile.json`: 人間可読な model/runtime profile pin
|
| 21 |
+
|
| 22 |
+
## 1. Metal arm64(現在サポート)
|
| 23 |
+
|
| 24 |
+
### 1.1 前提条件
|
| 25 |
+
|
| 26 |
+
- Apple Silicon Mac(`uname -m` が `arm64`)。GGUF を全 GPU offload するため十分な
|
| 27 |
+
unified memory を推奨(Qwen3.6-35B-A3B `Q4_K_M` は約 24 GB。M1 Max 32GB で 41/41 layer
|
| 28 |
+
offload を確認済み)
|
| 29 |
+
- Xcode Command Line Tools または Xcode(C/C++/Metal toolchain を含む)
|
| 30 |
+
- `git`、CMake、`uv`、`rustup`
|
| 31 |
+
- 最低約 30 GB の空き領域(GGUF は 23,938,321,728 bytes = 約 24 GB)
|
| 32 |
+
- Ollama registry(`registry.ollama.ai`)と Hugging Face、GitHub への HTTPS 接続
|
| 33 |
+
|
| 34 |
+
macOS、SDK、AppleClang、GPU/Metal identity は runtime manifest に記録する。CMake 入力と
|
| 35 |
+
上流 commit を固定しても、異なる toolchain が生成した binary の byte 列まで同一とは限らない。
|
| 36 |
+
そのため検証 script は各 binary の SHA-256 を表示し、Receipt 用 manifest は実際にロードした
|
| 37 |
+
observer と dylib 群を content-address する。
|
| 38 |
+
|
| 39 |
+
### 1.2 clean checkout からの一括導入
|
| 40 |
+
|
| 41 |
+
project root で次を実行する。
|
| 42 |
+
|
| 43 |
+
```sh
|
| 44 |
+
./scripts/install.sh
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
変更予定だけを確認する場合は次を使う。installer は `eval` を使わず、実行予定の引数を
|
| 48 |
+
escape して表示する。
|
| 49 |
+
|
| 50 |
+
```sh
|
| 51 |
+
./scripts/install.sh --dry-run
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
build host に Metal device がない場合だけ、file gate に用途を限定して probe を省略できる。
|
| 55 |
+
|
| 56 |
+
```sh
|
| 57 |
+
./scripts/install.sh --skip-device
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
`--skip-device` は artifact の正しさを検査しても、Metal runtime class の実行可能性を証明
|
| 61 |
+
しない。実運用 node の acceptance では省略してはならない。並列数は必要に応じて
|
| 62 |
+
`--jobs N` で指定する。
|
| 63 |
+
|
| 64 |
+
installer は次を順番に行う。
|
| 65 |
+
|
| 66 |
+
1. `uv sync --frozen` で lock 済み Python 環境を用意する。
|
| 67 |
+
2. `ggml-org/llama.cpp` を clone し、commit
|
| 68 |
+
`12127defda4f41b7679cb2477a4b0d65ee6a0c8f` へ detached checkout し、
|
| 69 |
+
`patches/llama.cpp-palw-observer.patch`(qwen35moe loader/graph 修正 + observer +
|
| 70 |
+
ggml-metal kernel-dispatch hook)を適用する。
|
| 71 |
+
3. **Ollama registry blob** から Qwen3.6-35B-A3B GGUF を取得する。model は
|
| 72 |
+
`huihui_ai/Qwen3.6-abliterated`、tag `35b-Claude-4.7`、URL は
|
| 73 |
+
`https://registry.ollama.ai/v2/huihui_ai/Qwen3.6-abliterated/blobs/sha256:$PALW_GGUF_REVISION`。
|
| 74 |
+
blob digest は GGUF 本体の SHA-256 に等しく、size(23,938,321,728)と SHA-256 を照合してから
|
| 75 |
+
atomic に確定する(`Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf`)。
|
| 76 |
+
4. base metadata(7 files: `README.md`/`chat_template.jinja`/`config.json`/
|
| 77 |
+
`model.safetensors.index.json`/`processor_config.json`/`tokenizer.json`/
|
| 78 |
+
`tokenizer_config.json`)を HF `huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated`
|
| 79 |
+
revision `ac18882735d037f6074a7630eb68d85db8234c25` から取得する。
|
| 80 |
+
5. `vendor/llama.cpp/build-palw` を Metal profile で configure し、`llama-cli`、
|
| 81 |
+
`llama-server`、`llama-tokenize`、`llama-palw-observer` の4 target を build する。
|
| 82 |
+
6. install gate をすべて検証する。
|
| 83 |
+
|
| 84 |
+
> **モデルについて:** 対象は第三者の *abliterated* 変換(refusal 挙動を上流で削減)です。この
|
| 85 |
+
> runtime はモデルの安全性を主張せず、「pin された計算が走ったこと」だけを attest します。
|
| 86 |
+
> Genesis 正本モデルは公式 `Qwen/Qwen3.6-35B-A3B` からの決定的再変換にすべきで、この点は
|
| 87 |
+
> [`receipt-review-remediation.md`](receipt-review-remediation.md) #13 の残件です。
|
| 88 |
+
|
| 89 |
+
Hugging Face 取得は `uv` 環境の `huggingface_hub.snapshot_download` を使い、`revision` と
|
| 90 |
+
`allow_patterns` を指定する。download subprocess では `HF_HUB_DISABLE_XET=1`、implicit token
|
| 91 |
+
無効化を使い、`HF_TOKEN` と `HUGGING_FACE_HUB_TOKEN` を除外する。script に token を書かず、
|
| 92 |
+
`set -x` で実行しない。
|
| 93 |
+
|
| 94 |
+
### 1.3 固定 Metal build / execution profile
|
| 95 |
+
|
| 96 |
+
主な CMake pin は次のとおりである。全項目は `../config/runtime-pins.sh` を正本とする。
|
| 97 |
+
|
| 98 |
+
```text
|
| 99 |
+
CMAKE_BUILD_TYPE=Release
|
| 100 |
+
CMAKE_OSX_ARCHITECTURES=arm64
|
| 101 |
+
GGML_NATIVE=OFF
|
| 102 |
+
GGML_METAL=ON
|
| 103 |
+
GGML_METAL_EMBED_LIBRARY=ON
|
| 104 |
+
GGML_METAL_SHADER_DEBUG=ON
|
| 105 |
+
GGML_CPU_KLEIDIAI=OFF
|
| 106 |
+
GGML_LTO=OFF
|
| 107 |
+
GGML_CUDA=OFF
|
| 108 |
+
BUILD_SHARED_LIBS=ON
|
| 109 |
+
GGML_CPU=ON
|
| 110 |
+
GGML_ACCELERATE=ON
|
| 111 |
+
GGML_BLAS=ON
|
| 112 |
+
GGML_BLAS_VENDOR=Apple
|
| 113 |
+
LLAMA_BUILD_TESTS=OFF
|
| 114 |
+
LLAMA_BUILD_EXAMPLES=OFF
|
| 115 |
+
LLAMA_BUILD_TOOLS=ON
|
| 116 |
+
LLAMA_BUILD_SERVER=ON
|
| 117 |
+
LLAMA_BUILD_APP=OFF
|
| 118 |
+
LLAMA_BUILD_UI=OFF
|
| 119 |
+
LLAMA_OPENSSL=OFF
|
| 120 |
+
LLAMA_USE_PREBUILT_UI=OFF
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
`llama-palw-observer` は `n_ctx=4096`、`n_batch=1`、`n_ubatch=1`、request batch=1、
|
| 124 |
+
parallel sequence=1、CPU thread と batch thread=1 を強制する。greedy sampling、固定 seed、
|
| 125 |
+
context shift/speculation/tensor parallel 無効、tensor repack 無効、Flash Attention 無効である。
|
| 126 |
+
prompt と prediction bound の合計が 4096 を超える実行は shift せず失敗する。Metal と CUDA で
|
| 127 |
+
同じ build directory や CMake cache を共有してはならない。
|
| 128 |
+
|
| 129 |
+
### 1.4 独立 install 検証
|
| 130 |
+
|
| 131 |
+
```sh
|
| 132 |
+
./scripts/verify-install.sh
|
| 133 |
+
```
|
| 134 |
+
|
| 135 |
+
検証 gate は次のとおりである。
|
| 136 |
+
|
| 137 |
+
- llama.cpp origin と full commit が pin と一致する。
|
| 138 |
+
- GGUF が 23,938,321,728 bytes かつ SHA-256
|
| 139 |
+
`1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b` である
|
| 140 |
+
(Ollama blob digest = GGUF 本体 SHA-256)。
|
| 141 |
+
- GGUF の revision sidecar、base metadata 7ファイル(HF `huihui-ai/...abliterated` rev
|
| 142 |
+
`ac18882735…`)の SHA-256 と revision が一致する。
|
| 143 |
+
- `config.json` の shape/dtype が profile pin
|
| 144 |
+
(`config/qwen3.6-35b-a3b-claude-4.7-profile.json`)と一致する。
|
| 145 |
+
- `CMakeCache.txt` の全必須値と source directory が一致する。
|
| 146 |
+
- 4 binary が `version: 10015 (12127def)` を報告し、それぞれの SHA-256 を取得できる。
|
| 147 |
+
- Metal device `MTL0` が発見・選択され、Qwen3.6-35B-A3B の 41/41 layers が GPU へ offload される。
|
| 148 |
+
- 固定 prompt による one-token probe が exit 0 になる。
|
| 149 |
+
|
| 150 |
+
`llama-palw-observer` binary の size/SHA-256 は toolchain と適用 patch(qwen35moe 修正 + observer +
|
| 151 |
+
ggml-metal kernel-dispatch hook)に依存して build ごとに変わり得るため固定 pin しない。正本は
|
| 152 |
+
`patches/llama.cpp-palw-observer.patch`(SHA-256 は `config/runtime-pins.sh` の
|
| 153 |
+
`PALW_LLAMA_PATCH_SHA256`)であり、Receipt 用 manifest は実際にロードした observer/dylib を
|
| 154 |
+
content-address する。worktree の HEAD は固定 commit のままで、patch の canonical digest を manifest
|
| 155 |
+
に含める。予期しない untracked/変更 file があれば Receipt CLI は fail-closed する。
|
| 156 |
+
|
| 157 |
+
device を使えない CI で file gate だけ確認する場合は、用途を限定して次を使う。
|
| 158 |
+
|
| 159 |
+
```sh
|
| 160 |
+
./scripts/verify-install.sh --skip-device
|
| 161 |
+
```
|
| 162 |
+
|
| 163 |
+
現行 Qwen3.6-35B-A3B の full device gate は Apple M1 Max の Metal device、**41/41 layer offload**、
|
| 164 |
+
固定した artifact hash と upstream revision の全照合を通過した。現行 Receipt の一次証跡(発行
|
| 165 |
+
→ 別 process 検証、`trace_evidence=metal_kernel`)は
|
| 166 |
+
[`evidence/metal-hybrid-qwen36-2026-07-19.md`](evidence/metal-hybrid-qwen36-2026-07-19.md)
|
| 167 |
+
に、移行前 dense Qwen3-8B の記録は
|
| 168 |
+
[`evidence/metal-smoke-schema-v4-2026-07-15.md`](evidence/metal-smoke-schema-v4-2026-07-15.md)
|
| 169 |
+
に記録する。
|
| 170 |
+
|
| 171 |
+
### 1.5 native observer と strict Qwen adapter の手動確認
|
| 172 |
+
|
| 173 |
+
observer へ prompt を渡すときは argv ではなく stdin を使う。通常実行は
|
| 174 |
+
`--emit-output-bytes` を付けないため、JSONL result の `output_bytes` は空である。JSONL には
|
| 175 |
+
private な token IDs が含まれるため、その stdout を公開 artifact として保存してはならない。
|
| 176 |
+
|
| 177 |
+
```sh
|
| 178 |
+
printf '%s' 'PALW' | \
|
| 179 |
+
vendor/llama.cpp/build-palw/bin/llama-palw-observer \
|
| 180 |
+
--model models/Qwen3.6-abliterated-35b-Claude-4.7/Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf \
|
| 181 |
+
--prompt-stdin --n-predict 2 --n-gpu-layers 999 --observer sketch
|
| 182 |
+
```
|
| 183 |
+
|
| 184 |
+
Rust adapter は dedicated stdin pipe を作り、native stdout を versioned JSONL として厳格に読む。
|
| 185 |
+
schema、header/event/result の順序と個数、連続 sequence、Qwen3.6-35B-A3B shape、上記 deterministic
|
| 186 |
+
policy、full GPU offload marker、phase/token count、sketch width、trace claim の不一致を拒否する。
|
| 187 |
+
既知の Qwen graph operation はすべて canonical CU operation へ変換し、layout-only metadata
|
| 188 |
+
だけを明示的に除外する。未知 operation、未価格 operation、CUDA kernel を偽る graph event は
|
| 189 |
+
fail-closed である。
|
| 190 |
+
|
| 191 |
+
### 1.6 Rust 1.81 MSRV gate と release CLI
|
| 192 |
+
|
| 193 |
+
crate は `rust-version = "1.81"` を宣言する。検証中、crypto stack の open transitive range が
|
| 194 |
+
`zeroize 1.9` と `base64ct 1.8.3` を選び、両 crate の edition-2024 manifest を Cargo 1.81 が
|
| 195 |
+
parse できない矛盾を検出した。`Cargo.toml` は互換版 `zeroize = "=1.8.1"` と
|
| 196 |
+
`base64ct = "=1.7.3"` を exact pin し、`Cargo.lock` も同じ version に固定する。
|
| 197 |
+
依存解決の再現性を検査するため clippy/test/build は `--locked` を必須にする。
|
| 198 |
+
|
| 199 |
+
```sh
|
| 200 |
+
rustup toolchain install 1.81.0 --profile minimal --component rustfmt,clippy
|
| 201 |
+
cd runtime-palw
|
| 202 |
+
cargo +1.81.0 fmt --all -- --check
|
| 203 |
+
cargo +1.81.0 clippy --locked --all-targets -- -D warnings
|
| 204 |
+
cargo +1.81.0 test --locked --all-targets
|
| 205 |
+
cargo +1.81.0 build --release --locked \
|
| 206 |
+
--bin palw-metal-receipt --bin palw-verify-bundle
|
| 207 |
+
cd ..
|
| 208 |
+
```
|
| 209 |
+
|
| 210 |
+
現行のRust all-target結果は合計 **224 passed, 2 ignored**(226 discovered)である。ignored 2件は
|
| 211 |
+
pinned model/observer を必要とし、通常 CI が model download や Metal 実機を暗黙に要求しないため
|
| 212 |
+
分離している。release build と汚染した親環境を使う手動 gate では 2/2 passed である。実モデル
|
| 213 |
+
Receipt E2E は本 runbook の次節と evidence 文書で別に検証する。
|
| 214 |
+
|
| 215 |
+
pedantic Clippy の `module_name_repetitions` だけは、protocol の versioned public API 名を module
|
| 216 |
+
外でも自己記述的に保つ設計判断として crate level で allow する。他の warning は
|
| 217 |
+
`-D warnings` で失敗させる。
|
| 218 |
+
|
| 219 |
+
実モデルで新しい Self Local Receipt set を生成する。audit key は exact 32-byte raw key とし、
|
| 220 |
+
output directory の外に一度だけ安全に作成・保管する。key file は current user 所有の single-link
|
| 221 |
+
regular file、mode `0400` または `0600` でなければならない。既存 key をこの手順で上書きしない。
|
| 222 |
+
|
| 223 |
+
```sh
|
| 224 |
+
set -eu
|
| 225 |
+
OUT="receipts/manual-$(date +%Y%m%d-%H%M%S)"
|
| 226 |
+
PROMPT_FILE="/path/to/private-prompt.txt"
|
| 227 |
+
AUDIT_KEY="$HOME/.config/misaka-palw/audit-keys/local-audit.key"
|
| 228 |
+
|
| 229 |
+
install -d -m 700 "$(dirname "$AUDIT_KEY")"
|
| 230 |
+
test ! -e "$AUDIT_KEY"
|
| 231 |
+
(umask 077 && /usr/bin/openssl rand 32 > "$AUDIT_KEY")
|
| 232 |
+
chmod 600 "$AUDIT_KEY"
|
| 233 |
+
|
| 234 |
+
runtime-palw/target/release/palw-metal-receipt \
|
| 235 |
+
--prompt-stdin --audit-key-file "$AUDIT_KEY" \
|
| 236 |
+
--output-dir "$OUT" --n-predict 2 < "$PROMPT_FILE"
|
| 237 |
+
```
|
| 238 |
+
|
| 239 |
+
`--prompt-stdin`、`--audit-key-file`、`--output-dir` はすべて必須である。prompt は UTF-8、非空、
|
| 240 |
+
最大 1 MiB を要求し、argv で prompt を受ける互換 option はない。source の省略、重複 option、
|
| 241 |
+
上限超過、zero/all-zero または不正 permission の audit key は inference または publication 前に
|
| 242 |
+
拒否する。wrapper は受け取った prompt を pinned tokenizer と native observer の専用 stdin pipe
|
| 243 |
+
へ渡す。output directory は新規または空で、symlink ではなく current user 所有でなければならず、
|
| 244 |
+
CLI が mode `0700` を強制する。
|
| 245 |
+
|
| 246 |
+
job ID、nonce、salt、scheduler/worker signing key、network ID は OS CSPRNG からローカル実行ごとに
|
| 247 |
+
生成されるため、Receipt ID は証跡例と同一にならない。これらの一時 identity は receipt set 内の
|
| 248 |
+
binding を検証するためのものであり、production network の登録済み scheduler/worker authority や
|
| 249 |
+
credential ではない。private signing key は publication 後に保持しない。
|
| 250 |
+
|
| 251 |
+
CLI は実行前後で model/runtime manifest を再構築して artifact 変更を検出し、署名済み request と
|
| 252 |
+
assignment、prompt/output opening、全 observer evidence、CU、schedule、graph trace を stateless
|
| 253 |
+
verify する。canonical binary を strict decode で round-trip し、secret scan を通過した後だけ
|
| 254 |
+
SQLite transaction で receipt/job/nullifier を受理する。private request/assignment、opening、owner
|
| 255 |
+
salt、検証用 signer record は XChaCha20-Poly1305 の `.palw.bundle` に認証付き暗号化する。Self Local
|
| 256 |
+
Receipt はこの時点では Work Ticket ではなく、future audit または challenge-window maturity が
|
| 257 |
+
別途必要である。
|
| 258 |
+
|
| 259 |
+
正常終了時の directory は同一 Receipt ID を basename とする次の set になる。
|
| 260 |
+
|
| 261 |
+
- `<id>.palw` (`0644`): 署名済み canonical public envelope
|
| 262 |
+
- `<id>.json` (`0644`): strict `misaka.palw.public-receipt.v2` metadata。unknown field を拒否し、
|
| 263 |
+
verifier が retained field を authenticated receipt/bundle と照合
|
| 264 |
+
- `<id>.palw.bundle` (`0600`): audit key で認証付き暗号化した private verification material
|
| 265 |
+
- `palw-state.sqlite3` (`0600`): application/schema identity と full DDL fingerprint を検査する schema v4 state
|
| 266 |
+
- `<id>.complete` (`0644`): `misaka.palw.receipt-set.v2` completion marker
|
| 267 |
+
|
| 268 |
+
CLI は WAL を main DB へ checkpoint/truncate し、DB と各 artifact を fsync して directory entry を
|
| 269 |
+
永続化した後、marker を最後に作成・fsync する。したがって portable set は `-wal` / `-shm` file に
|
| 270 |
+
依存しない。旧schemaや未知/legacy DBを暗黙にmigrateせずfail-closedに拒否する。
|
| 271 |
+
|
| 272 |
+
marker は receipt ID、bundle ID、公開 JSON byte 列の SHA-256 を bind し、crash 後に「前提 file を
|
| 273 |
+
永続化してから publication を完了した」ことを示す。ただし marker 自体は keyed MAC でも network
|
| 274 |
+
authority の署名でもなく、directory を変更できる同一 user は再計算できる。marker 単独を artifact
|
| 275 |
+
authenticity、network authorization、maturity の根拠にしてはならない。
|
| 276 |
+
|
| 277 |
+
別 process で artifact set を復元・再検証する。次は CLI が表示した ID を `.palw` basename から
|
| 278 |
+
取得する単発 set 用の例である。
|
| 279 |
+
|
| 280 |
+
```sh
|
| 281 |
+
RECEIPT="$(find "$OUT" -maxdepth 1 -type f -name '*.palw' -print)"
|
| 282 |
+
ID="$(basename "$RECEIPT" .palw)"
|
| 283 |
+
|
| 284 |
+
runtime-palw/target/release/palw-verify-bundle \
|
| 285 |
+
--receipt "$OUT/$ID.palw" \
|
| 286 |
+
--bundle "$OUT/$ID.palw.bundle" \
|
| 287 |
+
--public-json "$OUT/$ID.json" \
|
| 288 |
+
--audit-key-file "$AUDIT_KEY" \
|
| 289 |
+
--state-db "$OUT/palw-state.sqlite3"
|
| 290 |
+
```
|
| 291 |
+
|
| 292 |
+
verifier は artifact の exact filename、同一 private directory、owner、mode、link count、distinct inode、
|
| 293 |
+
bounded read/path race、v2 marker、公開 JSON の全 field、暗号化 bundle の authentication、署名・
|
| 294 |
+
assignment・manifest・evidence/opening、既存 DB acceptance を照合する。正常時は
|
| 295 |
+
`status=local_restored` と `trust_scope=embedded_local_snapshot` を出力する。この local mode は
|
| 296 |
+
発行時に暗号化した registry snapshot との continuity を示すだけで、後日の network revocation や
|
| 297 |
+
外部 authority を独立に取得しない。production verifier は library の external-trust API へ current
|
| 298 |
+
network ID、scheduler/signer registry、approved manifest hash を別経路から与える必要がある。
|
| 299 |
+
|
| 300 |
+
後段のticketingではrawな「mature」登録APIを使用しない。field/constructorが非公開の
|
| 301 |
+
`MatureEvidence`はSelf Local audit `Mature`またはSelf Replicated typed `MatchedReplicaPair`だけが
|
| 302 |
+
generic pathへ渡せる。Externalはgeneric registrationを拒否し、authority-confirmed durable settlement
|
| 303 |
+
transactionだけがmaturityを作る。`WorkTicketV2`はsourceに加えて`maturity_basis_id`と、Externalに必須の
|
| 304 |
+
authority-signed `weight_grant_id`をbindする。
|
| 305 |
+
|
| 306 |
+
production bonded pathではauthority-signed fundingをcreditし、scheduler-signed assignmentごとにlockして、
|
| 307 |
+
Receiptを`accept_bonded`で受理する。maturity登録はSelf Localで1件、replicatedで2件のactive assignment
|
| 308 |
+
bondを同じtransactionでrelease/linkする。`issue_ticket`はrequired link数、`issued_epoch >= mature_epoch`、
|
| 309 |
+
source未消費を再検査する。External settlementはsigned terminal confirmation、terminal、2 bond releases/
|
| 310 |
+
links、maturity、ticketを1 SQLite transactionでcommitする。External refundはstate 1..3からexpiry後にpairの
|
| 311 |
+
有無を問わず進め、terminalとeligible bond releaseをatomicにcommitするがticketを作らない。pending claimの
|
| 312 |
+
bondは解決までreleaseしない。
|
| 313 |
+
|
| 314 |
+
expiry releaseは未使用assignmentに加え、acceptedでもまだpairを持たないSelf Replicatedだけをsigned expiry後に
|
| 315 |
+
許す。pending canary/slash、paired receipt、Self Local、その他used assignmentはexpiry bypassを拒否する。
|
| 316 |
+
slash claimはinitial bond基準のimmutable targetを持ち、overlapを加算せずfinalized max-envelopeとpending
|
| 317 |
+
extensionへorder-independentにallocateする。appeal/decision windowはsigned claimed epochだけでなく、authority
|
| 318 |
+
registryでのverification/acceptance epochも期限内であることを要求する。Externalの
|
| 319 |
+
`SettlementPrepared` transitionは両assignmentがactiveでslash claimなしとpreflightする。
|
| 320 |
+
`SettlementPrepared`または`RefundPrepared`以後のnon-replay slashを拒否する。両prepared state後のauthority confirmation timeoutや
|
| 321 |
+
superseding terminalはないため、production運用はauthority availabilityとprepared-state recovery手順を
|
| 322 |
+
crate外で用意する。
|
| 323 |
+
|
| 324 |
+
これらはcore APIとdurable transitionの手順であり、production service一式を含まない。repository内には
|
| 325 |
+
network scheduler/worker registry service、beacon delivery/governance、auditor/re-execution executor、
|
| 326 |
+
bond/external authority governance service、payment railがない。signed funding/terminalは外部factの
|
| 327 |
+
authenticated statementであり、実collateral/rail movementをcrateが独立証明しない。railとSQLiteは
|
| 328 |
+
distributed atomic transactionではない。
|
| 329 |
+
したがって library test の成功やローカル生成 identity を production maturity/payment evidence として
|
| 330 |
+
扱わず、該当する要件は [`requirements.md`](requirements.md) の `In progress` のままである。
|
| 331 |
+
|
| 332 |
+
永続 store を検査する。
|
| 333 |
+
|
| 334 |
+
```sh
|
| 335 |
+
sqlite3 "$OUT/palw-state.sqlite3" \
|
| 336 |
+
'PRAGMA user_version; PRAGMA integrity_check; PRAGMA foreign_key_check;
|
| 337 |
+
SELECT COUNT(*) FROM receipts; SELECT COUNT(*) FROM jobs;'
|
| 338 |
+
```
|
| 339 |
+
|
| 340 |
+
current sourceの正常な単発実行はschema version `4`、`ok`、foreign-key violationなし、receipt `1`、job
|
| 341 |
+
`1`を返す。
|
| 342 |
+
store は `SQLITE_OPEN_NOFOLLOW`、WAL、`synchronous=FULL`、foreign keys、full sqlite_master DDL
|
| 343 |
+
fingerprint、transactional uniqueness を強制し、restart、競合 accept、rollback、pair/ticket/slash/
|
| 344 |
+
external terminal state を Rust test で検証する。
|
| 345 |
+
|
| 346 |
+
current schema-v4 証跡は `../receipts/final-v6/` にあり、Receipt ID は
|
| 347 |
+
`eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131`、bundle ID は
|
| 348 |
+
`359f1bedaeefc1e140bf8c0dbba11582cb5cc0be428dcd95bc6077721f8096e9` である。canonical
|
| 349 |
+
envelope 713 bytes、bundle 403,066 bytes、公開 JSON 3,427 bytes、marker 262 bytes、SQLite
|
| 350 |
+
282,624 bytes。SHA-256 は順に `85ecb4281a1cb4abf26d6e3e70c84bfb3cc2a6dad80e2022ea4a356165345a75`、
|
| 351 |
+
`b475193fcfe1aea3189066790f925cc3682d2ff5a48cdfa061d62db85d0cff78`、
|
| 352 |
+
`03bee886144a2c64dd5f4d2207f86c748f5a3e7891b43f82f077f051342c3d0b`、
|
| 353 |
+
`f3dc4e142eb602977c1ac065d51297418c8dca3967b6cdb53eb0dfb447d5c77b`、
|
| 354 |
+
`8a740c342a12c83ae211edfa8776b93a14ea9369e3d7bd19a1e780e0724c471e` である。separate verifier は
|
| 355 |
+
exit 0、`status=local_restored`、`trust_scope=embedded_local_snapshot` を返した。DB は application
|
| 356 |
+
`PALW` (`1346456663`)、schema v4、`integrity_check=ok`、foreign-key violationなし、receipt=1、job=1、
|
| 357 |
+
pair/audit/ticket/slash/external state=0で、最終検証後に `-wal` / `-shm` は残っていない。詳細は
|
| 358 |
+
[`evidence/metal-smoke-schema-v4-2026-07-15.md`](evidence/metal-smoke-schema-v4-2026-07-15.md)
|
| 359 |
+
を参照する。
|
| 360 |
+
|
| 361 |
+
historical schema-v3証跡は`../receipts/final-v5/`にあり、Receipt IDは
|
| 362 |
+
`ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68`、bundle ID は
|
| 363 |
+
`6fd4e57a6cbcd6fc1d9138989960b627c9ee4817bc3ac4ce889a1a1b41d7d63b` である。canonical
|
| 364 |
+
envelope 713 bytes、bundle 337,257 bytes、公開 JSON 3,427 bytes、marker 262 bytes、SQLite
|
| 365 |
+
126,976 bytes。separate verifier は exit 0、`status=local_restored`、
|
| 366 |
+
`trust_scope=embedded_local_snapshot` を返した。生成当時のDBはapplication `PALW`、schema v3、
|
| 367 |
+
`integrity_check=ok`、foreign-key violation なし、receipt=1、job=1、その他 state table=0 で、
|
| 368 |
+
最終 verifier 後に `-wal` / `-shm` は残っていない。詳細は
|
| 369 |
+
[`evidence/metal-smoke-2026-07-15.md`](evidence/metal-smoke-2026-07-15.md) を参照する。
|
| 370 |
+
current schema-v4 sourceはこの旧DBをsilent migrate/openしないため、final-v5をcurrent verifierのcontinuity
|
| 371 |
+
testへ流用しない。final-v6は新しいempty output directoryから生成したcurrent E2E証跡である。
|
| 372 |
+
|
| 373 |
+
### 1.7 冪等性と異常 artifact の扱い
|
| 374 |
+
|
| 375 |
+
installer は commit、content hash、size、Hub revision が一致する artifact を再利用する。既存の
|
| 376 |
+
GGUF または metadata が期待 hash と異なる場合は、上書きや削除をせず停止する。対象を調査・
|
| 377 |
+
保全し、必要なら別名へ移してから再実行する。
|
| 378 |
+
|
| 379 |
+
```sh
|
| 380 |
+
mv models/Qwen3.6-abliterated-35b-Claude-4.7/Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf \
|
| 381 |
+
models/Qwen3.6-abliterated-35b-Claude-4.7/Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf.rejected
|
| 382 |
+
./scripts/install.sh
|
| 383 |
+
```
|
| 384 |
+
|
| 385 |
+
途中で停止した Hugging Face の `.incomplete` cache は download library が再開に利用するため、
|
| 386 |
+
手動削除を前提にしない。Git worktree が固定 commit 以外で dirty な場合も自動 checkout しない。
|
| 387 |
+
|
| 388 |
+
## 2. CUDA(実験的・production 非発行)
|
| 389 |
+
|
| 390 |
+
`../runtime-palw/cuda/`の汎用device observerはGEMM/attention deterministic final-output tile sketch、
|
| 391 |
+
checked C ABI/canonical V1 codec、capacity/sequence/stream/poison stateを実装する。additive V2 transportは
|
| 392 |
+
origin、accumulator stage/dtype、sketch scheme、reduction segment、producer variant IDを含むexact
|
| 393 |
+
184-byte canonical recordを定義し、Rustが全unfiltered streamをexpected dispatch/runtimeへstrict bindする。
|
| 394 |
+
|
| 395 |
+
standalone V2 producer primitiveは、実のCUDA test kernel内でFP32 segmented accumulatorをepilogue/store前に
|
| 396 |
+
捕捉する。exact function pointer/attributes、launch nonce、compiled identity、sample coverage、fault maskを
|
| 397 |
+
fail-closedに検証する。Rustはさらにnetwork-scoped authority attestationをjob/execution、assignment、
|
| 398 |
+
runtime manifest/class/instance、producer integration、operation schedule、full transcript、epochへ署名bindする。
|
| 399 |
+
|
| 400 |
+
vendored llama.cppのQ4_K/Q6_K MMVQ producerはV3 full-K pre-epilogue hookへ接続済みである。
|
| 401 |
+
same-backend Qwen 1-token diagnostic E2Eで253/253 record(Q4_K 216 / Q6_K 37)、3回同一
|
| 402 |
+
fingerprintを確認した。FA-off attentionのcanonical 3-sublaunch grouping/strict binderと、実QK-score/
|
| 403 |
+
softmax/value-aggregation直後collector/typed associationも接続し、QK 36、softmax 36、PV 36を加えた
|
| 404 |
+
361/361 recordを3回同一fingerprintで取得した。Q4/Q6/QK/softmax/PV各先頭の選択launch拒否も
|
| 405 |
+
fail closedである。exact entry symbols/runtime attributes/cubin/DSO release manifest、361 expected tableを
|
| 406 |
+
検証するReceipt/RuntimeManifest/Request/Assignment V2、暗号化Bundle V2、SQLite V2も実装済みである。
|
| 407 |
+
ただしlive callback���diagnostic IDであり、production authorityからのReceipt発行には使用しない。
|
| 408 |
+
`ComputeReceiptV1` への変換はbuilder/verifierの両方が拒否する。
|
| 409 |
+
|
| 410 |
+
CUDA のない host では ABI、codec、header、production rejection gate だけを検証する。
|
| 411 |
+
|
| 412 |
+
```sh
|
| 413 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda-host \
|
| 414 |
+
-DPALW_CUDA_TRACE_ENABLE_CUDA=OFF -DBUILD_TESTING=ON
|
| 415 |
+
cmake --build build/palw-cuda-host
|
| 416 |
+
ctest --test-dir build/palw-cuda-host --output-on-failure -L host
|
| 417 |
+
```
|
| 418 |
+
|
| 419 |
+
AppleClang host ABI/codec を ASan+UBSan でも確認する場合は次を使う。この macOS ASan は leak
|
| 420 |
+
detection 非対応のため `detect_leaks=0` とし、これは LeakSanitizer の代替証跡ではない。
|
| 421 |
+
|
| 422 |
+
```sh
|
| 423 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda-sanitize \
|
| 424 |
+
-DPALW_CUDA_TRACE_ENABLE_CUDA=OFF -DBUILD_TESTING=ON \
|
| 425 |
+
-DCMAKE_BUILD_TYPE=Debug \
|
| 426 |
+
-DCMAKE_C_FLAGS='-Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer' \
|
| 427 |
+
-DCMAKE_CXX_FLAGS='-Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer'
|
| 428 |
+
cmake --build build/palw-cuda-sanitize
|
| 429 |
+
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1 \
|
| 430 |
+
UBSAN_OPTIONS=halt_on_error=1 \
|
| 431 |
+
ctest --test-dir build/palw-cuda-sanitize --output-on-failure -L host
|
| 432 |
+
```
|
| 433 |
+
|
| 434 |
+
production 発行を有効化する構成は意図どおり失敗しなければならない。
|
| 435 |
+
|
| 436 |
+
```sh
|
| 437 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda-production \
|
| 438 |
+
-DPALW_CUDA_PRODUCTION_KERNEL_TRACE=ON
|
| 439 |
+
```
|
| 440 |
+
|
| 441 |
+
NVIDIA host での実験 transport の device test は次で行う。exact CUDA toolkit、driver、NVCC、
|
| 442 |
+
cuBLAS、GPU model/compute capability、単一 `CMAKE_CUDA_ARCHITECTURES`、test 出力を保存する。
|
| 443 |
+
|
| 444 |
+
```sh
|
| 445 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda -DBUILD_TESTING=ON \
|
| 446 |
+
-DCMAKE_CUDA_ARCHITECTURES=89-real
|
| 447 |
+
cmake --build build/palw-cuda
|
| 448 |
+
ctest --test-dir build/palw-cuda --output-on-failure
|
| 449 |
+
```
|
| 450 |
+
|
| 451 |
+
現行証跡はWindows/WSL2、RTX 4060 Ti (`sm_89`)、driver 610.62、CUDA toolkit 13.3.1 /
|
| 452 |
+
NVCC 13.3.73で取得した。standalone CTestsは7/7 non-skipped、standalone producerは
|
| 453 |
+
20回の独立実行で同一encoded-transcript diagnostic fingerprintとなった。同じhostのQwenは
|
| 454 |
+
37/37 layerをGPU offloadし、dedicated observerは`n_batch=n_ubatch=1`で6/6同一event/result
|
| 455 |
+
streamを返した。最終grouped suiteは8/8 non-skipped、vendored MMVQ/attention same-backend gateは
|
| 456 |
+
361/361 V3 recordと3回同一fingerprintを返した。
|
| 457 |
+
詳細は[`evidence/cuda-wsl-sm89-2026-07-15.md`](evidence/cuda-wsl-sm89-2026-07-15.md)と
|
| 458 |
+
[`evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md`](evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md)と
|
| 459 |
+
[`evidence/cuda-v3-full-hook-sm89-2026-07-16.md`](evidence/cuda-v3-full-hook-sm89-2026-07-16.md)に固定する。
|
| 460 |
+
|
| 461 |
+
これによりNVIDIA実機不足というR32の外部blockerは解消したが、R32自体は未完了である。
|
| 462 |
+
vendored MMVQ/FA-off attention diagnostic hook、361-launch実機E2E、release manifest、Receipt V2/
|
| 463 |
+
bundle/persistenceは完了したが、R32のproduction完了にはauthority-derived canonical physical-layout IDを
|
| 464 |
+
使うlive callback、deployed trust roots、署名Receiptの独立restore、認可済みreplica/reproducibility matrixが
|
| 465 |
+
必要である。CUDA は Metal と異なる
|
| 466 |
+
`runtime_class_id` とし、cross-runtime determinism が別途証明されるまで k=2 replica として
|
| 467 |
+
直接照合しない。
|
| 468 |
+
|
| 469 |
+
## 3. CI gate 定義
|
| 470 |
+
|
| 471 |
+
[`../.github/workflows/palw-ci.yml`](../.github/workflows/palw-ci.yml) は checkout action を
|
| 472 |
+
commit SHA で固定し、credential persistence を無効化し、read-only contents permission を設定する。
|
| 473 |
+
push/PR は同じ event/ref の旧 run を cancel するが、manual NVIDIA run は event 名で分離して
|
| 474 |
+
cancel しない。push / pull request では次の2 job を定義する。
|
| 475 |
+
|
| 476 |
+
1. Ubuntu 24.04 に Rust 1.81.0、rustfmt、Clippy を install し、`fmt`、
|
| 477 |
+
`clippy --locked --all-targets -D warnings`、`test --locked --all-targets` を実行する。
|
| 478 |
+
2. Linux host-only CUDA ABI/codec/production-rejection gate を ASan+UBSan、leak detection 有効、
|
| 479 |
+
warning-as-error で build/test する。
|
| 480 |
+
|
| 481 |
+
手動 `workflow_dispatch` で `run_nvidia_experimental=true` を選んだ場合だけ、
|
| 482 |
+
`self-hosted, linux, x64, nvidia` label の runner で exact real SM architecture を指定し、experimental
|
| 483 |
+
CUDA transport を build/test する。`CUDA_VISIBLE_DEVICES=0` に固定し、`nvidia-smi` の実 compute
|
| 484 |
+
capability が選択した single `*-real` architecture と一致しなければ configure 前に失敗する。
|
| 485 |
+
V1 observer と standalone producer の両device executableを CTest 経由ではなく直接実行
|
| 486 |
+
するため、device/driver 不在を表す return code 77 は skip ではなく job failure になる。
|
| 487 |
+
|
| 488 |
+
この manual job は `PALW_CUDA_PRODUCTION_KERNEL_TRACE=OFF` であり、workflow 名にも `not R32` を
|
| 489 |
+
明記する。成功すれば final-output observer と standalone true-accumulator primitive を検査
|
| 490 |
+
できるが、repositoryの別実測で完了したMMVQ hookを���のmanual job自体は検査しない。
|
| 491 |
+
repositoryの別実測で完了したvendored-Qwen MMVQ+attention full stream、release manifest、Receipt V2も
|
| 492 |
+
このjob自体は検査しない。またproduction authority接続と必要なrepeatability matrixは満たさない。
|
| 493 |
+
workflow 定義の存在自体も runner での成功証跡ではないため、R32/R35 の未達 gate を解除しない。
|
docs/security-model.md
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Security Model
|
| 2 |
+
|
| 3 |
+
## Protected assets
|
| 4 |
+
|
| 5 |
+
- model artifact、tokenizer、runtime binary/dylib/source patch の同一性
|
| 6 |
+
- prompt、prompt/generated token IDs、decoded output、owner key、commitment opening、audit key の秘匿性
|
| 7 |
+
- token count、operation schedule、canonical CU、graph/kernel trace の完全性
|
| 8 |
+
- scheduler request/assignment、job/execution nullifier、Receipt の一回性
|
| 9 |
+
- replica、audit、escrow、bond/slashing、Work Ticket の状態遷移
|
| 10 |
+
|
| 11 |
+
## Trust and issuance boundary
|
| 12 |
+
|
| 13 |
+
単一の自己申告 Receipt は、悪意ある host に対する独立な暗号学的 proof ではない。本プロトコルは
|
| 14 |
+
次を組み合わせて不正コストを上げる。
|
| 15 |
+
|
| 16 |
+
- content-address された model/runtime manifest と Ed25519 scheduler/worker signature
|
| 17 |
+
- 同一 runtime class 内の独立 credential/runtime instance による k=2 exact match
|
| 18 |
+
- Receipt 発行後の future beacon による再実行 audit
|
| 19 |
+
- authority-signed funding、scheduler-signed assignment lock、conserved durable bond accounting、appeal
|
| 20 |
+
- scheduler-signed hidden precommitを期限後に開き、worker/scheduler timeoutを分離するdurable canary
|
| 21 |
+
- transactional replay、pair、audit、bond/slash/health、maturity、WorkTicketV2、external settlement registry
|
| 22 |
+
|
| 23 |
+
schema-v4 coreではこれらの多くがSQLite transactionで接続された。bonded Receipt acceptance、audit/canary
|
| 24 |
+
slash、maturity時bond release/link、External settlementからticketまでのlocal atomicityを持つ。ただし
|
| 25 |
+
production scheduler/auditor/authority/payment service全体をrepository内で実装したわけではない。
|
| 26 |
+
|
| 27 |
+
現行 Metal Self Local path は signed Receipt を発行できるが、evidence は `graph_fallback` であり
|
| 28 |
+
CUDA kernel proof ではない。mature weight には future audit または challenge window が必要である。
|
| 29 |
+
現行CLIはscheduler/worker keyとregistry snapshotをlocalに生成するため、その出力だけからproduction
|
| 30 |
+
scheduler authorizationやnetwork admissionを推論してはならない。
|
| 31 |
+
|
| 32 |
+
future-audit state、signed beacon provenance、audit replay、passing maturityはSQLiteへdurableに保存する。
|
| 33 |
+
ただしfinalized beaconの取得/governance、独立auditorへのassignment、model re-execution、private opening
|
| 34 |
+
deliveryは外部serviceのtrust boundaryである。crate内のlocal authority registryはnetwork consensusや
|
| 35 |
+
beacon finalityを実装しない。
|
| 36 |
+
|
| 37 |
+
CUDA code はadditive 184-byte V2 codecとstrict full-stream/dispatch/runtime binderを持つが、raw recordの
|
| 38 |
+
declared producer originはtransport metadataであってproofではない。authority署名をnetwork/job/execution/
|
| 39 |
+
assignment、runtime class/manifest、producer integration、operation schedule commitment、全scheduled
|
| 40 |
+
GEMM/attention coverage、full transcriptへbindし、producer
|
| 41 |
+
accumulator GEMMだけをReceipt V2 evidenceへ射影するtypestateも実装した。ただしV1にはこの
|
| 42 |
+
provenanceをcommitするfieldがないため、builderとverifierはCUDA `KernelSketch`をともに拒否する。
|
| 43 |
+
この署名は登録authorityによるexact transcript/integrationの承認をauthenticateするが、authorityの正しさや
|
| 44 |
+
GPU register由来を単独で暗号学的に証明しない。
|
| 45 |
+
|
| 46 |
+
standaloneのproducer-internal FP32 accumulator採取primitiveはWSL2 Ubuntu 24.04上のRTX 4060 Ti(sm_89)、CUDA Toolkit
|
| 47 |
+
13.3.1 / nvcc 13.3.73で最終grouped device suite 8/8とproducer 20/20同一diagnostic fingerprintを通過した。固定Qwenも
|
| 48 |
+
37/37 layer CUDA offloadとgraph observer 6/6同一diagnostic streamを確認済みである。vendored llama.cppの
|
| 49 |
+
Q4_K/Q6_K MMVQ producerはV3 full-K pre-epilogue hookへ接続済みで、same-backend 1-token diagnostic
|
| 50 |
+
E2Eは253/253 recordを取得する。V3 schema/binderはFA-off eager attentionのcanonical groupingを表現し、
|
| 51 |
+
3 stageのwork直後collectorとtyped associationも接続済みである。合計361 launchを3回同一fingerprintで
|
| 52 |
+
取得し、5 work classの拒否を確認した。exact symbol/runtime attributes/cubin/DSO release manifest、
|
| 53 |
+
Receipt/RuntimeManifest/Request/Assignment V2、暗号化Bundle V2、SQLite V2も実装・検証済みである。
|
| 54 |
+
ただしlive callbackはauthority-derived canonical physical-layout IDではなくdiagnostic IDを使用するため、
|
| 55 |
+
trace/producer production capability、vendor integration、Receipt mappingの各macroは0、production
|
| 56 |
+
CMake optionはconfigure時に失敗する。したがって
|
| 57 |
+
R32は`In progress`だがCUDA Receiptは発行不可である。
|
| 58 |
+
|
| 59 |
+
host OS、driver、GPU firmware まで敵対的とみなす場合は、TEE attestation または ZK/VC を追加
|
| 60 |
+
しなければならない。この v1 はその主張を行わない。
|
| 61 |
+
|
| 62 |
+
## Threat controls
|
| 63 |
+
|
| 64 |
+
| Threat | Primary controls | Fail condition |
|
| 65 |
+
|---|---|---|
|
| 66 |
+
| Fake token count | pinned runtime tokenizer IDs、prefill/decode graph step consistency、opening、audit | count/token vector/phase step が不一致 |
|
| 67 |
+
| Fake runtime | model/binary/dylib/source/build/host digest、manifest ID、allowlist | digest、class、実行前後 manifest が不一致 |
|
| 68 |
+
| Fake output | salted output commitment、signed shared nonce、replica/audit opening | nonce、token、stop reason、再実行 output が不一致 |
|
| 69 |
+
| Replay | domain-separated job/execution nullifier、SQLite unique constraint | receipt/nullifier/job slot が既に受理済み |
|
| 70 |
+
| Forked runtime | manifest digest、signed assignment、canary、independent runtime instance | 未許可 digest、credential/instance 重複、canary failure |
|
| 71 |
+
| Dummy execution | strict non-empty event stream、full event/token coverage、trace、replica/audit | event 欠落、unknown op、required evidence 不足 |
|
| 72 |
+
| Schedule rewrite | ordered hash chain、event count、CU、Receipt signature | reorder/insert/delete/shape mutation で chain または CU 不一致 |
|
| 73 |
+
| Receipt duplication | receipt/execution/job-slot uniqueness、pair/ticket one-shot state | duplicate accept、pair reuse、二重 ticket 化 |
|
| 74 |
+
| Trace forgery | manifest capability、strict graph claim、trace root/count、replica/audit | CUDA claim、scheme、root、count、tile metadata が不一致 |
|
| 75 |
+
| Secret leakage | stdin child pipe、output-byte omission、private opening schema、pre-write scan | canonical Receipt に prompt/token/key/nonce/salt bytes が出現 |
|
| 76 |
+
| Bundle substitution | receipt/public/AAD binding、XChaCha20-Poly1305 tag、strict decode | receipt/bundle/public digest、nonce、tagが不一致 |
|
| 77 |
+
| Incomplete output set | checkpoint/fsync、marker-last、core JSON field cross-check | marker欠落・ID/hash不一致(marker自体はunkeyedでauthenticity controlではない) |
|
| 78 |
+
| Local trust escalation | DB exact restoreとexternal anchored stateless pathの分離 | embedded key snapshotだけで第三者authorityを主張 |
|
| 79 |
+
| CUDA async failure | permanent poison、committed-count barrier、production gate | poisoned/pending/overflow context または非発行 capability |
|
| 80 |
+
| External funding/weight forgery | network-scoped authority capability、signed exact funding/grant、canonical replay ID | key/network/asset/amount/grant/epoch/signature不一致 |
|
| 81 |
+
| External double settlement | stable payment command、signed terminal confirmation、single durable terminal | command/distribution/pair/amount/epoch不一致、逆terminal、conflicting replay |
|
| 82 |
+
| Canary false slash | scheduler-signed precommit、atomic receipt acceptance、fault-party timeout attribution | precommit/request/assignment/window不一致、opening未到達、scheduler opening timeout |
|
| 83 |
+
| Bond funding/slash replay | signed funding event、typed primary proof、conservation reconciliation、appeal state | event/offense/canonical payload conflict、account/assignment/evidence不一致 |
|
| 84 |
+
| Dependency/MSRV drift | exact crypto pins、lockfile、Rust 1.81 all-target CI | lock変更、MSRV manifest parse失敗、lint/test failure |
|
| 85 |
+
| Premature Work Ticket | opaque maturity basis、required bond release links、WorkTicketV2、atomic one-shot issue | raw claim、epoch前倒し、bond link不足、grant不一致、source再消費 |
|
| 86 |
+
|
| 87 |
+
## Cryptographic rules
|
| 88 |
+
|
| 89 |
+
- hash は SHA3-256 とし、用途ごとの domain separation と version を必須にする。
|
| 90 |
+
- 可変長 field は canonical length-prefix し、曖昧な連結を禁止する。
|
| 91 |
+
- Receipt、manifest、request、assignment、future beacon、canary precommit、bond/external authority
|
| 92 |
+
evidence、verification bundle はstrict versioned canonical formだけを署名・hash/AEAD binding対象にする。
|
| 93 |
+
- output nonce、owner salt、private key seed は OS CSPRNG から 32 bytes 生成し、zero を拒否する。
|
| 94 |
+
- replica 用 output nonce は scheduler-signed request で共通指定し、worker による差し替えを防ぐ。
|
| 95 |
+
- prompt commitment も signed shared nonce、network、job、runtime tokenizer IDs に binding する。
|
| 96 |
+
- key ID、algorithmと署名をenvelopeに明記し、public keyはregistryから解決する。Receipt、scheduler
|
| 97 |
+
message、future beacon、canary precommit、bond/external authorityのEd25519検証は`verify_strict`を使い、
|
| 98 |
+
small-order/weak public keyを各registryへの登録時と検証時に拒否する。bond authorityはfunding/appeal/
|
| 99 |
+
decision、external authorityはfunding/demand-weight/terminalのcapabilityを分離する。
|
| 100 |
+
- verification bundle はXChaCha20-Poly1305(256-bit derived key、192-bit random nonce、128-bit tag)を
|
| 101 |
+
使い、receipt binding、public digest、nonce、canonical public sectionをAADへbindする。caller-owned
|
| 102 |
+
raw audit keyとprivate signing-key seedはbundleへserializeしない。
|
| 103 |
+
- replay/cardinality/terminal transition は process-local set ではなく durable transaction で確定する。
|
| 104 |
+
- MSRV gate、Clippy、test、release build は committed lockfile を使い、open transitive range が
|
| 105 |
+
toolchain 非互換 manifest を silent に選ばないようにする。
|
| 106 |
+
|
| 107 |
+
## Privacy rules
|
| 108 |
+
|
| 109 |
+
canonical Receipt と公開 JSON に prompt、raw output、prompt/generated token IDs、owner public key、
|
| 110 |
+
output nonce、owner salt、private key、accumulator 全体を含めない。公開 JSON は commitment、digest、
|
| 111 |
+
non-secret identifier/counter/protocol label、CU、artifact/observer summary、filename、privacy flagを記録する。
|
| 112 |
+
後述のlocal verifierがsemanticに照合するのはその一部である。
|
| 113 |
+
|
| 114 |
+
Receipt CLI は必須の `--prompt-stdin` を使い、UTF-8/非空/1 MiB 上限を inference 前に検査する。
|
| 115 |
+
`--prompt TEXT` は廃止され、unknown optionとして拒否する。CLIはさらに `--audit-key-file` を必須とし、
|
| 116 |
+
exact 32-byte nonzero key、owner、single link、regular-file、mode `0400`/`0600`、symlink/path race/inode
|
| 117 |
+
alias/output directory内配置をfail-closedに検査する。
|
| 118 |
+
Rust adapter は prompt を tokenizer/native child argv、stderr、error text に置かず専用 stdin pipe
|
| 119 |
+
で渡す。通常の Receipt 実行は native observer の `--emit-output-bytes` を使わないため decoded
|
| 120 |
+
output bytes は IPC result にも含まれない。ただし native JSONL は wrapper 内部で
|
| 121 |
+
prompt/generated token IDs を opening として運ぶため、この local pipe と process memory は
|
| 122 |
+
trusted privacy boundary である。debug QA で output bytes を明示的に有効化した stream を公開
|
| 123 |
+
ログへ流してはならない。
|
| 124 |
+
|
| 125 |
+
verification bundleのpublic sectionにはreceipt binding/ID、verification epoch、scheduler public-key
|
| 126 |
+
snapshot、manifest、execution evidenceを置く。worker public keyを含むsigner record、signed
|
| 127 |
+
request/assignment、output nonce、prompt/generated token IDs、stop reason、owner saltはencrypted private
|
| 128 |
+
sectionだけに置く。private signing-key seedとaudit keyはoutput artifactへ保持/serializeしない。CLI はcanonical bytesの
|
| 129 |
+
strict round-tripとprompt/token/key/nonce/salt scanを通過してからだけ`create_new`で書く。audit keyの
|
| 130 |
+
rotation/backup、bundle/openingのretention/deletionはcallerの運用責任で、このcrateに自動retention policy
|
| 131 |
+
はない。
|
| 132 |
+
|
| 133 |
+
tokenizer、observer、host/source identity helperは inherited environment を消去し、`LANG=C` と
|
| 134 |
+
`LC_ALL=C`だけを設定する。このallowlistはmanifestへbindされ、host identity helperはabsolute pathで
|
| 135 |
+
起動する。ただしsame-user debugger、process memory reader、malicious host kernelからlocal openingや
|
| 136 |
+
audit keyを保護するattestationは提供しない。
|
| 137 |
+
|
| 138 |
+
## Durable-state rules
|
| 139 |
+
|
| 140 |
+
SQLite store は WAL、`synchronous=FULL`、foreign key、application ID、schema version 4を検証する。
|
| 141 |
+
table/column/foreign-key/index集合に加え、non-internal `sqlite_master` の完全な
|
| 142 |
+
`(type,name,tbl_name,sql)`列をcanonical SHA3-256 fingerprintで照合する。旧schemaをsilent migrateせず、
|
| 143 |
+
既存objectを持つunclaimed DBも拒否する。Receipt ID、execution nullifier、job/replica slot、pair
|
| 144 |
+
membership、future audit/replay、bond funding/account/assignment/release/slash/appeal/health、signed canary、
|
| 145 |
+
maturity source/assignment link、Work Ticket v2、external escrow/payment command/terminalをunique constraintと
|
| 146 |
+
transactionで守る。
|
| 147 |
+
|
| 148 |
+
raw maturity flag を受ける public store API は持たない。original receiptの`accepted_at_epoch`、pairの
|
| 149 |
+
`matched_epoch`、signed beaconのclaimed epoch/key ID/canonical envelope、audit replayのissued/accepted
|
| 150 |
+
epochを保存し、epoch rollbackを拒否する。beaconを検証したcaller current epochは保存せず、restore時に
|
| 151 |
+
current `AcceptedReceipt.verified_at_epoch`とauthority registryから再確立する。selected auditは
|
| 152 |
+
audit-specific replay identityの一回予約、typed
|
| 153 |
+
projection verdict、terminal state、passing maturity sourceを同一transactionで確定し、non-selected
|
| 154 |
+
auditもwindow maturityとsource登録を同一transactionで確定する。bond rowがあるaudit pathとSelf
|
| 155 |
+
Replicated pathはmaturityと同じtransactionでrequired assignment bondをrelease/linkする。Work Ticketは
|
| 156 |
+
その`mature_epoch`より前には発行できず、job classに必要なrelease link数を満たすsourceだけを一度消費する。
|
| 157 |
+
|
| 158 |
+
bond fundingはauthority-verified typestateだけをcreditし、funding event ledgerとaccount buckets、active
|
| 159 |
+
assignment remaining、pending/finalized slash、healthをread/transition時にreconcileする。lockはexact
|
| 160 |
+
scheduler-signed assignmentにbindする。bonded assignmentのReceiptをgeneric `accept`で受けず、
|
| 161 |
+
`accept_bonded`または`accept_canary`のatomic pathを要求する。audit mismatch/timeoutとcanary mismatch/
|
| 162 |
+
receipt timeoutはtransition自身からtyped primary proofを作り、slash accountingを同じtransactionに含める。
|
| 163 |
+
各claimはinitial bond基準のimmutable targetを持ち、finalized max-envelopeを優先してpending extensionだけを
|
| 164 |
+
allocateする。overlapを加算せず、equal/weaker/strongerの到着順やreverse後にも全claimから再計算する。
|
| 165 |
+
v1のEquivocation追加penaltyは0である。
|
| 166 |
+
|
| 167 |
+
authority-verified appealはpending offense/worker/assignment/deadlineへexact bindする。signed submissionと
|
| 168 |
+
appeal verification/acceptance epochをappeal window内に��求し、decision windowは後者から開始する。signed
|
| 169 |
+
decision epochとdecision verification/acceptance epochもdeadline内でなければならない。期限経過後は
|
| 170 |
+
default-uphold、appealがなければappeal deadline後のfinalizationだけを認める。exact canonical replayは
|
| 171 |
+
idempotent、同じbusiness IDのconflicting payloadはfatalである。
|
| 172 |
+
|
| 173 |
+
pendingまたはuphold/default-final claimを持つassignmentからmaturity/ticketを生成しない。全claim解決後、
|
| 174 |
+
audit mismatch/timeout terminalはclaim reversal時も残額を`SlashResolved`
|
| 175 |
+
releaseする。canary fault terminalはmatching claimがuphold/default-finalの場合だけreleaseでき、reversed
|
| 176 |
+
canary claim単独では解放しない。External refundもrelease terminalであり、state 1..3からexpiry後にpairの
|
| 177 |
+
有無を問わず確定できる。eligible bond残額はrefund terminalでreleaseするが、pending claimを持つbondは解決まで
|
| 178 |
+
lockedに残す。expiry releaseは未使用またはaccepted-unpaired SelfReplicatedだけを許し、pending canary/slash、paired、Self Local、その他used
|
| 179 |
+
assignmentを拒否する。`fault_event_epoch`とdurable `applied_epoch`を分離し、terminal epoch/proofは
|
| 180 |
+
offense-sortedな完全claim/terminal fact setとmax effective epochからcanonicalに導出する。
|
| 181 |
+
|
| 182 |
+
scheduler-signed canary precommitはactive lockとcanonical envelopeを保存する。normal Receipt insertと
|
| 183 |
+
`ReceiptSubmitted`はatomicである。pass terminal、mismatch/slash、receipt-missing worker slash、opening-
|
| 184 |
+
missing scheduler fault/no-worker-slashをそれぞれ一transactionで確定する。passとopening-missingはbondを
|
| 185 |
+
releaseせず、pending canary中のmaturityを拒否する。terminal後のmature epochをcanary completion以後へ
|
| 186 |
+
遅延し、maturity transactionだけが`Mature` release/linkを行う。
|
| 187 |
+
|
| 188 |
+
External settlementはauthority-verified funding/grant、scheduler request、k=2 pair、stable command、signed
|
| 189 |
+
terminal confirmationを順にbindする。settlement confirmationはterminal、maturity、両worker bond release/
|
| 190 |
+
link、WorkTicketV2を一SQLite transactionでcommitする。refundはterminalとeligible bond releaseをatomicに
|
| 191 |
+
commitするが、maturity/ticketを生成せず、pending claimのbondは解決までreleaseしない。
|
| 192 |
+
`SettlementPrepared` transitionは両bondがactiveでpending/upheld/default-final slashなしと同じtransactionで
|
| 193 |
+
preflightする。`SettlementPrepared`または`RefundPrepared`以後のnon-replay slashを拒否する。
|
| 194 |
+
|
| 195 |
+
restartでは`restore_audit`がselected pass/mismatch terminalを`AuditReplayRequired`で拒否する。
|
| 196 |
+
`restore_selected_audit_with_replay`だけがstored challenge/canonical replayと全identity/epochを再照合し、
|
| 197 |
+
再計算したmatch bit、submission commitment、completed epochをdurable terminalへexact比較する。
|
| 198 |
+
|
| 199 |
+
DB file の possession は signer authorization を代替しない。受理前の stateless verifier が署名、
|
| 200 |
+
request/assignment、manifest/evidence/opening を検証し、その typestate と canonical bytes だけを
|
| 201 |
+
store へ渡す。
|
| 202 |
+
|
| 203 |
+
発行時はowned non-symlink output directoryを`0700`に固定し、Receipt/公開JSON/completion markerを
|
| 204 |
+
`0644`、暗号化bundle/DBを`0600`にする。DBはWAL `TRUNCATE` checkpoint、connection drop、main-file
|
| 205 |
+
`fsync`を完了してからpublic artifactsを書き、各fileを`fsync`した後にmarkerを最後に作ってdirectoryを
|
| 206 |
+
`fsync`する。marker v2はreceipt ID、bundle ID、公開JSON SHA-256を記録する。これはcross-file atomic
|
| 207 |
+
renameではないためlate failureでpartial setは残り得るが、local verifierは全protected artifactの
|
| 208 |
+
same-directory/expected filename/mode/owner/type/link count、exact marker、typed公開JSON
|
| 209 |
+
`misaka.palw.public-receipt.v2`全体がsigned Receiptと
|
| 210 |
+
authenticated bundle manifest/evidenceへ一致しないsetを拒否する。unknown fieldも全階層で拒否する。
|
| 211 |
+
|
| 212 |
+
markerはunkeyed plain textでsignature/AEAD protectionを持たず、same-owner writerは公開JSONとmarkerを
|
| 213 |
+
一緒に置換できる。しかしverifierは保持する`artifacts`と`observer_summary`を含むtyped文書全体を
|
| 214 |
+
authenticated dataから再構成してexact照合するため、markerを書き直しても改変JSONは受理されない。
|
| 215 |
+
marker/JSONはcompletenessとhuman-readable projectionのboundaryであり、canonical Receiptとauthenticated
|
| 216 |
+
bundleのauthorityを代替しない。
|
| 217 |
+
|
| 218 |
+
`verify_bundle_and_restore`はembedded snapshotsで再検証した後、既存DB rowへのexact continuityだけを
|
| 219 |
+
認め、missing rowをinsertしない。第三者用`verify_bundle_stateless_with_trust`は外部scheduler/signer
|
| 220 |
+
registry、expected network、approved manifest hashを必須とし、embedded snapshotをauthorityにしない。
|
| 221 |
+
後者はbundle-bound historical `verification_epoch`でのstateless verificationであり、present-time network
|
| 222 |
+
acceptanceやdurable replay reservationではない。
|
| 223 |
+
|
| 224 |
+
fresh APIはcaller-selected epochがbundleのhistorical verification epoch���上であることを要求する。
|
| 225 |
+
`verify_bundle_and_restore_at_epoch`はlocal embedded snapshotsでfresh `AcceptedReceipt`を作りoriginal durable
|
| 226 |
+
acceptance epochを保持するが、bundle作成後のrevocationは学習できない。
|
| 227 |
+
`verify_bundle_stateless_at_epoch_with_trust`はexternal rootsでfresh stateless typestateを作るがDB continuityを
|
| 228 |
+
検査しない。production restartではcurrent external rootsと既存DB rowを同時に検査する
|
| 229 |
+
`verify_bundle_and_restore_at_epoch_with_trust`を使う。future audit restoreではepochをbeacon以上にし、
|
| 230 |
+
present-time network admissionは別途判断する。現行CLIはhistorical default restoreだけを呼び、fresh epochは
|
| 231 |
+
library/service APIで指定する。
|
| 232 |
+
|
| 233 |
+
## Residual risks
|
| 234 |
+
|
| 235 |
+
- greedy decode でも driver/kernel/toolchain 差により bitwise output が変わり得る。
|
| 236 |
+
- Metal graph-level logical-prefix sketch は lossy で、CUDA kernel/accumulator trace より弱い。
|
| 237 |
+
- observer callback の read-only access は timing と synchronization を変え得る。
|
| 238 |
+
- k=2 replica が同一所有者・同一障害 domain なら共謀耐性がない。
|
| 239 |
+
- external registry/finality serviceが供給するfuture beaconが予測・操作可能ならaudit samplingが弱くなる。
|
| 240 |
+
- auditor scheduling、model re-execution、opening deliveryはcrate外であり、durable audit stateだけでは
|
| 241 |
+
independent replayの運用を保証しない。
|
| 242 |
+
- bond/external authority registryのproduction governance、key distribution、revocation deliveryはcrate外で、
|
| 243 |
+
同梱in-memory registryはnetwork consensusではない。
|
| 244 |
+
- signed funding/terminal evidenceはauthorityのstatementをauthenticateするが、実collateralやpayment railを
|
| 245 |
+
crateが独立観測したproofではない。rail movementとlocal SQLite commitはdistributed atomicではない。
|
| 246 |
+
- External `SettlementPrepared`/`RefundPrepared`後にauthority confirmationが来ない場合のtimeoutや
|
| 247 |
+
superseding terminalはなく、prepared stateのoperational recoveryは外部serviceに依存する。
|
| 248 |
+
- durable canaryはscheduler opening欠落をscheduler faultとしてworker slashから分離するが、production
|
| 249 |
+
schedulerのprecommit/opening deliveryとavailabilityはcrate外である。
|
| 250 |
+
- durable slashへ自動接続済みなのはaudit mismatch/timeoutとcanary mismatch/receipt timeoutである。
|
| 251 |
+
invalid-manifest、equivocation、duplicate-executionのproduction typed proof/orchestrationは未統合である。
|
| 252 |
+
- legacy in-memory `BondLedger`、`CanaryRecord`、`ExternalEscrow` helperはraw caller mutationを許すため、
|
| 253 |
+
schema-v4 signed/durable authority pathの代用にしてはならない。
|
| 254 |
+
- `future_audits.state=4`はpublic transitionではdeadlineを保持するが、SQL constraint単独では
|
| 255 |
+
`deadline_epoch NOT NULL`を要求しない。constraint-validなDB corruptionはload/release時にfail closedとなるが、
|
| 256 |
+
schema-level hardening余地が残る。
|
| 257 |
+
- CU table は実時間・電力を表さず、versioned governance の対象である。
|
| 258 |
+
- encrypted bundleはaudit keyを取得したsame-user/malicious hostからopeningを守らず、key backup/rotation/
|
| 259 |
+
retentionも自動化しない。
|
| 260 |
+
- CI workflowやRTX実機でのvendored MMVQ diagnostic hook/E2E成功も、FA-off attentionの361-launch実機coverage、
|
| 261 |
+
production-approved kernel manifest identity、authority-bound full-stream verification、Receipt V2を代替せず、
|
| 262 |
+
R32 production acceptance authorityを与えない。
|
| 263 |
+
|
| 264 |
+
production scheduler/network transport、governance key distribution、beacon/authority service、payment rail、
|
| 265 |
+
NVIDIA CUDAのfull production issuance pathも未統合である。
|
| 266 |
+
|
| 267 |
+
これらは runtime class 分離、independent identity、future beacon finality、versioned CU policy、
|
| 268 |
+
bond/slashing、source統合済みFA-off attention hookの実機full-stream検証、release manifest authorityと
|
| 269 |
+
attestation/proof layerで緩和する。
|
docs/state-machines.md
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# PALW State Machines and Policy V1
|
| 2 |
+
|
| 3 |
+
本書は現行 `runtime-palw` が実際に持つtypestate、legacy in-memory helper、schema-v4 SQLite stateを
|
| 4 |
+
区別して記述する。receipt/audit/canary/bond/external/maturityの主要transitionはdurable transactionで接続
|
| 5 |
+
されたが、production scheduler/auditor/authority/payment service全体を実装した単一lifecycle daemonはない。
|
| 6 |
+
|
| 7 |
+
## 1. Receipt verification and durable acceptance
|
| 8 |
+
|
| 9 |
+
実装済みの型遷移:
|
| 10 |
+
|
| 11 |
+
```text
|
| 12 |
+
canonical bytes / SignedReceiptV1
|
| 13 |
+
|
|
| 14 |
+
v
|
| 15 |
+
UnverifiedReceipt
|
| 16 |
+
| verify_stateless(...)
|
| 17 |
+
v
|
| 18 |
+
StatelesslyVerifiedReceipt
|
| 19 |
+
| StateStore::accept (SQLite transaction)
|
| 20 |
+
v
|
| 21 |
+
AcceptedReceipt
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
`verify_stateless` は body/signature、scheduler-derived assignment authorization、manifest、
|
| 25 |
+
schedule/CU/trace、prompt/output openingを検証する。`StateStore::accept` はその後にのみ receipt ID、
|
| 26 |
+
execution nullifier、job class、replica slotと`accepted_at_epoch`を永続予約し、成功した値だけを
|
| 27 |
+
`AcceptedReceipt`へ昇格する。process restart後は同じcanonical signed receiptとruntime instanceで
|
| 28 |
+
再度stateless verifyし、`restore_accepted`でoriginal acceptance epochを保持したtypestateを復元する。
|
| 29 |
+
この値はrestart時の`verified_at_epoch`と区別される。
|
| 30 |
+
|
| 31 |
+
exact assignmentのbond rowが存在するReceiptをgeneric `accept`へ渡すと
|
| 32 |
+
`BondedReceiptRequiresAtomicAcceptance`になる。production bonded pathはactive lockとのworker/request/
|
| 33 |
+
assignment/class/slot/runtime/epoch bindingを同じtransactionで検査する`accept_bonded`を使う。canaryは
|
| 34 |
+
後述の`accept_canary`を使い、Receipt insertとcanary state更新の間のcrash gapを作らない。
|
| 35 |
+
|
| 36 |
+
現行DBには `Received`、`Rejected`、`AwaitingBeacon` 等のreceipt lifecycle列はない。したがって
|
| 37 |
+
genericな `Received -> ... -> Ticketed` CAS machineやtransition logは未実装である。拒否は各APIの
|
| 38 |
+
errorであり、Rejected rowを保存しない。
|
| 39 |
+
|
| 40 |
+
### Self Local path
|
| 41 |
+
|
| 42 |
+
```text
|
| 43 |
+
AcceptedReceipt
|
| 44 |
+
-> AuditRecord::new
|
| 45 |
+
-> authority-signed future beacon verify/apply
|
| 46 |
+
-> StateStore::store_audit_selection
|
| 47 |
+
-> StateStore::complete_selected_audit
|
| 48 |
+
または StateStore::mature_unselected_audit
|
| 49 |
+
-> assignment bond release/link(bonded path)
|
| 50 |
+
-> StateStore::issue_ticket -> WorkTicketV2
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
`AuditRecord::new` はexact `AcceptedReceipt`からnetwork、receipt ID、issued/accepted epoch、job/requestを
|
| 54 |
+
bindする。beacon適用後のselectionとsigned beacon provenanceは`future_audits`へ保存する。selected path
|
| 55 |
+
では`complete_selected_audit`がaudit-specific replay identity、typed projection verdict、terminal state、
|
| 56 |
+
passing maturity sourceを1 transactionで確定する。non-selected pathでは
|
| 57 |
+
`mature_unselected_audit`がchallenge-window maturityとsource登録を1 transactionで確定する。
|
| 58 |
+
rawなprojection match boolやlocal maturity markerをstoreへ渡すpublic APIはない。bonded sourceならpassing
|
| 59 |
+
maturityと同じtransactionでassignmentを`Mature` releaseしてsourceへlinkし、mismatch/timeoutならtyped
|
| 60 |
+
slashを同じtransactionで適用する。historical unbonded Self Local rowはmatureになり得るが、required bond
|
| 61 |
+
release linkがないためWork Ticket発行gateを通らない。
|
| 62 |
+
|
| 63 |
+
ただしfinalized future beaconの取得/governance、independent auditor assignment、model再実行、encrypted
|
| 64 |
+
opening配送は外部serviceのtrust boundaryである。durable state machineがそれらのproduction serviceを
|
| 65 |
+
実装したことにはならない。
|
| 66 |
+
|
| 67 |
+
### Restart verification bundle
|
| 68 |
+
|
| 69 |
+
Receipt CLI は `--prompt-stdin` とoutput directory外の `--audit-key-file` を必須にする。argv promptの
|
| 70 |
+
`--prompt TEXT`は存在しない。bundle public sectionはreceipt binding/ID、verification epoch、scheduler
|
| 71 |
+
key snapshot、manifest、execution evidenceを含み、worker public keyを含むsigner record、signed
|
| 72 |
+
request/assignment、prompt/output opening、owner saltはXChaCha20-Poly1305 private sectionへ暗号化する。
|
| 73 |
+
|
| 74 |
+
発行setはoutput directory `0700`、Receipt/公開JSON/marker `0644`、bundle/DB `0600`。DBをWAL
|
| 75 |
+
`TRUNCATE` checkpointし、DBと各fileを`fsync`した後、receipt ID、bundle ID、公開JSON SHA-256を記録する
|
| 76 |
+
marker v2を最後に書く。cross-file atomic commitではないため途中artifactは残り得るが、markerのない
|
| 77 |
+
setはcompleteではない。markerはunkeyed plain textで、crash-completeness signal以上のauthorityを持たない。
|
| 78 |
+
|
| 79 |
+
local `verify_bundle_and_restore` はembedded key snapshotsでstateless verificationをやり直し、既存DBの
|
| 80 |
+
exact accepted rowだけをrestoreする。local CLIは`--public-json`も必須とし、全artifactのsame private
|
| 81 |
+
directory/expected filename/mode、marker v2、typed公開JSON `misaka.palw.public-receipt.v2`全体を検査する。保持する`artifacts`と
|
| 82 |
+
`observer_summary`はauthenticated bundle manifest/evidenceから再構成してexact照合し、extra fieldは
|
| 83 |
+
��階層で拒否する。same-owner writerはJSONとmarkerを一緒に置換できるが、改変JSONはこの照合を通らない。
|
| 84 |
+
canonical Receipt/authenticated bundleをauthorityとする。missing rowを
|
| 85 |
+
insertしない。external
|
| 86 |
+
`verify_bundle_stateless_with_trust`はexpected network、external scheduler/signer registry、approved
|
| 87 |
+
manifest hashを必須にするDBなしのpathで、embedded snapshotsをauthorityにせず、bundle-bound historical
|
| 88 |
+
`verification_epoch`を検証する。present-time admissionとdurable acceptは行わない。
|
| 89 |
+
|
| 90 |
+
future beacon後のrestoreには`verify_bundle_and_restore_at_epoch`がcaller-selected epochをhistorical値
|
| 91 |
+
以上へ進め、original durable acceptance epochを保持したfresh `AcceptedReceipt`を返す。ただしembedded
|
| 92 |
+
snapshotはlater revocationを学習しない。productionはcurrent external rootsとDB continuityを同時に検査する
|
| 93 |
+
`verify_bundle_and_restore_at_epoch_with_trust`を使う。statelessだけなら
|
| 94 |
+
`verify_bundle_stateless_at_epoch_with_trust`を使う。全fresh APIはepoch rollbackを拒否する。現行verifier
|
| 95 |
+
CLIはhistorical default pathだけを呼ぶため、fresh epochはlibrary/service APIで指定する。
|
| 96 |
+
|
| 97 |
+
### Replicated path
|
| 98 |
+
|
| 99 |
+
```text
|
| 100 |
+
AcceptedReceipt(slot 0) + AcceptedReceipt(slot 1)
|
| 101 |
+
-> K2Matcher::match_pair
|
| 102 |
+
-> MatchedReplicaPair
|
| 103 |
+
-> StateStore::store_pair
|
| 104 |
+
-> MatureEvidence::from_self_replicated_pair
|
| 105 |
+
-> StateStore::register_mature_evidence
|
| 106 |
+
-> assignment bonds 2件をatomic release/link
|
| 107 |
+
-> StateStore::issue_ticket -> WorkTicketV2
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
matcher は2 Receiptのprojectionとreceipt/execution/signer/credential/owner/assignment/runtime-instanceの
|
| 111 |
+
独立性を検査する。`current_epoch`は両receiptのissued、original accepted、current verified epoch以上、
|
| 112 |
+
expiry以下でなければならない。DBはpair本体と2 memberを同一transactionで保存する。
|
| 113 |
+
`MatchedReplicaPair` はmatchに使った`current_epoch`をprivate `matched_epoch`として保持し、durable
|
| 114 |
+
canonical pairにもcommitする。public constructorがその値をmaturity epochとしてopaque evidenceへ
|
| 115 |
+
封入する。rawなpair maturity登録APIは存在せず、`register_mature_evidence`はstored pairの
|
| 116 |
+
network/class/CU/matched epochとtyped evidenceを照合する。さらにpair member 2件からassignment IDを再取得し、
|
| 117 |
+
両方がauthority-funded active lockでなければsource登録transaction全体をrollbackする。成功時は2件を
|
| 118 |
+
`Mature` releaseしてsourceへlinkする。replay/restart時は同じlinksを再利用し、ticketは一回だけ発行できる。
|
| 119 |
+
|
| 120 |
+
External Replicatedではpublic maturity registrationを拒否し、authority-confirmed durable settlement
|
| 121 |
+
transactionだけがmaturity、2件のbond release/link、WorkTicketV2を作る。詳細は第6節を参照する。
|
| 122 |
+
|
| 123 |
+
## 2. Scheduler messages
|
| 124 |
+
|
| 125 |
+
現行実装は job/assignment の operational lifecycle table を持たない。実装されているのは immutable
|
| 126 |
+
signed-message validation である。
|
| 127 |
+
|
| 128 |
+
```text
|
| 129 |
+
JobRequestV1 --scheduler Ed25519--> SignedJobRequestV1
|
| 130 |
+
|
|
| 131 |
+
+-- exact network/model/runtime/shape/evidence/epoch/escrow policy
|
| 132 |
+
v
|
| 133 |
+
AssignmentV1 --scheduler Ed25519--> SignedAssignmentV1
|
| 134 |
+
|
|
| 135 |
+
+-- request binding, slot, credential, runtime instance, epoch containment
|
| 136 |
+
v
|
| 137 |
+
AssignmentAuthorizationRecord
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
- scheduler key は network-scoped registry、valid-from/through、revocationで検証する。Ed25519は
|
| 141 |
+
`verify_strict`を使い、weak/small-order key recordを拒否する。
|
| 142 |
+
- Self Localはslot 0、replicatedはslot 0/1だけ。
|
| 143 |
+
- replicated requestは`GemmTraced`を要求する。
|
| 144 |
+
- assignment validity intervalはrequest interval内でなければならない。
|
| 145 |
+
- receipt verifierはassignmentのepochをexact一致でbindし、current epochが範囲外なら拒否する。
|
| 146 |
+
|
| 147 |
+
`Requested/Scheduled/Running/Cancelled` 状態、scheduler queue、assignment cancellation、renewalは
|
| 148 |
+
このcrateの状態機械にはない。cancelled stop reasonもwire protocolにはない。現行Receipt CLIはlocal
|
| 149 |
+
scheduler keyを自己生成するため、production scheduler/network transportとの統合は別途必要である。
|
| 150 |
+
|
| 151 |
+
## 3. Future audit
|
| 152 |
+
|
| 153 |
+
`AuditRecord` の実装済み遷移:
|
| 154 |
+
|
| 155 |
+
```text
|
| 156 |
+
AwaitingBeacon
|
| 157 |
+
| apply_beacon(VerifiedFutureBeacon)
|
| 158 |
+
+--> NotSelected { mature_epoch }
|
| 159 |
+
| | StateStore::mature_unselected_audit(current >= mature_epoch)
|
| 160 |
+
| +--> Mature { ChallengeWindowElapsed } + mature source (atomic)
|
| 161 |
+
|
|
| 162 |
+
+--> Selected { challenge/beacon authority/deadline }
|
| 163 |
+
| complete_selected_audit(distinct StatelesslyVerifiedReceipt)
|
| 164 |
+
| before/equal deadline; typed projection match
|
| 165 |
+
+--> Mature { SelectedAuditPassed } + replay + source (atomic)
|
| 166 |
+
|
|
| 167 |
+
| typed projection mismatch before/equal deadline
|
| 168 |
+
+--> FailedMismatch + replay (atomic)
|
| 169 |
+
|
|
| 170 |
+
| expire_selected_audit(current_epoch > deadline)
|
| 171 |
+
+--> FailedTimeout
|
| 172 |
+
```
|
| 173 |
+
|
| 174 |
+
`SignedFutureBeaconV1`はversion/network/epoch/value body��authority key ID、Ed25519 signatureをstrict
|
| 175 |
+
canonical decodeする。network-scoped authority registryはkey validity/revocation/weak keyを検査し、
|
| 176 |
+
`verify_strict`成功後だけraw constructorを持たない`VerifiedFutureBeacon`を返す。beacon epochはverification
|
| 177 |
+
時点以下かつoriginal receiptのissued epochとdurable accepted epochの両方より後でなければならない。
|
| 178 |
+
beacon finalityとauthority registry governanceはcaller側serviceの責任である。
|
| 179 |
+
|
| 180 |
+
selection は `(network, receipt, beacon_epoch, beacon_value)` の256-bit digestと固定256-bit thresholdの
|
| 181 |
+
strict `<` 比較。v1 thresholdは一様digestの1/16、selected response windowは2 epoch、non-selected
|
| 182 |
+
challenge windowは5 epochで、完全なfixed policyをpolicy IDへhashする。`store_audit_selection`はoriginal
|
| 183 |
+
receiptのissued/accepted epoch、job/request binding、policy ID、beacon ID/value/authority key、canonical
|
| 184 |
+
signed beacon、challenge/deadlineまたはmature epochを保存する。
|
| 185 |
+
|
| 186 |
+
selected replayはnormal receipt slotへacceptせず、audit-specific `audit_replays` table/typestateへ一度だけ
|
| 187 |
+
予約する。replayはbeacon後にissuedされ、submit epochがreplay issued/current stateless verified epoch以上、
|
| 188 |
+
deadline以下でなければならない。originalとreplayはsame network/job/requestかつdistinct receipt、execution
|
| 189 |
+
nullifier、assignment、runtime instance、signer key、worker credential、owner commitmentである。
|
| 190 |
+
`VerifiedReplayVerdict`自身が両`MatchProjectionV1`を比較するため、external callerはraw match boolを作れない。
|
| 191 |
+
|
| 192 |
+
restart時の`restore_audit`はstored rowとoriginal `AcceptedReceipt`をexact照合し、canonical signed beaconを
|
| 193 |
+
current authority registryで再検証し、selection/challenge/deadlineを再計算する。selected pass/mismatch
|
| 194 |
+
terminalは`restore_audit`単独では`AuditReplayRequired`になり、
|
| 195 |
+
`restore_selected_audit_with_replay`がaudit rowとcanonical replay、全identity、issued/accepted epochを
|
| 196 |
+
restoreし、match bit、submission commitment、completed epochをstored terminalへexact比較する。
|
| 197 |
+
なお、prompt/opening配送、auditor assignment、model実行そのもの、auditor service identityはこのcrate外
|
| 198 |
+
である。
|
| 199 |
+
|
| 200 |
+
## 4. Canary
|
| 201 |
+
|
| 202 |
+
canary は通常の signed request/assignment/Receipt を使い、Receipt bodyに markerを追加しない。
|
| 203 |
+
期待projectionはsalt付きcommitmentだけを先に公開する。v1ではSelf Local/Self Replicatedだけを許し、
|
| 204 |
+
paid External Replicated requestをhidden scheduler probeに転用しない。
|
| 205 |
+
|
| 206 |
+
```text
|
| 207 |
+
SignedCanaryPrecommitV1
|
| 208 |
+
| scheduler registry + request + assignment + active bond verify
|
| 209 |
+
v
|
| 210 |
+
AwaitingReceipt (durable)
|
| 211 |
+
| accept_canary(StatelesslyVerifiedReceipt), now <= receipt_deadline
|
| 212 |
+
+--> ReceiptSubmitted + normal Receipt row (atomic)
|
| 213 |
+
| | valid opening, opening_epoch <= now <= opening_deadline
|
| 214 |
+
| +--> Passed, no slash (bond remains locked)
|
| 215 |
+
| +--> FailedMismatch + typed CanaryFailure slash (atomic)
|
| 216 |
+
| |
|
| 217 |
+
| +-- now > opening_deadline
|
| 218 |
+
| --> TimedOut { OpeningMissing, scheduler fault }, no slash
|
| 219 |
+
| (bond remains locked)
|
| 220 |
+
|
|
| 221 |
+
+-- now > receipt_deadline
|
| 222 |
+
--> TimedOut { ReceiptMissing, worker fault } + typed CanaryFailure slash
|
| 223 |
+
```
|
| 224 |
+
|
| 225 |
+
precommit bodyはnetwork、canary/job/request/assignment/worker、expected commitment、created/receipt/opening
|
| 226 |
+
windowをbindし、`canary-precommit/v1` IDをschedulerがstrict Ed25519署名する。registry keyはbody creation
|
| 227 |
+
からopening deadlineまで有効で、verification epoch時点にrevokedであってはならない。完全なorderingは
|
| 228 |
+
次である。
|
| 229 |
+
|
| 230 |
+
```text
|
| 231 |
+
assignment.issued <= created <= receipt_deadline <= assignment.expires
|
| 232 |
+
< opening_epoch <= opening_deadline
|
| 233 |
+
```
|
| 234 |
+
|
| 235 |
+
`register_verified_canary`はcanonical signed precommitをactive healthy assignment bondへbindし、同じ
|
| 236 |
+
assignmentの既存Receipt、別canary、External classを拒否する。`accept_canary`はnetwork、worker、job、
|
| 237 |
+
request、assignmentとdeadlineを検査し、normal replay/cardinality reservationと`ReceiptSubmitted`を
|
| 238 |
+
`BEGIN IMMEDIATE` transactionで確定する。
|
| 239 |
+
|
| 240 |
+
不正なsalt/projection openingはstateを変えずerrorとし、schedulerの壊れたopeningをworker slashへ
|
| 241 |
+
変換しない。valid commitment opening後のprojection mismatchだけがworker faultである。receipt欠落は
|
| 242 |
+
worker action欠落、opening欠落はscheduler action欠落とdurableに記録し、後者はworkerを不健康化/
|
| 243 |
+
slashしない。passとOpeningMissingはassignment bondをreleaseせず、pending canaryがある間はmaturityを
|
| 244 |
+
拒否する。terminal後のsource maturityはcanary completion epoch以上へ遅延し、そのmaturity transactionが
|
| 245 |
+
bondを`Mature` release/linkする。明示expiryは未使用またはaccepted-unpaired SelfReplicatedだけに許し、
|
| 246 |
+
pending canary/slash、paired、Self Local、その他used assignmentを拒否する。terminal proof、fault party、
|
| 247 |
+
deadline、projection digestをschema constraintとload時のsemantic validationで再検査する。
|
| 248 |
+
legacy in-memory `CanaryRecord` helperは残るが、production authority pathはこのsigned/durable APIである。
|
| 249 |
+
|
| 250 |
+
## 5. Bond and slashing
|
| 251 |
+
|
| 252 |
+
authoritative pathはschema-v4 SQLite accountである。network-scoped bond authority registryはEd25519 keyの
|
| 253 |
+
validity/revocationとfunding/appeal/decision capabilityを分離する。`VerifiedBondFunding`はnetwork、worker、
|
| 254 |
+
funding event、asset、exact amount/finality epochをbindし、canonical signed envelopeだけをcreditできる。
|
| 255 |
+
same event/envelope replayはidempotent、same IDのconflicting payloadはfatalである。
|
| 256 |
+
|
| 257 |
+
```text
|
| 258 |
+
authority-signed finalized funding
|
| 259 |
+
-> available
|
| 260 |
+
-> lock_verified_assignment(scheduler-signed request + assignment)
|
| 261 |
+
-> locked assignment
|
| 262 |
+
+-- verified maturity --> Released + mature-source link
|
| 263 |
+
+-- eligible signed expiry --> Released
|
| 264 |
+
+-- typed fault --> immutable claim + derived pending allocation + unhealthy
|
| 265 |
+
+-- no appeal after deadline --> finalized_slashed
|
| 266 |
+
+-- verified appeal
|
| 267 |
+
+-- signed Uphold --> finalized_slashed
|
| 268 |
+
+-- signed Reverse --> allocation recompute
|
| 269 |
+
+-- decision deadline elapsed --> default Uphold
|
| 270 |
+
```
|
| 271 |
+
|
| 272 |
+
assignment lockはexact scheduler-signed request/assignmentをcurrent registryで検証し、uniqueかつjob class
|
| 273 |
+
minimum以上、account healthy、epoch内でなければならない。bonded assignmentのReceiptはgeneric acceptを
|
| 274 |
+
拒否し、active lockを同一transactionで検査する。release reasonは`Mature`、`Expired`、
|
| 275 |
+
`CancelledBeforeExecution`、`SlashResolved`である。public durable pathで自動生成するのはmaturity、未使用または
|
| 276 |
+
accepted-unpaired SelfReplicatedのexpiry、全slash claim解決後のtyped fault/refund terminal releaseである。
|
| 277 |
+
pending canary/slash、paired receipt、Self Local、その他used assignmentはexpiry releaseを拒否する。
|
| 278 |
+
|
| 279 |
+
account snapshot/transitionは次に加え、funding event合計、active assignment remaining、slash status別合計、
|
| 280 |
+
healthをDB ledgerから再計算する。
|
| 281 |
+
|
| 282 |
+
```text
|
| 283 |
+
available + locked + pending_slashed + finalized_slashed == total_funded
|
| 284 |
+
sum(assignment.remaining_amount) == locked
|
| 285 |
+
sum(verified funding event.amount) == total_funded
|
| 286 |
+
sum(pending/final slash.allocated_amount) == pending_slashed/finalized_slashed
|
| 287 |
+
```
|
| 288 |
+
|
| 289 |
+
default policy:
|
| 290 |
+
|
| 291 |
+
| SlashReason tag | Reason | Assignment bond slash | Additional penalty |
|
| 292 |
+
|---:|---|---:|---:|
|
| 293 |
+
| 1 | `InvalidManifest` | 100% | 0 |
|
| 294 |
+
| 2 | `AuditMismatch` | 100% | 0 |
|
| 295 |
+
| 3 | `Equivocation` | 100% | 0 |
|
| 296 |
+
| 4 | `DuplicateExecution` | 50% | 0 |
|
| 297 |
+
| 5 | `CanaryFailure` | 100% | 0 |
|
| 298 |
+
| 6 | `AuditTimeout` | policy値、default 25% | 0 |
|
| 299 |
+
|
| 300 |
+
割合はinitial assignment amountにceil適用したimmutable claim targetである。allocationは全claimから
|
| 301 |
+
order-independentに再計算する。finalized(uphold/default uphold)のmax-envelopeを優先し、pendingはその
|
| 302 |
+
extensionだけを受けるため、overlapを加算しない。late equal/weaker claimは既存envelopeに覆われれば0、
|
| 303 |
+
stronger claimはdeltaだけをallocateする。reverseも同じ再計算を行う。partial target後のremainderはactive
|
| 304 |
+
lockとして残り、pendingまたはuphold/default-final claimを持つassignmentはmaturity/Work Ticketを生成しない。
|
| 305 |
+
reverseはそのclaim allocationを0へ再配分するが、既存finalized envelopeをpendingへ戻さない。全claim解決後、
|
| 306 |
+
audit mismatch/timeout terminalはreverse時も`SlashResolved` releaseし、canary fault terminalはmatching claimが
|
| 307 |
+
uphold/default-finalの場合だけreleaseする。reversed canary claim単独ではreleaseしない。External refundも
|
| 308 |
+
release terminal、eligible unpaired SelfReplicatedはexpiry、別のstronger claimは追加deltaへ進める。
|
| 309 |
+
durable offense IDはreason、assignment、worker、policy、typed primary
|
| 310 |
+
proofへbindし、attachment追加は同じoffenseへidempotent mergeする。audit mismatch/timeoutとcanary
|
| 311 |
+
mismatch/receipt timeoutはstate transition自身がproofを作るため、callerはreason/raw hashからこれらの
|
| 312 |
+
slashを捏造できない。invalid manifest、equivocation、duplicate executionのproduction proof wiringは未完了。
|
| 313 |
+
|
| 314 |
+
`fault_event_epoch`はtyped proofが示す発生時刻、`applied_epoch`はdurable claim受理時刻として別に保存する。
|
| 315 |
+
late equal/weaker/stronger claimはpending-full state 2にも保存できるが、fully finalized/exhausted state 3は
|
| 316 |
+
新claimを拒否する。terminal epoch/proofはoffense ID順の全claim、各effective epochのmax、typed terminal fact
|
| 317 |
+
setからcanonicalに導出する。audit/canary terminalとExternal prepared/terminalは新evidence cutoffで、
|
| 318 |
+
Externalは`SettlementPrepared`または`RefundPrepared`以後のnon-replay slashを拒否する。
|
| 319 |
+
|
| 320 |
+
standard policyのappeal deadlineはdurable slash `applied_epoch`から100 epochである。signed
|
| 321 |
+
`submitted_epoch`とappeal verification epochの両方をinclusive window内に要求し、後者をdurable
|
| 322 |
+
`accepted_epoch`として保存する。decision deadlineはそのaccepted epochから100である。
|
| 323 |
+
`VerifiedSlashAppeal`はnetwork/worker/offense/assignment/appeal ID/submitted epochをbindする。
|
| 324 |
+
`VerifiedSlashDecision`はappeal/offense、`Uphold|Reverse`、decided epochをbindし、signed decided epochと
|
| 325 |
+
decision verification/acceptance epochの両方をdeadline以下でだけ受理する。`current_epoch > decision_deadline`なら
|
| 326 |
+
`finalize_stale_slash_appeal`がdeterministic default-upholdをcommitする。appealなしは
|
| 327 |
+
`current_epoch > appeal_deadline`でだけfinalizeできる。balance、slash/appeal/assignment terminal、health
|
| 328 |
+
eventは各transactionで全claim allocationから再導出する。offenseごとにappealは1件でfirst stored
|
| 329 |
+
signed/default decisionが勝ち、exact canonical replayだけは期限後もno-opである。
|
| 330 |
+
|
| 331 |
+
legacy `BondLedger`はlocal arithmetic/test helperとして残り、raw initial balance/deposit/reasonを受ける。
|
| 332 |
+
productionではこれをauthority-signed durable pathの代わりに使わない。authority署名も実collateralを
|
| 333 |
+
crateが独立観測した証明ではなく、production registry/funding serviceは外部trust boundaryである。
|
| 334 |
+
|
| 335 |
+
## 6. External escrow
|
| 336 |
+
|
| 337 |
+
durable External Replicated pathは3種類のnetwork-scoped authority evidenceを要求する。
|
| 338 |
+
|
| 339 |
+
- exact finalized `VerifiedFundingAttestation`
|
| 340 |
+
- funding attestationとfunded bonusへbindした`VerifiedDemandWeightGrant`
|
| 341 |
+
- stable payment commandとexact distributionへbindした`VerifiedTerminalConfirmation`
|
| 342 |
+
|
| 343 |
+
authority keyはfunding/demand-weight/terminal capability、validity/revocation、strict Ed25519を検査する。
|
| 344 |
+
durable transitionは次である。
|
| 345 |
+
|
| 346 |
+
```text
|
| 347 |
+
Verified exact funding + Verified demand grant
|
| 348 |
+
-> Funded
|
| 349 |
+
-> Assigned(scheduler-signed External request)
|
| 350 |
+
-> EvidenceReady(typed k=2 pair)
|
| 351 |
+
-> SettlementPrepared(stable payment command)
|
| 352 |
+
-> Settled + maturity + 2 bond releases/links + WorkTicketV2 (atomic)
|
| 353 |
+
|
| 354 |
+
Funded | Assigned | EvidenceReady (state 1..3), now > terms expiry
|
| 355 |
+
-> RefundPrepared(stable payment command)
|
| 356 |
+
-> Refunded + eligible assignment bond releases (atomic; no maturity/ticket)
|
| 357 |
+
```
|
| 358 |
+
|
| 359 |
+
funding attestation amountとterminal distribution totalは次にexact一致する。
|
| 360 |
+
|
| 361 |
+
```text
|
| 362 |
+
required_reward + demand_bonus_amount + protocol_fee + failure_reserve
|
| 363 |
+
```
|
| 364 |
+
|
| 365 |
+
bonus amountはbase rewardに対するpayout cap、bonus bpsはweight cap(default +5,000)以内で、grantの
|
| 366 |
+
asset/funding/amount/bps/intervalをtermsへexact bindする。assignmentはnetwork-scoped scheduler signature、
|
| 367 |
+
ExternalReplicated class、escrow reference、prompt commitment、constraints、epoch containmentを検査する。
|
| 368 |
+
|
| 369 |
+
EvidenceReadyにはtyped `MatchedReplicaPair`が必要で、network、request commitment、class、CU、expiryを
|
| 370 |
+
照合する。settlement commandはworkerへbase+bonus、protocol fee、failure reserveのrequester refundを
|
| 371 |
+
exact配分する。`SettlementPrepared`をcommitする`BEGIN IMMEDIATE` transactionは両assignmentがactive state 0で
|
| 372 |
+
pending/upheld/default-final slashなしとpreflightする。`SettlementPrepared`と`RefundPrepared`はいずれも
|
| 373 |
+
以後のnon-replay slashをcut offする。authority
|
| 374 |
+
confirmation後、terminal、maturity basis/weight grant、両worker assignmentの
|
| 375 |
+
Mature release/link、WorkTicketV2 insert、source consumptionを1transactionでcommitする。どちらかのbondが
|
| 376 |
+
missing/nonactiveならsettlement transactionはrollbackし、escrowだけをworker bondの代用にしない。exact
|
| 377 |
+
confirmation replayはstored ticketを返す。refund commandはstate 1..3のいずれからもterms expiry後に作れ、
|
| 378 |
+
required total全額をrequesterへ返す。pair/EvidenceReadyの存在はrefundを妨げない。confirmed refundはterminalと
|
| 379 |
+
関連するeligible active assignment bondの残額releaseを同じtransactionでcommitし、maturity/ticketは生じない。
|
| 380 |
+
pending slash claimがあるassignmentはreleaseせず、claimがuphold/reverse/defaultのいずれかへ解決した後にだけ
|
| 381 |
+
残額をresolved-terminal releaseできる。finalized slash allocationはrelease対象に戻さない。
|
| 382 |
+
|
| 383 |
+
legacy in-memory `ExternalEscrow` helperは残るが、production authority pathはこのdurable APIである。crateは
|
| 384 |
+
実payment railを操作せず、terminal authorityがrail finalityを正しく署名することを信頼する。rail movement
|
| 385 |
+
とSQLite commitはdistributed atomicではなく、dispute/rail recovery/governance serviceもcrate外である。
|
| 386 |
+
`SettlementPrepared`/`RefundPrepared`後にauthority confirmationが永久に来ない場合のtimeout/superseding
|
| 387 |
+
terminalも未実装であり、prepared stateのoperational recoveryは外部service boundaryである。
|
| 388 |
+
|
| 389 |
+
## 7. Work Ticket and weight
|
| 390 |
+
|
| 391 |
+
typed maturity source:
|
| 392 |
+
|
| 393 |
+
- Self Local: primary durable pathは`mature_unselected_audit`または`complete_selected_audit`がaudit
|
| 394 |
+
terminalと同じtransactionでsourceを���録する。bondedならassignmentをrelease/linkする。typed
|
| 395 |
+
constructorを使う場合もstored durable auditのexact state/basis/epochと再照合する
|
| 396 |
+
- Self Replicated: `MatureEvidence::from_self_replicated_pair(MatchedReplicaPair)`。
|
| 397 |
+
maturity epochはmatcherが記録した`matched_epoch`。2 assignment bondを同じtransactionでrelease/linkする
|
| 398 |
+
- External Replicated: authority-confirmed settlement transactionだけ。confirmation ID/epochとauthority-
|
| 399 |
+
signed weight grantをbindし、2 assignment bondをrelease/linkして即時ticketをcommitする
|
| 400 |
+
|
| 401 |
+
`MatureEvidence`のfieldと低水準constructorはpublicではないため、外部callerはsource/class/CU/
|
| 402 |
+
maturity reason/demand bonus/basis/grant/epochを自己申告できない。`StateStore::register_mature_evidence`は
|
| 403 |
+
opaque proofをdurable receipt/pair/audit stateと再照合し、Externalはこのgeneric APIから拒否する。
|
| 404 |
+
|
| 405 |
+
`WeightPolicy::v1()`:
|
| 406 |
+
|
| 407 |
+
| Evidence basis | `weight_bps` | `weighted_CU` |
|
| 408 |
+
|---|---:|---|
|
| 409 |
+
| Self Local, challenge window elapsed | 2,500 | `ceil(CU*2500/10000)` |
|
| 410 |
+
| Self Local, selected audit passed | 5,000 | `ceil(CU*5000/10000)` |
|
| 411 |
+
| Self Replicated pair | 10,000 | `CU` |
|
| 412 |
+
| External Replicated pair | 10,000 + funded demand bps(最大5,000) | 同じceil式 |
|
| 413 |
+
|
| 414 |
+
`WorkTicketV2`はversion、network、source、`maturity_basis_id`、optional `weight_grant_id`、job class、
|
| 415 |
+
policy version、CU、weight、issued epochを`work-ticket/v2` IDへhashする。Self classのgrantは必ずNone、
|
| 416 |
+
Externalはzero bonusでもauthority grant IDが必須である。
|
| 417 |
+
|
| 418 |
+
`StateStore::issue_ticket`は`issued_epoch >= stored mature_epoch`、required replica数と
|
| 419 |
+
`mature_source_assignments` release link数を検査し、ticket insertと`consumed_ticket_id`更新を同じ
|
| 420 |
+
transactionで行う。通常pathの二回目は`SourceAlreadyConsumed`になる。Externalだけはterminal confirmation
|
| 421 |
+
transaction内で同じissuerを呼び、exact terminal replay時はstored ticketを返す。
|
| 422 |
+
|
| 423 |
+
このweight変換はproduction network admissionやCUDA approvalそのものではない。bond gateはworker
|
| 424 |
+
collateral lifecycleを閉じるが、runtime classがproduction approvedか、authority registryがnetwork
|
| 425 |
+
governanceに採用されたかは別のadmission/service decisionである。
|
| 426 |
+
|
| 427 |
+
## 8. Durable SQLite invariants
|
| 428 |
+
|
| 429 |
+
`StateStore` は application ID `PALW`、schema version 4、`foreign_keys=ON`、`WAL`、
|
| 430 |
+
`synchronous=FULL`、30秒busy timeoutを要求し、mutationは`BEGIN IMMEDIATE` transactionで行う。
|
| 431 |
+
SQLite integerがsignedであるため、consensus `u64` は8-byte big-endian BLOBとして保存する。旧schema
|
| 432 |
+
の暗黙migrationはなく、既存objectを持つapplication/user version 0 DBもclaimしない。
|
| 433 |
+
|
| 434 |
+
open時はexact table set、column order、foreign-key count、required indexに加え、全non-internal
|
| 435 |
+
`sqlite_master (type,name,tbl_name,sql)`をcanonical encodeしたSHA3-256をcompiled v4 goldenと照合する。
|
| 436 |
+
同じtable/column名を保ったconstraint/index/DDL mutationも拒否する。portable snapshot/markerの前には
|
| 437 |
+
`wal_checkpoint(TRUNCATE)`がbusy 0かつ全frame checkpoint済みであることを要求する。
|
| 438 |
+
|
| 439 |
+
### Receipt and job
|
| 440 |
+
|
| 441 |
+
- `receipt_id` はDB全体でunique
|
| 442 |
+
- `execution_nullifier` はDB全体でunique
|
| 443 |
+
- `(network_id, job_nullifier, replica_slot)` はunique
|
| 444 |
+
- `(network_id, job_nullifier)` ごとのjob classは不変
|
| 445 |
+
- Self Localはslot 0のみ、replicatedはslot 0/1のみ
|
| 446 |
+
- canonical signed envelopeとauthorized runtime instanceを保存し、restart restore時にexact一致
|
| 447 |
+
- `accepted_at_epoch`はfirst stateful acceptanceのstateless verification epochを保存し、restart時の
|
| 448 |
+
`verified_at_epoch`で上書きしない
|
| 449 |
+
- restoreは`issued_epoch <= accepted_at_epoch <= expires_epoch`かつ
|
| 450 |
+
`accepted_at_epoch <= current verified_at_epoch`を要求し、epoch rollbackを拒否
|
| 451 |
+
- assignment bond rowが存在するReceiptはgeneric acceptを拒否し、active exact lockとのatomic acceptanceを要求
|
| 452 |
+
|
| 453 |
+
### Pair
|
| 454 |
+
|
| 455 |
+
- pair candidateはprojection digest/pair IDを再計算
|
| 456 |
+
- member 2件が両方accepted、同network/job/class、未失効でcandidate metadataと一致し、相互の
|
| 457 |
+
execution nullifierは異なる
|
| 458 |
+
- `(network_id, job_nullifier)` は最大1 pair
|
| 459 |
+
- receiptは最大1 pairのmember
|
| 460 |
+
- pair rowと2 member rowは1transaction。partial pairはcommitされない
|
| 461 |
+
- exact canonical replayはidempotent、同ID異内容はconflict
|
| 462 |
+
- `matched_epoch`はmemberのissued/accepted epoch以上かつexpiry以下で、durable canonical pairにcommit
|
| 463 |
+
|
| 464 |
+
### Future audit and replay
|
| 465 |
+
|
| 466 |
+
- original accepted receiptはSelf Localで、stored network/job/request/issued/accepted epochとexact一致
|
| 467 |
+
- applied beaconはoriginal issued/accepted epochより後、verification時点以下で、canonical signed envelope、
|
| 468 |
+
beacon ID/value/authority key IDを保存
|
| 469 |
+
- restore時はcurrent authority registryのvalidity/revocation/strict Ed25519 verificationを再適用し、
|
| 470 |
+
selection、challenge ID、deadlineを再計算
|
| 471 |
+
- selected challenge/original receiptごとにaudit replayは最大1件。replay receipt/execution/assignmentは
|
| 472 |
+
`audit_replays` table内でunique(normal `receipts` tableとのglobal uniquenessではない)
|
| 473 |
+
- replay issued epochはbeaconより後、accepted epochはissued/current verification以上かつdeadline以下
|
| 474 |
+
- selected passはreplay insert、audit terminal/maturity、Self Local mature sourceを1transaction
|
| 475 |
+
- bonded selected passは同じtransactionでassignment release/link。selected mismatchはreplay insert、failed
|
| 476 |
+
terminal、typed slashを1transaction。timeoutと競合して片方だけcommitし、bonded timeoutもtyped slash
|
| 477 |
+
- non-selected maturityはaudit terminal、Self Local mature source、bondedならrelease/linkを1transaction
|
| 478 |
+
|
| 479 |
+
### Mature source and ticket
|
| 480 |
+
|
| 481 |
+
- `source_id` はDB全体でunique
|
| 482 |
+
- public registrationは`MatureEvidence`のみ。raw source/class/reason/epoch登録APIはない
|
| 483 |
+
- receipt sourceはaccepted Self Localとexact network/class/CUが一致し、typed maturity reasonを持つ
|
| 484 |
+
- pair sourceはstored replicated pairとexact network/class/CUが一致する
|
| 485 |
+
- `maturity_basis_id`は全classに必須、`weight_grant_id`はExternalだけに必須
|
| 486 |
+
- demand bonusはExternal Replicatedだけ、maturity epochはtyped evidence/terminal confirmationから保存
|
| 487 |
+
- sourceとrequired assignment release IDを`mature_source_assignments`でlink。countはrequired replica数と一致
|
| 488 |
+
- `source_id` はwork ticketでもunique
|
| 489 |
+
- ticket issued epochはstored maturity epoch以上
|
| 490 |
+
- ticket insertとsource consumed更新は1transaction
|
| 491 |
+
|
| 492 |
+
### Bond, canary, slash, and external terminal
|
| 493 |
+
|
| 494 |
+
- funding event、assignment、release、offense、appeal、canary、external authority evidence/terminalのbusiness
|
| 495 |
+
IDはunique。canonical exact replayだけidempotent
|
| 496 |
+
- bond accountはavailable/locked/pending/finalized合計、funding ledger、active assignment、slash status、healthをreconcile
|
| 497 |
+
- slash claimはfault/applied epoch、immutable target、derived allocationを分離し、offense-sorted complete setから
|
| 498 |
+
assignment terminal epoch/proofを再導出
|
| 499 |
+
- assignment terminal rowはremaining 0、terminal epoch/proofを必須とし、network/worker foreign keyでbind
|
| 500 |
+
- canary precommitはsigned envelopeのbody/key ID、assignment/worker/request/windowとstored rowを再照合
|
| 501 |
+
- canary terminalはpass/mismatch/receipt timeout/opening timeoutごとのrequired/forbidden fieldとfault partyをconstraint
|
| 502 |
+
- appealは`submitted <= accepted <= appeal_deadline`、decisionは`decided <= accepted <= decision_deadline`。
|
| 503 |
+
pendingだけdecisionを受け、期限後default upholdは別terminal state
|
| 504 |
+
- external keyは`(network_id, escrow_reference)`。funding/grant/command/confirmation IDの再利用を拒否
|
| 505 |
+
- terminalは`Settled`または`Refunded`のどちらか一方で、command/confirmation distribution totalはfunded totalとexact一致
|
| 506 |
+
- settlementはterminal/maturity/bond links/ticketを1transaction、refundはterminalとeligible bond releaseを
|
| 507 |
+
1transactionでcommitする。pending claim分のbondは解決までlocked、conflicting replayはfatal
|
| 508 |
+
|
| 509 |
+
future audit/replayのrow、signed beacon、selection/challenge、replay terminal outcomeを再検証するrestore
|
| 510 |
+
APIと、bundleからrollbackなしでfresh later-epoch `AcceptedReceipt`を作るAPIは実装されている。bond/canary/
|
| 511 |
+
external rowはverified typestateのcanonical signed bytesを保存し、load時にbody-to-row binding/ledger invariantsを
|
| 512 |
+
再検査するが、production registry governanceやexternal rail finalityをDB自身が再取得するわけではない。
|
| 513 |
+
|
| 514 |
+
## 9. Metal GraphFallback and CUDA R32 in-progress non-issuance
|
| 515 |
+
|
| 516 |
+
現行 Qwen3.6-35B-A3B Metal runtime classは `TraceCapability::GraphFallback`。sketch modeでも各scheduled GEMM
|
| 517 |
+
に1 synthetic graph tileを作るだけで、CUDA kernel/tile evidenceを名乗らない。
|
| 518 |
+
|
| 519 |
+
`TraceCapability::KernelSketch` とwire tagは将来互換のため存在する。CUDAはadditive exact 184-byte V2
|
| 520 |
+
recordとRust strict full-stream/dispatch/runtime binderを持つが、raw declared accumulator originはproofではない。
|
| 521 |
+
authority署名、registry/runtime/job、operation schedule commitment、scheduled GEMM/attention coverage、
|
| 522 |
+
full transcriptを検証した場合だけ
|
| 523 |
+
`BoundCudaTranscriptV1 -> AuthorityBoundCudaTranscriptV2 -> AuthorityBoundCudaReceiptEvidenceV2`
|
| 524 |
+
と進む、public raw constructorのないtypestateを実装した。V3 authority typestateは別versionの
|
| 525 |
+
Receipt V2 builder/verifier、暗号化Bundle V2、SQLite V2 state machineへ接続されている。V1 builder/verifierは
|
| 526 |
+
引き続きCUDA `KernelSketch`をfail closedで拒否する。
|
| 527 |
+
|
| 528 |
+
Windows WSL2 Ubuntu 24.04のRTX 4060 Ti(sm_89)、CUDA Toolkit 13.3.1 / nvcc 13.3.73では、固定Qwenの37/37
|
| 529 |
+
layer offloadとbatch 1 graph observer 6/6同一diagnostic streamを確認した。standaloneのtrue FP32
|
| 530 |
+
producer-accumulator採取primitiveも最終grouped device suite 8/8とproducer 20/20同一diagnostic
|
| 531 |
+
fingerprintを通過した。vendored llama.cpp Q4_K/Q6_K MMVQ producerはV3 full-K pre-epilogue hookへ
|
| 532 |
+
接続済みで、same-backend Qwen 1-token diagnostic E2Eは253 MMVQ recordを取得する。
|
| 533 |
+
|
| 534 |
+
FlashAttention-onlyのV2で表せなかったFA-off attentionに対し、V3 schema/binderはcanonical
|
| 535 |
+
3-sublaunch groupingと実entry point直後collector/typed associationを実装する。253 MMVQにQK/softmax/PV
|
| 536 |
+
各36を加えた361-launch実機E2E、5 work-class negative、exact release manifest、V2 stateless verification、
|
| 537 |
+
encrypted bundle、atomic persistence/restart/replay/rollback gateは完了した。live callbackへの
|
| 538 |
+
authority-derived canonical physical-layout ID接続はproduction境界として未統合である。
|
| 539 |
+
`PALW_CUDA_TRACE_PRODUCTION_CAPABLE=0`、`PALW_CUDA_PRODUCER_VENDOR_RUNTIME_INTEGRATED=0`、
|
| 540 |
+
`PALW_CUDA_PRODUCER_RECEIPT_MAPPING_AVAILABLE=0`、`PALW_CUDA_PRODUCER_PRODUCTION_CAPABLE=0`で、
|
| 541 |
+
production CMake gateは意図的にfatalのままである。
|
| 542 |
+
|
| 543 |
+
したがってR32は`In progress`であり、完了するまでproduction CUDA Receiptを発行せず、CUDA
|
| 544 |
+
`KernelSketch`を根拠に
|
| 545 |
+
production Work Ticketを発行しない。Metal GraphFallbackのlocal/development receiptと、production
|
| 546 |
+
CUDA approvalは別gateである。
|
| 547 |
+
|
| 548 |
+
さらにproduction scheduler/network、governance-backed signer/beacon/bond/external registryとauthority
|
| 549 |
+
service、finalized beacon delivery、independent auditor re-execution、payment railは未統合である。invalid-
|
| 550 |
+
manifest/equivocation/duplicate-executionのdurable typed slash proof wiringも残る。個別typestateやSQLite
|
| 551 |
+
transitionの実装をproduction lifecycle service全体の完成と読み替えない。
|
models/.gitkeep
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
patches/llama.cpp-palw-full.patch
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
patches/llama.cpp-palw-observer.patch
ADDED
|
@@ -0,0 +1,1792 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
diff --git a/ggml/include/ggml-metal.h b/ggml/include/ggml-metal.h
|
| 2 |
+
index 433838f0..213e148d 100644
|
| 3 |
+
--- a/ggml/include/ggml-metal.h
|
| 4 |
+
+++ b/ggml/include/ggml-metal.h
|
| 5 |
+
@@ -56,6 +56,21 @@ GGML_BACKEND_API void ggml_backend_metal_capture_next_compute(ggml_backend_t bac
|
| 6 |
+
|
| 7 |
+
GGML_BACKEND_API ggml_backend_reg_t ggml_backend_metal_reg(void);
|
| 8 |
+
|
| 9 |
+
+// PALW kernel-level dispatch hook.
|
| 10 |
+
+//
|
| 11 |
+
+// When set (process-global), the callback is invoked for every Metal compute
|
| 12 |
+
+// dispatch with the bound pipeline (kernel) name and the launch geometry
|
| 13 |
+
+// (threadgroup grid tg0..2 and threads-per-threadgroup tptg0..2). This lets the
|
| 14 |
+
+// PALW observer produce a kernel-level execution trace bound to the actual GPU
|
| 15 |
+
+// kernel dispatches rather than to graph-node outputs. Pass NULL to disable.
|
| 16 |
+
+typedef void (*ggml_metal_palw_dispatch_cb)(
|
| 17 |
+
+ void * user_data,
|
| 18 |
+
+ const char * pipeline,
|
| 19 |
+
+ int tg0, int tg1, int tg2,
|
| 20 |
+
+ int tptg0, int tptg1, int tptg2);
|
| 21 |
+
+
|
| 22 |
+
+GGML_BACKEND_API void ggml_metal_palw_set_dispatch_hook(ggml_metal_palw_dispatch_cb cb, void * user_data);
|
| 23 |
+
+
|
| 24 |
+
#ifdef __cplusplus
|
| 25 |
+
}
|
| 26 |
+
#endif
|
| 27 |
+
diff --git a/ggml/src/ggml-metal/ggml-metal-device.m b/ggml/src/ggml-metal/ggml-metal-device.m
|
| 28 |
+
index 80e47f2c..3e36c08d 100644
|
| 29 |
+
--- a/ggml/src/ggml-metal/ggml-metal-device.m
|
| 30 |
+
+++ b/ggml/src/ggml-metal/ggml-metal-device.m
|
| 31 |
+
@@ -1,5 +1,6 @@
|
| 32 |
+
#import "ggml-metal-device.h"
|
| 33 |
+
|
| 34 |
+
+#import "ggml-metal.h"
|
| 35 |
+
#import "ggml-impl.h"
|
| 36 |
+
#import "ggml-backend-impl.h"
|
| 37 |
+
|
| 38 |
+
@@ -72,6 +73,9 @@ void ggml_metal_cv_set_bool(ggml_metal_cv_t cv, bool value, int32_t idx) {
|
| 39 |
+
|
| 40 |
+
struct ggml_metal_pipeline {
|
| 41 |
+
id<MTLComputePipelineState> obj;
|
| 42 |
+
+
|
| 43 |
+
+ // PALW: stable kernel (pipeline) name, captured for kernel-level tracing.
|
| 44 |
+
+ char name[128];
|
| 45 |
+
};
|
| 46 |
+
|
| 47 |
+
ggml_metal_pipeline_t ggml_metal_pipeline_init(void) {
|
| 48 |
+
@@ -79,6 +83,7 @@ ggml_metal_pipeline_t ggml_metal_pipeline_init(void) {
|
| 49 |
+
|
| 50 |
+
*res = (struct ggml_metal_pipeline) {
|
| 51 |
+
/*.obj =*/ nil,
|
| 52 |
+
+ /*.name =*/ {0},
|
| 53 |
+
};
|
| 54 |
+
|
| 55 |
+
return res;
|
| 56 |
+
@@ -443,6 +448,8 @@ struct ggml_metal_pipeline_with_params ggml_metal_library_compile_pipeline(ggml_
|
| 57 |
+
|
| 58 |
+
res.pipeline = ggml_metal_pipeline_init();
|
| 59 |
+
res.pipeline->obj = obj;
|
| 60 |
+
+ // PALW: record the stable kernel name for kernel-level dispatch tracing.
|
| 61 |
+
+ snprintf(res.pipeline->name, sizeof(res.pipeline->name), "%s", name);
|
| 62 |
+
|
| 63 |
+
ggml_metal_pipelines_add(lib->pipelines, name, res.pipeline);
|
| 64 |
+
}
|
| 65 |
+
@@ -458,8 +465,23 @@ struct ggml_metal_pipeline_with_params ggml_metal_library_compile_pipeline(ggml_
|
| 66 |
+
|
| 67 |
+
struct ggml_metal_encoder {
|
| 68 |
+
id<MTLComputeCommandEncoder> obj;
|
| 69 |
+
+
|
| 70 |
+
+ // PALW: name of the pipeline currently bound, for kernel-level dispatch tracing.
|
| 71 |
+
+ const char * cur_pipeline;
|
| 72 |
+
};
|
| 73 |
+
|
| 74 |
+
+// PALW: process-global kernel-dispatch hook. When set, it is invoked for every
|
| 75 |
+
+// Metal compute dispatch with the bound pipeline (kernel) name and the launch
|
| 76 |
+
+// geometry (threadgroup grid + threads-per-threadgroup). Used by the PALW
|
| 77 |
+
+// observer to produce a kernel-level (not graph-fallback) execution trace.
|
| 78 |
+
+static ggml_metal_palw_dispatch_cb g_palw_dispatch_cb = NULL;
|
| 79 |
+
+static void * g_palw_dispatch_ud = NULL;
|
| 80 |
+
+
|
| 81 |
+
+void ggml_metal_palw_set_dispatch_hook(ggml_metal_palw_dispatch_cb cb, void * user_data) {
|
| 82 |
+
+ g_palw_dispatch_cb = cb;
|
| 83 |
+
+ g_palw_dispatch_ud = user_data;
|
| 84 |
+
+}
|
| 85 |
+
+
|
| 86 |
+
ggml_metal_encoder_t ggml_metal_encoder_init(ggml_metal_cmd_buf_t cmd_buf_raw, bool concurrent) {
|
| 87 |
+
ggml_metal_encoder_t res = calloc(1, sizeof(struct ggml_metal_encoder));
|
| 88 |
+
|
| 89 |
+
@@ -491,6 +513,8 @@ void ggml_metal_encoder_debug_group_pop (ggml_metal_encoder_t encoder) {
|
| 90 |
+
|
| 91 |
+
void ggml_metal_encoder_set_pipeline(ggml_metal_encoder_t encoder, struct ggml_metal_pipeline_with_params pipeline) {
|
| 92 |
+
[encoder->obj setComputePipelineState:pipeline.pipeline->obj];
|
| 93 |
+
+ // PALW: remember the bound kernel name so dispatches can be attributed to it.
|
| 94 |
+
+ encoder->cur_pipeline = pipeline.pipeline->name;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
void ggml_metal_encoder_set_bytes(ggml_metal_encoder_t encoder, void * data, size_t size, int idx) {
|
| 98 |
+
@@ -506,6 +530,11 @@ void ggml_metal_encoder_set_threadgroup_memory_size(ggml_metal_encoder_t encoder
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
void ggml_metal_encoder_dispatch_threadgroups(ggml_metal_encoder_t encoder, int tg0, int tg1, int tg2, int tptg0, int tptg1, int tptg2) {
|
| 102 |
+
+ // PALW: report the kernel-level dispatch (bound pipeline + launch geometry).
|
| 103 |
+
+ if (g_palw_dispatch_cb) {
|
| 104 |
+
+ g_palw_dispatch_cb(g_palw_dispatch_ud, encoder->cur_pipeline ? encoder->cur_pipeline : "",
|
| 105 |
+
+ tg0, tg1, tg2, tptg0, tptg1, tptg2);
|
| 106 |
+
+ }
|
| 107 |
+
[encoder->obj dispatchThreadgroups:MTLSizeMake(tg0, tg1, tg2) threadsPerThreadgroup:MTLSizeMake(tptg0, tptg1, tptg2)];
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
diff --git a/src/models/qwen35moe.cpp b/src/models/qwen35moe.cpp
|
| 111 |
+
index 7b0876cb..4d955261 100644
|
| 112 |
+
--- a/src/models/qwen35moe.cpp
|
| 113 |
+
+++ b/src/models/qwen35moe.cpp
|
| 114 |
+
@@ -6,7 +6,18 @@ void llama_model_qwen35moe::load_arch_hparams(llama_model_loader & ml) {
|
| 115 |
+
ml.get_key(LLM_KV_EXPERT_SHARED_FEED_FORWARD_LENGTH, hparams.n_ff_shexp, false);
|
| 116 |
+
ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps);
|
| 117 |
+
|
| 118 |
+
- ml.get_key_or_arr(LLM_KV_ROPE_DIMENSION_SECTIONS, hparams.rope_sections, 4, true);
|
| 119 |
+
+ // PALW: newer HF->GGUF conversions write 3 mrope sections ([t, h, w]) and
|
| 120 |
+
+ // omit the trailing zero; older conversions write 4. Accept both forms and
|
| 121 |
+
+ // zero-pad so the pinned runtime loads current upstream GGUF artifacts.
|
| 122 |
+
+ {
|
| 123 |
+
+ std::vector<int32_t> sections;
|
| 124 |
+
+ ml.get_arr(LLM_KV_ROPE_DIMENSION_SECTIONS, sections, true);
|
| 125 |
+
+ if (sections.size() != 3 && sections.size() != 4) {
|
| 126 |
+
+ throw std::runtime_error("rope.dimension_sections must have 3 or 4 entries");
|
| 127 |
+
+ }
|
| 128 |
+
+ std::fill(hparams.rope_sections.begin(), hparams.rope_sections.end(), 0);
|
| 129 |
+
+ std::copy(sections.begin(), sections.end(), hparams.rope_sections.begin());
|
| 130 |
+
+ }
|
| 131 |
+
|
| 132 |
+
// Load linear attention (gated delta net) parameters
|
| 133 |
+
ml.get_key(LLM_KV_SSM_CONV_KERNEL, hparams.ssm_d_conv);
|
| 134 |
+
@@ -73,8 +84,13 @@ void llama_model_qwen35moe::load_arch_tensors(llama_model_loader & ml) {
|
| 135 |
+
layer.attn_post_norm = create_tensor(tn(LLM_TENSOR_ATTN_POST_NORM, "weight", il), { n_embd }, flags);
|
| 136 |
+
|
| 137 |
+
if (!hparams.is_recr(il)) {
|
| 138 |
+
- // Attention layers
|
| 139 |
+
- create_tensor_qkv(layer, il, n_embd, n_embd_head_k * n_head * 2, n_embd_k_gqa, n_embd_v_gqa, flags);
|
| 140 |
+
+ // Attention layers. The LLAMA_LOAD_LOCALS macro derives the global
|
| 141 |
+
+ // n_embd_k_gqa/n_embd_v_gqa from layer 0, which in this MoE is a
|
| 142 |
+
+ // linear-attention (recurrent) layer with n_head_kv == 0. Use the
|
| 143 |
+
+ // uniform full-attention KV projection width instead.
|
| 144 |
+
+ const int64_t n_embd_k_gqa_attn = hparams.n_embd_k_gqa_max();
|
| 145 |
+
+ const int64_t n_embd_v_gqa_attn = hparams.n_embd_v_gqa_max();
|
| 146 |
+
+ create_tensor_qkv(layer, il, n_embd, n_embd_head_k * n_head * 2, n_embd_k_gqa_attn, n_embd_v_gqa_attn, flags);
|
| 147 |
+
layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", il), { n_embd_head_k * n_head, n_embd }, flags);
|
| 148 |
+
|
| 149 |
+
// Q/K normalization for attention layers
|
| 150 |
+
@@ -86,7 +102,12 @@ void llama_model_qwen35moe::load_arch_tensors(llama_model_loader & ml) {
|
| 151 |
+
layer.wqkv = create_tensor(tn(LLM_TENSOR_ATTN_QKV, "weight", il), { n_embd, key_dim * 2 + value_dim }, TENSOR_NOT_REQUIRED);
|
| 152 |
+
layer.wqkv_gate = create_tensor(tn(LLM_TENSOR_ATTN_GATE, "weight", il), { n_embd, value_dim }, TENSOR_NOT_REQUIRED);
|
| 153 |
+
layer.ssm_conv1d = create_tensor(tn(LLM_TENSOR_SSM_CONV1D, "weight", il), { hparams.ssm_d_conv, conv_dim }, flags);
|
| 154 |
+
- layer.ssm_dt = create_tensor(tn(LLM_TENSOR_SSM_DT, "bias", il), { hparams.ssm_dt_rank }, flags);
|
| 155 |
+
+ // PALW: some conversions store the delta-time bias without the
|
| 156 |
+
+ // ".bias" suffix ("blk.N.ssm_dt"). Accept both spellings.
|
| 157 |
+
+ layer.ssm_dt = create_tensor(tn(LLM_TENSOR_SSM_DT, "bias", il), { hparams.ssm_dt_rank }, flags | TENSOR_NOT_REQUIRED);
|
| 158 |
+
+ if (!layer.ssm_dt) {
|
| 159 |
+
+ layer.ssm_dt = create_tensor(tn(LLM_TENSOR_SSM_DT, il), { hparams.ssm_dt_rank }, flags);
|
| 160 |
+
+ }
|
| 161 |
+
layer.ssm_a = create_tensor(tn(LLM_TENSOR_SSM_A_NOSCAN, il), { hparams.ssm_dt_rank }, flags);
|
| 162 |
+
layer.ssm_beta = create_tensor(tn(LLM_TENSOR_SSM_BETA, "weight", il), { n_embd, n_v_heads }, flags);
|
| 163 |
+
layer.ssm_alpha = create_tensor(tn(LLM_TENSOR_SSM_ALPHA, "weight", il), { n_embd, n_v_heads }, flags);
|
| 164 |
+
@@ -116,7 +137,11 @@ void llama_model_qwen35moe::load_arch_tensors(llama_model_loader & ml) {
|
| 165 |
+
layer.attn_norm = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "weight", il), { n_embd }, 0);
|
| 166 |
+
layer.attn_post_norm = create_tensor(tn(LLM_TENSOR_ATTN_POST_NORM, "weight", il), { n_embd }, 0);
|
| 167 |
+
|
| 168 |
+
- create_tensor_qkv(layer, il, n_embd, n_embd_head_k * n_head * 2, n_embd_k_gqa, n_embd_v_gqa, 0);
|
| 169 |
+
+ // The MTP layer index has no entry in the per-layer n_head_kv array, so
|
| 170 |
+
+ // derive the KV projection width from the full-attention trunk layers.
|
| 171 |
+
+ const int64_t n_embd_k_gqa_mtp = hparams.n_embd_k_gqa_max();
|
| 172 |
+
+ const int64_t n_embd_v_gqa_mtp = hparams.n_embd_v_gqa_max();
|
| 173 |
+
+ create_tensor_qkv(layer, il, n_embd, n_embd_head_k * n_head * 2, n_embd_k_gqa_mtp, n_embd_v_gqa_mtp, 0);
|
| 174 |
+
layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", il), { n_embd_head_k * n_head, n_embd }, 0);
|
| 175 |
+
layer.attn_q_norm = create_tensor(tn(LLM_TENSOR_ATTN_Q_NORM, "weight", il), { n_embd_head_k }, 0);
|
| 176 |
+
layer.attn_k_norm = create_tensor(tn(LLM_TENSOR_ATTN_K_NORM, "weight", il), { n_embd_head_k }, 0);
|
| 177 |
+
@@ -147,6 +172,24 @@ void llama_model_qwen35moe::load_arch_tensors(llama_model_loader & ml) {
|
| 178 |
+
for (int i = n_layer; i < n_layer_all; ++i) {
|
| 179 |
+
load_block_mtp(i);
|
| 180 |
+
}
|
| 181 |
+
+
|
| 182 |
+
+ // PALW: the Ollama-packaged Qwen3.6-35B-A3B GGUF bundles the multimodal
|
| 183 |
+
+ // vision tower ("v.*") and, when the next-token/MTP head is not enabled by
|
| 184 |
+
+ // hyperparameters, the MTP sub-model ("mtp.*") in the same file. The pinned
|
| 185 |
+
+ // text runtime never builds those sibling sub-models, so account for their
|
| 186 |
+
+ // tensors here; otherwise done_getting_tensors() rejects the load for
|
| 187 |
+
+ // having created fewer tensors than the file contains. This does not weaken
|
| 188 |
+
+ // the check for a genuinely missing text tensor: only tensors that exist in
|
| 189 |
+
+ // the file under these sibling prefixes are counted, exactly once each.
|
| 190 |
+
+ for (const auto & entry : ml.weights_map) {
|
| 191 |
+
+ const std::string & name = entry.first;
|
| 192 |
+
+ const bool is_vision = name.rfind("v.", 0) == 0;
|
| 193 |
+
+ const bool is_mtp = name.rfind("mtp.", 0) == 0;
|
| 194 |
+
+ if (is_vision || is_mtp) {
|
| 195 |
+
+ ml.size_data -= ggml_nbytes(entry.second.tensor);
|
| 196 |
+
+ ml.n_created++;
|
| 197 |
+
+ }
|
| 198 |
+
+ }
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
std::unique_ptr<llm_graph_context> llama_model_qwen35moe::build_arch_graph(const llm_graph_params & params) const {
|
| 202 |
+
@@ -287,6 +330,12 @@ ggml_tensor * llama_model_qwen35moe::graph::build_layer_attn(
|
| 203 |
+
const int64_t n_embd_head = hparams.n_embd_head_v();
|
| 204 |
+
GGML_ASSERT(n_embd_head == hparams.n_embd_head_k());
|
| 205 |
+
|
| 206 |
+
+ // PALW: the llm_graph_context base initializes n_head/n_head_kv from layer
|
| 207 |
+
+ // 0, which in this hybrid MoE is a linear-attention layer with n_head_kv 0.
|
| 208 |
+
+ // Use the per-layer counts for the full-attention reshapes below.
|
| 209 |
+
+ const int64_t n_head = hparams.n_head(il);
|
| 210 |
+
+ const int64_t n_head_kv = hparams.n_head_kv(il);
|
| 211 |
+
+
|
| 212 |
+
// Order: joint QG projection, QG split, Q norm, KV projection, K norm, RoPE, attention
|
| 213 |
+
|
| 214 |
+
// Qwen3Next uses a single Q projection that outputs query + gate
|
| 215 |
+
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
|
| 216 |
+
index 780df326..a1f04870 100644
|
| 217 |
+
--- a/tools/CMakeLists.txt
|
| 218 |
+
+++ b/tools/CMakeLists.txt
|
| 219 |
+
@@ -28,6 +28,7 @@ else()
|
| 220 |
+
endif()
|
| 221 |
+
add_subdirectory(tokenize)
|
| 222 |
+
add_subdirectory(parser)
|
| 223 |
+
+ add_subdirectory(palw-observer)
|
| 224 |
+
add_subdirectory(tts)
|
| 225 |
+
add_subdirectory(mtmd)
|
| 226 |
+
if (GGML_RPC)
|
| 227 |
+
diff --git a/tools/palw-observer/CMakeLists.txt b/tools/palw-observer/CMakeLists.txt
|
| 228 |
+
new file mode 100644
|
| 229 |
+
index 00000000..40e3ffd8
|
| 230 |
+
--- /dev/null
|
| 231 |
+
+++ b/tools/palw-observer/CMakeLists.txt
|
| 232 |
+
@@ -0,0 +1,9 @@
|
| 233 |
+
+set(TARGET llama-palw-observer)
|
| 234 |
+
+
|
| 235 |
+
+add_executable(${TARGET} palw-observer.cpp)
|
| 236 |
+
+target_link_libraries(${TARGET} PRIVATE llama llama-common-base ${CMAKE_THREAD_LIBS_INIT})
|
| 237 |
+
+target_compile_features(${TARGET} PRIVATE cxx_std_17)
|
| 238 |
+
+
|
| 239 |
+
+if(LLAMA_TOOLS_INSTALL)
|
| 240 |
+
+ install(TARGETS ${TARGET} RUNTIME)
|
| 241 |
+
+endif()
|
| 242 |
+
diff --git a/tools/palw-observer/README.md b/tools/palw-observer/README.md
|
| 243 |
+
new file mode 100644
|
| 244 |
+
index 00000000..efd1823b
|
| 245 |
+
--- /dev/null
|
| 246 |
+
+++ b/tools/palw-observer/README.md
|
| 247 |
+
@@ -0,0 +1,66 @@
|
| 248 |
+
+# PALW native graph observer
|
| 249 |
+
+
|
| 250 |
+
+`llama-palw-observer` is a non-interactive, single-request Qwen3.6-35B-A3B runner.
|
| 251 |
+
+It uses only the public llama and ggml APIs and writes versioned JSONL records to
|
| 252 |
+
+stdout. Runtime and model logs are written to stderr.
|
| 253 |
+
+
|
| 254 |
+
+## Build and run
|
| 255 |
+
+
|
| 256 |
+
+```sh
|
| 257 |
+
+cmake --build build-palw --target llama-palw-observer -j
|
| 258 |
+
+build-palw/bin/llama-palw-observer \
|
| 259 |
+
+ --model /path/to/Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf \
|
| 260 |
+
+ --prompt "Hello" \
|
| 261 |
+
+ --n-predict 8 \
|
| 262 |
+
+ --observer graph
|
| 263 |
+
+```
|
| 264 |
+
+
|
| 265 |
+
+The runner fixes greedy sampling, request batch, logical/physical token batch,
|
| 266 |
+
+parallel sequences, tensor parallelism, and CPU thread counts to one. It also
|
| 267 |
+
+disables context shifting, speculation, Flash Attention, and split-model tensor
|
| 268 |
+
+parallelism. The prompt is therefore evaluated one token at a time. The context
|
| 269 |
+
+is sized before execution and the run fails instead of shifting when the prompt
|
| 270 |
+
+and prediction bound exceed the model training context.
|
| 271 |
+
+
|
| 272 |
+
+The accepted model profile is hybrid Qwen3.6-35B-A3B (mixture-of-experts):
|
| 273 |
+
+architecture `qwen35moe`, 40 layers, 2048 hidden elements, and a 248320-token
|
| 274 |
+
+vocabulary, decoder-only. Per-layer head counts vary (the model alternates
|
| 275 |
+
+linear-attention/state-space layers with full-attention layers), so head counts
|
| 276 |
+
+are not part of the accepted profile. Other profiles fail before a header or
|
| 277 |
+
+inference result is emitted. Legitimate zero-element recurrent-state-cache graph
|
| 278 |
+
+nodes are skipped rather than treated as errors.
|
| 279 |
+
+
|
| 280 |
+
+## Observer modes
|
| 281 |
+
+
|
| 282 |
+
+- `off` installs no scheduler callback.
|
| 283 |
+
+- `graph` emits metadata for every graph node from the callback's `ask` stage.
|
| 284 |
+
+ It never requests tensor data.
|
| 285 |
+
+- `sketch` emits the same metadata and requests post-compute data only for plain
|
| 286 |
+
+ `MUL_MAT` nodes (indirect expert GEMM, `MUL_MAT_ID`, is emitted as an ordinary
|
| 287 |
+
+ metadata node, not sketched). It copies at most the first 64 contiguous output
|
| 288 |
+
+ elements through `ggml_backend_tensor_get`. Each element becomes one
|
| 289 |
+
+ hexadecimal nibble: one sign bit and a fixed three-bit magnitude bucket. The
|
| 290 |
+
+ resulting 64 hex digits are a 256-bit sketch. Raw activation values are never
|
| 291 |
+
+ serialized.
|
| 292 |
+
+
|
| 293 |
+
+Nibble bit 3 is the sign bit. Bits 0-2 use these absolute-value buckets: zero,
|
| 294 |
+
+`(0, 2^-8)`, `[2^-8, 2^-4)`, `[2^-4, 2^-2)`, `[2^-2, 1)`, `[1, 4)`,
|
| 295 |
+
+`[4, 16)`, and `[16, infinity)`. Fewer than 64 available elements are padded
|
| 296 |
+
+with zero nibbles.
|
| 297 |
+
+
|
| 298 |
+
+Every stdout line has `schema`, `schema_version`, and `record`. A successful run
|
| 299 |
+
+contains one `header`, zero or more `event` records, and one `result`. The result
|
| 300 |
+
+contains prompt token IDs, sampled token IDs (including an EOG token when one is
|
| 301 |
+
+sampled), the non-special generated output bytes, and the stop reason.
|
| 302 |
+
+
|
| 303 |
+
+## Limits
|
| 304 |
+
+
|
| 305 |
+
+This target is a runtime-observation prototype, not a PALW receipt generator.
|
| 306 |
+
+It does not calculate canonical compute units, sign receipts, form commitments,
|
| 307 |
+
+or trace CUDA kernels. The sketch tile is explicitly identified as
|
| 308 |
+
+`graph_fallback_logical_prefix_v1`, and `kernel_trace.claim` is
|
| 309 |
+
+`not_a_cuda_kernel_trace`. Scheduler callbacks add synchronization and can
|
| 310 |
+
+change timing, but they must not change token IDs or output bytes. The sketch is
|
| 311 |
+
+lossy observation data, not a cryptographic proof. Graph topology and floating
|
| 312 |
+
+point results can vary across backends or hardware, so byte identity is only
|
| 313 |
+
+claimed for repeated runs of the same pinned model, runtime, and backend class.
|
| 314 |
+
diff --git a/tools/palw-observer/palw-observer.cpp b/tools/palw-observer/palw-observer.cpp
|
| 315 |
+
new file mode 100644
|
| 316 |
+
index 00000000..83fc243b
|
| 317 |
+
--- /dev/null
|
| 318 |
+
+++ b/tools/palw-observer/palw-observer.cpp
|
| 319 |
+
@@ -0,0 +1,1473 @@
|
| 320 |
+
+#include "ggml-backend.h"
|
| 321 |
+
+#include "ggml.h"
|
| 322 |
+
+#include "ggml-metal.h"
|
| 323 |
+
+#include "llama.h"
|
| 324 |
+
+#include "build-info.h"
|
| 325 |
+
+
|
| 326 |
+
+#include <algorithm>
|
| 327 |
+
+#include <array>
|
| 328 |
+
+#include <charconv>
|
| 329 |
+
+#include <clocale>
|
| 330 |
+
+#include <cmath>
|
| 331 |
+
+#include <cstdint>
|
| 332 |
+
+#include <cstdio>
|
| 333 |
+
+#include <cstring>
|
| 334 |
+
+#include <exception>
|
| 335 |
+
+#include <limits>
|
| 336 |
+
+#include <memory>
|
| 337 |
+
+#include <string>
|
| 338 |
+
+#include <string_view>
|
| 339 |
+
+#include <utility>
|
| 340 |
+
+#include <vector>
|
| 341 |
+
+
|
| 342 |
+
+namespace {
|
| 343 |
+
+
|
| 344 |
+
+constexpr const char * SCHEMA_NAME = "misaka.palw.runtime_observer";
|
| 345 |
+
+// Schema v2 adds "route" records: the real mixture-of-experts Top-K expert
|
| 346 |
+
+// selection (the `ffn_moe_topk` tensor) read back post-compute. Consumers that
|
| 347 |
+
+// only understand v1 must reject v2.
|
| 348 |
+
+constexpr int SCHEMA_VERSION = 2;
|
| 349 |
+
+constexpr size_t SKETCH_SAMPLES = 64;
|
| 350 |
+
+// Upper bound on selected-expert indices read back from one routing tensor:
|
| 351 |
+
+// n_expert_used (Top-K) * n_tokens for a single mixture-of-experts layer.
|
| 352 |
+
+constexpr size_t MAX_ROUTE_INDICES = 262144;
|
| 353 |
+
+
|
| 354 |
+
+// PALW #5 diagnostic: empirically map Metal kernel dispatches to graph nodes so
|
| 355 |
+
+// the node<->dispatch correlation can be validated before it is committed as a
|
| 356 |
+
+// kernel-level trace. Enabled only when PALW_TRACE_DIAG is set in the env.
|
| 357 |
+
+static bool g_diag_enabled = false;
|
| 358 |
+
+constexpr uint32_t PALW_CONTEXT_TOKENS = 4096;
|
| 359 |
+
+
|
| 360 |
+
+enum class observer_mode {
|
| 361 |
+
+ off,
|
| 362 |
+
+ graph,
|
| 363 |
+
+ sketch,
|
| 364 |
+
+};
|
| 365 |
+
+
|
| 366 |
+
+struct options {
|
| 367 |
+
+ std::string model_path;
|
| 368 |
+
+ std::string prompt;
|
| 369 |
+
+ int32_t n_predict = -1;
|
| 370 |
+
+ int32_t n_gpu_layers = 999;
|
| 371 |
+
+ observer_mode mode = observer_mode::off;
|
| 372 |
+
+ bool prompt_set = false;
|
| 373 |
+
+ bool prompt_stdin = false;
|
| 374 |
+
+ bool emit_output_bytes = false;
|
| 375 |
+
+};
|
| 376 |
+
+
|
| 377 |
+
+struct model_metadata {
|
| 378 |
+
+ std::vector<std::pair<std::string, std::string>> entries;
|
| 379 |
+
+};
|
| 380 |
+
+
|
| 381 |
+
+static const char * mode_name(observer_mode mode) {
|
| 382 |
+
+ switch (mode) {
|
| 383 |
+
+ case observer_mode::off: return "off";
|
| 384 |
+
+ case observer_mode::graph: return "graph";
|
| 385 |
+
+ case observer_mode::sketch: return "sketch";
|
| 386 |
+
+ }
|
| 387 |
+
+ return "invalid";
|
| 388 |
+
+}
|
| 389 |
+
+
|
| 390 |
+
+static void log_callback(ggml_log_level level, const char * text, void *) {
|
| 391 |
+
+ const char * label = "unknown";
|
| 392 |
+
+ switch (level) {
|
| 393 |
+
+ case GGML_LOG_LEVEL_NONE: label = "none"; break;
|
| 394 |
+
+ case GGML_LOG_LEVEL_DEBUG: label = "debug"; break;
|
| 395 |
+
+ case GGML_LOG_LEVEL_INFO: label = "info"; break;
|
| 396 |
+
+ case GGML_LOG_LEVEL_WARN: label = "warn"; break;
|
| 397 |
+
+ case GGML_LOG_LEVEL_ERROR: label = "error"; break;
|
| 398 |
+
+ case GGML_LOG_LEVEL_CONT: label = "cont"; break;
|
| 399 |
+
+ }
|
| 400 |
+
+ std::fprintf(stderr, "[llama:%s] %s", label, text ? text : "");
|
| 401 |
+
+}
|
| 402 |
+
+
|
| 403 |
+
+static void print_usage(const char * argv0) {
|
| 404 |
+
+ std::fprintf(stderr,
|
| 405 |
+
+ "usage: %s --model MODEL (--prompt TEXT|--prompt-stdin) --n-predict N "
|
| 406 |
+
+ "[--observer off|graph|sketch] [--n-gpu-layers N] [--emit-output-bytes]\n",
|
| 407 |
+
+ argv0);
|
| 408 |
+
+}
|
| 409 |
+
+
|
| 410 |
+
+static bool parse_i32(const char * value, int32_t min_value, int32_t max_value, int32_t & result) {
|
| 411 |
+
+ if (!value || value[0] == '\0') {
|
| 412 |
+
+ return false;
|
| 413 |
+
+ }
|
| 414 |
+
+ int32_t parsed = 0;
|
| 415 |
+
+ const char * end = value + std::strlen(value);
|
| 416 |
+
+ const auto converted = std::from_chars(value, end, parsed);
|
| 417 |
+
+ if (converted.ec != std::errc() || converted.ptr != end || parsed < min_value || parsed > max_value) {
|
| 418 |
+
+ return false;
|
| 419 |
+
+ }
|
| 420 |
+
+ result = parsed;
|
| 421 |
+
+ return true;
|
| 422 |
+
+}
|
| 423 |
+
+
|
| 424 |
+
+static bool take_value(int argc, char ** argv, int & i, const char * option, const char *& value) {
|
| 425 |
+
+ if (i + 1 >= argc) {
|
| 426 |
+
+ std::fprintf(stderr, "error: %s requires a value\n", option);
|
| 427 |
+
+ return false;
|
| 428 |
+
+ }
|
| 429 |
+
+ value = argv[++i];
|
| 430 |
+
+ return true;
|
| 431 |
+
+}
|
| 432 |
+
+
|
| 433 |
+
+static bool parse_options(int argc, char ** argv, options & opts, bool & help, bool & version) {
|
| 434 |
+
+ help = false;
|
| 435 |
+
+ version = false;
|
| 436 |
+
+ for (int i = 1; i < argc; ++i) {
|
| 437 |
+
+ const std::string_view arg(argv[i]);
|
| 438 |
+
+ const char * value = nullptr;
|
| 439 |
+
+ if (arg == "--help" || arg == "-h") {
|
| 440 |
+
+ help = true;
|
| 441 |
+
+ return true;
|
| 442 |
+
+ } else if (arg == "--version") {
|
| 443 |
+
+ version = true;
|
| 444 |
+
+ return true;
|
| 445 |
+
+ } else if (arg == "--model" || arg == "-m") {
|
| 446 |
+
+ if (!take_value(argc, argv, i, argv[i], value)) {
|
| 447 |
+
+ return false;
|
| 448 |
+
+ }
|
| 449 |
+
+ opts.model_path = value;
|
| 450 |
+
+ } else if (arg == "--prompt" || arg == "-p") {
|
| 451 |
+
+ if (opts.prompt_stdin) {
|
| 452 |
+
+ std::fprintf(stderr, "error: --prompt and --prompt-stdin are mutually exclusive\n");
|
| 453 |
+
+ return false;
|
| 454 |
+
+ }
|
| 455 |
+
+ if (!take_value(argc, argv, i, argv[i], value)) {
|
| 456 |
+
+ return false;
|
| 457 |
+
+ }
|
| 458 |
+
+ opts.prompt = value;
|
| 459 |
+
+ opts.prompt_set = true;
|
| 460 |
+
+ } else if (arg == "--prompt-stdin") {
|
| 461 |
+
+ if (opts.prompt_set || opts.prompt_stdin) {
|
| 462 |
+
+ std::fprintf(stderr, "error: prompt input may be selected only once\n");
|
| 463 |
+
+ return false;
|
| 464 |
+
+ }
|
| 465 |
+
+ opts.prompt_stdin = true;
|
| 466 |
+
+ } else if (arg == "--emit-output-bytes") {
|
| 467 |
+
+ opts.emit_output_bytes = true;
|
| 468 |
+
+ } else if (arg == "--n-predict" || arg == "-n") {
|
| 469 |
+
+ if (!take_value(argc, argv, i, argv[i], value) ||
|
| 470 |
+
+ !parse_i32(value, 0, 65536, opts.n_predict)) {
|
| 471 |
+
+ std::fprintf(stderr, "error: --n-predict must be an integer in [0, 65536]\n");
|
| 472 |
+
+ return false;
|
| 473 |
+
+ }
|
| 474 |
+
+ } else if (arg == "--n-gpu-layers" || arg == "-ngl") {
|
| 475 |
+
+ if (!take_value(argc, argv, i, argv[i], value) ||
|
| 476 |
+
+ !parse_i32(value, -1, 100000, opts.n_gpu_layers)) {
|
| 477 |
+
+ std::fprintf(stderr, "error: --n-gpu-layers must be an integer in [-1, 100000]\n");
|
| 478 |
+
+ return false;
|
| 479 |
+
+ }
|
| 480 |
+
+ } else if (arg == "--observer") {
|
| 481 |
+
+ if (!take_value(argc, argv, i, argv[i], value)) {
|
| 482 |
+
+ return false;
|
| 483 |
+
+ }
|
| 484 |
+
+ const std::string_view mode(value);
|
| 485 |
+
+ if (mode == "off") {
|
| 486 |
+
+ opts.mode = observer_mode::off;
|
| 487 |
+
+ } else if (mode == "graph") {
|
| 488 |
+
+ opts.mode = observer_mode::graph;
|
| 489 |
+
+ } else if (mode == "sketch") {
|
| 490 |
+
+ opts.mode = observer_mode::sketch;
|
| 491 |
+
+ } else {
|
| 492 |
+
+ std::fprintf(stderr, "error: --observer must be off, graph, or sketch\n");
|
| 493 |
+
+ return false;
|
| 494 |
+
+ }
|
| 495 |
+
+ } else {
|
| 496 |
+
+ std::fprintf(stderr, "error: unknown argument: %s\n", argv[i]);
|
| 497 |
+
+ return false;
|
| 498 |
+
+ }
|
| 499 |
+
+ }
|
| 500 |
+
+
|
| 501 |
+
+ if (opts.model_path.empty()) {
|
| 502 |
+
+ std::fprintf(stderr, "error: --model is required\n");
|
| 503 |
+
+ return false;
|
| 504 |
+
+ }
|
| 505 |
+
+ if (opts.prompt_stdin) {
|
| 506 |
+
+ std::array<char, 8192> buffer = {};
|
| 507 |
+
+ while (true) {
|
| 508 |
+
+ const size_t count = std::fread(buffer.data(), 1, buffer.size(), stdin);
|
| 509 |
+
+ if (count != 0) {
|
| 510 |
+
+ if (opts.prompt.size() > static_cast<size_t>(std::numeric_limits<int32_t>::max()) - count) {
|
| 511 |
+
+ std::fprintf(stderr, "error: stdin prompt exceeds the tokenizer API bound\n");
|
| 512 |
+
+ return false;
|
| 513 |
+
+ }
|
| 514 |
+
+ opts.prompt.append(buffer.data(), count);
|
| 515 |
+
+ }
|
| 516 |
+
+ if (count != buffer.size()) {
|
| 517 |
+
+ if (std::ferror(stdin)) {
|
| 518 |
+
+ std::fprintf(stderr, "error: failed to read prompt from stdin\n");
|
| 519 |
+
+ return false;
|
| 520 |
+
+ }
|
| 521 |
+
+ break;
|
| 522 |
+
+ }
|
| 523 |
+
+ }
|
| 524 |
+
+ opts.prompt_set = true;
|
| 525 |
+
+ }
|
| 526 |
+
+ if (!opts.prompt_set) {
|
| 527 |
+
+ std::fprintf(stderr, "error: --prompt is required (an explicitly empty prompt is allowed)\n");
|
| 528 |
+
+ return false;
|
| 529 |
+
+ }
|
| 530 |
+
+ if (opts.n_predict < 0) {
|
| 531 |
+
+ std::fprintf(stderr, "error: --n-predict is required\n");
|
| 532 |
+
+ return false;
|
| 533 |
+
+ }
|
| 534 |
+
+ if (opts.prompt.size() > static_cast<size_t>(std::numeric_limits<int32_t>::max())) {
|
| 535 |
+
+ std::fprintf(stderr, "error: prompt exceeds the tokenizer API bound\n");
|
| 536 |
+
+ return false;
|
| 537 |
+
+ }
|
| 538 |
+
+ return true;
|
| 539 |
+
+}
|
| 540 |
+
+
|
| 541 |
+
+static void append_json_string(std::string & out, std::string_view value) {
|
| 542 |
+
+ static constexpr char hex[] = "0123456789abcdef";
|
| 543 |
+
+ out.push_back('"');
|
| 544 |
+
+ for (const unsigned char c : value) {
|
| 545 |
+
+ switch (c) {
|
| 546 |
+
+ case '"': out += "\\\""; break;
|
| 547 |
+
+ case '\\': out += "\\\\"; break;
|
| 548 |
+
+ case '\b': out += "\\b"; break;
|
| 549 |
+
+ case '\f': out += "\\f"; break;
|
| 550 |
+
+ case '\n': out += "\\n"; break;
|
| 551 |
+
+ case '\r': out += "\\r"; break;
|
| 552 |
+
+ case '\t': out += "\\t"; break;
|
| 553 |
+
+ default:
|
| 554 |
+
+ if (c < 0x20) {
|
| 555 |
+
+ out += "\\u00";
|
| 556 |
+
+ out.push_back(hex[c >> 4]);
|
| 557 |
+
+ out.push_back(hex[c & 0x0f]);
|
| 558 |
+
+ } else {
|
| 559 |
+
+ out.push_back(static_cast<char>(c));
|
| 560 |
+
+ }
|
| 561 |
+
+ break;
|
| 562 |
+
+ }
|
| 563 |
+
+ }
|
| 564 |
+
+ out.push_back('"');
|
| 565 |
+
+}
|
| 566 |
+
+
|
| 567 |
+
+static void append_bool(std::string & out, bool value) {
|
| 568 |
+
+ out += value ? "true" : "false";
|
| 569 |
+
+}
|
| 570 |
+
+
|
| 571 |
+
+template<typename T>
|
| 572 |
+
+static void append_integer(std::string & out, T value) {
|
| 573 |
+
+ out += std::to_string(value);
|
| 574 |
+
+}
|
| 575 |
+
+
|
| 576 |
+
+static void append_float(std::string & out, double value) {
|
| 577 |
+
+ if (!std::isfinite(value)) {
|
| 578 |
+
+ out += "null";
|
| 579 |
+
+ return;
|
| 580 |
+
+ }
|
| 581 |
+
+ char buffer[64];
|
| 582 |
+
+ const int n = std::snprintf(buffer, sizeof(buffer), "%.9g", value);
|
| 583 |
+
+ if (n <= 0 || static_cast<size_t>(n) >= sizeof(buffer)) {
|
| 584 |
+
+ out += "null";
|
| 585 |
+
+ return;
|
| 586 |
+
+ }
|
| 587 |
+
+ out.append(buffer, static_cast<size_t>(n));
|
| 588 |
+
+}
|
| 589 |
+
+
|
| 590 |
+
+static bool write_json_line(const std::string & line) {
|
| 591 |
+
+ if (std::fwrite(line.data(), 1, line.size(), stdout) != line.size() ||
|
| 592 |
+
+ std::fputc('\n', stdout) == EOF || std::fflush(stdout) != 0) {
|
| 593 |
+
+ std::fprintf(stderr, "error: failed to write JSONL to stdout\n");
|
| 594 |
+
+ return false;
|
| 595 |
+
+ }
|
| 596 |
+
+ return true;
|
| 597 |
+
+}
|
| 598 |
+
+
|
| 599 |
+
+static void append_record_prefix(std::string & out, const char * record) {
|
| 600 |
+
+ out += "{\"schema\":\"";
|
| 601 |
+
+ out += SCHEMA_NAME;
|
| 602 |
+
+ out += "\",\"schema_version\":";
|
| 603 |
+
+ append_integer(out, SCHEMA_VERSION);
|
| 604 |
+
+ out += ",\"record\":";
|
| 605 |
+
+ append_json_string(out, record);
|
| 606 |
+
+}
|
| 607 |
+
+
|
| 608 |
+
+static size_t bounded_name_length(const char * name) {
|
| 609 |
+
+ size_t length = 0;
|
| 610 |
+
+ while (length < GGML_MAX_NAME && name[length] != '\0') {
|
| 611 |
+
+ ++length;
|
| 612 |
+
+ }
|
| 613 |
+
+ return length;
|
| 614 |
+
+}
|
| 615 |
+
+
|
| 616 |
+
+static std::string_view tensor_name(const ggml_tensor * tensor) {
|
| 617 |
+
+ if (!tensor) {
|
| 618 |
+
+ return {};
|
| 619 |
+
+ }
|
| 620 |
+
+ return std::string_view(tensor->name, bounded_name_length(tensor->name));
|
| 621 |
+
+}
|
| 622 |
+
+
|
| 623 |
+
+static std::string lowercase(std::string_view value) {
|
| 624 |
+
+ std::string result;
|
| 625 |
+
+ result.reserve(value.size());
|
| 626 |
+
+ for (const unsigned char c : value) {
|
| 627 |
+
+ if (c >= 'A' && c <= 'Z') {
|
| 628 |
+
+ result.push_back(static_cast<char>(c - 'A' + 'a'));
|
| 629 |
+
+ } else {
|
| 630 |
+
+ result.push_back(static_cast<char>(c));
|
| 631 |
+
+ }
|
| 632 |
+
+ }
|
| 633 |
+
+ return result;
|
| 634 |
+
+}
|
| 635 |
+
+
|
| 636 |
+
+static bool has_text(std::string_view value, std::string_view needle) {
|
| 637 |
+
+ return value.find(needle) != std::string_view::npos;
|
| 638 |
+
+}
|
| 639 |
+
+
|
| 640 |
+
+static void collect_related_names(const ggml_tensor * tensor, std::vector<std::string_view> & names) {
|
| 641 |
+
+ if (!tensor) {
|
| 642 |
+
+ return;
|
| 643 |
+
+ }
|
| 644 |
+
+ if (!tensor_name(tensor).empty()) {
|
| 645 |
+
+ names.push_back(tensor_name(tensor));
|
| 646 |
+
+ }
|
| 647 |
+
+ if (tensor->view_src && !tensor_name(tensor->view_src).empty()) {
|
| 648 |
+
+ names.push_back(tensor_name(tensor->view_src));
|
| 649 |
+
+ }
|
| 650 |
+
+ for (int i = 0; i < GGML_MAX_SRC; ++i) {
|
| 651 |
+
+ const ggml_tensor * src = tensor->src[i];
|
| 652 |
+
+ if (!src) {
|
| 653 |
+
+ continue;
|
| 654 |
+
+ }
|
| 655 |
+
+ if (!tensor_name(src).empty()) {
|
| 656 |
+
+ names.push_back(tensor_name(src));
|
| 657 |
+
+ }
|
| 658 |
+
+ if (src->view_src && !tensor_name(src->view_src).empty()) {
|
| 659 |
+
+ names.push_back(tensor_name(src->view_src));
|
| 660 |
+
+ }
|
| 661 |
+
+ }
|
| 662 |
+
+}
|
| 663 |
+
+
|
| 664 |
+
+static bool related_names_contain(const ggml_tensor * tensor, std::string_view needle) {
|
| 665 |
+
+ std::vector<std::string_view> names;
|
| 666 |
+
+ collect_related_names(tensor, names);
|
| 667 |
+
+ for (const auto name : names) {
|
| 668 |
+
+ if (has_text(lowercase(name), needle)) {
|
| 669 |
+
+ return true;
|
| 670 |
+
+ }
|
| 671 |
+
+ }
|
| 672 |
+
+ return false;
|
| 673 |
+
+}
|
| 674 |
+
+
|
| 675 |
+
+static bool parse_decimal_at(std::string_view name, size_t offset, int & value) {
|
| 676 |
+
+ if (offset >= name.size() || name[offset] < '0' || name[offset] > '9') {
|
| 677 |
+
+ return false;
|
| 678 |
+
+ }
|
| 679 |
+
+ uint64_t parsed = 0;
|
| 680 |
+
+ size_t i = offset;
|
| 681 |
+
+ while (i < name.size() && name[i] >= '0' && name[i] <= '9') {
|
| 682 |
+
+ parsed = parsed * 10 + static_cast<unsigned>(name[i] - '0');
|
| 683 |
+
+ if (parsed > static_cast<uint64_t>(std::numeric_limits<int>::max())) {
|
| 684 |
+
+ return false;
|
| 685 |
+
+ }
|
| 686 |
+
+ ++i;
|
| 687 |
+
+ }
|
| 688 |
+
+ value = static_cast<int>(parsed);
|
| 689 |
+
+ return true;
|
| 690 |
+
+}
|
| 691 |
+
+
|
| 692 |
+
+static bool parse_layer_from_name(std::string_view name, int & layer) {
|
| 693 |
+
+ const size_t dash = name.rfind('-');
|
| 694 |
+
+ if (dash != std::string_view::npos && dash + 1 < name.size()) {
|
| 695 |
+
+ int parsed = -1;
|
| 696 |
+
+ if (parse_decimal_at(name, dash + 1, parsed)) {
|
| 697 |
+
+ size_t end = dash + 1;
|
| 698 |
+
+ while (end < name.size() && name[end] >= '0' && name[end] <= '9') {
|
| 699 |
+
+ ++end;
|
| 700 |
+
+ }
|
| 701 |
+
+ if (end == name.size()) {
|
| 702 |
+
+ layer = parsed;
|
| 703 |
+
+ return true;
|
| 704 |
+
+ }
|
| 705 |
+
+ }
|
| 706 |
+
+ }
|
| 707 |
+
+
|
| 708 |
+
+ const size_t block = name.find("blk.");
|
| 709 |
+
+ if (block != std::string_view::npos && parse_decimal_at(name, block + 4, layer)) {
|
| 710 |
+
+ return true;
|
| 711 |
+
+ }
|
| 712 |
+
+
|
| 713 |
+
+ if (has_text(lowercase(name), "cache_")) {
|
| 714 |
+
+ const size_t marker = name.rfind("_l");
|
| 715 |
+
+ if (marker != std::string_view::npos && parse_decimal_at(name, marker + 2, layer)) {
|
| 716 |
+
+ return true;
|
| 717 |
+
+ }
|
| 718 |
+
+ }
|
| 719 |
+
+ return false;
|
| 720 |
+
+}
|
| 721 |
+
+
|
| 722 |
+
+static int tensor_layer(const ggml_tensor * tensor) {
|
| 723 |
+
+ int layer = -1;
|
| 724 |
+
+ if (parse_layer_from_name(tensor_name(tensor), layer)) {
|
| 725 |
+
+ return layer;
|
| 726 |
+
+ }
|
| 727 |
+
+ std::vector<std::string_view> names;
|
| 728 |
+
+ collect_related_names(tensor, names);
|
| 729 |
+
+ for (const auto name : names) {
|
| 730 |
+
+ if (parse_layer_from_name(name, layer)) {
|
| 731 |
+
+ return layer;
|
| 732 |
+
+ }
|
| 733 |
+
+ }
|
| 734 |
+
+ return -1;
|
| 735 |
+
+}
|
| 736 |
+
+
|
| 737 |
+
+static void append_shape(std::string & out, const ggml_tensor * tensor) {
|
| 738 |
+
+ out.push_back('[');
|
| 739 |
+
+ for (int i = 0; i < GGML_MAX_DIMS; ++i) {
|
| 740 |
+
+ if (i != 0) {
|
| 741 |
+
+ out.push_back(',');
|
| 742 |
+
+ }
|
| 743 |
+
+ append_integer(out, tensor->ne[i]);
|
| 744 |
+
+ }
|
| 745 |
+
+ out.push_back(']');
|
| 746 |
+
+}
|
| 747 |
+
+
|
| 748 |
+
+static void append_token_ids(std::string & out, const std::vector<llama_token> & tokens) {
|
| 749 |
+
+ out.push_back('[');
|
| 750 |
+
+ for (size_t i = 0; i < tokens.size(); ++i) {
|
| 751 |
+
+ if (i != 0) {
|
| 752 |
+
+ out.push_back(',');
|
| 753 |
+
+ }
|
| 754 |
+
+ append_integer(out, tokens[i]);
|
| 755 |
+
+ }
|
| 756 |
+
+ out.push_back(']');
|
| 757 |
+
+}
|
| 758 |
+
+
|
| 759 |
+
+class graph_observer {
|
| 760 |
+
+public:
|
| 761 |
+
+ graph_observer(observer_mode mode, int32_t n_layers) : mode_(mode), n_layers_(n_layers) {}
|
| 762 |
+
+
|
| 763 |
+
+ void set_phase(const char * phase, int64_t step) {
|
| 764 |
+
+ phase_ = phase;
|
| 765 |
+
+ phase_step_ = step;
|
| 766 |
+
+ }
|
| 767 |
+
+
|
| 768 |
+
+ bool failed() const {
|
| 769 |
+
+ return failed_;
|
| 770 |
+
+ }
|
| 771 |
+
+
|
| 772 |
+
+ const std::string & error() const {
|
| 773 |
+
+ return error_;
|
| 774 |
+
+ }
|
| 775 |
+
+
|
| 776 |
+
+ uint64_t event_count() const {
|
| 777 |
+
+ return event_sequence_;
|
| 778 |
+
+ }
|
| 779 |
+
+
|
| 780 |
+
+ static bool callback(ggml_tensor * tensor, bool ask, void * user_data) noexcept {
|
| 781 |
+
+ auto * observer = static_cast<graph_observer *>(user_data);
|
| 782 |
+
+ try {
|
| 783 |
+
+ return observer->on_tensor(tensor, ask);
|
| 784 |
+
+ } catch (const std::exception & exception) {
|
| 785 |
+
+ observer->fail(std::string("observer exception: ") + exception.what());
|
| 786 |
+
+ } catch (...) {
|
| 787 |
+
+ observer->fail("observer exception: unknown");
|
| 788 |
+
+ }
|
| 789 |
+
+ return false;
|
| 790 |
+
+ }
|
| 791 |
+
+
|
| 792 |
+
+private:
|
| 793 |
+
+ observer_mode mode_;
|
| 794 |
+
+ int32_t n_layers_;
|
| 795 |
+
+ std::string phase_ = "uninitialized";
|
| 796 |
+
+ int64_t phase_step_ = -1;
|
| 797 |
+
+ uint64_t event_sequence_ = 0;
|
| 798 |
+
+ bool failed_ = false;
|
| 799 |
+
+ std::string error_;
|
| 800 |
+
+
|
| 801 |
+
+ // Kernel-level dispatch capture (Metal). Every compute dispatch is appended
|
| 802 |
+
+ // here by the backend hook; each GEMM node is then attributed to the actual
|
| 803 |
+
+ // matmul kernel dispatch that produced it (validated 1:1 on-device).
|
| 804 |
+
+ struct kdispatch {
|
| 805 |
+
+ std::string kernel;
|
| 806 |
+
+ int tg[3];
|
| 807 |
+
+ int tptg[3];
|
| 808 |
+
+ };
|
| 809 |
+
+ std::vector<kdispatch> dispatches_;
|
| 810 |
+
+ size_t processed_dispatches_ = 0;
|
| 811 |
+
+ bool have_kernel_ = false;
|
| 812 |
+
+ kdispatch current_kernel_{};
|
| 813 |
+
+
|
| 814 |
+
+public:
|
| 815 |
+
+ // Called by the ggml-metal dispatch hook for every compute dispatch.
|
| 816 |
+
+ void on_dispatch(const char * kernel, int tg0, int tg1, int tg2, int tptg0, int tptg1, int tptg2) {
|
| 817 |
+
+ kdispatch d;
|
| 818 |
+
+ d.kernel = kernel ? kernel : "";
|
| 819 |
+
+ d.tg[0] = tg0; d.tg[1] = tg1; d.tg[2] = tg2;
|
| 820 |
+
+ d.tptg[0] = tptg0; d.tptg[1] = tptg1; d.tptg[2] = tptg2;
|
| 821 |
+
+ dispatches_.push_back(std::move(d));
|
| 822 |
+
+ if (g_diag_enabled) {
|
| 823 |
+
+ std::fprintf(stderr, "PALW_DIAG dispatch #%zu pipeline=%s tg=%d,%d,%d tptg=%d,%d,%d\n",
|
| 824 |
+
+ dispatches_.size(), kernel ? kernel : "", tg0, tg1, tg2, tptg0, tptg1, tptg2);
|
| 825 |
+
+ }
|
| 826 |
+
+ }
|
| 827 |
+
+
|
| 828 |
+
+ static void dispatch_hook(void * user_data, const char * pipeline,
|
| 829 |
+
+ int tg0, int tg1, int tg2, int tptg0, int tptg1, int tptg2) {
|
| 830 |
+
+ static_cast<graph_observer *>(user_data)->on_dispatch(
|
| 831 |
+
+ pipeline, tg0, tg1, tg2, tptg0, tptg1, tptg2);
|
| 832 |
+
+ }
|
| 833 |
+
+
|
| 834 |
+
+private:
|
| 835 |
+
+ // Attributes the just-computed GEMM node to the last matmul (non-expert-id)
|
| 836 |
+
+ // dispatch in its ASK->POST window. Expert GEMMs use distinct `*_id_*`
|
| 837 |
+
+ // kernels and are excluded. Returns false (fail-closed) if none is found.
|
| 838 |
+
+ bool resolve_gemm_kernel() {
|
| 839 |
+
+ have_kernel_ = false;
|
| 840 |
+
+ for (size_t i = dispatches_.size(); i > processed_dispatches_; --i) {
|
| 841 |
+
+ const std::string & k = dispatches_[i - 1].kernel;
|
| 842 |
+
+ const bool is_matmul =
|
| 843 |
+
+ (k.find("mul_mv") != std::string::npos || k.find("mul_mm") != std::string::npos) &&
|
| 844 |
+
+ k.find("_id") == std::string::npos;
|
| 845 |
+
+ if (is_matmul) {
|
| 846 |
+
+ current_kernel_ = dispatches_[i - 1];
|
| 847 |
+
+ have_kernel_ = true;
|
| 848 |
+
+ break;
|
| 849 |
+
+ }
|
| 850 |
+
+ }
|
| 851 |
+
+ processed_dispatches_ = dispatches_.size();
|
| 852 |
+
+ if (!have_kernel_) {
|
| 853 |
+
+ fail("no matmul kernel dispatch found for GEMM node");
|
| 854 |
+
+ return false;
|
| 855 |
+
+ }
|
| 856 |
+
+ return true;
|
| 857 |
+
+ }
|
| 858 |
+
+
|
| 859 |
+
+ void fail(std::string message) {
|
| 860 |
+
+ if (!failed_) {
|
| 861 |
+
+ failed_ = true;
|
| 862 |
+
+ error_ = std::move(message);
|
| 863 |
+
+ std::fprintf(stderr, "observer error: %s\n", error_.c_str());
|
| 864 |
+
+ }
|
| 865 |
+
+ }
|
| 866 |
+
+
|
| 867 |
+
+ bool validate_tensor(const ggml_tensor * tensor, bool validate_op) {
|
| 868 |
+
+ if (!tensor) {
|
| 869 |
+
+ fail("null graph tensor");
|
| 870 |
+
+ return false;
|
| 871 |
+
+ }
|
| 872 |
+
+ if (bounded_name_length(tensor->name) == GGML_MAX_NAME) {
|
| 873 |
+
+ fail("graph tensor name is not terminated");
|
| 874 |
+
+ return false;
|
| 875 |
+
+ }
|
| 876 |
+
+ const int type = static_cast<int>(tensor->type);
|
| 877 |
+
+ if (type < 0 || type >= static_cast<int>(GGML_TYPE_COUNT)) {
|
| 878 |
+
+ fail("graph tensor type is outside public ggml bounds");
|
| 879 |
+
+ return false;
|
| 880 |
+
+ }
|
| 881 |
+
+ if (validate_op) {
|
| 882 |
+
+ const int op = static_cast<int>(tensor->op);
|
| 883 |
+
+ if (op < 0 || op >= static_cast<int>(GGML_OP_COUNT)) {
|
| 884 |
+
+ fail("graph op is outside public ggml bounds");
|
| 885 |
+
+ return false;
|
| 886 |
+
+ }
|
| 887 |
+
+ }
|
| 888 |
+
+
|
| 889 |
+
+ // An empty (zero-element) tensor is valid graph metadata for recurrent
|
| 890 |
+
+ // state gathers and carries no storage to validate.
|
| 891 |
+
+ if (is_empty(tensor)) {
|
| 892 |
+
+ return true;
|
| 893 |
+
+ }
|
| 894 |
+
+
|
| 895 |
+
+ uint64_t elements = 1;
|
| 896 |
+
+ for (int i = 0; i < GGML_MAX_DIMS; ++i) {
|
| 897 |
+
+ const uint64_t dimension = static_cast<uint64_t>(tensor->ne[i]);
|
| 898 |
+
+ if (elements > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) / dimension) {
|
| 899 |
+
+ fail("graph tensor element count overflows int64");
|
| 900 |
+
+ return false;
|
| 901 |
+
+ }
|
| 902 |
+
+ elements *= dimension;
|
| 903 |
+
+ }
|
| 904 |
+
+ if (elements != static_cast<uint64_t>(ggml_nelements(tensor)) || ggml_nbytes(tensor) == 0) {
|
| 905 |
+
+ fail("graph tensor storage bounds are inconsistent");
|
| 906 |
+
+ return false;
|
| 907 |
+
+ }
|
| 908 |
+
+ return true;
|
| 909 |
+
+ }
|
| 910 |
+
+
|
| 911 |
+
+ bool validate_node(const ggml_tensor * tensor) {
|
| 912 |
+
+ if (!validate_tensor(tensor, true)) {
|
| 913 |
+
+ return false;
|
| 914 |
+
+ }
|
| 915 |
+
+ for (int i = 0; i < GGML_MAX_SRC; ++i) {
|
| 916 |
+
+ if (tensor->src[i] && !validate_tensor(tensor->src[i], false)) {
|
| 917 |
+
+ return false;
|
| 918 |
+
+ }
|
| 919 |
+
+ }
|
| 920 |
+
+ const int layer = tensor_layer(tensor);
|
| 921 |
+
+ if (layer >= n_layers_) {
|
| 922 |
+
+ fail("graph layer id exceeds model layer count");
|
| 923 |
+
+ return false;
|
| 924 |
+
+ }
|
| 925 |
+
+ if (is_gemm(tensor)) {
|
| 926 |
+
+ if (!tensor->src[0] || !tensor->src[1]) {
|
| 927 |
+
+ fail("GEMM node is missing an input");
|
| 928 |
+
+ return false;
|
| 929 |
+
+ }
|
| 930 |
+
+ if (tensor->src[0]->ne[0] != tensor->src[1]->ne[0] ||
|
| 931 |
+
+ tensor->ne[0] != tensor->src[0]->ne[1] ||
|
| 932 |
+
+ tensor->ne[1] != tensor->src[1]->ne[1]) {
|
| 933 |
+
+ fail("GEMM dimensions are inconsistent");
|
| 934 |
+
+ return false;
|
| 935 |
+
+ }
|
| 936 |
+
+ }
|
| 937 |
+
+ return true;
|
| 938 |
+
+ }
|
| 939 |
+
+
|
| 940 |
+
+ // Only the plain dense GEMM is sketched. Indirect expert GEMM
|
| 941 |
+
+ // (GGML_OP_MUL_MAT_ID) is emitted as an ordinary metadata node; its
|
| 942 |
+
+ // batched, id-indexed output layout is committed by the adapter as a
|
| 943 |
+
+ // generic compute operation rather than an accumulator sketch.
|
| 944 |
+
+ static bool is_gemm(const ggml_tensor * tensor) {
|
| 945 |
+
+ return tensor->op == GGML_OP_MUL_MAT;
|
| 946 |
+
+ }
|
| 947 |
+
+
|
| 948 |
+
+ static bool is_empty(const ggml_tensor * tensor) {
|
| 949 |
+
+ for (int i = 0; i < GGML_MAX_DIMS; ++i) {
|
| 950 |
+
+ if (tensor->ne[i] <= 0) {
|
| 951 |
+
+ return true;
|
| 952 |
+
+ }
|
| 953 |
+
+ }
|
| 954 |
+
+ return false;
|
| 955 |
+
+ }
|
| 956 |
+
+
|
| 957 |
+
+ // The mixture-of-experts Top-K selection tensor: the concrete list of expert
|
| 958 |
+
+ // indices chosen per token. Captured post-compute so the receipt commits the
|
| 959 |
+
+ // real routing, not merely that routing of some shape occurred. Matched by
|
| 960 |
+
+ // the llama.cpp `cb` label and the I32 index type.
|
| 961 |
+
+ static bool is_route_tensor(const ggml_tensor * tensor) {
|
| 962 |
+
+ return tensor->type == GGML_TYPE_I32 &&
|
| 963 |
+
+ has_text(lowercase(tensor_name(tensor)), "ffn_moe_topk");
|
| 964 |
+
+ }
|
| 965 |
+
+
|
| 966 |
+
+ std::vector<std::string> categories(const ggml_tensor * tensor) const {
|
| 967 |
+
+ std::vector<std::string> result;
|
| 968 |
+
+ if (is_gemm(tensor)) {
|
| 969 |
+
+ result.emplace_back("gemm");
|
| 970 |
+
+ }
|
| 971 |
+
+ if (tensor->op == GGML_OP_NORM || tensor->op == GGML_OP_RMS_NORM ||
|
| 972 |
+
+ tensor->op == GGML_OP_GROUP_NORM || tensor->op == GGML_OP_L2_NORM) {
|
| 973 |
+
+ result.emplace_back("norm");
|
| 974 |
+
+ }
|
| 975 |
+
+ if (tensor->op == GGML_OP_ROPE || tensor->op == GGML_OP_ROPE_BACK) {
|
| 976 |
+
+ result.emplace_back("rope");
|
| 977 |
+
+ }
|
| 978 |
+
+ if (tensor->op == GGML_OP_FLASH_ATTN_EXT || tensor->op == GGML_OP_FLASH_ATTN_BACK ||
|
| 979 |
+
+ related_names_contain(tensor, "attn") || related_names_contain(tensor, "qcur") ||
|
| 980 |
+
+ related_names_contain(tensor, "kcur") || related_names_contain(tensor, "vcur") ||
|
| 981 |
+
+ related_names_contain(tensor, "kq")) {
|
| 982 |
+
+ result.emplace_back("attention");
|
| 983 |
+
+ }
|
| 984 |
+
+ if (related_names_contain(tensor, "cache_") || related_names_contain(tensor, "_cache")) {
|
| 985 |
+
+ result.emplace_back("kv_cache");
|
| 986 |
+
+ }
|
| 987 |
+
+ if (result.empty()) {
|
| 988 |
+
+ result.emplace_back("other");
|
| 989 |
+
+ }
|
| 990 |
+
+ return result;
|
| 991 |
+
+ }
|
| 992 |
+
+
|
| 993 |
+
+ static int magnitude_bucket(float value) {
|
| 994 |
+
+ const float magnitude = std::fabs(value);
|
| 995 |
+
+ if (magnitude == 0.0f) return 0;
|
| 996 |
+
+ if (magnitude < 0.00390625f) return 1;
|
| 997 |
+
+ if (magnitude < 0.0625f) return 2;
|
| 998 |
+
+ if (magnitude < 0.25f) return 3;
|
| 999 |
+
+ if (magnitude < 1.0f) return 4;
|
| 1000 |
+
+ if (magnitude < 4.0f) return 5;
|
| 1001 |
+
+ if (magnitude < 16.0f) return 6;
|
| 1002 |
+
+ return 7;
|
| 1003 |
+
+ }
|
| 1004 |
+
+
|
| 1005 |
+
+ bool make_sketch(const ggml_tensor * tensor, std::string & sketch, size_t & copied_bytes, size_t & sampled) {
|
| 1006 |
+
+ if (!tensor->buffer || !ggml_is_contiguous(tensor)) {
|
| 1007 |
+
+ fail("GEMM output is not backed by a contiguous public backend tensor");
|
| 1008 |
+
+ return false;
|
| 1009 |
+
+ }
|
| 1010 |
+
+
|
| 1011 |
+
+ size_t element_size = 0;
|
| 1012 |
+
+ switch (tensor->type) {
|
| 1013 |
+
+ case GGML_TYPE_F32: element_size = sizeof(float); break;
|
| 1014 |
+
+ case GGML_TYPE_F16: element_size = sizeof(ggml_fp16_t); break;
|
| 1015 |
+
+ case GGML_TYPE_BF16: element_size = sizeof(ggml_bf16_t); break;
|
| 1016 |
+
+ default:
|
| 1017 |
+
+ fail("GEMM output type is unsupported by sign/bucket sketch v1");
|
| 1018 |
+
+ return false;
|
| 1019 |
+
+ }
|
| 1020 |
+
+
|
| 1021 |
+
+ const uint64_t n_elements = static_cast<uint64_t>(ggml_nelements(tensor));
|
| 1022 |
+
+ sampled = static_cast<size_t>(std::min<uint64_t>(SKETCH_SAMPLES, n_elements));
|
| 1023 |
+
+ if (sampled > std::numeric_limits<size_t>::max() / element_size) {
|
| 1024 |
+
+ fail("GEMM sketch copy bound overflows size_t");
|
| 1025 |
+
+ return false;
|
| 1026 |
+
+ }
|
| 1027 |
+
+ copied_bytes = sampled * element_size;
|
| 1028 |
+
+ if (copied_bytes > ggml_nbytes(tensor)) {
|
| 1029 |
+
+ fail("GEMM sketch copy exceeds tensor storage");
|
| 1030 |
+
+ return false;
|
| 1031 |
+
+ }
|
| 1032 |
+
+
|
| 1033 |
+
+ std::vector<uint8_t> host(copied_bytes);
|
| 1034 |
+
+ ggml_backend_tensor_get(tensor, host.data(), 0, copied_bytes);
|
| 1035 |
+
+
|
| 1036 |
+
+ static constexpr char hex[] = "0123456789abcdef";
|
| 1037 |
+
+ sketch.assign(SKETCH_SAMPLES, '0');
|
| 1038 |
+
+ for (size_t i = 0; i < sampled; ++i) {
|
| 1039 |
+
+ float value = 0.0f;
|
| 1040 |
+
+ if (tensor->type == GGML_TYPE_F32) {
|
| 1041 |
+
+ std::memcpy(&value, host.data() + i * element_size, sizeof(value));
|
| 1042 |
+
+ } else if (tensor->type == GGML_TYPE_F16) {
|
| 1043 |
+
+ ggml_fp16_t packed;
|
| 1044 |
+
+ std::memcpy(&packed, host.data() + i * element_size, sizeof(packed));
|
| 1045 |
+
+ value = ggml_fp16_to_fp32(packed);
|
| 1046 |
+
+ } else {
|
| 1047 |
+
+ ggml_bf16_t packed;
|
| 1048 |
+
+ std::memcpy(&packed, host.data() + i * element_size, sizeof(packed));
|
| 1049 |
+
+ value = ggml_bf16_to_fp32(packed);
|
| 1050 |
+
+ }
|
| 1051 |
+
+ if (!std::isfinite(value)) {
|
| 1052 |
+
+ fail("GEMM sketch encountered a non-finite output");
|
| 1053 |
+
+ return false;
|
| 1054 |
+
+ }
|
| 1055 |
+
+ const unsigned nibble = (std::signbit(value) ? 8u : 0u) |
|
| 1056 |
+
+ static_cast<unsigned>(magnitude_bucket(value));
|
| 1057 |
+
+ sketch[i] = hex[nibble];
|
| 1058 |
+
+ }
|
| 1059 |
+
+ return true;
|
| 1060 |
+
+ }
|
| 1061 |
+
+
|
| 1062 |
+
+ void append_tensor_metadata(std::string & out, const ggml_tensor * tensor) const {
|
| 1063 |
+
+ out += "\"name\":";
|
| 1064 |
+
+ append_json_string(out, tensor_name(tensor));
|
| 1065 |
+
+ out += ",\"op\":";
|
| 1066 |
+
+ append_json_string(out, ggml_op_name(tensor->op));
|
| 1067 |
+
+ out += ",\"type\":";
|
| 1068 |
+
+ append_json_string(out, ggml_type_name(tensor->type));
|
| 1069 |
+
+ out += ",\"shape\":";
|
| 1070 |
+
+ append_shape(out, tensor);
|
| 1071 |
+
+ out += ",\"n_bytes\":";
|
| 1072 |
+
+ append_integer(out, ggml_nbytes(tensor));
|
| 1073 |
+
+ }
|
| 1074 |
+
+
|
| 1075 |
+
+ bool emit_event(const ggml_tensor * tensor, const char * stage,
|
| 1076 |
+
+ const std::string * sketch, size_t copied_bytes, size_t sampled) {
|
| 1077 |
+
+ std::string line;
|
| 1078 |
+
+ line.reserve(2048);
|
| 1079 |
+
+ append_record_prefix(line, "event");
|
| 1080 |
+
+ line += ",\"event_seq\":";
|
| 1081 |
+
+ append_integer(line, event_sequence_++);
|
| 1082 |
+
+ line += ",\"observer\":";
|
| 1083 |
+
+ append_json_string(line, mode_name(mode_));
|
| 1084 |
+
+ line += ",\"phase\":";
|
| 1085 |
+
+ append_json_string(line, phase_);
|
| 1086 |
+
+ line += ",\"phase_step\":";
|
| 1087 |
+
+ append_integer(line, phase_step_);
|
| 1088 |
+
+ line += ",\"stage\":";
|
| 1089 |
+
+ append_json_string(line, stage);
|
| 1090 |
+
+
|
| 1091 |
+
+ const int layer = tensor_layer(tensor);
|
| 1092 |
+
+ line += ",\"layer\":";
|
| 1093 |
+
+ if (layer < 0) {
|
| 1094 |
+
+ line += "null";
|
| 1095 |
+
+ } else {
|
| 1096 |
+
+ append_integer(line, layer);
|
| 1097 |
+
+ }
|
| 1098 |
+
+
|
| 1099 |
+
+ line += ",\"categories\":[";
|
| 1100 |
+
+ const auto node_categories = categories(tensor);
|
| 1101 |
+
+ for (size_t i = 0; i < node_categories.size(); ++i) {
|
| 1102 |
+
+ if (i != 0) {
|
| 1103 |
+
+ line.push_back(',');
|
| 1104 |
+
+ }
|
| 1105 |
+
+ append_json_string(line, node_categories[i]);
|
| 1106 |
+
+ }
|
| 1107 |
+
+ line += "],\"tensor\":{";
|
| 1108 |
+
+ append_tensor_metadata(line, tensor);
|
| 1109 |
+
+ line += "},\"sources\":[";
|
| 1110 |
+
+ bool first_source = true;
|
| 1111 |
+
+ for (int i = 0; i < GGML_MAX_SRC; ++i) {
|
| 1112 |
+
+ if (!tensor->src[i]) {
|
| 1113 |
+
+ continue;
|
| 1114 |
+
+ }
|
| 1115 |
+
+ if (!first_source) {
|
| 1116 |
+
+ line.push_back(',');
|
| 1117 |
+
+ }
|
| 1118 |
+
+ first_source = false;
|
| 1119 |
+
+ line.push_back('{');
|
| 1120 |
+
+ append_tensor_metadata(line, tensor->src[i]);
|
| 1121 |
+
+ line.push_back('}');
|
| 1122 |
+
+ }
|
| 1123 |
+
+ line.push_back(']');
|
| 1124 |
+
+
|
| 1125 |
+
+ if (is_gemm(tensor)) {
|
| 1126 |
+
+ line += ",\"gemm\":{\"variant\":\"ggml_graph_op_v1\",\"m\":";
|
| 1127 |
+
+ append_integer(line, tensor->src[0]->ne[1]);
|
| 1128 |
+
+ line += ",\"n\":";
|
| 1129 |
+
+ append_integer(line, tensor->src[1]->ne[1]);
|
| 1130 |
+
+ line += ",\"k\":";
|
| 1131 |
+
+ append_integer(line, tensor->src[0]->ne[0]);
|
| 1132 |
+
+ line += ",\"batch_shape\":[";
|
| 1133 |
+
+ append_integer(line, tensor->ne[2]);
|
| 1134 |
+
+ line.push_back(',');
|
| 1135 |
+
+ append_integer(line, tensor->ne[3]);
|
| 1136 |
+
+ line += "]}";
|
| 1137 |
+
+ }
|
| 1138 |
+
+
|
| 1139 |
+
+ if (sketch) {
|
| 1140 |
+
+ line += ",\"sketch\":{\"version\":\"sign_bucket_256_v1\",\"bits\":256,";
|
| 1141 |
+
+ line += "\"encoding\":\"hex\",\"probe\":\"contiguous_prefix_64_v1\",";
|
| 1142 |
+
+ line += "\"sample_count\":";
|
| 1143 |
+
+ append_integer(line, sampled);
|
| 1144 |
+
+ line += ",\"copied_bytes\":";
|
| 1145 |
+
+ append_integer(line, copied_bytes);
|
| 1146 |
+
+ line += ",\"value\":";
|
| 1147 |
+
+ append_json_string(line, *sketch);
|
| 1148 |
+
+ line += "},\"tile\":{\"variant\":\"graph_fallback_logical_prefix_v1\",";
|
| 1149 |
+
+ line += "\"linear_offset\":0,\"linear_elements\":";
|
| 1150 |
+
+ append_integer(line, sampled);
|
| 1151 |
+
+ if (have_kernel_) {
|
| 1152 |
+
+ // Kernel-level binding: the actual Metal compute pipeline (kernel)
|
| 1153 |
+
+ // and its launch geometry that produced this GEMM output. This is
|
| 1154 |
+
+ // launch-geometry + output-sketch bound to a real GPU dispatch,
|
| 1155 |
+
+ // not a CUDA-style intra-kernel accumulator sketch.
|
| 1156 |
+
+ line += "},\"kernel_trace\":{\"available\":true,\"backend\":\"metal\",";
|
| 1157 |
+
+ line += "\"claim\":\"metal_kernel_launch_bound_v1\",\"kernel\":";
|
| 1158 |
+
+ append_json_string(line, current_kernel_.kernel);
|
| 1159 |
+
+ line += ",\"threadgroups\":[";
|
| 1160 |
+
+ append_integer(line, current_kernel_.tg[0]);
|
| 1161 |
+
+ line.push_back(',');
|
| 1162 |
+
+ append_integer(line, current_kernel_.tg[1]);
|
| 1163 |
+
+ line.push_back(',');
|
| 1164 |
+
+ append_integer(line, current_kernel_.tg[2]);
|
| 1165 |
+
+ line += "],\"threads_per_threadgroup\":[";
|
| 1166 |
+
+ append_integer(line, current_kernel_.tptg[0]);
|
| 1167 |
+
+ line.push_back(',');
|
| 1168 |
+
+ append_integer(line, current_kernel_.tptg[1]);
|
| 1169 |
+
+ line.push_back(',');
|
| 1170 |
+
+ append_integer(line, current_kernel_.tptg[2]);
|
| 1171 |
+
+ line += "]}";
|
| 1172 |
+
+ } else {
|
| 1173 |
+
+ line += "},\"kernel_trace\":{\"available\":false,\"backend\":\"none\",";
|
| 1174 |
+
+ line += "\"claim\":\"not_a_cuda_kernel_trace\"}";
|
| 1175 |
+
+ }
|
| 1176 |
+
+ }
|
| 1177 |
+
+
|
| 1178 |
+
+ line.push_back('}');
|
| 1179 |
+
+ if (!write_json_line(line)) {
|
| 1180 |
+
+ fail("stdout JSONL write failed");
|
| 1181 |
+
+ return false;
|
| 1182 |
+
+ }
|
| 1183 |
+
+ return true;
|
| 1184 |
+
+ }
|
| 1185 |
+
+
|
| 1186 |
+
+ // Reads the mixture-of-experts Top-K selection tensor back from the compute
|
| 1187 |
+
+ // backend and emits a "route" record carrying the real per-token selected
|
| 1188 |
+
+ // expert indices. ne[0] is the number of experts selected per token (Top-K);
|
| 1189 |
+
+ // the remaining dimensions are the token count.
|
| 1190 |
+
+ bool emit_route(const ggml_tensor * tensor) {
|
| 1191 |
+
+ if (!tensor->buffer) {
|
| 1192 |
+
+ fail("route tensor has no backend buffer");
|
| 1193 |
+
+ return false;
|
| 1194 |
+
+ }
|
| 1195 |
+
+ const uint64_t experts_used = static_cast<uint64_t>(tensor->ne[0]);
|
| 1196 |
+
+ const uint64_t tokens = static_cast<uint64_t>(tensor->ne[1]) *
|
| 1197 |
+
+ static_cast<uint64_t>(tensor->ne[2]) * static_cast<uint64_t>(tensor->ne[3]);
|
| 1198 |
+
+ const uint64_t total = experts_used * tokens;
|
| 1199 |
+
+ if (experts_used == 0 || tokens == 0 || total > MAX_ROUTE_INDICES) {
|
| 1200 |
+
+ fail("route tensor shape is out of bounds");
|
| 1201 |
+
+ return false;
|
| 1202 |
+
+ }
|
| 1203 |
+
+
|
| 1204 |
+
+ // Read each selected index using the tensor's byte strides, so a strided
|
| 1205 |
+
+ // Top-K view of the argsort output is captured correctly.
|
| 1206 |
+
+ std::vector<int32_t> indices;
|
| 1207 |
+
+ indices.reserve(static_cast<size_t>(total));
|
| 1208 |
+
+ for (uint64_t t = 0; t < tokens; ++t) {
|
| 1209 |
+
+ for (uint64_t e = 0; e < experts_used; ++e) {
|
| 1210 |
+
+ const size_t offset = static_cast<size_t>(e) * tensor->nb[0] +
|
| 1211 |
+
+ static_cast<size_t>(t) * tensor->nb[1];
|
| 1212 |
+
+ if (offset + sizeof(int32_t) > ggml_nbytes(tensor)) {
|
| 1213 |
+
+ fail("route tensor read exceeds tensor storage");
|
| 1214 |
+
+ return false;
|
| 1215 |
+
+ }
|
| 1216 |
+
+ int32_t value = 0;
|
| 1217 |
+
+ ggml_backend_tensor_get(tensor, &value, offset, sizeof(int32_t));
|
| 1218 |
+
+ indices.push_back(value);
|
| 1219 |
+
+ }
|
| 1220 |
+
+ }
|
| 1221 |
+
+
|
| 1222 |
+
+ std::string line;
|
| 1223 |
+
+ line.reserve(1024);
|
| 1224 |
+
+ append_record_prefix(line, "route");
|
| 1225 |
+
+ line += ",\"event_seq\":";
|
| 1226 |
+
+ append_integer(line, event_sequence_++);
|
| 1227 |
+
+ line += ",\"observer\":";
|
| 1228 |
+
+ append_json_string(line, mode_name(mode_));
|
| 1229 |
+
+ line += ",\"phase\":";
|
| 1230 |
+
+ append_json_string(line, phase_);
|
| 1231 |
+
+ line += ",\"phase_step\":";
|
| 1232 |
+
+ append_integer(line, phase_step_);
|
| 1233 |
+
+ const int layer = tensor_layer(tensor);
|
| 1234 |
+
+ line += ",\"layer\":";
|
| 1235 |
+
+ if (layer < 0) {
|
| 1236 |
+
+ line += "null";
|
| 1237 |
+
+ } else {
|
| 1238 |
+
+ append_integer(line, layer);
|
| 1239 |
+
+ }
|
| 1240 |
+
+ line += ",\"experts_used\":";
|
| 1241 |
+
+ append_integer(line, experts_used);
|
| 1242 |
+
+ line += ",\"tokens\":";
|
| 1243 |
+
+ append_integer(line, tokens);
|
| 1244 |
+
+ line += ",\"selected_experts\":[";
|
| 1245 |
+
+ for (size_t i = 0; i < indices.size(); ++i) {
|
| 1246 |
+
+ if (i != 0) {
|
| 1247 |
+
+ line.push_back(',');
|
| 1248 |
+
+ }
|
| 1249 |
+
+ append_integer(line, indices[i]);
|
| 1250 |
+
+ }
|
| 1251 |
+
+ line += "]}";
|
| 1252 |
+
+ if (!write_json_line(line)) {
|
| 1253 |
+
+ fail("stdout JSONL write failed");
|
| 1254 |
+
+ return false;
|
| 1255 |
+
+ }
|
| 1256 |
+
+ return true;
|
| 1257 |
+
+ }
|
| 1258 |
+
+
|
| 1259 |
+
+ bool on_tensor(ggml_tensor * tensor, bool ask) {
|
| 1260 |
+
+ if (failed_ || mode_ == observer_mode::off) {
|
| 1261 |
+
+ return false;
|
| 1262 |
+
+ }
|
| 1263 |
+
+ // Recurrent (state-space / gated-delta-net) layers gather an initially
|
| 1264 |
+
+ // empty state cache, producing legitimate zero-element graph nodes. They
|
| 1265 |
+
+ // perform no compute, so they are skipped rather than treated as errors.
|
| 1266 |
+
+ if (tensor && is_empty(tensor)) {
|
| 1267 |
+
+ return false;
|
| 1268 |
+
+ }
|
| 1269 |
+
+ if (!validate_node(tensor)) {
|
| 1270 |
+
+ return false;
|
| 1271 |
+
+ }
|
| 1272 |
+
+
|
| 1273 |
+
+ if (g_diag_enabled && is_gemm(tensor)) {
|
| 1274 |
+
+ std::fprintf(stderr, "PALW_DIAG %s MUL_MAT node=%.*s layer=%d dispatch#=%zu\n",
|
| 1275 |
+
+ ask ? "ASK " : "POST", (int) tensor_name(tensor).size(), tensor_name(tensor).data(),
|
| 1276 |
+
+ tensor_layer(tensor), dispatches_.size());
|
| 1277 |
+
+ }
|
| 1278 |
+
+
|
| 1279 |
+
+ if (ask) {
|
| 1280 |
+
+ if (mode_ == observer_mode::graph) {
|
| 1281 |
+
+ emit_event(tensor, "ask_metadata", nullptr, 0, 0);
|
| 1282 |
+
+ return false;
|
| 1283 |
+
+ }
|
| 1284 |
+
+ if (is_gemm(tensor)) {
|
| 1285 |
+
+ return true;
|
| 1286 |
+
+ }
|
| 1287 |
+
+ // Sketch mode also reads back the mixture-of-experts Top-K selection
|
| 1288 |
+
+ // so the receipt commits the real routing content.
|
| 1289 |
+
+ if (is_route_tensor(tensor)) {
|
| 1290 |
+
+ return true;
|
| 1291 |
+
+ }
|
| 1292 |
+
+ emit_event(tensor, "ask_metadata", nullptr, 0, 0);
|
| 1293 |
+
+ return false;
|
| 1294 |
+
+ }
|
| 1295 |
+
+
|
| 1296 |
+
+ if (mode_ != observer_mode::sketch) {
|
| 1297 |
+
+ fail("unexpected post-compute callback");
|
| 1298 |
+
+ return false;
|
| 1299 |
+
+ }
|
| 1300 |
+
+ if (is_route_tensor(tensor)) {
|
| 1301 |
+
+ return emit_route(tensor);
|
| 1302 |
+
+ }
|
| 1303 |
+
+ if (!is_gemm(tensor)) {
|
| 1304 |
+
+ fail("unexpected post-compute callback");
|
| 1305 |
+
+ return false;
|
| 1306 |
+
+ }
|
| 1307 |
+
+
|
| 1308 |
+
+ // Bind this GEMM to the actual Metal matmul kernel dispatch that produced
|
| 1309 |
+
+ // it before sketching its output.
|
| 1310 |
+
+ if (!resolve_gemm_kernel()) {
|
| 1311 |
+
+ return false;
|
| 1312 |
+
+ }
|
| 1313 |
+
+ std::string sketch;
|
| 1314 |
+
+ size_t copied_bytes = 0;
|
| 1315 |
+
+ size_t sampled = 0;
|
| 1316 |
+
+ if (!make_sketch(tensor, sketch, copied_bytes, sampled)) {
|
| 1317 |
+
+ return false;
|
| 1318 |
+
+ }
|
| 1319 |
+
+ return emit_event(tensor, "post_compute_sketch", &sketch, copied_bytes, sampled);
|
| 1320 |
+
+ }
|
| 1321 |
+
+};
|
| 1322 |
+
+
|
| 1323 |
+
+static bool get_model_string(const llama_model * model, int32_t index, bool key, std::string & value) {
|
| 1324 |
+
+ std::vector<char> buffer(256);
|
| 1325 |
+
+ for (int attempt = 0; attempt < 3; ++attempt) {
|
| 1326 |
+
+ const int32_t length = key
|
| 1327 |
+
+ ? llama_model_meta_key_by_index(model, index, buffer.data(), buffer.size())
|
| 1328 |
+
+ : llama_model_meta_val_str_by_index(model, index, buffer.data(), buffer.size());
|
| 1329 |
+
+ if (length < 0) {
|
| 1330 |
+
+ return false;
|
| 1331 |
+
+ }
|
| 1332 |
+
+ if (static_cast<size_t>(length) < buffer.size()) {
|
| 1333 |
+
+ value.assign(buffer.data(), static_cast<size_t>(length));
|
| 1334 |
+
+ return true;
|
| 1335 |
+
+ }
|
| 1336 |
+
+ buffer.resize(static_cast<size_t>(length) + 1);
|
| 1337 |
+
+ }
|
| 1338 |
+
+ return false;
|
| 1339 |
+
+}
|
| 1340 |
+
+
|
| 1341 |
+
+static bool read_model_metadata(const llama_model * model, model_metadata & metadata) {
|
| 1342 |
+
+ const int32_t count = llama_model_meta_count(model);
|
| 1343 |
+
+ if (count < 0 || count > 100000) {
|
| 1344 |
+
+ std::fprintf(stderr, "error: model metadata count is outside bounds\n");
|
| 1345 |
+
+ return false;
|
| 1346 |
+
+ }
|
| 1347 |
+
+ metadata.entries.reserve(static_cast<size_t>(count));
|
| 1348 |
+
+ for (int32_t i = 0; i < count; ++i) {
|
| 1349 |
+
+ std::string key;
|
| 1350 |
+
+ std::string value;
|
| 1351 |
+
+ if (!get_model_string(model, i, true, key) || !get_model_string(model, i, false, value)) {
|
| 1352 |
+
+ std::fprintf(stderr, "error: failed to read model metadata index %d\n", i);
|
| 1353 |
+
+ return false;
|
| 1354 |
+
+ }
|
| 1355 |
+
+ metadata.entries.emplace_back(std::move(key), std::move(value));
|
| 1356 |
+
+ }
|
| 1357 |
+
+ return true;
|
| 1358 |
+
+}
|
| 1359 |
+
+
|
| 1360 |
+
+static const std::string * find_metadata(const model_metadata & metadata, const char * key) {
|
| 1361 |
+
+ for (const auto & entry : metadata.entries) {
|
| 1362 |
+
+ if (entry.first == key) {
|
| 1363 |
+
+ return &entry.second;
|
| 1364 |
+
+ }
|
| 1365 |
+
+ }
|
| 1366 |
+
+ return nullptr;
|
| 1367 |
+
+}
|
| 1368 |
+
+
|
| 1369 |
+
+static bool validate_qwen36_35b_a3b_profile(const llama_model * model, const model_metadata & metadata) {
|
| 1370 |
+
+ const std::string * architecture = find_metadata(metadata, "general.architecture");
|
| 1371 |
+
+ const llama_vocab * vocab = llama_model_get_vocab(model);
|
| 1372 |
+
+ if (!architecture || *architecture != "qwen35moe" ||
|
| 1373 |
+
+ llama_model_n_layer(model) != 40 ||
|
| 1374 |
+
+ llama_model_n_embd(model) != 2048 ||
|
| 1375 |
+
+ llama_vocab_n_tokens(vocab) != 248320 ||
|
| 1376 |
+
+ llama_model_has_encoder(model) || !llama_model_has_decoder(model)) {
|
| 1377 |
+
+ std::fprintf(stderr,
|
| 1378 |
+
+ "error: model is not the supported Qwen3.6-35B-A3B MoE profile "
|
| 1379 |
+
+ "(qwen35moe, 40 layers, 2048 hidden, 248320 vocab); observed "
|
| 1380 |
+
+ "arch=%s layers=%d embd=%d head=%d head_kv=%d vocab=%d\n",
|
| 1381 |
+
+ architecture ? architecture->c_str() : "(none)",
|
| 1382 |
+
+ llama_model_n_layer(model),
|
| 1383 |
+
+ llama_model_n_embd(model),
|
| 1384 |
+
+ llama_model_n_head(model),
|
| 1385 |
+
+ llama_model_n_head_kv(model),
|
| 1386 |
+
+ llama_vocab_n_tokens(vocab));
|
| 1387 |
+
+ return false;
|
| 1388 |
+
+ }
|
| 1389 |
+
+ return true;
|
| 1390 |
+
+}
|
| 1391 |
+
+
|
| 1392 |
+
+static const char * device_type_name(enum ggml_backend_dev_type type) {
|
| 1393 |
+
+ switch (type) {
|
| 1394 |
+
+ case GGML_BACKEND_DEVICE_TYPE_CPU: return "cpu";
|
| 1395 |
+
+ case GGML_BACKEND_DEVICE_TYPE_GPU: return "gpu";
|
| 1396 |
+
+ case GGML_BACKEND_DEVICE_TYPE_IGPU: return "igpu";
|
| 1397 |
+
+ case GGML_BACKEND_DEVICE_TYPE_ACCEL: return "accelerator";
|
| 1398 |
+
+ case GGML_BACKEND_DEVICE_TYPE_META: return "meta";
|
| 1399 |
+
+ }
|
| 1400 |
+
+ return "unknown";
|
| 1401 |
+
+}
|
| 1402 |
+
+
|
| 1403 |
+
+static bool emit_header(const options & opts, const llama_model * model, const llama_context * context,
|
| 1404 |
+
+ const model_metadata & metadata, size_t prompt_tokens) {
|
| 1405 |
+
+ char description[1024] = {};
|
| 1406 |
+
+ const int32_t description_length = llama_model_desc(model, description, sizeof(description));
|
| 1407 |
+
+ if (description_length < 0 || static_cast<size_t>(description_length) >= sizeof(description)) {
|
| 1408 |
+
+ std::fprintf(stderr, "error: model description exceeds header bound\n");
|
| 1409 |
+
+ return false;
|
| 1410 |
+
+ }
|
| 1411 |
+
+
|
| 1412 |
+
+ std::string line;
|
| 1413 |
+
+ line.reserve(32768);
|
| 1414 |
+
+ append_record_prefix(line, "header");
|
| 1415 |
+
+ line += ",\"observer\":";
|
| 1416 |
+
+ append_json_string(line, mode_name(opts.mode));
|
| 1417 |
+
+ line += ",\"trace_variant\":";
|
| 1418 |
+
+ if (opts.mode == observer_mode::off) {
|
| 1419 |
+
+ append_json_string(line, "none");
|
| 1420 |
+
+ } else if (opts.mode == observer_mode::graph) {
|
| 1421 |
+
+ append_json_string(line, "ggml_sched_ask_metadata_v1");
|
| 1422 |
+
+ } else {
|
| 1423 |
+
+ append_json_string(line, "ggml_sched_fixed_prefix_sketch_v1");
|
| 1424 |
+
+ }
|
| 1425 |
+
+ line += ",\"cuda_kernel_trace\":false";
|
| 1426 |
+
+
|
| 1427 |
+
+ line += ",\"model\":{\"path\":";
|
| 1428 |
+
+ append_json_string(line, opts.model_path);
|
| 1429 |
+
+ line += ",\"description\":";
|
| 1430 |
+
+ append_json_string(line, description);
|
| 1431 |
+
+ line += ",\"tensor_size_bytes\":";
|
| 1432 |
+
+ append_integer(line, llama_model_size(model));
|
| 1433 |
+
+ line += ",\"parameter_count\":";
|
| 1434 |
+
+ append_integer(line, llama_model_n_params(model));
|
| 1435 |
+
+ line += ",\"file_type\":";
|
| 1436 |
+
+ append_integer(line, static_cast<int>(llama_model_ftype(model)));
|
| 1437 |
+
+ line += ",\"n_ctx_train\":";
|
| 1438 |
+
+ append_integer(line, llama_model_n_ctx_train(model));
|
| 1439 |
+
+ line += ",\"n_embd\":";
|
| 1440 |
+
+ append_integer(line, llama_model_n_embd(model));
|
| 1441 |
+
+ line += ",\"n_layer\":";
|
| 1442 |
+
+ append_integer(line, llama_model_n_layer(model));
|
| 1443 |
+
+ line += ",\"n_head\":";
|
| 1444 |
+
+ append_integer(line, llama_model_n_head(model));
|
| 1445 |
+
+ line += ",\"n_head_kv\":";
|
| 1446 |
+
+ append_integer(line, llama_model_n_head_kv(model));
|
| 1447 |
+
+ line += ",\"n_vocab\":";
|
| 1448 |
+
+ append_integer(line, llama_vocab_n_tokens(llama_model_get_vocab(model)));
|
| 1449 |
+
+ line += ",\"rope_type\":";
|
| 1450 |
+
+ append_integer(line, static_cast<int>(llama_model_rope_type(model)));
|
| 1451 |
+
+ line += ",\"rope_freq_scale_train\":";
|
| 1452 |
+
+ append_float(line, llama_model_rope_freq_scale_train(model));
|
| 1453 |
+
+ line += ",\"metadata\":[";
|
| 1454 |
+
+ for (size_t i = 0; i < metadata.entries.size(); ++i) {
|
| 1455 |
+
+ if (i != 0) {
|
| 1456 |
+
+ line.push_back(',');
|
| 1457 |
+
+ }
|
| 1458 |
+
+ line += "{\"key\":";
|
| 1459 |
+
+ append_json_string(line, metadata.entries[i].first);
|
| 1460 |
+
+ line += ",\"value\":";
|
| 1461 |
+
+ append_json_string(line, metadata.entries[i].second);
|
| 1462 |
+
+ line.push_back('}');
|
| 1463 |
+
+ }
|
| 1464 |
+
+ line += "]}";
|
| 1465 |
+
+
|
| 1466 |
+
+ line += ",\"runtime\":{\"ggml_version\":";
|
| 1467 |
+
+ append_json_string(line, ggml_version());
|
| 1468 |
+
+ line += ",\"ggml_commit\":";
|
| 1469 |
+
+ append_json_string(line, ggml_commit());
|
| 1470 |
+
+ line += ",\"system_info\":";
|
| 1471 |
+
+ append_json_string(line, llama_print_system_info());
|
| 1472 |
+
+ line += ",\"supports_gpu_offload\":";
|
| 1473 |
+
+ append_bool(line, llama_supports_gpu_offload());
|
| 1474 |
+
+ line += ",\"requested_gpu_layers\":";
|
| 1475 |
+
+ append_integer(line, opts.n_gpu_layers);
|
| 1476 |
+
+ line += ",\"devices\":[";
|
| 1477 |
+
+ const size_t device_count = ggml_backend_dev_count();
|
| 1478 |
+
+ for (size_t i = 0; i < device_count; ++i) {
|
| 1479 |
+
+ if (i != 0) {
|
| 1480 |
+
+ line.push_back(',');
|
| 1481 |
+
+ }
|
| 1482 |
+
+ const ggml_backend_dev_t device = ggml_backend_dev_get(i);
|
| 1483 |
+
+ ggml_backend_dev_props properties = {};
|
| 1484 |
+
+ ggml_backend_dev_get_props(device, &properties);
|
| 1485 |
+
+ line += "{\"name\":";
|
| 1486 |
+
+ append_json_string(line, properties.name ? properties.name : "");
|
| 1487 |
+
+ line += ",\"description\":";
|
| 1488 |
+
+ append_json_string(line, properties.description ? properties.description : "");
|
| 1489 |
+
+ line += ",\"type\":";
|
| 1490 |
+
+ append_json_string(line, device_type_name(properties.type));
|
| 1491 |
+
+ line += ",\"memory_free_observed\":";
|
| 1492 |
+
+ append_integer(line, properties.memory_free);
|
| 1493 |
+
+ line += ",\"memory_total\":";
|
| 1494 |
+
+ append_integer(line, properties.memory_total);
|
| 1495 |
+
+ line.push_back('}');
|
| 1496 |
+
+ }
|
| 1497 |
+
+ line += "]}";
|
| 1498 |
+
+
|
| 1499 |
+
+ line += ",\"execution_policy\":{\"sampling\":\"greedy\",\"temperature\":0,";
|
| 1500 |
+
+ line += "\"top_p\":1,\"top_k\":0,\"batch\":1,\"request_batch\":1,\"n_batch\":";
|
| 1501 |
+
+ append_integer(line, llama_n_batch(context));
|
| 1502 |
+
+ line += ",\"n_ubatch\":";
|
| 1503 |
+
+ append_integer(line, llama_n_ubatch(context));
|
| 1504 |
+
+ line += ",\"parallel\":1,\"parallel_sequences\":";
|
| 1505 |
+
+ append_integer(line, llama_n_seq_max(context));
|
| 1506 |
+
+ line += ",\"tensor_parallel\":1,\"split_mode\":\"none\",\"scheduler_parallel\":false,";
|
| 1507 |
+
+ line += "\"tensor_repack\":false,";
|
| 1508 |
+
+ line += "\"context_shift\":false,\"speculation\":false,\"flash_attention\":false,";
|
| 1509 |
+
+ line += "\"threads\":1,\"threads_batch\":1,\"n_predict\":";
|
| 1510 |
+
+ append_integer(line, opts.n_predict);
|
| 1511 |
+
+ line += ",\"n_ctx\":";
|
| 1512 |
+
+ append_integer(line, llama_n_ctx(context));
|
| 1513 |
+
+ line += ",\"prompt_tokens\":";
|
| 1514 |
+
+ append_integer(line, prompt_tokens);
|
| 1515 |
+
+ line += ",\"tokenization\":{\"add_special\":true,\"parse_special\":true}}";
|
| 1516 |
+
+
|
| 1517 |
+
+ line += ",\"observation_policy\":{\"read_only\":true,";
|
| 1518 |
+
+ line += "\"graph_metadata_stage\":\"ask\",\"sketch_bits\":256,";
|
| 1519 |
+
+ line += "\"sketch_probe\":\"gemm_output_contiguous_prefix_64\",";
|
| 1520 |
+
+ line += "\"raw_activation_values_published\":false,";
|
| 1521 |
+
+ line += "\"tile_variant\":\"graph_fallback_logical_prefix_v1\",";
|
| 1522 |
+
+ line += "\"kernel_trace_claim\":\"none\"}";
|
| 1523 |
+
+ line.push_back('}');
|
| 1524 |
+
+ return write_json_line(line);
|
| 1525 |
+
+}
|
| 1526 |
+
+
|
| 1527 |
+
+static bool tokenize_prompt(const llama_vocab * vocab, const std::string & prompt,
|
| 1528 |
+
+ std::vector<llama_token> & tokens) {
|
| 1529 |
+
+ const int32_t length = static_cast<int32_t>(prompt.size());
|
| 1530 |
+
+ const int32_t required = llama_tokenize(vocab, prompt.data(), length, nullptr, 0, true, true);
|
| 1531 |
+
+ if (required == std::numeric_limits<int32_t>::min()) {
|
| 1532 |
+
+ std::fprintf(stderr, "error: tokenizer result overflow\n");
|
| 1533 |
+
+ return false;
|
| 1534 |
+
+ }
|
| 1535 |
+
+ const int32_t count = required < 0 ? -required : required;
|
| 1536 |
+
+ if (count <= 0) {
|
| 1537 |
+
+ std::fprintf(stderr, "error: prompt tokenization produced no tokens\n");
|
| 1538 |
+
+ return false;
|
| 1539 |
+
+ }
|
| 1540 |
+
+ tokens.resize(static_cast<size_t>(count));
|
| 1541 |
+
+ const int32_t actual = llama_tokenize(vocab, prompt.data(), length,
|
| 1542 |
+
+ tokens.data(), count, true, true);
|
| 1543 |
+
+ if (actual != count) {
|
| 1544 |
+
+ std::fprintf(stderr, "error: prompt tokenization was not stable across sizing calls\n");
|
| 1545 |
+
+ return false;
|
| 1546 |
+
+ }
|
| 1547 |
+
+ return true;
|
| 1548 |
+
+}
|
| 1549 |
+
+
|
| 1550 |
+
+static bool append_token_piece(const llama_vocab * vocab, llama_token token,
|
| 1551 |
+
+ std::vector<uint8_t> & output) {
|
| 1552 |
+
+ std::array<char, 64> small = {};
|
| 1553 |
+
+ int32_t length = llama_token_to_piece(vocab, token, small.data(), small.size(), 0, false);
|
| 1554 |
+
+ if (length >= 0) {
|
| 1555 |
+
+ output.insert(output.end(), small.begin(), small.begin() + length);
|
| 1556 |
+
+ return true;
|
| 1557 |
+
+ }
|
| 1558 |
+
+ if (length == std::numeric_limits<int32_t>::min()) {
|
| 1559 |
+
+ return false;
|
| 1560 |
+
+ }
|
| 1561 |
+
+ const int32_t required = -length;
|
| 1562 |
+
+ std::vector<char> buffer(static_cast<size_t>(required));
|
| 1563 |
+
+ length = llama_token_to_piece(vocab, token, buffer.data(), required, 0, false);
|
| 1564 |
+
+ if (length != required) {
|
| 1565 |
+
+ return false;
|
| 1566 |
+
+ }
|
| 1567 |
+
+ output.insert(output.end(), buffer.begin(), buffer.end());
|
| 1568 |
+
+ return true;
|
| 1569 |
+
+}
|
| 1570 |
+
+
|
| 1571 |
+
+static bool emit_result(const options & opts, const char * status, const char * stop_reason,
|
| 1572 |
+
+ const std::vector<llama_token> & prompt_tokens,
|
| 1573 |
+
+ const std::vector<llama_token> & generated_tokens,
|
| 1574 |
+
+ const std::vector<uint8_t> & output_bytes,
|
| 1575 |
+
+ const graph_observer & observer, const std::string & error) {
|
| 1576 |
+
+ std::string line;
|
| 1577 |
+
+ line.reserve(1024 + prompt_tokens.size() * 12 + generated_tokens.size() * 12 + output_bytes.size() * 4);
|
| 1578 |
+
+ append_record_prefix(line, "result");
|
| 1579 |
+
+ line += ",\"status\":";
|
| 1580 |
+
+ append_json_string(line, status);
|
| 1581 |
+
+ line += ",\"observer\":";
|
| 1582 |
+
+ append_json_string(line, mode_name(opts.mode));
|
| 1583 |
+
+ line += ",\"stop_reason\":";
|
| 1584 |
+
+ append_json_string(line, stop_reason);
|
| 1585 |
+
+ line += ",\"prompt_token_ids\":";
|
| 1586 |
+
+ append_token_ids(line, prompt_tokens);
|
| 1587 |
+
+ line += ",\"generated_token_ids\":";
|
| 1588 |
+
+ append_token_ids(line, generated_tokens);
|
| 1589 |
+
+ line += ",\"output_bytes\":[";
|
| 1590 |
+
+ const size_t published_output_bytes = opts.emit_output_bytes ? output_bytes.size() : 0;
|
| 1591 |
+
+ for (size_t i = 0; i < published_output_bytes; ++i) {
|
| 1592 |
+
+ if (i != 0) {
|
| 1593 |
+
+ line.push_back(',');
|
| 1594 |
+
+ }
|
| 1595 |
+
+ append_integer(line, static_cast<unsigned>(output_bytes[i]));
|
| 1596 |
+
+ }
|
| 1597 |
+
+ line += "],\"output_n_bytes\":";
|
| 1598 |
+
+ append_integer(line, published_output_bytes);
|
| 1599 |
+
+ line += ",\"event_count\":";
|
| 1600 |
+
+ append_integer(line, observer.event_count());
|
| 1601 |
+
+ if (!error.empty()) {
|
| 1602 |
+
+ line += ",\"error\":";
|
| 1603 |
+
+ append_json_string(line, error);
|
| 1604 |
+
+ }
|
| 1605 |
+
+ line.push_back('}');
|
| 1606 |
+
+ return write_json_line(line);
|
| 1607 |
+
+}
|
| 1608 |
+
+
|
| 1609 |
+
+struct backend_guard {
|
| 1610 |
+
+ ~backend_guard() {
|
| 1611 |
+
+ llama_backend_free();
|
| 1612 |
+
+ }
|
| 1613 |
+
+};
|
| 1614 |
+
+
|
| 1615 |
+
+} // namespace
|
| 1616 |
+
+
|
| 1617 |
+
+int main(int argc, char ** argv) {
|
| 1618 |
+
+ std::setlocale(LC_NUMERIC, "C");
|
| 1619 |
+
+ llama_log_set(log_callback, nullptr);
|
| 1620 |
+
+
|
| 1621 |
+
+ options opts;
|
| 1622 |
+
+ bool help = false;
|
| 1623 |
+
+ bool version = false;
|
| 1624 |
+
+ if (!parse_options(argc, argv, opts, help, version)) {
|
| 1625 |
+
+ print_usage(argv[0]);
|
| 1626 |
+
+ return 2;
|
| 1627 |
+
+ }
|
| 1628 |
+
+ if (version) {
|
| 1629 |
+
+ std::fprintf(stderr, "version: %d (%s)\n", llama_build_number(), llama_commit());
|
| 1630 |
+
+ return 0;
|
| 1631 |
+
+ }
|
| 1632 |
+
+ if (help) {
|
| 1633 |
+
+ print_usage(argv[0]);
|
| 1634 |
+
+ return 0;
|
| 1635 |
+
+ }
|
| 1636 |
+
+
|
| 1637 |
+
+ llama_backend_init();
|
| 1638 |
+
+ backend_guard backend_cleanup;
|
| 1639 |
+
+ ggml_backend_load_all();
|
| 1640 |
+
+
|
| 1641 |
+
+ llama_model_params model_params = llama_model_default_params();
|
| 1642 |
+
+ model_params.n_gpu_layers = opts.n_gpu_layers;
|
| 1643 |
+
+ model_params.split_mode = LLAMA_SPLIT_MODE_NONE;
|
| 1644 |
+
+ model_params.main_gpu = 0;
|
| 1645 |
+
+ model_params.use_mmap = true;
|
| 1646 |
+
+ model_params.use_mlock = false;
|
| 1647 |
+
+ model_params.check_tensors = true;
|
| 1648 |
+
+ model_params.use_extra_bufts = false;
|
| 1649 |
+
+
|
| 1650 |
+
+ using model_ptr = std::unique_ptr<llama_model, decltype(&llama_model_free)>;
|
| 1651 |
+
+ model_ptr model(llama_model_load_from_file(opts.model_path.c_str(), model_params), llama_model_free);
|
| 1652 |
+
+ if (!model) {
|
| 1653 |
+
+ std::fprintf(stderr, "error: failed to load model\n");
|
| 1654 |
+
+ return 3;
|
| 1655 |
+
+ }
|
| 1656 |
+
+
|
| 1657 |
+
+ model_metadata metadata;
|
| 1658 |
+
+ if (!read_model_metadata(model.get(), metadata) || !validate_qwen36_35b_a3b_profile(model.get(), metadata)) {
|
| 1659 |
+
+ return 3;
|
| 1660 |
+
+ }
|
| 1661 |
+
+
|
| 1662 |
+
+ const llama_vocab * vocab = llama_model_get_vocab(model.get());
|
| 1663 |
+
+ std::vector<llama_token> prompt_tokens;
|
| 1664 |
+
+ if (!tokenize_prompt(vocab, opts.prompt, prompt_tokens)) {
|
| 1665 |
+
+ return 3;
|
| 1666 |
+
+ }
|
| 1667 |
+
+
|
| 1668 |
+
+ const uint64_t required_context = prompt_tokens.size() + static_cast<uint64_t>(opts.n_predict);
|
| 1669 |
+
+ if (required_context > PALW_CONTEXT_TOKENS ||
|
| 1670 |
+
+ PALW_CONTEXT_TOKENS > static_cast<uint64_t>(llama_model_n_ctx_train(model.get()))) {
|
| 1671 |
+
+ std::fprintf(stderr, "error: prompt plus n-predict exceeds the fixed PALW context bound\n");
|
| 1672 |
+
+ return 3;
|
| 1673 |
+
+ }
|
| 1674 |
+
+
|
| 1675 |
+
+ graph_observer observer(opts.mode, llama_model_n_layer(model.get()));
|
| 1676 |
+
+ llama_context_params context_params = llama_context_default_params();
|
| 1677 |
+
+ context_params.n_ctx = PALW_CONTEXT_TOKENS;
|
| 1678 |
+
+ context_params.n_batch = 1;
|
| 1679 |
+
+ context_params.n_ubatch = 1;
|
| 1680 |
+
+ context_params.n_seq_max = 1;
|
| 1681 |
+
+ context_params.n_outputs_max = 1;
|
| 1682 |
+
+ context_params.n_threads = 1;
|
| 1683 |
+
+ context_params.n_threads_batch = 1;
|
| 1684 |
+
+ context_params.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_DISABLED;
|
| 1685 |
+
+ context_params.type_k = GGML_TYPE_F16;
|
| 1686 |
+
+ context_params.type_v = GGML_TYPE_F16;
|
| 1687 |
+
+ context_params.embeddings = false;
|
| 1688 |
+
+ context_params.offload_kqv = true;
|
| 1689 |
+
+ context_params.no_perf = true;
|
| 1690 |
+
+ context_params.op_offload = true;
|
| 1691 |
+
+ context_params.kv_unified = false;
|
| 1692 |
+
+ if (opts.mode != observer_mode::off) {
|
| 1693 |
+
+ context_params.cb_eval = graph_observer::callback;
|
| 1694 |
+
+ context_params.cb_eval_user_data = &observer;
|
| 1695 |
+
+ g_diag_enabled = std::getenv("PALW_TRACE_DIAG") != nullptr;
|
| 1696 |
+
+ // Capture every Metal kernel dispatch so GEMMs can be bound to the actual
|
| 1697 |
+
+ // kernel + launch geometry that produced them (kernel-level trace).
|
| 1698 |
+
+ if (opts.mode == observer_mode::sketch) {
|
| 1699 |
+
+ ggml_metal_palw_set_dispatch_hook(graph_observer::dispatch_hook, &observer);
|
| 1700 |
+
+ }
|
| 1701 |
+
+ }
|
| 1702 |
+
+
|
| 1703 |
+
+ using context_ptr = std::unique_ptr<llama_context, decltype(&llama_free)>;
|
| 1704 |
+
+ context_ptr context(llama_init_from_model(model.get(), context_params), llama_free);
|
| 1705 |
+
+ if (!context) {
|
| 1706 |
+
+ std::fprintf(stderr, "error: failed to initialize context\n");
|
| 1707 |
+
+ return 3;
|
| 1708 |
+
+ }
|
| 1709 |
+
+ if (llama_n_batch(context.get()) != 1 || llama_n_ubatch(context.get()) != 1 ||
|
| 1710 |
+
+ llama_n_seq_max(context.get()) != 1 || llama_n_ctx(context.get()) != PALW_CONTEXT_TOKENS ||
|
| 1711 |
+
+ llama_n_threads(context.get()) != 1 || llama_n_threads_batch(context.get()) != 1) {
|
| 1712 |
+
+ std::fprintf(stderr, "error: runtime did not honor the deterministic execution policy\n");
|
| 1713 |
+
+ return 3;
|
| 1714 |
+
+ }
|
| 1715 |
+
+
|
| 1716 |
+
+ if (!emit_header(opts, model.get(), context.get(), metadata, prompt_tokens.size())) {
|
| 1717 |
+
+ return 4;
|
| 1718 |
+
+ }
|
| 1719 |
+
+
|
| 1720 |
+
+ std::vector<llama_token> generated_tokens;
|
| 1721 |
+
+ std::vector<uint8_t> output_bytes;
|
| 1722 |
+
+ generated_tokens.reserve(static_cast<size_t>(opts.n_predict));
|
| 1723 |
+
+
|
| 1724 |
+
+ for (size_t i = 0; i < prompt_tokens.size(); ++i) {
|
| 1725 |
+
+ observer.set_phase("prefill", static_cast<int64_t>(i));
|
| 1726 |
+
+ llama_token token = prompt_tokens[i];
|
| 1727 |
+
+ const int32_t decode_status = llama_decode(context.get(), llama_batch_get_one(&token, 1));
|
| 1728 |
+
+ if (decode_status != 0) {
|
| 1729 |
+
+ const std::string error = "llama_decode prefill status " + std::to_string(decode_status);
|
| 1730 |
+
+ emit_result(opts, "error", "decode_error", prompt_tokens, generated_tokens,
|
| 1731 |
+
+ output_bytes, observer, error);
|
| 1732 |
+
+ return 5;
|
| 1733 |
+
+ }
|
| 1734 |
+
+ if (observer.failed()) {
|
| 1735 |
+
+ emit_result(opts, "error", "observer_error", prompt_tokens, generated_tokens,
|
| 1736 |
+
+ output_bytes, observer, observer.error());
|
| 1737 |
+
+ return 5;
|
| 1738 |
+
+ }
|
| 1739 |
+
+ }
|
| 1740 |
+
+
|
| 1741 |
+
+ using sampler_ptr = std::unique_ptr<llama_sampler, decltype(&llama_sampler_free)>;
|
| 1742 |
+
+ sampler_ptr sampler(llama_sampler_init_greedy(), llama_sampler_free);
|
| 1743 |
+
+ if (!sampler) {
|
| 1744 |
+
+ emit_result(opts, "error", "sampler_error", prompt_tokens, generated_tokens,
|
| 1745 |
+
+ output_bytes, observer, "failed to initialize greedy sampler");
|
| 1746 |
+
+ return 5;
|
| 1747 |
+
+ }
|
| 1748 |
+
+
|
| 1749 |
+
+ const char * stop_reason = "n_predict";
|
| 1750 |
+
+ for (int32_t i = 0; i < opts.n_predict; ++i) {
|
| 1751 |
+
+ const llama_token token = llama_sampler_sample(sampler.get(), context.get(), -1);
|
| 1752 |
+
+ if (token < 0 || token >= llama_vocab_n_tokens(vocab)) {
|
| 1753 |
+
+ emit_result(opts, "error", "sampler_error", prompt_tokens, generated_tokens,
|
| 1754 |
+
+ output_bytes, observer, "greedy sampler returned an out-of-range token");
|
| 1755 |
+
+ return 5;
|
| 1756 |
+
+ }
|
| 1757 |
+
+ generated_tokens.push_back(token);
|
| 1758 |
+
+ if (llama_vocab_is_eog(vocab, token)) {
|
| 1759 |
+
+ stop_reason = "eog";
|
| 1760 |
+
+ break;
|
| 1761 |
+
+ }
|
| 1762 |
+
+ if (!append_token_piece(vocab, token, output_bytes)) {
|
| 1763 |
+
+ emit_result(opts, "error", "detokenize_error", prompt_tokens, generated_tokens,
|
| 1764 |
+
+ output_bytes, observer, "failed to convert generated token to bytes");
|
| 1765 |
+
+ return 5;
|
| 1766 |
+
+ }
|
| 1767 |
+
+ if (i + 1 == opts.n_predict) {
|
| 1768 |
+
+ break;
|
| 1769 |
+
+ }
|
| 1770 |
+
+
|
| 1771 |
+
+ observer.set_phase("decode", i);
|
| 1772 |
+
+ llama_token mutable_token = token;
|
| 1773 |
+
+ const int32_t decode_status = llama_decode(context.get(), llama_batch_get_one(&mutable_token, 1));
|
| 1774 |
+
+ if (decode_status != 0) {
|
| 1775 |
+
+ const std::string error = "llama_decode generation status " + std::to_string(decode_status);
|
| 1776 |
+
+ emit_result(opts, "error", "decode_error", prompt_tokens, generated_tokens,
|
| 1777 |
+
+ output_bytes, observer, error);
|
| 1778 |
+
+ return 5;
|
| 1779 |
+
+ }
|
| 1780 |
+
+ if (observer.failed()) {
|
| 1781 |
+
+ emit_result(opts, "error", "observer_error", prompt_tokens, generated_tokens,
|
| 1782 |
+
+ output_bytes, observer, observer.error());
|
| 1783 |
+
+ return 5;
|
| 1784 |
+
+ }
|
| 1785 |
+
+ }
|
| 1786 |
+
+
|
| 1787 |
+
+ if (!emit_result(opts, "ok", stop_reason, prompt_tokens, generated_tokens,
|
| 1788 |
+
+ output_bytes, observer, {})) {
|
| 1789 |
+
+ return 4;
|
| 1790 |
+
+ }
|
| 1791 |
+
+ return 0;
|
| 1792 |
+
+}
|
pyproject.toml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "misaka-palw-runtime"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "Model acquisition tooling for the MISAKA PALW Qwen3.6-35B-A3B runtime"
|
| 5 |
+
readme = "README.md"
|
| 6 |
+
requires-python = ">=3.12,<3.13"
|
| 7 |
+
dependencies = [
|
| 8 |
+
"huggingface-hub[hf-xet]>=0.30,<2",
|
| 9 |
+
]
|
| 10 |
+
|
| 11 |
+
[tool.uv]
|
| 12 |
+
package = false
|
receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.complete
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
misaka.palw.receipt-set.v2
|
| 2 |
+
receipt_id=ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68
|
| 3 |
+
bundle_id=6fd4e57a6cbcd6fc1d9138989960b627c9ee4817bc3ac4ce889a1a1b41d7d63b
|
| 4 |
+
public_json_sha256=3aa158cacd9c790a85f550e232e1b5b3a5c3f1d81aaa0c5b56b57bb08f1dca22
|
receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"artifacts": {
|
| 3 |
+
"llama_commit": "12127defda4f41b7679cb2477a4b0d65ee6a0c8f",
|
| 4 |
+
"model_bytes": 5027783488,
|
| 5 |
+
"model_palw_root": "ad7d0e950531195bc2cf84f112fee6487777f78120c9a809cf9306c7a7a8684f",
|
| 6 |
+
"tokenizer_palw_root": "63839f0ab58084bbaa108a877e52bebd685b2c0616fcfab684a08354dee713dd"
|
| 7 |
+
},
|
| 8 |
+
"canonical_compute_units": 12135,
|
| 9 |
+
"canonical_receipt_file": "ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw",
|
| 10 |
+
"completion_marker": "ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.complete",
|
| 11 |
+
"cu_ruleset_id": "d8ef60255b3ba7ab12062942771b3e0ac9a674f151c3c321fe82c7d1fe52d299",
|
| 12 |
+
"decode_tokens": 2,
|
| 13 |
+
"durable_state_database": "palw-state.sqlite3",
|
| 14 |
+
"encrypted_verification_bundle": "ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw.bundle",
|
| 15 |
+
"evidence_level": "gemm_traced",
|
| 16 |
+
"execution_nullifier": "da2977c18f045718d8027301d8045e979db7d17b38d288daf6b897a4ebd0bad2",
|
| 17 |
+
"expires_epoch": 100,
|
| 18 |
+
"gemm_trace_root": "ebfd5d143ee57b1db20751ae4d241479fa9447cd5fcc7052fccce129604b78bc",
|
| 19 |
+
"issued_epoch": 1,
|
| 20 |
+
"job_class": "self_local",
|
| 21 |
+
"job_nullifier": "bb669cc73bb376766555e99592399a93b713ab190f3f9447a1f79046c19a0cbb",
|
| 22 |
+
"model_profile_id": "0c58c66b03bb471a248cb36be954b42945c6694c148370e6852f674ff98e64d4",
|
| 23 |
+
"network_id": "5314ef28b17106c232db89c7ada20d4e72f7d20bb95a7025c5c9abcec19055d9",
|
| 24 |
+
"observer_summary": {
|
| 25 |
+
"canonical_operations": 4890,
|
| 26 |
+
"decode_graph_steps": 1,
|
| 27 |
+
"gemm_events": 1625,
|
| 28 |
+
"prefill_graph_steps": 4
|
| 29 |
+
},
|
| 30 |
+
"operation_schedule_commitment": "6ee6163863df1a9a715bb42dc89d7431c13e0cb2538d022d074ca07c11aabab7",
|
| 31 |
+
"output_commitment": "ab778d40a2e00f8d047a5e5c79924e3667aad43c12af9aceea95044843353de8",
|
| 32 |
+
"owner_commitment": "eb8102e4a86b9636e528caa80926b17b5b2044a9d2c7ccf8bbcd650cefe0c406",
|
| 33 |
+
"prefill_tokens": 4,
|
| 34 |
+
"privacy": {
|
| 35 |
+
"decoded_output_bytes_retained": false,
|
| 36 |
+
"generated_tokens_public": false,
|
| 37 |
+
"output_nonce_public": false,
|
| 38 |
+
"owner_salt_encrypted": true,
|
| 39 |
+
"owner_salt_public": false,
|
| 40 |
+
"private_signing_keys_retained": false,
|
| 41 |
+
"prompt_output_opening_encrypted": true,
|
| 42 |
+
"prompt_tokens_public": false,
|
| 43 |
+
"signed_assignment_encrypted": true,
|
| 44 |
+
"signed_request_encrypted": true
|
| 45 |
+
},
|
| 46 |
+
"receipt_id": "ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68",
|
| 47 |
+
"replica_slot": 0,
|
| 48 |
+
"request_commitment": "fbed17891d3e8e326e18ba00dbdec05de729b33c2f271581a03988b214c615e1",
|
| 49 |
+
"runtime_class_id": "5b2fd7a56d73aa9757e516f92cbc7b4d43995ebe9ed27e445b9b7ab4cd8c7bc9",
|
| 50 |
+
"runtime_manifest_hash": "2b9c3cd05942f16b36ab348bc71033c33e8f7aa6872ce4c0c0fcac3ba0212bc1",
|
| 51 |
+
"schedule_event_count": 4890,
|
| 52 |
+
"scheduler_job_id": "407bacfe3d8ad3dcfa7ba0ab15f7d16b95473d6c43f26755fa08dd2617fdf447",
|
| 53 |
+
"schema": "misaka.palw.public-receipt.v2",
|
| 54 |
+
"shape_profile_id": "c4f8ae70ab6fda2707d841a64d79d36cff58509ea7f228eb4c93b693e630d674",
|
| 55 |
+
"signed_assignment_id": "2aa43b4369cbd2f584898764aefc99005afb81bc633882dddf6525022f0e9c68",
|
| 56 |
+
"signer_key_id": "af0ff7daae66f1fc903775994351e8c099b1fa2e9495f1d84f4a0d8ba08d5d91",
|
| 57 |
+
"timestamp_millis": 1784101608591,
|
| 58 |
+
"trace_event_count": 1625,
|
| 59 |
+
"trace_evidence": "graph_fallback",
|
| 60 |
+
"trace_scheme_id": "809191d894ecc9d0ec53b1b2da9eafa5856eb26c6bfc641ea6405c041130d8a0",
|
| 61 |
+
"verification_bundle_id": "6fd4e57a6cbcd6fc1d9138989960b627c9ee4817bc3ac4ce889a1a1b41d7d63b",
|
| 62 |
+
"worker_credential_id": "ff0bc29f4f856fb7dec1c39e8f4dcd7e20990917b04242a6bfa87d05e9ca341e"
|
| 63 |
+
}
|
receipts/final-v5/ab2b3196a6c0935aafd4d563a9d2e1d71d828cc87a378ae77b8e49c102033b68.palw
ADDED
|
Binary file (713 Bytes). View file
|
|
|
receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.complete
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
misaka.palw.receipt-set.v2
|
| 2 |
+
receipt_id=eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131
|
| 3 |
+
bundle_id=359f1bedaeefc1e140bf8c0dbba11582cb5cc0be428dcd95bc6077721f8096e9
|
| 4 |
+
public_json_sha256=03bee886144a2c64dd5f4d2207f86c748f5a3e7891b43f82f077f051342c3d0b
|
receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"artifacts": {
|
| 3 |
+
"llama_commit": "12127defda4f41b7679cb2477a4b0d65ee6a0c8f",
|
| 4 |
+
"model_bytes": 5027783488,
|
| 5 |
+
"model_palw_root": "ad7d0e950531195bc2cf84f112fee6487777f78120c9a809cf9306c7a7a8684f",
|
| 6 |
+
"tokenizer_palw_root": "63839f0ab58084bbaa108a877e52bebd685b2c0616fcfab684a08354dee713dd"
|
| 7 |
+
},
|
| 8 |
+
"canonical_compute_units": 14562,
|
| 9 |
+
"canonical_receipt_file": "eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.palw",
|
| 10 |
+
"completion_marker": "eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.complete",
|
| 11 |
+
"cu_ruleset_id": "d8ef60255b3ba7ab12062942771b3e0ac9a674f151c3c321fe82c7d1fe52d299",
|
| 12 |
+
"decode_tokens": 2,
|
| 13 |
+
"durable_state_database": "palw-state.sqlite3",
|
| 14 |
+
"encrypted_verification_bundle": "eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.palw.bundle",
|
| 15 |
+
"evidence_level": "gemm_traced",
|
| 16 |
+
"execution_nullifier": "1ff2d8035bee73c268c9ab39ea493f6f6112c28c1508a9e4ed972a09124ed5a8",
|
| 17 |
+
"expires_epoch": 100,
|
| 18 |
+
"gemm_trace_root": "53c906957957aa34cd5c66fc9ad8c863e541732ead6728e3125d78dff6c133f1",
|
| 19 |
+
"issued_epoch": 1,
|
| 20 |
+
"job_class": "self_local",
|
| 21 |
+
"job_nullifier": "848144497db27d8e39d38d1e41bf05cd7cc54fbd7e4267dc16db6c5cb0c81e73",
|
| 22 |
+
"model_profile_id": "0c58c66b03bb471a248cb36be954b42945c6694c148370e6852f674ff98e64d4",
|
| 23 |
+
"network_id": "5314ef28b17106c232db89c7ada20d4e72f7d20bb95a7025c5c9abcec19055d9",
|
| 24 |
+
"observer_summary": {
|
| 25 |
+
"canonical_operations": 5868,
|
| 26 |
+
"decode_graph_steps": 1,
|
| 27 |
+
"gemm_events": 1950,
|
| 28 |
+
"prefill_graph_steps": 5
|
| 29 |
+
},
|
| 30 |
+
"operation_schedule_commitment": "ad5b7b98c81354be64a9021cb7a20838ccf9d555576fc0743c79286ea29681f6",
|
| 31 |
+
"output_commitment": "6dab6a439df562c1da3dc54c4d0390b951631d0b54cfce023fa7429541c63acf",
|
| 32 |
+
"owner_commitment": "784f01145a243ff47af1e5a8f10900e70d8923208f754ad44818ba062ca4c4b3",
|
| 33 |
+
"prefill_tokens": 5,
|
| 34 |
+
"privacy": {
|
| 35 |
+
"decoded_output_bytes_retained": false,
|
| 36 |
+
"generated_tokens_public": false,
|
| 37 |
+
"output_nonce_public": false,
|
| 38 |
+
"owner_salt_encrypted": true,
|
| 39 |
+
"owner_salt_public": false,
|
| 40 |
+
"private_signing_keys_retained": false,
|
| 41 |
+
"prompt_output_opening_encrypted": true,
|
| 42 |
+
"prompt_tokens_public": false,
|
| 43 |
+
"signed_assignment_encrypted": true,
|
| 44 |
+
"signed_request_encrypted": true
|
| 45 |
+
},
|
| 46 |
+
"receipt_id": "eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131",
|
| 47 |
+
"replica_slot": 0,
|
| 48 |
+
"request_commitment": "baa38c80930d4af9186c4b708d2cbfef2f1ee789caef11dcd3c5a66dfbe11921",
|
| 49 |
+
"runtime_class_id": "c38307d57c847f3c276247411c563daf50fc7576cf1f6488ab29fe9a56970c5c",
|
| 50 |
+
"runtime_manifest_hash": "5920accc3a0a0529c5f0c0a4050d6bf00d4d8fdf2b9772b64af2b4fdac2b84dd",
|
| 51 |
+
"schedule_event_count": 5868,
|
| 52 |
+
"scheduler_job_id": "5425d9aa3d39fa5d80275d60a498274979bff103cc7a8214bf2418f4c3b6d81b",
|
| 53 |
+
"schema": "misaka.palw.public-receipt.v2",
|
| 54 |
+
"shape_profile_id": "c4f8ae70ab6fda2707d841a64d79d36cff58509ea7f228eb4c93b693e630d674",
|
| 55 |
+
"signed_assignment_id": "022501b13963fa70d45d86dae37386f0ed41bb9ae79646beb1fc41fca159e4f6",
|
| 56 |
+
"signer_key_id": "d1c014d205033b8b7e01a712bce01d57afd1fa8a0d96f4bf1809c551827b31ef",
|
| 57 |
+
"timestamp_millis": 1784111006188,
|
| 58 |
+
"trace_event_count": 1950,
|
| 59 |
+
"trace_evidence": "graph_fallback",
|
| 60 |
+
"trace_scheme_id": "809191d894ecc9d0ec53b1b2da9eafa5856eb26c6bfc641ea6405c041130d8a0",
|
| 61 |
+
"verification_bundle_id": "359f1bedaeefc1e140bf8c0dbba11582cb5cc0be428dcd95bc6077721f8096e9",
|
| 62 |
+
"worker_credential_id": "99663e6ddd5e0e38684beebf9d9c46872e960745bf9ab66bfbaa92e60af822d5"
|
| 63 |
+
}
|
receipts/final-v6/eb51b08c3b86ef5df2cdebcfa9fcef812ec72197b3ad40ae2c5ba68cf4278131.palw
ADDED
|
Binary file (713 Bytes). View file
|
|
|
receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.complete
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
misaka.palw.receipt-set.v2
|
| 2 |
+
receipt_id=8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9
|
| 3 |
+
bundle_id=f5b8a2968c4ea266b2cbbabf351a171e0fa2581984eff63362de2640fcdcf9db
|
| 4 |
+
public_json_sha256=2bc670c2de4147fa150126cc36a5f35b5c0600f0835b334e3d36de58ccbf5154
|
receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"artifacts": {
|
| 3 |
+
"llama_commit": "12127defda4f41b7679cb2477a4b0d65ee6a0c8f",
|
| 4 |
+
"model_bytes": 23938321728,
|
| 5 |
+
"model_palw_root": "f94585e843a993db3ff8f34232b72128784cb074942d3263a05d5da6dc25ef06",
|
| 6 |
+
"tokenizer_palw_root": "a5b09fef67156eaeb5b98e0c406a304c7b0fca75861bd2d7c02b4185a64ce762"
|
| 7 |
+
},
|
| 8 |
+
"canonical_compute_units": 41692,
|
| 9 |
+
"canonical_receipt_file": "8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.palw",
|
| 10 |
+
"completion_marker": "8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.complete",
|
| 11 |
+
"cu_ruleset_id": "43a5feef177b389f976361b22ac9d57da65815261282005bc78d1666a37870ce",
|
| 12 |
+
"decode_tokens": 2,
|
| 13 |
+
"durable_state_database": "palw-state.sqlite3",
|
| 14 |
+
"encrypted_verification_bundle": "8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.palw.bundle",
|
| 15 |
+
"evidence_level": "gemm_traced",
|
| 16 |
+
"execution_nullifier": "1ea89b576f78cbbbc1f878b8f786e2aa6158b9d3a9762b43146207ddba85e16e",
|
| 17 |
+
"expert_route": {
|
| 18 |
+
"root": "5e4ea70ba91658e6a24cf3da00ac747eae4985ea5f0dc8f46009cc827bbc1c9e",
|
| 19 |
+
"route_event_count": 240
|
| 20 |
+
},
|
| 21 |
+
"expires_epoch": 100,
|
| 22 |
+
"gemm_trace_root": "78f6f15a768bcfa90597c2ee1cb25c4e08beb32f869e5dfb45f43fc9bb6d84f7",
|
| 23 |
+
"issued_epoch": 1,
|
| 24 |
+
"job_class": "self_local",
|
| 25 |
+
"job_nullifier": "2d8b5b9d5ea6699c47b06c1defb044f9a6582b216cd438a172ee6af92fd8bfb9",
|
| 26 |
+
"mint": {
|
| 27 |
+
"class": "local_self_consistent_v0_1",
|
| 28 |
+
"eligible": false,
|
| 29 |
+
"ineligible_reasons": [
|
| 30 |
+
"trace is a Metal kernel-launch-bound sketch, not an intra-kernel accumulator proof",
|
| 31 |
+
"assignment is an embedded local snapshot, not a network-anchored challenge-bound assignment",
|
| 32 |
+
"signing identity is ephemeral and not bonded to a persistent worker credential"
|
| 33 |
+
],
|
| 34 |
+
"mainnet_ready": false,
|
| 35 |
+
"weight": 0
|
| 36 |
+
},
|
| 37 |
+
"model_profile_id": "b6b83a274a889fc5dfa2044b9158111b3849f880a05eb7ebcf560d036515d472",
|
| 38 |
+
"network_id": "5314ef28b17106c232db89c7ada20d4e72f7d20bb95a7025c5c9abcec19055d9",
|
| 39 |
+
"observer_summary": {
|
| 40 |
+
"canonical_operations": 13770,
|
| 41 |
+
"decode_graph_steps": 1,
|
| 42 |
+
"gemm_events": 2466,
|
| 43 |
+
"prefill_graph_steps": 5
|
| 44 |
+
},
|
| 45 |
+
"operation_schedule_commitment": "eb29962a094774e4de78c426cd653249540aab371a0a69372f0a4b4371696322",
|
| 46 |
+
"output_commitment": "16d16907a410297aec0f01527c89304461fc1390f8afa49c091b63b1d422b9e0",
|
| 47 |
+
"owner_commitment": "64c702b1d90842b85e4e554cc18413a04c1309db0f47c300e4102d9e042c5284",
|
| 48 |
+
"prefill_tokens": 5,
|
| 49 |
+
"privacy": {
|
| 50 |
+
"decoded_output_bytes_retained": false,
|
| 51 |
+
"generated_tokens_public": false,
|
| 52 |
+
"output_nonce_public": false,
|
| 53 |
+
"owner_salt_encrypted": true,
|
| 54 |
+
"owner_salt_public": false,
|
| 55 |
+
"private_signing_keys_retained": false,
|
| 56 |
+
"prompt_output_opening_encrypted": true,
|
| 57 |
+
"prompt_tokens_public": false,
|
| 58 |
+
"signed_assignment_encrypted": true,
|
| 59 |
+
"signed_request_encrypted": true
|
| 60 |
+
},
|
| 61 |
+
"receipt_id": "8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9",
|
| 62 |
+
"replica_slot": 0,
|
| 63 |
+
"request_commitment": "d9a4994816b1bf29f561cbe181e57c086a89a17a0407cc0e9c8960cf223f16b8",
|
| 64 |
+
"runtime_class_id": "8f6f536118a72be70dab2028535c3bb95e3de9a3bac0e9b81cf78677ae902a9c",
|
| 65 |
+
"runtime_manifest_hash": "8a07a1767a7e503259f9b157d932454ce790f428f7b8d271d4b472f1f5103963",
|
| 66 |
+
"schedule_event_count": 13770,
|
| 67 |
+
"scheduler_job_id": "ea681cd4d99163aec502aba3d23513197f861ce4e6495243c85a404f910f823e",
|
| 68 |
+
"schema": "misaka.palw.public-receipt.v2",
|
| 69 |
+
"semantic_compute_units_v3": 41692,
|
| 70 |
+
"semantic_schedule": {
|
| 71 |
+
"attention_ops": 20,
|
| 72 |
+
"commitment": "e6fc731e80e9b1135beced7f178dd8c9eda542507cb4c143451b523c361ead34",
|
| 73 |
+
"expert_route_ops": 80,
|
| 74 |
+
"forward_passes": 2,
|
| 75 |
+
"gemm_ops": 82,
|
| 76 |
+
"total_ops": 764
|
| 77 |
+
},
|
| 78 |
+
"shape_profile_id": "c4f8ae70ab6fda2707d841a64d79d36cff58509ea7f228eb4c93b693e630d674",
|
| 79 |
+
"signed_assignment_id": "94dec962b00f395a8ef349f4227f2bdebc716f261b7ce8a88e17efe31c5778b8",
|
| 80 |
+
"signer_key_id": "b2d968277c5e5464a273c92c5d501565367117b68c7d949823bd2403f77601ed",
|
| 81 |
+
"timestamp_millis": 1784446365200,
|
| 82 |
+
"trace_event_count": 2466,
|
| 83 |
+
"trace_evidence": "metal_kernel",
|
| 84 |
+
"trace_scheme_id": "809191d894ecc9d0ec53b1b2da9eafa5856eb26c6bfc641ea6405c041130d8a0",
|
| 85 |
+
"verification_bundle_id": "f5b8a2968c4ea266b2cbbabf351a171e0fa2581984eff63362de2640fcdcf9db",
|
| 86 |
+
"worker_credential_id": "94351cf05b8fa9c4a6b2a31a492ba08f0931cb659a44ae06d7d39ebd2cf0bff0"
|
| 87 |
+
}
|
receipts/final-v7/8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9.palw
ADDED
|
Binary file (713 Bytes). View file
|
|
|
runtime-palw/Cargo.lock
ADDED
|
@@ -0,0 +1,852 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is automatically @generated by Cargo.
|
| 2 |
+
# It is not intended for manual editing.
|
| 3 |
+
version = 3
|
| 4 |
+
|
| 5 |
+
[[package]]
|
| 6 |
+
name = "aead"
|
| 7 |
+
version = "0.5.2"
|
| 8 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 9 |
+
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
| 10 |
+
dependencies = [
|
| 11 |
+
"crypto-common 0.1.7",
|
| 12 |
+
"generic-array",
|
| 13 |
+
]
|
| 14 |
+
|
| 15 |
+
[[package]]
|
| 16 |
+
name = "ahash"
|
| 17 |
+
version = "0.8.12"
|
| 18 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 19 |
+
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
| 20 |
+
dependencies = [
|
| 21 |
+
"cfg-if",
|
| 22 |
+
"once_cell",
|
| 23 |
+
"version_check",
|
| 24 |
+
"zerocopy",
|
| 25 |
+
]
|
| 26 |
+
|
| 27 |
+
[[package]]
|
| 28 |
+
name = "arrayref"
|
| 29 |
+
version = "0.3.9"
|
| 30 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 31 |
+
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
| 32 |
+
|
| 33 |
+
[[package]]
|
| 34 |
+
name = "arrayvec"
|
| 35 |
+
version = "0.7.8"
|
| 36 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 37 |
+
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
|
| 38 |
+
|
| 39 |
+
[[package]]
|
| 40 |
+
name = "autocfg"
|
| 41 |
+
version = "1.5.1"
|
| 42 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 43 |
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
| 44 |
+
|
| 45 |
+
[[package]]
|
| 46 |
+
name = "base64ct"
|
| 47 |
+
version = "1.7.3"
|
| 48 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 49 |
+
checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3"
|
| 50 |
+
|
| 51 |
+
[[package]]
|
| 52 |
+
name = "bitflags"
|
| 53 |
+
version = "2.13.0"
|
| 54 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 55 |
+
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
| 56 |
+
|
| 57 |
+
[[package]]
|
| 58 |
+
name = "blake2b_simd"
|
| 59 |
+
version = "1.0.4"
|
| 60 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 61 |
+
checksum = "b79834656f71332577234b50bfc009996f7449e0c056884e6a02492ded0ca2f3"
|
| 62 |
+
dependencies = [
|
| 63 |
+
"arrayref",
|
| 64 |
+
"arrayvec",
|
| 65 |
+
"constant_time_eq",
|
| 66 |
+
]
|
| 67 |
+
|
| 68 |
+
[[package]]
|
| 69 |
+
name = "block-buffer"
|
| 70 |
+
version = "0.10.4"
|
| 71 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 72 |
+
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
| 73 |
+
dependencies = [
|
| 74 |
+
"generic-array",
|
| 75 |
+
]
|
| 76 |
+
|
| 77 |
+
[[package]]
|
| 78 |
+
name = "cc"
|
| 79 |
+
version = "1.2.67"
|
| 80 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 81 |
+
checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38"
|
| 82 |
+
dependencies = [
|
| 83 |
+
"find-msvc-tools",
|
| 84 |
+
"shlex",
|
| 85 |
+
]
|
| 86 |
+
|
| 87 |
+
[[package]]
|
| 88 |
+
name = "cfg-if"
|
| 89 |
+
version = "1.0.4"
|
| 90 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 91 |
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
| 92 |
+
|
| 93 |
+
[[package]]
|
| 94 |
+
name = "chacha20"
|
| 95 |
+
version = "0.9.1"
|
| 96 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 97 |
+
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
|
| 98 |
+
dependencies = [
|
| 99 |
+
"cfg-if",
|
| 100 |
+
"cipher",
|
| 101 |
+
"cpufeatures 0.2.17",
|
| 102 |
+
]
|
| 103 |
+
|
| 104 |
+
[[package]]
|
| 105 |
+
name = "chacha20poly1305"
|
| 106 |
+
version = "0.10.1"
|
| 107 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 108 |
+
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
|
| 109 |
+
dependencies = [
|
| 110 |
+
"aead",
|
| 111 |
+
"chacha20",
|
| 112 |
+
"cipher",
|
| 113 |
+
"poly1305",
|
| 114 |
+
"zeroize",
|
| 115 |
+
]
|
| 116 |
+
|
| 117 |
+
[[package]]
|
| 118 |
+
name = "cipher"
|
| 119 |
+
version = "0.4.4"
|
| 120 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 121 |
+
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
| 122 |
+
dependencies = [
|
| 123 |
+
"crypto-common 0.1.7",
|
| 124 |
+
"inout",
|
| 125 |
+
"zeroize",
|
| 126 |
+
]
|
| 127 |
+
|
| 128 |
+
[[package]]
|
| 129 |
+
name = "cmov"
|
| 130 |
+
version = "0.5.4"
|
| 131 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 132 |
+
checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
|
| 133 |
+
|
| 134 |
+
[[package]]
|
| 135 |
+
name = "const-oid"
|
| 136 |
+
version = "0.9.6"
|
| 137 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 138 |
+
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
| 139 |
+
|
| 140 |
+
[[package]]
|
| 141 |
+
name = "const-oid"
|
| 142 |
+
version = "0.10.2"
|
| 143 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 144 |
+
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
| 145 |
+
|
| 146 |
+
[[package]]
|
| 147 |
+
name = "constant_time_eq"
|
| 148 |
+
version = "0.4.2"
|
| 149 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 150 |
+
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
|
| 151 |
+
|
| 152 |
+
[[package]]
|
| 153 |
+
name = "cpufeatures"
|
| 154 |
+
version = "0.2.17"
|
| 155 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 156 |
+
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
| 157 |
+
dependencies = [
|
| 158 |
+
"libc",
|
| 159 |
+
]
|
| 160 |
+
|
| 161 |
+
[[package]]
|
| 162 |
+
name = "cpufeatures"
|
| 163 |
+
version = "0.3.0"
|
| 164 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 165 |
+
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
| 166 |
+
dependencies = [
|
| 167 |
+
"libc",
|
| 168 |
+
]
|
| 169 |
+
|
| 170 |
+
[[package]]
|
| 171 |
+
name = "crypto-common"
|
| 172 |
+
version = "0.1.7"
|
| 173 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 174 |
+
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
| 175 |
+
dependencies = [
|
| 176 |
+
"generic-array",
|
| 177 |
+
"rand_core 0.6.4",
|
| 178 |
+
"typenum",
|
| 179 |
+
]
|
| 180 |
+
|
| 181 |
+
[[package]]
|
| 182 |
+
name = "crypto-common"
|
| 183 |
+
version = "0.2.2"
|
| 184 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 185 |
+
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
| 186 |
+
dependencies = [
|
| 187 |
+
"getrandom 0.4.3",
|
| 188 |
+
"hybrid-array",
|
| 189 |
+
"rand_core 0.10.1",
|
| 190 |
+
]
|
| 191 |
+
|
| 192 |
+
[[package]]
|
| 193 |
+
name = "ctutils"
|
| 194 |
+
version = "0.4.2"
|
| 195 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 196 |
+
checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
|
| 197 |
+
dependencies = [
|
| 198 |
+
"cmov",
|
| 199 |
+
]
|
| 200 |
+
|
| 201 |
+
[[package]]
|
| 202 |
+
name = "curve25519-dalek"
|
| 203 |
+
version = "4.1.3"
|
| 204 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 205 |
+
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
| 206 |
+
dependencies = [
|
| 207 |
+
"cfg-if",
|
| 208 |
+
"cpufeatures 0.2.17",
|
| 209 |
+
"curve25519-dalek-derive",
|
| 210 |
+
"digest 0.10.7",
|
| 211 |
+
"fiat-crypto",
|
| 212 |
+
"rustc_version",
|
| 213 |
+
"subtle",
|
| 214 |
+
"zeroize",
|
| 215 |
+
]
|
| 216 |
+
|
| 217 |
+
[[package]]
|
| 218 |
+
name = "curve25519-dalek-derive"
|
| 219 |
+
version = "0.1.1"
|
| 220 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 221 |
+
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
| 222 |
+
dependencies = [
|
| 223 |
+
"proc-macro2",
|
| 224 |
+
"quote",
|
| 225 |
+
"syn",
|
| 226 |
+
]
|
| 227 |
+
|
| 228 |
+
[[package]]
|
| 229 |
+
name = "der"
|
| 230 |
+
version = "0.7.10"
|
| 231 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 232 |
+
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
| 233 |
+
dependencies = [
|
| 234 |
+
"const-oid 0.9.6",
|
| 235 |
+
"zeroize",
|
| 236 |
+
]
|
| 237 |
+
|
| 238 |
+
[[package]]
|
| 239 |
+
name = "der"
|
| 240 |
+
version = "0.8.1"
|
| 241 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 242 |
+
checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d"
|
| 243 |
+
dependencies = [
|
| 244 |
+
"const-oid 0.10.2",
|
| 245 |
+
"zeroize",
|
| 246 |
+
]
|
| 247 |
+
|
| 248 |
+
[[package]]
|
| 249 |
+
name = "digest"
|
| 250 |
+
version = "0.10.7"
|
| 251 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 252 |
+
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
| 253 |
+
dependencies = [
|
| 254 |
+
"block-buffer",
|
| 255 |
+
"crypto-common 0.1.7",
|
| 256 |
+
]
|
| 257 |
+
|
| 258 |
+
[[package]]
|
| 259 |
+
name = "digest"
|
| 260 |
+
version = "0.11.3"
|
| 261 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 262 |
+
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
| 263 |
+
dependencies = [
|
| 264 |
+
"crypto-common 0.2.2",
|
| 265 |
+
]
|
| 266 |
+
|
| 267 |
+
[[package]]
|
| 268 |
+
name = "ed25519"
|
| 269 |
+
version = "2.2.3"
|
| 270 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 271 |
+
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
| 272 |
+
dependencies = [
|
| 273 |
+
"pkcs8 0.10.2",
|
| 274 |
+
"signature 2.2.0",
|
| 275 |
+
]
|
| 276 |
+
|
| 277 |
+
[[package]]
|
| 278 |
+
name = "ed25519-dalek"
|
| 279 |
+
version = "2.2.0"
|
| 280 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 281 |
+
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
|
| 282 |
+
dependencies = [
|
| 283 |
+
"curve25519-dalek",
|
| 284 |
+
"ed25519",
|
| 285 |
+
"rand_core 0.6.4",
|
| 286 |
+
"serde",
|
| 287 |
+
"sha2",
|
| 288 |
+
"subtle",
|
| 289 |
+
"zeroize",
|
| 290 |
+
]
|
| 291 |
+
|
| 292 |
+
[[package]]
|
| 293 |
+
name = "fallible-iterator"
|
| 294 |
+
version = "0.3.0"
|
| 295 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 296 |
+
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
| 297 |
+
|
| 298 |
+
[[package]]
|
| 299 |
+
name = "fallible-streaming-iterator"
|
| 300 |
+
version = "0.1.9"
|
| 301 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 302 |
+
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
| 303 |
+
|
| 304 |
+
[[package]]
|
| 305 |
+
name = "fiat-crypto"
|
| 306 |
+
version = "0.2.9"
|
| 307 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 308 |
+
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
| 309 |
+
|
| 310 |
+
[[package]]
|
| 311 |
+
name = "find-msvc-tools"
|
| 312 |
+
version = "0.1.9"
|
| 313 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 314 |
+
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
| 315 |
+
|
| 316 |
+
[[package]]
|
| 317 |
+
name = "generic-array"
|
| 318 |
+
version = "0.14.7"
|
| 319 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 320 |
+
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
| 321 |
+
dependencies = [
|
| 322 |
+
"typenum",
|
| 323 |
+
"version_check",
|
| 324 |
+
]
|
| 325 |
+
|
| 326 |
+
[[package]]
|
| 327 |
+
name = "getrandom"
|
| 328 |
+
version = "0.2.17"
|
| 329 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 330 |
+
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
| 331 |
+
dependencies = [
|
| 332 |
+
"cfg-if",
|
| 333 |
+
"libc",
|
| 334 |
+
"wasi",
|
| 335 |
+
]
|
| 336 |
+
|
| 337 |
+
[[package]]
|
| 338 |
+
name = "getrandom"
|
| 339 |
+
version = "0.4.3"
|
| 340 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 341 |
+
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
| 342 |
+
dependencies = [
|
| 343 |
+
"cfg-if",
|
| 344 |
+
"libc",
|
| 345 |
+
"r-efi",
|
| 346 |
+
"rand_core 0.10.1",
|
| 347 |
+
]
|
| 348 |
+
|
| 349 |
+
[[package]]
|
| 350 |
+
name = "hashbrown"
|
| 351 |
+
version = "0.14.5"
|
| 352 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 353 |
+
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
| 354 |
+
dependencies = [
|
| 355 |
+
"ahash",
|
| 356 |
+
]
|
| 357 |
+
|
| 358 |
+
[[package]]
|
| 359 |
+
name = "hashlink"
|
| 360 |
+
version = "0.9.1"
|
| 361 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 362 |
+
checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
|
| 363 |
+
dependencies = [
|
| 364 |
+
"hashbrown",
|
| 365 |
+
]
|
| 366 |
+
|
| 367 |
+
[[package]]
|
| 368 |
+
name = "hex"
|
| 369 |
+
version = "0.4.3"
|
| 370 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 371 |
+
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
| 372 |
+
|
| 373 |
+
[[package]]
|
| 374 |
+
name = "hybrid-array"
|
| 375 |
+
version = "0.4.13"
|
| 376 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 377 |
+
checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c"
|
| 378 |
+
dependencies = [
|
| 379 |
+
"ctutils",
|
| 380 |
+
"typenum",
|
| 381 |
+
]
|
| 382 |
+
|
| 383 |
+
[[package]]
|
| 384 |
+
name = "inout"
|
| 385 |
+
version = "0.1.4"
|
| 386 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 387 |
+
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
| 388 |
+
dependencies = [
|
| 389 |
+
"generic-array",
|
| 390 |
+
]
|
| 391 |
+
|
| 392 |
+
[[package]]
|
| 393 |
+
name = "itoa"
|
| 394 |
+
version = "1.0.18"
|
| 395 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 396 |
+
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
| 397 |
+
|
| 398 |
+
[[package]]
|
| 399 |
+
name = "keccak"
|
| 400 |
+
version = "0.1.6"
|
| 401 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 402 |
+
checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
|
| 403 |
+
dependencies = [
|
| 404 |
+
"cpufeatures 0.2.17",
|
| 405 |
+
]
|
| 406 |
+
|
| 407 |
+
[[package]]
|
| 408 |
+
name = "keccak"
|
| 409 |
+
version = "0.2.0"
|
| 410 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 411 |
+
checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa"
|
| 412 |
+
dependencies = [
|
| 413 |
+
"cfg-if",
|
| 414 |
+
"cpufeatures 0.3.0",
|
| 415 |
+
]
|
| 416 |
+
|
| 417 |
+
[[package]]
|
| 418 |
+
name = "libc"
|
| 419 |
+
version = "0.2.186"
|
| 420 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 421 |
+
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
| 422 |
+
|
| 423 |
+
[[package]]
|
| 424 |
+
name = "libsqlite3-sys"
|
| 425 |
+
version = "0.30.1"
|
| 426 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 427 |
+
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
|
| 428 |
+
dependencies = [
|
| 429 |
+
"cc",
|
| 430 |
+
"pkg-config",
|
| 431 |
+
"vcpkg",
|
| 432 |
+
]
|
| 433 |
+
|
| 434 |
+
[[package]]
|
| 435 |
+
name = "memchr"
|
| 436 |
+
version = "2.8.3"
|
| 437 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 438 |
+
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
| 439 |
+
|
| 440 |
+
[[package]]
|
| 441 |
+
name = "ml-dsa"
|
| 442 |
+
version = "0.1.1"
|
| 443 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 444 |
+
checksum = "add6b9d92e496f16f4526d68ff29da1483aba4b119baeab8bed3b9e3544a6f3d"
|
| 445 |
+
dependencies = [
|
| 446 |
+
"const-oid 0.10.2",
|
| 447 |
+
"crypto-common 0.2.2",
|
| 448 |
+
"ctutils",
|
| 449 |
+
"hybrid-array",
|
| 450 |
+
"module-lattice",
|
| 451 |
+
"pkcs8 0.11.0",
|
| 452 |
+
"shake",
|
| 453 |
+
"signature 3.0.0",
|
| 454 |
+
]
|
| 455 |
+
|
| 456 |
+
[[package]]
|
| 457 |
+
name = "module-lattice"
|
| 458 |
+
version = "0.2.3"
|
| 459 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 460 |
+
checksum = "0c61b87c9683ab7cb1c6871d261ad5479b6b10ceb52c4352aaca3b5d35a8febe"
|
| 461 |
+
dependencies = [
|
| 462 |
+
"ctutils",
|
| 463 |
+
"hybrid-array",
|
| 464 |
+
"num-traits",
|
| 465 |
+
]
|
| 466 |
+
|
| 467 |
+
[[package]]
|
| 468 |
+
name = "num-traits"
|
| 469 |
+
version = "0.2.19"
|
| 470 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 471 |
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
| 472 |
+
dependencies = [
|
| 473 |
+
"autocfg",
|
| 474 |
+
]
|
| 475 |
+
|
| 476 |
+
[[package]]
|
| 477 |
+
name = "once_cell"
|
| 478 |
+
version = "1.21.4"
|
| 479 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 480 |
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
| 481 |
+
|
| 482 |
+
[[package]]
|
| 483 |
+
name = "opaque-debug"
|
| 484 |
+
version = "0.3.1"
|
| 485 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 486 |
+
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
| 487 |
+
|
| 488 |
+
[[package]]
|
| 489 |
+
name = "pkcs8"
|
| 490 |
+
version = "0.10.2"
|
| 491 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 492 |
+
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
| 493 |
+
dependencies = [
|
| 494 |
+
"der 0.7.10",
|
| 495 |
+
"spki 0.7.3",
|
| 496 |
+
]
|
| 497 |
+
|
| 498 |
+
[[package]]
|
| 499 |
+
name = "pkcs8"
|
| 500 |
+
version = "0.11.0"
|
| 501 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 502 |
+
checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7"
|
| 503 |
+
dependencies = [
|
| 504 |
+
"der 0.8.1",
|
| 505 |
+
"spki 0.8.0",
|
| 506 |
+
]
|
| 507 |
+
|
| 508 |
+
[[package]]
|
| 509 |
+
name = "pkg-config"
|
| 510 |
+
version = "0.3.33"
|
| 511 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 512 |
+
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
|
| 513 |
+
|
| 514 |
+
[[package]]
|
| 515 |
+
name = "poly1305"
|
| 516 |
+
version = "0.8.0"
|
| 517 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 518 |
+
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
|
| 519 |
+
dependencies = [
|
| 520 |
+
"cpufeatures 0.2.17",
|
| 521 |
+
"opaque-debug",
|
| 522 |
+
"universal-hash",
|
| 523 |
+
]
|
| 524 |
+
|
| 525 |
+
[[package]]
|
| 526 |
+
name = "proc-macro2"
|
| 527 |
+
version = "1.0.106"
|
| 528 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 529 |
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
| 530 |
+
dependencies = [
|
| 531 |
+
"unicode-ident",
|
| 532 |
+
]
|
| 533 |
+
|
| 534 |
+
[[package]]
|
| 535 |
+
name = "quote"
|
| 536 |
+
version = "1.0.46"
|
| 537 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 538 |
+
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
| 539 |
+
dependencies = [
|
| 540 |
+
"proc-macro2",
|
| 541 |
+
]
|
| 542 |
+
|
| 543 |
+
[[package]]
|
| 544 |
+
name = "r-efi"
|
| 545 |
+
version = "6.0.0"
|
| 546 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 547 |
+
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
| 548 |
+
|
| 549 |
+
[[package]]
|
| 550 |
+
name = "rand_core"
|
| 551 |
+
version = "0.6.4"
|
| 552 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 553 |
+
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
| 554 |
+
dependencies = [
|
| 555 |
+
"getrandom 0.2.17",
|
| 556 |
+
]
|
| 557 |
+
|
| 558 |
+
[[package]]
|
| 559 |
+
name = "rand_core"
|
| 560 |
+
version = "0.10.1"
|
| 561 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 562 |
+
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
| 563 |
+
|
| 564 |
+
[[package]]
|
| 565 |
+
name = "runtime-palw"
|
| 566 |
+
version = "0.1.0"
|
| 567 |
+
dependencies = [
|
| 568 |
+
"base64ct",
|
| 569 |
+
"blake2b_simd",
|
| 570 |
+
"chacha20poly1305",
|
| 571 |
+
"ed25519-dalek",
|
| 572 |
+
"getrandom 0.2.17",
|
| 573 |
+
"hex",
|
| 574 |
+
"ml-dsa",
|
| 575 |
+
"rusqlite",
|
| 576 |
+
"serde",
|
| 577 |
+
"serde_json",
|
| 578 |
+
"sha2",
|
| 579 |
+
"sha3",
|
| 580 |
+
"thiserror",
|
| 581 |
+
"zeroize",
|
| 582 |
+
]
|
| 583 |
+
|
| 584 |
+
[[package]]
|
| 585 |
+
name = "rusqlite"
|
| 586 |
+
version = "0.32.1"
|
| 587 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 588 |
+
checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e"
|
| 589 |
+
dependencies = [
|
| 590 |
+
"bitflags",
|
| 591 |
+
"fallible-iterator",
|
| 592 |
+
"fallible-streaming-iterator",
|
| 593 |
+
"hashlink",
|
| 594 |
+
"libsqlite3-sys",
|
| 595 |
+
"smallvec",
|
| 596 |
+
]
|
| 597 |
+
|
| 598 |
+
[[package]]
|
| 599 |
+
name = "rustc_version"
|
| 600 |
+
version = "0.4.1"
|
| 601 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 602 |
+
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
| 603 |
+
dependencies = [
|
| 604 |
+
"semver",
|
| 605 |
+
]
|
| 606 |
+
|
| 607 |
+
[[package]]
|
| 608 |
+
name = "semver"
|
| 609 |
+
version = "1.0.28"
|
| 610 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 611 |
+
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
| 612 |
+
|
| 613 |
+
[[package]]
|
| 614 |
+
name = "serde"
|
| 615 |
+
version = "1.0.228"
|
| 616 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 617 |
+
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
| 618 |
+
dependencies = [
|
| 619 |
+
"serde_core",
|
| 620 |
+
"serde_derive",
|
| 621 |
+
]
|
| 622 |
+
|
| 623 |
+
[[package]]
|
| 624 |
+
name = "serde_core"
|
| 625 |
+
version = "1.0.228"
|
| 626 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 627 |
+
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
| 628 |
+
dependencies = [
|
| 629 |
+
"serde_derive",
|
| 630 |
+
]
|
| 631 |
+
|
| 632 |
+
[[package]]
|
| 633 |
+
name = "serde_derive"
|
| 634 |
+
version = "1.0.228"
|
| 635 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 636 |
+
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
| 637 |
+
dependencies = [
|
| 638 |
+
"proc-macro2",
|
| 639 |
+
"quote",
|
| 640 |
+
"syn",
|
| 641 |
+
]
|
| 642 |
+
|
| 643 |
+
[[package]]
|
| 644 |
+
name = "serde_json"
|
| 645 |
+
version = "1.0.150"
|
| 646 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 647 |
+
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
| 648 |
+
dependencies = [
|
| 649 |
+
"itoa",
|
| 650 |
+
"memchr",
|
| 651 |
+
"serde",
|
| 652 |
+
"serde_core",
|
| 653 |
+
"zmij",
|
| 654 |
+
]
|
| 655 |
+
|
| 656 |
+
[[package]]
|
| 657 |
+
name = "sha2"
|
| 658 |
+
version = "0.10.9"
|
| 659 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 660 |
+
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
| 661 |
+
dependencies = [
|
| 662 |
+
"cfg-if",
|
| 663 |
+
"cpufeatures 0.2.17",
|
| 664 |
+
"digest 0.10.7",
|
| 665 |
+
]
|
| 666 |
+
|
| 667 |
+
[[package]]
|
| 668 |
+
name = "sha3"
|
| 669 |
+
version = "0.10.9"
|
| 670 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 671 |
+
checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874"
|
| 672 |
+
dependencies = [
|
| 673 |
+
"digest 0.10.7",
|
| 674 |
+
"keccak 0.1.6",
|
| 675 |
+
]
|
| 676 |
+
|
| 677 |
+
[[package]]
|
| 678 |
+
name = "shake"
|
| 679 |
+
version = "0.1.0"
|
| 680 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 681 |
+
checksum = "09057cb2149ad4cbd2da1e26b351f9a4c354219421229c69c3063e6f61947c4a"
|
| 682 |
+
dependencies = [
|
| 683 |
+
"digest 0.11.3",
|
| 684 |
+
"keccak 0.2.0",
|
| 685 |
+
"sponge-cursor",
|
| 686 |
+
]
|
| 687 |
+
|
| 688 |
+
[[package]]
|
| 689 |
+
name = "shlex"
|
| 690 |
+
version = "2.0.1"
|
| 691 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 692 |
+
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
| 693 |
+
|
| 694 |
+
[[package]]
|
| 695 |
+
name = "signature"
|
| 696 |
+
version = "2.2.0"
|
| 697 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 698 |
+
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
| 699 |
+
dependencies = [
|
| 700 |
+
"rand_core 0.6.4",
|
| 701 |
+
]
|
| 702 |
+
|
| 703 |
+
[[package]]
|
| 704 |
+
name = "signature"
|
| 705 |
+
version = "3.0.0"
|
| 706 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 707 |
+
checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5"
|
| 708 |
+
dependencies = [
|
| 709 |
+
"digest 0.11.3",
|
| 710 |
+
"rand_core 0.10.1",
|
| 711 |
+
]
|
| 712 |
+
|
| 713 |
+
[[package]]
|
| 714 |
+
name = "smallvec"
|
| 715 |
+
version = "1.15.2"
|
| 716 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 717 |
+
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
| 718 |
+
|
| 719 |
+
[[package]]
|
| 720 |
+
name = "spki"
|
| 721 |
+
version = "0.7.3"
|
| 722 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 723 |
+
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
|
| 724 |
+
dependencies = [
|
| 725 |
+
"base64ct",
|
| 726 |
+
"der 0.7.10",
|
| 727 |
+
]
|
| 728 |
+
|
| 729 |
+
[[package]]
|
| 730 |
+
name = "spki"
|
| 731 |
+
version = "0.8.0"
|
| 732 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 733 |
+
checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f"
|
| 734 |
+
dependencies = [
|
| 735 |
+
"base64ct",
|
| 736 |
+
"der 0.8.1",
|
| 737 |
+
]
|
| 738 |
+
|
| 739 |
+
[[package]]
|
| 740 |
+
name = "sponge-cursor"
|
| 741 |
+
version = "0.1.0"
|
| 742 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 743 |
+
checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620"
|
| 744 |
+
|
| 745 |
+
[[package]]
|
| 746 |
+
name = "subtle"
|
| 747 |
+
version = "2.6.1"
|
| 748 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 749 |
+
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
| 750 |
+
|
| 751 |
+
[[package]]
|
| 752 |
+
name = "syn"
|
| 753 |
+
version = "2.0.119"
|
| 754 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 755 |
+
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
| 756 |
+
dependencies = [
|
| 757 |
+
"proc-macro2",
|
| 758 |
+
"quote",
|
| 759 |
+
"unicode-ident",
|
| 760 |
+
]
|
| 761 |
+
|
| 762 |
+
[[package]]
|
| 763 |
+
name = "thiserror"
|
| 764 |
+
version = "2.0.18"
|
| 765 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 766 |
+
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
| 767 |
+
dependencies = [
|
| 768 |
+
"thiserror-impl",
|
| 769 |
+
]
|
| 770 |
+
|
| 771 |
+
[[package]]
|
| 772 |
+
name = "thiserror-impl"
|
| 773 |
+
version = "2.0.18"
|
| 774 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 775 |
+
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
| 776 |
+
dependencies = [
|
| 777 |
+
"proc-macro2",
|
| 778 |
+
"quote",
|
| 779 |
+
"syn",
|
| 780 |
+
]
|
| 781 |
+
|
| 782 |
+
[[package]]
|
| 783 |
+
name = "typenum"
|
| 784 |
+
version = "1.20.1"
|
| 785 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 786 |
+
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
| 787 |
+
|
| 788 |
+
[[package]]
|
| 789 |
+
name = "unicode-ident"
|
| 790 |
+
version = "1.0.24"
|
| 791 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 792 |
+
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
| 793 |
+
|
| 794 |
+
[[package]]
|
| 795 |
+
name = "universal-hash"
|
| 796 |
+
version = "0.5.1"
|
| 797 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 798 |
+
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
| 799 |
+
dependencies = [
|
| 800 |
+
"crypto-common 0.1.7",
|
| 801 |
+
"subtle",
|
| 802 |
+
]
|
| 803 |
+
|
| 804 |
+
[[package]]
|
| 805 |
+
name = "vcpkg"
|
| 806 |
+
version = "0.2.15"
|
| 807 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 808 |
+
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
| 809 |
+
|
| 810 |
+
[[package]]
|
| 811 |
+
name = "version_check"
|
| 812 |
+
version = "0.9.5"
|
| 813 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 814 |
+
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
| 815 |
+
|
| 816 |
+
[[package]]
|
| 817 |
+
name = "wasi"
|
| 818 |
+
version = "0.11.1+wasi-snapshot-preview1"
|
| 819 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 820 |
+
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
| 821 |
+
|
| 822 |
+
[[package]]
|
| 823 |
+
name = "zerocopy"
|
| 824 |
+
version = "0.8.54"
|
| 825 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 826 |
+
checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19"
|
| 827 |
+
dependencies = [
|
| 828 |
+
"zerocopy-derive",
|
| 829 |
+
]
|
| 830 |
+
|
| 831 |
+
[[package]]
|
| 832 |
+
name = "zerocopy-derive"
|
| 833 |
+
version = "0.8.54"
|
| 834 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 835 |
+
checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5"
|
| 836 |
+
dependencies = [
|
| 837 |
+
"proc-macro2",
|
| 838 |
+
"quote",
|
| 839 |
+
"syn",
|
| 840 |
+
]
|
| 841 |
+
|
| 842 |
+
[[package]]
|
| 843 |
+
name = "zeroize"
|
| 844 |
+
version = "1.8.1"
|
| 845 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 846 |
+
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
| 847 |
+
|
| 848 |
+
[[package]]
|
| 849 |
+
name = "zmij"
|
| 850 |
+
version = "1.0.23"
|
| 851 |
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
| 852 |
+
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
runtime-palw/Cargo.toml
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[package]
|
| 2 |
+
name = "runtime-palw"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
edition = "2021"
|
| 5 |
+
rust-version = "1.81"
|
| 6 |
+
description = "Deterministic PALW receipt core for Qwen runtimes"
|
| 7 |
+
license = "Apache-2.0"
|
| 8 |
+
|
| 9 |
+
[workspace]
|
| 10 |
+
|
| 11 |
+
[[bin]]
|
| 12 |
+
name = "palw-worker"
|
| 13 |
+
path = "src/bin/palw-worker.rs"
|
| 14 |
+
required-features = ["ml-dsa"]
|
| 15 |
+
[[bin]]
|
| 16 |
+
name = "palw-integer-receipt"
|
| 17 |
+
path = "src/bin/palw-integer-receipt.rs"
|
| 18 |
+
required-features = ["ml-dsa"]
|
| 19 |
+
|
| 20 |
+
[[bin]]
|
| 21 |
+
name = "palw-verify-integer"
|
| 22 |
+
path = "src/bin/palw-verify-integer.rs"
|
| 23 |
+
required-features = ["ml-dsa"]
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
[dependencies]
|
| 27 |
+
chacha20poly1305 = { version = "=0.10.1", features = ["std"] }
|
| 28 |
+
ed25519-dalek = { version = "2.1", features = ["rand_core"] }
|
| 29 |
+
getrandom = "0.2"
|
| 30 |
+
rusqlite = { version = "0.32", features = ["bundled"] }
|
| 31 |
+
serde = { version = "1", features = ["derive"] }
|
| 32 |
+
serde_json = "1"
|
| 33 |
+
sha2 = "0.10"
|
| 34 |
+
sha3 = "0.10"
|
| 35 |
+
thiserror = "2"
|
| 36 |
+
# The crypto stack leaves these transitive ranges open. Newer releases use an
|
| 37 |
+
# edition-2024 Cargo manifest, so pin compatible versions to preserve MSRV 1.81.
|
| 38 |
+
base64ct = "=1.7.3"
|
| 39 |
+
# `curve25519-dalek` accepts any zeroize 1.x release, but zeroize 1.9's
|
| 40 |
+
# manifest requires Cargo's edition-2024 support. Keep the declared 1.81 MSRV
|
| 41 |
+
# honest by constraining the transitive resolver to the last compatible line.
|
| 42 |
+
zeroize = "=1.8.1"
|
| 43 |
+
blake2b_simd = "1"
|
| 44 |
+
ml-dsa = { version = "0.1.0-pre.2", optional = true }
|
| 45 |
+
|
| 46 |
+
[dev-dependencies]
|
| 47 |
+
hex = "0.4"
|
| 48 |
+
|
| 49 |
+
[lints.rust]
|
| 50 |
+
unsafe_code = "forbid"
|
| 51 |
+
missing_docs = "warn"
|
| 52 |
+
|
| 53 |
+
[lints.clippy]
|
| 54 |
+
all = { level = "warn", priority = -1 }
|
| 55 |
+
pedantic = { level = "warn", priority = -1 }
|
| 56 |
+
missing_errors_doc = "allow"
|
| 57 |
+
missing_panics_doc = "allow"
|
| 58 |
+
module_name_repetitions = "allow"
|
| 59 |
+
similar_names = "allow"
|
| 60 |
+
|
| 61 |
+
[features]
|
| 62 |
+
ml-dsa = ["dep:ml-dsa"]
|
runtime-palw/cuda/CMakeLists.txt
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cmake_minimum_required(VERSION 3.24)
|
| 2 |
+
project(misaka_palw_cuda_trace LANGUAGES C CXX)
|
| 3 |
+
|
| 4 |
+
include(CTest)
|
| 5 |
+
|
| 6 |
+
option(PALW_CUDA_TRACE_ENABLE_CUDA "Build the CUDA trace implementation" ON)
|
| 7 |
+
option(
|
| 8 |
+
PALW_CUDA_PRODUCTION_KERNEL_TRACE
|
| 9 |
+
"Enable production receipt issuance from native CUDA kernel evidence"
|
| 10 |
+
OFF
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
if(PALW_CUDA_PRODUCTION_KERNEL_TRACE)
|
| 14 |
+
message(FATAL_ERROR
|
| 15 |
+
"PALW CUDA production kernel trace is unavailable. "
|
| 16 |
+
"The live diagnostic callback does not consume authority-derived canonical operation, plan, "
|
| 17 |
+
"and physical-layout identities, and deployed governance/trust plus an approved NVIDIA "
|
| 18 |
+
"replica/reproducibility matrix are unavailable; "
|
| 19 |
+
"R32 remains closed.")
|
| 20 |
+
endif()
|
| 21 |
+
|
| 22 |
+
add_executable(palw_cuda_trace_abi_contract
|
| 23 |
+
abi_contract_test.cpp
|
| 24 |
+
record_codec.cpp
|
| 25 |
+
)
|
| 26 |
+
target_include_directories(palw_cuda_trace_abi_contract PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
| 27 |
+
target_compile_features(palw_cuda_trace_abi_contract PRIVATE cxx_std_17)
|
| 28 |
+
target_compile_definitions(palw_cuda_trace_abi_contract PRIVATE
|
| 29 |
+
PALW_CUDA_TRACE_NO_CUDA_HEADERS=1
|
| 30 |
+
PALW_CUDA_TRACE_GOLDEN_FIXTURE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/fixtures/trace_record_v2.hex"
|
| 31 |
+
PALW_CUDA_TRACE_GOLDEN_FIXTURE_V3_PATH="${CMAKE_CURRENT_SOURCE_DIR}/fixtures/trace_record_v3.hex"
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
add_executable(palw_cuda_trace_c_header_contract header_c_contract_test.c)
|
| 35 |
+
target_include_directories(palw_cuda_trace_c_header_contract PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
| 36 |
+
target_compile_features(palw_cuda_trace_c_header_contract PRIVATE c_std_11)
|
| 37 |
+
target_compile_definitions(palw_cuda_trace_c_header_contract PRIVATE PALW_CUDA_TRACE_NO_CUDA_HEADERS=1)
|
| 38 |
+
if(MSVC)
|
| 39 |
+
target_compile_options(palw_cuda_trace_c_header_contract PRIVATE /W4 /WX)
|
| 40 |
+
else()
|
| 41 |
+
target_compile_options(palw_cuda_trace_c_header_contract PRIVATE
|
| 42 |
+
-Wall -Wextra -Wpedantic -Werror)
|
| 43 |
+
endif()
|
| 44 |
+
|
| 45 |
+
add_executable(palw_cuda_producer_contract
|
| 46 |
+
producer_contract_test.cpp
|
| 47 |
+
producer_contract.cpp
|
| 48 |
+
record_codec.cpp
|
| 49 |
+
)
|
| 50 |
+
target_include_directories(palw_cuda_producer_contract PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
| 51 |
+
target_compile_features(palw_cuda_producer_contract PRIVATE cxx_std_17)
|
| 52 |
+
target_compile_definitions(palw_cuda_producer_contract PRIVATE PALW_CUDA_TRACE_NO_CUDA_HEADERS=1)
|
| 53 |
+
|
| 54 |
+
add_executable(palw_cuda_llama_mmvq_bridge_contract
|
| 55 |
+
llama_mmvq_bridge_contract_test.cpp
|
| 56 |
+
)
|
| 57 |
+
target_include_directories(palw_cuda_llama_mmvq_bridge_contract PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
| 58 |
+
target_compile_features(palw_cuda_llama_mmvq_bridge_contract PRIVATE cxx_std_17)
|
| 59 |
+
target_compile_definitions(palw_cuda_llama_mmvq_bridge_contract PRIVATE PALW_CUDA_TRACE_NO_CUDA_HEADERS=1)
|
| 60 |
+
if(MSVC)
|
| 61 |
+
target_compile_options(palw_cuda_llama_mmvq_bridge_contract PRIVATE /W4 /WX)
|
| 62 |
+
else()
|
| 63 |
+
target_compile_options(palw_cuda_llama_mmvq_bridge_contract PRIVATE
|
| 64 |
+
-Wall -Wextra -Wpedantic -Werror)
|
| 65 |
+
endif()
|
| 66 |
+
|
| 67 |
+
if(BUILD_TESTING)
|
| 68 |
+
add_test(NAME palw_cuda_trace_abi_contract COMMAND palw_cuda_trace_abi_contract)
|
| 69 |
+
add_test(NAME palw_cuda_trace_c_header_contract COMMAND palw_cuda_trace_c_header_contract)
|
| 70 |
+
add_test(NAME palw_cuda_producer_contract COMMAND palw_cuda_producer_contract)
|
| 71 |
+
add_test(NAME palw_cuda_llama_mmvq_bridge_contract COMMAND palw_cuda_llama_mmvq_bridge_contract)
|
| 72 |
+
add_test(
|
| 73 |
+
NAME palw_cuda_trace_production_gate
|
| 74 |
+
COMMAND "${CMAKE_COMMAND}"
|
| 75 |
+
"-DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}"
|
| 76 |
+
"-DBINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}/production-gate-check"
|
| 77 |
+
-P "${CMAKE_CURRENT_SOURCE_DIR}/production_gate_test.cmake"
|
| 78 |
+
)
|
| 79 |
+
set_tests_properties(palw_cuda_trace_abi_contract PROPERTIES LABELS "host;abi;palw")
|
| 80 |
+
set_tests_properties(palw_cuda_trace_c_header_contract PROPERTIES LABELS "host;abi;palw")
|
| 81 |
+
set_tests_properties(palw_cuda_producer_contract PROPERTIES LABELS "host;producer;palw")
|
| 82 |
+
set_tests_properties(palw_cuda_llama_mmvq_bridge_contract PROPERTIES LABELS "host;abi;producer;palw")
|
| 83 |
+
set_tests_properties(palw_cuda_trace_production_gate PROPERTIES LABELS "host;gate;palw")
|
| 84 |
+
endif()
|
| 85 |
+
|
| 86 |
+
if(NOT PALW_CUDA_TRACE_ENABLE_CUDA)
|
| 87 |
+
message(STATUS "PALW CUDA implementation disabled; only the host ABI contract target is available")
|
| 88 |
+
return()
|
| 89 |
+
endif()
|
| 90 |
+
|
| 91 |
+
include(CheckLanguage)
|
| 92 |
+
check_language(CUDA)
|
| 93 |
+
if(NOT CMAKE_CUDA_COMPILER)
|
| 94 |
+
message(FATAL_ERROR
|
| 95 |
+
"PALW CUDA trace requires nvcc/CUDA. "
|
| 96 |
+
"Use -DPALW_CUDA_TRACE_ENABLE_CUDA=OFF only for the host ABI contract gate.")
|
| 97 |
+
endif()
|
| 98 |
+
enable_language(CUDA)
|
| 99 |
+
find_package(CUDAToolkit REQUIRED)
|
| 100 |
+
|
| 101 |
+
add_library(palw_cuda_trace STATIC
|
| 102 |
+
accumulator.cu
|
| 103 |
+
attention_trace.cu
|
| 104 |
+
gemm_trace.cu
|
| 105 |
+
producer_accumulator.cu
|
| 106 |
+
producer_contract.cpp
|
| 107 |
+
record_codec.cpp
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
target_include_directories(palw_cuda_trace PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
| 111 |
+
target_link_libraries(palw_cuda_trace PUBLIC CUDA::cudart)
|
| 112 |
+
target_compile_features(palw_cuda_trace PUBLIC cxx_std_17)
|
| 113 |
+
set_target_properties(palw_cuda_trace PROPERTIES
|
| 114 |
+
CUDA_STANDARD 17
|
| 115 |
+
CUDA_STANDARD_REQUIRED ON
|
| 116 |
+
CUDA_SEPARABLE_COMPILATION ON
|
| 117 |
+
POSITION_INDEPENDENT_CODE ON
|
| 118 |
+
)
|
| 119 |
+
|
| 120 |
+
target_compile_options(palw_cuda_trace PRIVATE
|
| 121 |
+
$<$<COMPILE_LANGUAGE:CUDA>:--fmad=false;--prec-div=true;--prec-sqrt=true>
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
if(BUILD_TESTING)
|
| 125 |
+
target_compile_definitions(palw_cuda_trace PRIVATE PALW_CUDA_TRACE_TESTING=1)
|
| 126 |
+
add_executable(palw_cuda_trace_device_test cuda_trace_test.cu)
|
| 127 |
+
target_include_directories(palw_cuda_trace_device_test PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
| 128 |
+
target_link_libraries(palw_cuda_trace_device_test PRIVATE palw_cuda_trace CUDA::cudart)
|
| 129 |
+
target_compile_features(palw_cuda_trace_device_test PRIVATE cxx_std_17)
|
| 130 |
+
target_compile_definitions(palw_cuda_trace_device_test PRIVATE PALW_CUDA_TRACE_TESTING=1)
|
| 131 |
+
set_target_properties(palw_cuda_trace_device_test PROPERTIES
|
| 132 |
+
CUDA_STANDARD 17
|
| 133 |
+
CUDA_STANDARD_REQUIRED ON
|
| 134 |
+
)
|
| 135 |
+
add_test(NAME palw_cuda_trace_device COMMAND palw_cuda_trace_device_test)
|
| 136 |
+
set_tests_properties(palw_cuda_trace_device PROPERTIES
|
| 137 |
+
LABELS "cuda;gpu;palw"
|
| 138 |
+
SKIP_RETURN_CODE 77
|
| 139 |
+
)
|
| 140 |
+
|
| 141 |
+
add_executable(palw_cuda_producer_device_test producer_accumulator_test.cu)
|
| 142 |
+
target_include_directories(palw_cuda_producer_device_test PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
| 143 |
+
target_link_libraries(palw_cuda_producer_device_test PRIVATE palw_cuda_trace CUDA::cudart)
|
| 144 |
+
target_compile_features(palw_cuda_producer_device_test PRIVATE cxx_std_17)
|
| 145 |
+
set_target_properties(palw_cuda_producer_device_test PROPERTIES
|
| 146 |
+
CUDA_STANDARD 17
|
| 147 |
+
CUDA_STANDARD_REQUIRED ON
|
| 148 |
+
)
|
| 149 |
+
add_test(NAME palw_cuda_producer_device COMMAND palw_cuda_producer_device_test)
|
| 150 |
+
set_tests_properties(palw_cuda_producer_device PROPERTIES
|
| 151 |
+
LABELS "cuda;gpu;producer;palw"
|
| 152 |
+
SKIP_RETURN_CODE 77
|
| 153 |
+
)
|
| 154 |
+
|
| 155 |
+
add_executable(palw_cuda_grouped_capture_info grouped_capture_info.cu)
|
| 156 |
+
target_include_directories(palw_cuda_grouped_capture_info PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
| 157 |
+
target_link_libraries(palw_cuda_grouped_capture_info PRIVATE palw_cuda_trace CUDA::cudart)
|
| 158 |
+
target_compile_features(palw_cuda_grouped_capture_info PRIVATE cxx_std_17)
|
| 159 |
+
set_target_properties(palw_cuda_grouped_capture_info PROPERTIES
|
| 160 |
+
CUDA_STANDARD 17
|
| 161 |
+
CUDA_STANDARD_REQUIRED ON
|
| 162 |
+
)
|
| 163 |
+
add_test(NAME palw_cuda_grouped_capture_info COMMAND palw_cuda_grouped_capture_info)
|
| 164 |
+
set_tests_properties(palw_cuda_grouped_capture_info PROPERTIES
|
| 165 |
+
LABELS "cuda;gpu;producer;manifest;palw"
|
| 166 |
+
SKIP_RETURN_CODE 77
|
| 167 |
+
)
|
| 168 |
+
endif()
|
runtime-palw/cuda/README.md
ADDED
|
@@ -0,0 +1,683 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# PALW CUDA trace backend
|
| 2 |
+
|
| 3 |
+
This directory contains five related but deliberately separate experimental
|
| 4 |
+
contracts:
|
| 5 |
+
|
| 6 |
+
- the CUDA device observer writes V1 records for deterministic, fixed-width
|
| 7 |
+
GEMM and attention tile sketches over the final contiguous `float` output;
|
| 8 |
+
- the standalone producer API writes V2 records from FP32 accumulator values
|
| 9 |
+
passed directly by an instrumented producer kernel before epilogue/output
|
| 10 |
+
storage, and launches only one registered exact CUDA function pointer; and
|
| 11 |
+
- an additive V2 C ABI/codec can carry declared accumulator provenance,
|
| 12 |
+
reduction-segment metadata, and a producer-variant digest, and the Rust
|
| 13 |
+
runtime can strictly decode and bind a complete V2 stream to expected
|
| 14 |
+
dispatch and runtime metadata;
|
| 15 |
+
- an additive 452-byte V3 codec and Rust binder carry exact schedule/group,
|
| 16 |
+
launch-geometry, work-entry, and capture identities and represent the three
|
| 17 |
+
FA-off eager-attention sublaunch roles; and
|
| 18 |
+
- an opt-in, request-local llama.cpp bridge instruments the exact unfused,
|
| 19 |
+
single-column Q4_K/Q6_K MMVQ specializations at their full-K pre-epilogue
|
| 20 |
+
FP32 accumulator point plus the FA-off QK/softmax/PV paths, and fails closed
|
| 21 |
+
on association/identity mismatch.
|
| 22 |
+
|
| 23 |
+
The standalone hook is a real device-side accumulator capture primitive: its
|
| 24 |
+
device test computes segmented dot-product accumulators in registers, captures
|
| 25 |
+
them before an independently variable epilogue, and emits V2 without reading the
|
| 26 |
+
final output. It requires exactly 32 canonical samples per tile and K segment,
|
| 27 |
+
rejects duplicate/missing samples, and detects a stale launch nonce or a compiled
|
| 28 |
+
producer identity mismatch. The existing generic GEMM/attention observer remains
|
| 29 |
+
V1 final-output-only.
|
| 30 |
+
|
| 31 |
+
The vendored MMVQ bridge is available for diagnostic collection, but this does
|
| 32 |
+
**not** make the Qwen path production- or Receipt-capable. The exact launch
|
| 33 |
+
wrapper checks one CUDA function pointer, current SM, and exact
|
| 34 |
+
`cudaFuncGetAttributes` values, then uses that same pointer in `cudaLaunchKernel`.
|
| 35 |
+
The producer supplies compiled dispatch/work/capture IDs to the device hook,
|
| 36 |
+
while the host descriptor supplies a committed binary digest. Binding those
|
| 37 |
+
identifiers to the actual release cubin is implemented by the strict release
|
| 38 |
+
manifest; governance approval remains an authority responsibility. CUDA does not expose a trustworthy
|
| 39 |
+
current-entry-point identity to an arbitrary device helper.
|
| 40 |
+
|
| 41 |
+
The CUDA implementation is fail-closed. Compiling with `nvcc`, passing both
|
| 42 |
+
non-skipped real-device CTests, and passing a reproducibility matrix on the exact
|
| 43 |
+
supported NVIDIA hardware/software manifest are necessary but not sufficient
|
| 44 |
+
for production approval; R32 also requires the FA-off eager-attention producer
|
| 45 |
+
hooks, release binding, Receipt V2 mapping, and complete MMVQ-plus-attention
|
| 46 |
+
device E2E. Those fixed-profile experimental gates are complete; R32 production
|
| 47 |
+
approval still requires the live canonical authority callback, deployed trust
|
| 48 |
+
roots, and replica/reproducibility evidence.
|
| 49 |
+
The no-CUDA CTests prove the C/C++ ABI and canonical codecs. Rust host tests add
|
| 50 |
+
strict V2/V3 decoding and expected-stream binding, but neither host test suite
|
| 51 |
+
proves where a device sketch originated or which kernel actually ran.
|
| 52 |
+
The public headers fix their production-capable macros to zero. Configuring
|
| 53 |
+
with `-DPALW_CUDA_PRODUCTION_KERNEL_TRACE=ON` always fails: this transport cannot
|
| 54 |
+
be enabled for production receipt issuance.
|
| 55 |
+
|
| 56 |
+
The historical MMVQ-only SM89 results are in
|
| 57 |
+
[`../../docs/evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md`](../../docs/evidence/cuda-v3-mmvq-hook-sm89-2026-07-15.md):
|
| 58 |
+
three positive one-token runs each finalized 253 records (216 Q4_K, 37 Q6_K)
|
| 59 |
+
with fingerprint `6618cafb2d66fc5c`, and a zero-based index-17 rejection stopped
|
| 60 |
+
at 17 accepted records. The current full-stream evidence is
|
| 61 |
+
[`../../docs/evidence/cuda-v3-full-hook-sm89-2026-07-16.md`](../../docs/evidence/cuda-v3-full-hook-sm89-2026-07-16.md):
|
| 62 |
+
three 361/361 runs, 253 MMVQ plus 108 attention records, five work-class
|
| 63 |
+
rejections, and the exact release manifest. The tool reports
|
| 64 |
+
`diagnostic_only=true` and `receipt_authority=false` in both modes.
|
| 65 |
+
|
| 66 |
+
## Standalone V2 producer-accumulator contract
|
| 67 |
+
|
| 68 |
+
`palw_cuda_producer_trace.h` exposes the host session/launch ABI and
|
| 69 |
+
`palw_cuda_producer_trace.cuh` exposes
|
| 70 |
+
`palw_cuda_producer_capture_accumulator_f32`. The capture call belongs inside
|
| 71 |
+
the producer, at the declared K-segment boundary, while the FP32 accumulator is
|
| 72 |
+
still a register/local value and before epilogue or final store. A producer
|
| 73 |
+
thread calls it exactly once for every logical output and segment. Unsampled
|
| 74 |
+
outputs are ignored; the fixed sample-position function selects 32 ordinals per
|
| 75 |
+
tile, including repeated positions for small tiles.
|
| 76 |
+
|
| 77 |
+
Segment boundaries are canonical, contiguous, and nonempty. Integrations use
|
| 78 |
+
`palw_cuda_producer_segment_begin/end(k, segment, count)`, which partitions the
|
| 79 |
+
full `[0, k)` range by integer quotient/remainder without overlap or gaps.
|
| 80 |
+
`reduction_segment_count > k` is rejected. The audited dispatch variant must
|
| 81 |
+
commit this partition contract; the standalone helper cannot detect a producer
|
| 82 |
+
that computes a different semantic range and then lies about the segment index.
|
| 83 |
+
|
| 84 |
+
Records are initialized and stored in canonical order:
|
| 85 |
+
|
| 86 |
+
```text
|
| 87 |
+
tile_index = tile_row * tile_grid_columns + tile_column
|
| 88 |
+
record_index = base_record
|
| 89 |
+
+ tile_index * reduction_segment_count
|
| 90 |
+
+ reduction_segment_index
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
For each record, a 32-bit atomic sample mask proves every selected ordinal was
|
| 94 |
+
seen. A second mask makes duplicate observation fatal. Sketch lanes use a
|
| 95 |
+
commutative integer XOR of canonicalized FP32 contributions tagged with sample,
|
| 96 |
+
logical row/column, and segment; scheduling cannot change the result. The hook
|
| 97 |
+
never loads the final-output buffer. `-0.0` and NaN payloads use the same
|
| 98 |
+
canonicalization as V1.
|
| 99 |
+
|
| 100 |
+
`palw_cuda_producer_trace_prepare` validates GEMM shape, canonical record count,
|
| 101 |
+
strict logical sequence, strictly increasing nonzero request-local nonce, exact
|
| 102 |
+
SM, launch geometry, nonzero identity digests, and exact CUDA-reported binary/
|
| 103 |
+
PTX/register/max-thread attributes. It initializes records on the bound stream
|
| 104 |
+
and returns a library-owned device view. `palw_cuda_producer_trace_launch`
|
| 105 |
+
rejects a function pointer different from the prepared pointer and launches the
|
| 106 |
+
prepared pointer itself. It also injects the immutable prepared device view at
|
| 107 |
+
the kernel-argument index registered with the audited ABI during `prepare`;
|
| 108 |
+
`launch` has no free index/count input. A caller-provided substitute view is
|
| 109 |
+
therefore never marshalled to the kernel. Finalization synchronizes and accepts records only if
|
| 110 |
+
every sample was observed exactly once and no view, nonce, index, identity, or
|
| 111 |
+
metadata fault occurred. Every copied V2 semantic metadata field is re-encoded
|
| 112 |
+
and compared with the host-retained immutable launch expectation; only the four
|
| 113 |
+
data-dependent sketch lanes may differ. Any integrity failure permanently poisons the context;
|
| 114 |
+
copied bytes are diagnostic only.
|
| 115 |
+
|
| 116 |
+
The three identity domains are intentionally separate:
|
| 117 |
+
|
| 118 |
+
- `producer_variant_id` commits the canonical dispatch descriptor and is in V2;
|
| 119 |
+
- `entry_point_id` commits the fully specialized producer entry-point contract;
|
| 120 |
+
- `kernel_binary_digest` commits the release cubin/fatbin artifact.
|
| 121 |
+
|
| 122 |
+
The wrapper proves which registered CUDA function pointer it launched in the
|
| 123 |
+
current trusted process. It cannot derive either digest from a function pointer,
|
| 124 |
+
prove that a caller-provided digest matches loaded machine code, or prove that
|
| 125 |
+
an unreviewed producer passed a semantically genuine accumulator. Production
|
| 126 |
+
therefore additionally needs audited vendored integration, release-binary
|
| 127 |
+
attestation, actual-dispatch coverage, and the closed Receipt mapping gate.
|
| 128 |
+
|
| 129 |
+
## V1 device observer and deterministic record order
|
| 130 |
+
|
| 131 |
+
The observer launch is enqueued immediately after the operation being observed,
|
| 132 |
+
on the same CUDA stream. One CUDA block and one active thread handle each logical
|
| 133 |
+
output tile. For a tile grid with columns `grid_x`, the canonical tile index is:
|
| 134 |
+
|
| 135 |
+
```text
|
| 136 |
+
tile_index = tile_row * grid_x + tile_column
|
| 137 |
+
record_index = base_record + tile_index
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
Each thread writes directly to that record index. CUDA block scheduling therefore
|
| 141 |
+
cannot reorder records. A tile reads 32 fixed logical positions, canonicalizes
|
| 142 |
+
`-0.0` to `+0.0` and every NaN payload to one quiet-NaN bit pattern, and produces
|
| 143 |
+
four integer mixing lanes. It uses no floating-point reduction and no atomics.
|
| 144 |
+
|
| 145 |
+
This makes the observer deterministic for identical output bits and metadata on
|
| 146 |
+
the same supported stack. It does not make an upstream GEMM or attention kernel
|
| 147 |
+
numerically deterministic. A legitimate upstream bit change is expected to
|
| 148 |
+
change a sketch, and cross-GPU repeatability has not yet been established.
|
| 149 |
+
|
| 150 |
+
The current launch path writes `palw_cuda_trace_record` with schema V1. V2 has a
|
| 151 |
+
separate ordering contract: the Rust binder requires logical launches in
|
| 152 |
+
consecutive zero-based order, and within each launch requires tile-major then
|
| 153 |
+
reduction-segment-major order. The C codec validates each record's tile and
|
| 154 |
+
segment consistency; the Rust binder validates the cross-record ordering. The
|
| 155 |
+
current CUDA observer does not produce those V2 records.
|
| 156 |
+
|
| 157 |
+
## Validated V1 device contracts
|
| 158 |
+
|
| 159 |
+
All dimensions must be nonzero and fit in `uint32_t`. Common validation also
|
| 160 |
+
rejects null or misaligned pointers, address and multiplication overflow, a row
|
| 161 |
+
stride smaller than the logical width, out-of-range layer/phase/dtype/quantization
|
| 162 |
+
tags, invalid tile geometry, more than `UINT32_MAX` tiles, CUDA grid limits, a
|
| 163 |
+
nonconsecutive sequence, a second CUDA stream, pending copies, and insufficient
|
| 164 |
+
record capacity.
|
| 165 |
+
|
| 166 |
+
The `float` pointer is the sketch transport. `dtype` records the logical operation
|
| 167 |
+
dtype and may therefore differ from the transport type.
|
| 168 |
+
|
| 169 |
+
GEMM uses ggml's contiguous storage for a logical `[m, n]` result:
|
| 170 |
+
|
| 171 |
+
```text
|
| 172 |
+
storage [batch][n][m], m is contiguous
|
| 173 |
+
output_rows n * batch
|
| 174 |
+
output_columns m
|
| 175 |
+
row_stride >= m
|
| 176 |
+
m, n, k, batch nonzero and <= UINT32_MAX
|
| 177 |
+
```
|
| 178 |
+
|
| 179 |
+
Attention uses:
|
| 180 |
+
|
| 181 |
+
```text
|
| 182 |
+
storage [batch][query_tokens][heads * head_dim]
|
| 183 |
+
output_rows query_tokens * batch
|
| 184 |
+
output_columns heads * head_dim
|
| 185 |
+
row_stride >= output_columns
|
| 186 |
+
causal exactly 0 or 1
|
| 187 |
+
causal KV length key_value_tokens >= query_tokens
|
| 188 |
+
decode query length exactly 1
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
Prefill requires `decode_step == 0`; decode requires a step that fits in
|
| 192 |
+
`uint32_t`. Attention always records quantization `NONE`.
|
| 193 |
+
|
| 194 |
+
## State, rollback, and poison semantics
|
| 195 |
+
|
| 196 |
+
One context is permanently bound to the first CUDA stream used with it and is
|
| 197 |
+
not thread-safe. The required sequence starts at zero.
|
| 198 |
+
|
| 199 |
+
| Event | Count/sequence effect | Resulting state |
|
| 200 |
+
| --- | --- | --- |
|
| 201 |
+
| Validation failure | No change | Reusable |
|
| 202 |
+
| Sequence mismatch | No change | Reusable |
|
| 203 |
+
| Capacity failure | No reservation and no sequence consumption | Sticky overflow |
|
| 204 |
+
| Immediate observed/trace launch error | No reservation for that launch | Permanently poisoned |
|
| 205 |
+
| Successful immediate trace launch | Reserves every tile and consumes one sequence | Queued, not committed |
|
| 206 |
+
| Successful synchronize | Commits all accepted launches and completes a pending copy | Reusable |
|
| 207 |
+
| Asynchronous stream failure at synchronize | Existing reservations remain diagnostic only | Permanently poisoned |
|
| 208 |
+
| D2H enqueue failure | No new copy becomes usable | Permanently poisoned |
|
| 209 |
+
|
| 210 |
+
`palw_cuda_trace_count` reports accepted/reserved records, including queued work.
|
| 211 |
+
`palw_cuda_trace_committed_count` advances only after a successful
|
| 212 |
+
`palw_cuda_trace_synchronize`. An immediate failure rolls back implicitly because
|
| 213 |
+
the host counters advance only after `cudaGetLastError` reports success. An
|
| 214 |
+
asynchronous failure cannot safely roll back already queued device writes, so the
|
| 215 |
+
context is poisoned and every later launch, copy, synchronize, or reset fails
|
| 216 |
+
closed with `PALW_CUDA_TRACE_POISONED`. Destroy it, fail the enclosing inference
|
| 217 |
+
request, and rebuild the affected CUDA backend/stream before a later request;
|
| 218 |
+
allocating only a fresh trace context is not proof that an asynchronous device
|
| 219 |
+
failure was recovered. If synchronization fails after a D2H enqueue, do not
|
| 220 |
+
consume or release the host buffer until that backend/stream teardown completes.
|
| 221 |
+
|
| 222 |
+
Overflow is also a receipt failure. It can be cleared only by synchronizing any
|
| 223 |
+
work accepted before the overflow and then resetting. Reset clears counts,
|
| 224 |
+
sequence, and overflow, but does not change the permanent stream binding and can
|
| 225 |
+
never clear CUDA poison. Destroying a context or releasing a host copy buffer
|
| 226 |
+
while work is pending is a caller error.
|
| 227 |
+
|
| 228 |
+
## Canonical V1/V2/V3 encoding: never hash native memory
|
| 229 |
+
|
| 230 |
+
`palw_cuda_trace_record` has a checked native ABI size of 144 bytes, including a
|
| 231 |
+
reserved byte and native tail padding. `palw_cuda_trace_record_v2` has a checked
|
| 232 |
+
native ABI size of 192 bytes and more padding between fields. None of that
|
| 233 |
+
padding is transport or consensus data. Hashing or serializing either raw struct
|
| 234 |
+
is forbidden.
|
| 235 |
+
|
| 236 |
+
`palw_cuda_trace_encode_record_v1` validates a schema-V1 record and writes
|
| 237 |
+
exactly 139 big-endian bytes, field by field, in this order:
|
| 238 |
+
|
| 239 |
+
```text
|
| 240 |
+
9 * u64 kernel_sequence .. key_value_tokens
|
| 241 |
+
4 * u64 sketch lanes
|
| 242 |
+
7 * u32 layer_id .. output_columns
|
| 243 |
+
1 * u16 schema_version
|
| 244 |
+
5 * u8 kind, phase, dtype, quantization, causal
|
| 245 |
+
```
|
| 246 |
+
|
| 247 |
+
The additive `palw_cuda_trace_encode_record_v2` requires schema V2 and writes the
|
| 248 |
+
same 139-byte semantic prefix followed by:
|
| 249 |
+
|
| 250 |
+
```text
|
| 251 |
+
3 * u8 declared_origin, accumulator_stage, accumulator_dtype
|
| 252 |
+
1 * u16 sketch_scheme
|
| 253 |
+
2 * u32 reduction_segment_index, reduction_segment_count
|
| 254 |
+
32 bytes producer_variant_id
|
| 255 |
+
```
|
| 256 |
+
|
| 257 |
+
The result is exactly 184 bytes. The V1 reserved byte and all native padding are
|
| 258 |
+
excluded from both encodings. V2 does not replace V1: the generic observer and
|
| 259 |
+
its copy API still use the V1 native record. The standalone producer session has
|
| 260 |
+
a separate V2 device buffer/finalizer and never relabels a V1 observation.
|
| 261 |
+
|
| 262 |
+
Both the C++ codec and Rust decoder reject unknown tags, zero producer-variant
|
| 263 |
+
IDs, and inconsistent provenance tuples. Final-output records must use no
|
| 264 |
+
accumulator stage or dtype, the final-output sketch scheme, and zero reduction
|
| 265 |
+
segment fields. A producer-accumulator declaration is accepted only for GEMM,
|
| 266 |
+
FP32 scalar-accumulator sketches, an approved pre-reduction or full-K stage, and
|
| 267 |
+
a valid nonempty segment range; full-K evidence must be a single segment.
|
| 268 |
+
|
| 269 |
+
These checks establish canonical syntax and internal consistency only. In
|
| 270 |
+
particular, the C codec cannot prove that `producer_variant_id` is canonical or
|
| 271 |
+
that `declared_origin` is true.
|
| 272 |
+
|
| 273 |
+
V3 is a separate additive schema with a checked 464-byte native record and an
|
| 274 |
+
exact 452-byte canonical encoding. It extends the V2 semantic prefix with exact
|
| 275 |
+
schedule and attention-group ownership, sublaunch role/count, physical layout
|
| 276 |
+
and launch geometry, and operation/group/plan/layout/work/capture identities.
|
| 277 |
+
The V3 codec never serializes native padding. Neither V1 nor V2 Receipt code may
|
| 278 |
+
reinterpret a V3 record.
|
| 279 |
+
|
| 280 |
+
## Rust V2/V3 stream binding
|
| 281 |
+
|
| 282 |
+
`runtime-palw/src/cuda_trace.rs` provides `RawCudaTraceRecordV2::decode_strict`
|
| 283 |
+
for exactly one 184-byte record and `decode_cuda_trace_v2_stream` for a
|
| 284 |
+
concatenated exact-size stream. `bind_cuda_trace_v2` then validates the complete,
|
| 285 |
+
unfiltered stream before any possible GEMM-only projection. It requires:
|
| 286 |
+
|
| 287 |
+
- an immutable, nonempty expected-launch table with consecutive zero-based
|
| 288 |
+
logical launch sequences and strictly increasing schedule indices;
|
| 289 |
+
- exact record count and contiguous tile/segment order for every GEMM and
|
| 290 |
+
attention launch;
|
| 291 |
+
- equality of operation shape, phase/decode step, layer, tile geometry,
|
| 292 |
+
provenance tuple, segment count, and canonical dispatch-variant digest;
|
| 293 |
+
- the initial profile of one CUDA accelerator, tensor parallelism one, no tensor
|
| 294 |
+
repack, batch one for bound operations, and flash attention enabled whenever
|
| 295 |
+
an attention launch is expected; and
|
| 296 |
+
- an exact supported dispatch descriptor: currently unfused single-column
|
| 297 |
+
llama.cpp MMVQ metadata or a pinned flash-attention specialization digest.
|
| 298 |
+
|
| 299 |
+
For a validated expected dispatch, `derive_cuda_kernel_id` binds the runtime
|
| 300 |
+
manifest's kernel binary digest, kernel algorithm digest, source commit, CUDA SM
|
| 301 |
+
architecture, and canonical dispatch descriptor. This is a host-side identity
|
| 302 |
+
derivation from trusted expected metadata. Until the vendored producer reports
|
| 303 |
+
and is checked against the actual selected specialization, it is not proof of
|
| 304 |
+
the kernel entry point that executed.
|
| 305 |
+
|
| 306 |
+
The result, `BoundCudaTranscriptV1`, intentionally exposes only the immutable
|
| 307 |
+
raw records, bound launch ranges, expected descriptors, and derived producer
|
| 308 |
+
kernel IDs. Raw or merely bound records have no conversion to receipt evidence
|
| 309 |
+
and cannot authorize receipt issuance or upgrade `TraceCapability`.
|
| 310 |
+
|
| 311 |
+
`runtime-palw/src/cuda_attestation.rs` adds a separate, no-public-constructor
|
| 312 |
+
authority typestate. A network-scoped Ed25519 authority envelope commits the
|
| 313 |
+
exact job/execution, signed assignment, runtime instance/class/manifest,
|
| 314 |
+
reviewed producer integration, operation schedule, full unfiltered transcript,
|
| 315 |
+
and epochs. Registry verification checks validity, revocation, and exact
|
| 316 |
+
runtime/integration approval, then requires every scheduled GEMM and attention
|
| 317 |
+
index exactly once. Only the resulting `AuthorityBoundCudaTranscriptV2` may be
|
| 318 |
+
projected to `AuthorityBoundCudaReceiptEvidenceV2`, and that projection includes
|
| 319 |
+
only true producer-accumulator GEMMs while retaining the full transcript
|
| 320 |
+
commitment. The newer V3 authority and `receipt_v2_flow` bind the complete fixed
|
| 321 |
+
361-launch profile into the implemented Receipt V2. The V1 builder
|
| 322 |
+
and verifier both reject CUDA `KernelSketch`, including a hand-built/resigned V1
|
| 323 |
+
body, because V1 has no field for the authority provenance commitment.
|
| 324 |
+
|
| 325 |
+
The deterministic Qwen profile currently has flash attention disabled. In the
|
| 326 |
+
measured three-token graph stream, 975 GEMMs split into 759 quantized MMVQ
|
| 327 |
+
events (253/token: Q4_K 648 and Q6_K 111 total) and 216 eager-attention F16
|
| 328 |
+
`MUL_MAT` events (72/token). The V3 schema and Rust binder now represent each
|
| 329 |
+
FA-off eager group as QK-score GEMM, masked/scaled softmax, and PV GEMM
|
| 330 |
+
sublaunches with separate covered schedule indices. The vendored QK-score,
|
| 331 |
+
masked/scaled softmax, and PV work paths now enqueue the grouped collector on
|
| 332 |
+
the same stream and are associated from typed graph metadata. The resulting
|
| 333 |
+
361-launch MMVQ-plus-attention stream passed three real-model device runs with
|
| 334 |
+
identical fingerprints and five work-class rejection gates. The implemented V2
|
| 335 |
+
verifier binds a strict authority-provided expected table; the live diagnostic
|
| 336 |
+
callback does not yet receive that canonical authority table.
|
| 337 |
+
|
| 338 |
+
## Build and test gates
|
| 339 |
+
|
| 340 |
+
The normal configuration requires CUDA and fails instead of silently compiling a
|
| 341 |
+
stub. It builds the experimental transport and its tests, not a production
|
| 342 |
+
receipt path:
|
| 343 |
+
|
| 344 |
+
```sh
|
| 345 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda -DBUILD_TESTING=ON
|
| 346 |
+
cmake --build build/palw-cuda
|
| 347 |
+
ctest --test-dir build/palw-cuda --output-on-failure
|
| 348 |
+
```
|
| 349 |
+
|
| 350 |
+
The explicit production gate is intentionally closed:
|
| 351 |
+
|
| 352 |
+
```sh
|
| 353 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda-production \
|
| 354 |
+
-DPALW_CUDA_PRODUCTION_KERNEL_TRACE=ON
|
| 355 |
+
# FATAL_ERROR: vendored integration/Receipt mapping/reproducibility remain incomplete
|
| 356 |
+
```
|
| 357 |
+
|
| 358 |
+
Production builds must additionally set one exact `CMAKE_CUDA_ARCHITECTURES`
|
| 359 |
+
value that matches the committed runtime class (for example `90-real` for an
|
| 360 |
+
approved `sm_90` class); compiler-default or fat-binary ambiguity is not an
|
| 361 |
+
acceptable reproducibility gate.
|
| 362 |
+
|
| 363 |
+
On a machine without CUDA, the V1/V2 header, layout, enum-tag, canonical codec,
|
| 364 |
+
golden-fixture, and closed production-gate contracts can be tested:
|
| 365 |
+
|
| 366 |
+
```sh
|
| 367 |
+
cmake -S runtime-palw/cuda -B build/palw-cuda-host \
|
| 368 |
+
-DPALW_CUDA_TRACE_ENABLE_CUDA=OFF -DBUILD_TESTING=ON
|
| 369 |
+
cmake --build build/palw-cuda-host
|
| 370 |
+
ctest --test-dir build/palw-cuda-host --output-on-failure -L host
|
| 371 |
+
```
|
| 372 |
+
|
| 373 |
+
The Rust cross-language contract is independent of CUDA hardware:
|
| 374 |
+
|
| 375 |
+
```sh
|
| 376 |
+
cargo +1.81 test --locked --test cuda_trace_contract
|
| 377 |
+
```
|
| 378 |
+
|
| 379 |
+
It decodes the shared V2 golden bytes also produced and checked by the C++ codec
|
| 380 |
+
test, and exercises strict
|
| 381 |
+
length/tag/provenance validation, complete GEMM-plus-attention stream binding,
|
| 382 |
+
missing/duplicate/reordered/mutated failures, launch/schedule constraints,
|
| 383 |
+
dispatch compatibility, runtime-class restrictions, and manifest/SM/dispatch
|
| 384 |
+
kernel-ID derivation. These are transport and metadata-binding tests, not device
|
| 385 |
+
producer tests.
|
| 386 |
+
|
| 387 |
+
One device CTest exercises the final-output V1 observer. It covers GEMM and
|
| 388 |
+
attention record count/order, same-stream
|
| 389 |
+
repeatability, sampled mutation sensitivity and tile isolation, dtype/phase/
|
| 390 |
+
quantization/shape/stride/tile validation, causal and decode constraints,
|
| 391 |
+
capacity/reset behavior, exact sequence enforcement, stream binding, copy and
|
| 392 |
+
commit states, permanent launch-failure poison, and recovery only through a new
|
| 393 |
+
trace context for the injected non-sticky invalid-configuration error. It
|
| 394 |
+
returns CTest skip code 77 if no CUDA device/driver is available. A
|
| 395 |
+
future R32 production review must treat a skipped device test as **not
|
| 396 |
+
verified**, not as a pass.
|
| 397 |
+
|
| 398 |
+
The second device CTest exercises the standalone V2 producer primitive with a
|
| 399 |
+
real segmented GEMM test kernel. It proves that an epilogue-only mutation changes
|
| 400 |
+
final output but not pre-epilogue evidence, while an input/accumulator mutation
|
| 401 |
+
does change evidence. It also rejects the wrong launch pointer, a compiled
|
| 402 |
+
identity mismatch, and an uninstrumented producer with incomplete coverage.
|
| 403 |
+
It proves that a producer-side V2 metadata overwrite is rejected by the
|
| 404 |
+
host-retained expectation and that a substituted caller view is replaced by the
|
| 405 |
+
prepared view. This is a primitive-level test kernel, not the vendored Qwen
|
| 406 |
+
producer E2E.
|
| 407 |
+
|
| 408 |
+
### Verification in this checkout (2026-07-15)
|
| 409 |
+
|
| 410 |
+
- The host-only configuration built with AppleClang 21 using
|
| 411 |
+
`-Wall -Wextra -Wpedantic -Werror`; all five host CTests passed (5/5), including
|
| 412 |
+
pure producer-descriptor validation and
|
| 413 |
+
the nested configuration test that proves the production gate rejects this
|
| 414 |
+
transport.
|
| 415 |
+
- The same five host CTests passed under AppleClang AddressSanitizer and
|
| 416 |
+
UndefinedBehaviorSanitizer (5/5) with no sanitizer report.
|
| 417 |
+
- The default CUDA-required configuration failed at configure time as intended:
|
| 418 |
+
no CUDA compiler was found.
|
| 419 |
+
- `nvcc` and an NVIDIA device are unavailable on this Apple arm64 host. On the
|
| 420 |
+
separate Windows/WSL2 NVIDIA gate, an RTX 4060 Ti (`sm_89`), driver 610.62,
|
| 421 |
+
CUDA toolkit 13.3.1/NVCC 13.3.73, and `CMAKE_CUDA_ARCHITECTURES=89-real` built
|
| 422 |
+
the final grouped build passed all eight CTests, including three non-skipped
|
| 423 |
+
device/collector tests.
|
| 424 |
+
The standalone producer test then passed 20 separate executions with the same
|
| 425 |
+
encoded-transcript diagnostic fingerprint `c1a38ed138200874` each time. This
|
| 426 |
+
is primitive-level SM89 evidence, not vendored Qwen E2E or a cross-stack
|
| 427 |
+
reproducibility matrix.
|
| 428 |
+
- `cargo +1.81 test --locked --test cuda_trace_contract` passed all thirteen Rust
|
| 429 |
+
V2 codec/binding/authority-typestate tests on this host. Those host tests do
|
| 430 |
+
not replace producer device evidence.
|
| 431 |
+
- `cargo +1.81 test --locked --test cuda_trace_v3_contract` passed all nine V3
|
| 432 |
+
codec, identity, dispatch, FA-off grouping, and binding contract tests. The
|
| 433 |
+
complete locked Rust 1.81.0 gate passed 224 tests, with 2 real-model tests
|
| 434 |
+
ignored (226 discovered); fmt, Clippy `-D warnings`, and rustdoc `-D warnings`
|
| 435 |
+
also passed.
|
| 436 |
+
- The final opt-in vendored V3 build on the same RTX 4060 Ti/NVCC 13.3.73 stack
|
| 437 |
+
passed three one-token positive runs with 361/361 committed records and the
|
| 438 |
+
same `22f3a57e3640a8c6` canonical-record diagnostic fingerprint: Q4_K 216,
|
| 439 |
+
Q6_K 37, and QK/softmax/PV 36 each. Rejecting the first Q4_K, Q6_K, QK,
|
| 440 |
+
softmax, or PV launch stopped at the exact selected position. A strict release
|
| 441 |
+
manifest bound six exact symbols, runtime attributes, cubins, fatbin, and the
|
| 442 |
+
loaded DSO. This is complete vendored hook diagnostic E2E, not production
|
| 443 |
+
Receipt-authority E2E.
|
| 444 |
+
|
| 445 |
+
## Historical V2 integration design and current V3 delta
|
| 446 |
+
|
| 447 |
+
The original design below was pinned to vendored llama.cpp commit
|
| 448 |
+
`12127defda4f41b7679cb2477a4b0d65ee6a0c8f`. Its default-off build boundary,
|
| 449 |
+
request-local state, exact association, graph/fusion/concurrency rejection, and
|
| 450 |
+
fail-closed principles now inform the active V3 MMVQ diagnostic bridge. Code
|
| 451 |
+
snippets and V2 type names in this section are retained as the historical
|
| 452 |
+
baseline, not as a literal description of the current V3 call sites. Attention
|
| 453 |
+
producer integration and Receipt/Bundle/SQLite V2 are now implemented; the
|
| 454 |
+
production authority callback and issuance gate remain future work.
|
| 455 |
+
|
| 456 |
+
### Opt-in build boundary
|
| 457 |
+
|
| 458 |
+
Add a default-off `GGML_CUDA_PALW_TRACE` CMake option. Only when it is enabled,
|
| 459 |
+
require a `PALW_CUDA_TRACE_SOURCE_DIR`, add this directory with
|
| 460 |
+
`EXCLUDE_FROM_ALL`, link `palw_cuda_trace` into `ggml-cuda`, and define the hook:
|
| 461 |
+
|
| 462 |
+
```cmake
|
| 463 |
+
option(GGML_CUDA_PALW_TRACE "Enable fail-closed PALW CUDA observation" OFF)
|
| 464 |
+
set(PALW_CUDA_TRACE_SOURCE_DIR "" CACHE PATH "PALW CUDA trace source")
|
| 465 |
+
|
| 466 |
+
if (GGML_CUDA_PALW_TRACE)
|
| 467 |
+
if (NOT IS_DIRECTORY "${PALW_CUDA_TRACE_SOURCE_DIR}")
|
| 468 |
+
message(FATAL_ERROR "GGML_CUDA_PALW_TRACE requires PALW_CUDA_TRACE_SOURCE_DIR")
|
| 469 |
+
endif()
|
| 470 |
+
set(PALW_CUDA_TRACE_ENABLE_CUDA ON CACHE BOOL "" FORCE)
|
| 471 |
+
add_subdirectory("${PALW_CUDA_TRACE_SOURCE_DIR}"
|
| 472 |
+
"${CMAKE_CURRENT_BINARY_DIR}/palw-trace" EXCLUDE_FROM_ALL)
|
| 473 |
+
target_link_libraries(ggml-cuda PRIVATE palw_cuda_trace)
|
| 474 |
+
target_compile_definitions(ggml-cuda PRIVATE GGML_CUDA_PALW_TRACE=1)
|
| 475 |
+
endif()
|
| 476 |
+
```
|
| 477 |
+
|
| 478 |
+
`GGML_CUDA_PALW_TRACE` in this design is an experimental data-collection hook
|
| 479 |
+
only. Any receipt-issuing build must additionally require
|
| 480 |
+
`PALW_CUDA_TRACE_PRODUCTION_CAPABLE == 1` and enable
|
| 481 |
+
`PALW_CUDA_PRODUCTION_KERNEL_TRACE`; both checks intentionally fail today.
|
| 482 |
+
|
| 483 |
+
The final patch must also verify compatible dynamic/static CUDA-runtime linkage
|
| 484 |
+
for both llama.cpp link modes. With the option off, the existing target, ABI, and
|
| 485 |
+
runtime behavior must remain unchanged.
|
| 486 |
+
|
| 487 |
+
### Per-request registration API
|
| 488 |
+
|
| 489 |
+
Do not use global mutable metadata and do not infer layer or phase from tensor
|
| 490 |
+
names. Add an optional PALW state object to `ggml_backend_cuda_context` in
|
| 491 |
+
`ggml/src/ggml-cuda/common.cuh`. Before graph compute, the runtime observer
|
| 492 |
+
registers an immutable table keyed by `const ggml_tensor *` with one entry per
|
| 493 |
+
expected CUDA node. It must contain the same information represented by Rust
|
| 494 |
+
`ExpectedCudaLaunchV1`:
|
| 495 |
+
|
| 496 |
+
```text
|
| 497 |
+
node pointer, expected op and exact dispatch descriptor, logical launch sequence,
|
| 498 |
+
schedule index, layer, phase/decode step, logical dtype, quantization, causal,
|
| 499 |
+
tile geometry, declared provenance tuple, expected reduction segment count
|
| 500 |
+
```
|
| 501 |
+
|
| 502 |
+
The table is sorted by logical launch sequence, starts at zero, has strictly
|
| 503 |
+
increasing schedule indices, contains no duplicate node, and has a precomputed
|
| 504 |
+
expected record total. A request also owns the trace context, pinned host record
|
| 505 |
+
buffer, observed-node bitmap, and sticky PALW status. Beginning a request rejects
|
| 506 |
+
a reused/poisoned state or an unsupported execution mode. Finalization requires
|
| 507 |
+
every registered node exactly once and no unexpected eligible node.
|
| 508 |
+
|
| 509 |
+
### Central call sites
|
| 510 |
+
|
| 511 |
+
In `ggml/src/ggml-cuda/ggml-cuda.cu`, place hooks in the central dispatcher after
|
| 512 |
+
the final producer returns:
|
| 513 |
+
|
| 514 |
+
```cpp
|
| 515 |
+
case GGML_OP_MUL_MAT: {
|
| 516 |
+
const auto variant = ggml_cuda_mul_mat(ctx, dst->src[0], dst->src[1], dst);
|
| 517 |
+
ggml_cuda_palw_after_node(ctx, dst, variant); // same stream, after producer
|
| 518 |
+
break;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
case GGML_OP_FLASH_ATTN_EXT: {
|
| 522 |
+
const auto variant = ggml_cuda_flash_attn_ext(ctx, dst);
|
| 523 |
+
ggml_cuda_palw_after_node(ctx, dst, variant); // same ctx.stream()
|
| 524 |
+
break;
|
| 525 |
+
}
|
| 526 |
+
```
|
| 527 |
+
|
| 528 |
+
Those dispatcher hooks establish complete operation coverage and report the
|
| 529 |
+
selected dispatch; they cannot by themselves observe a producer accumulator.
|
| 530 |
+
True accumulator sampling must be instrumented inside the selected producer
|
| 531 |
+
kernel at the declared stage, with the dispatcher hook checking that the
|
| 532 |
+
expected node and specialization emitted exactly the required V2 records.
|
| 533 |
+
|
| 534 |
+
This location is important. `ggml_cuda_mul_mat` near line 1731 has early returns
|
| 535 |
+
for FWHT, cuBLAS, MMVF, MMF, MMVQ, and MMQ variants; hooking inside only one
|
| 536 |
+
variant would silently omit records. The dispatcher cases are near lines 2119
|
| 537 |
+
and 2224 in the pinned commit.
|
| 538 |
+
|
| 539 |
+
The shown return value is part of the required patch: every producer path must
|
| 540 |
+
report the actually selected stable dispatch token. The implemented Rust V1
|
| 541 |
+
dispatch contract is deliberately narrower than llama.cpp's full selector: it
|
| 542 |
+
accepts only an unfused, single-column MMVQ specialization with exact weight
|
| 543 |
+
type, small-K flag, architecture parameter table, warp count, and rows per
|
| 544 |
+
block, or a flash-attention descriptor with a nonzero exact specialization
|
| 545 |
+
digest. FWHT, cuBLAS, MMVF, MMF, MMQ, fused MMVQ, and any unclassified attention
|
| 546 |
+
specialization must fail closed until a versioned descriptor supports them.
|
| 547 |
+
|
| 548 |
+
The hook must compare the actual token with the registered expected dispatch and
|
| 549 |
+
place the canonical dispatch digest into every V2 record. Rust already derives a
|
| 550 |
+
host-side `producer_kernel_id` from the committed kernel binary and algorithm
|
| 551 |
+
digests, runtime source commit, SM architecture, and validated dispatch. A
|
| 552 |
+
coarse "GEMM" or "attention" label is insufficient, and that derivation does not
|
| 553 |
+
prove actual execution until the device integration supplies and authenticates
|
| 554 |
+
the selected specialization.
|
| 555 |
+
|
| 556 |
+
Some logical dispatches run an ordered bundle of conversion, GEMM/attention,
|
| 557 |
+
and fixup kernels rather than one entry point. The current singular Rust
|
| 558 |
+
`kernel_id` contract cannot silently represent such a bundle. Either restrict
|
| 559 |
+
the approved runtime to a proven single-producer path, hook and record each
|
| 560 |
+
actual kernel under a revised grouping contract, or version the receipt schema
|
| 561 |
+
with an explicit ordered-bundle identity.
|
| 562 |
+
|
| 563 |
+
The bridge accepts only contiguous `GGML_TYPE_F32` destination tensors and uses
|
| 564 |
+
overflow-checked dimensions:
|
| 565 |
+
|
| 566 |
+
| Operation | PALW mapping from ggml |
|
| 567 |
+
| --- | --- |
|
| 568 |
+
| GEMM | `m = dst->ne[0]`, `n = dst->ne[1]`, `k = src0->ne[0]`, `batch = dst->ne[2] * dst->ne[3]`, rows `n * batch`, columns/stride `m` |
|
| 569 |
+
| Flash attention | `query_tokens = Q->ne[1]`, `key_value_tokens = K->ne[1]`, `heads = Q->ne[2] = dst->ne[1]`, `head_dim = V->ne[0] = dst->ne[0]`, `batch = Q->ne[3] = dst->ne[3]`, rows `query_tokens * batch`, columns/stride `heads * head_dim` |
|
| 570 |
+
|
| 571 |
+
The registered descriptor supplies causal policy, logical dtype, quantization,
|
| 572 |
+
phase, layer, and decode step. A non-null attention mask is not sufficient proof
|
| 573 |
+
of causality. Any tensor/layout/descriptor disagreement fails the request before
|
| 574 |
+
the trace launch.
|
| 575 |
+
|
| 576 |
+
The hook stores a PALW error in the backend context. Change
|
| 577 |
+
`ggml_cuda_graph_evaluate_and_capture` to return failure immediately after the
|
| 578 |
+
current `ggml_cuda_compute_forward` call if that sticky status is non-OK, and
|
| 579 |
+
have `ggml_backend_cuda_graph_compute` return `GGML_STATUS_FAILED`. Do not reuse
|
| 580 |
+
the existing `false` return from `ggml_cuda_compute_forward`, because that path
|
| 581 |
+
currently means "unsupported op" and is followed by `GGML_ASSERT(ok)`.
|
| 582 |
+
|
| 583 |
+
The current `palw_cuda_trace_copy_async` path copies only native V1 final-output
|
| 584 |
+
records. A producer integration must add a separately reviewed V2 device-buffer
|
| 585 |
+
and copy path; relabeling or wrapping a copied V1 record as producer-accumulator
|
| 586 |
+
evidence is forbidden. After graph submission, finalization must synchronize the
|
| 587 |
+
same stream, check committed count and exact node/record coverage, encode every
|
| 588 |
+
V2 record, strictly decode it in Rust, and call `bind_cuda_trace_v2`. Any hook,
|
| 589 |
+
CUDA, overflow, coverage, codec, decoder, or binding error fails the request.
|
| 590 |
+
Even success produces diagnostic bound transport only. It must next pass the
|
| 591 |
+
authority verification described above; a successful authority-bound projection
|
| 592 |
+
still suppresses V1 receipt issuance. Current V3 authority evidence is accepted
|
| 593 |
+
only by the separately versioned Receipt V2 flow.
|
| 594 |
+
|
| 595 |
+
The CUDA `kernel_sequence` is a zero-based **logical launch** sequence. Every
|
| 596 |
+
tile belonging to one registered GEMM or attention launch carries the same raw
|
| 597 |
+
sequence, and attention launches consume sequence values. This deliberately does
|
| 598 |
+
not match the current Rust `GemmTraceSample.kernel_sequence`, which is a
|
| 599 |
+
zero-based sequence over GEMM tile events only. `bind_cuda_trace_v2` now performs
|
| 600 |
+
the complete unfiltered validation: launch sequences are consecutive, each
|
| 601 |
+
registered launch owns one contiguous tile/segment range, every record in that
|
| 602 |
+
range has matching metadata and dispatch digest, and all expected GEMM and
|
| 603 |
+
attention launches are present exactly once. Filtering or resequencing first
|
| 604 |
+
could hide a missing or reordered attention launch and remains forbidden.
|
| 605 |
+
|
| 606 |
+
Raw or merely bound CUDA records must never be passed to `GemmTrace::push_group`
|
| 607 |
+
or represented as `TraceEvidenceKind::KernelSketch`. Only the authority-verified
|
| 608 |
+
typestate can create the implemented future-V2 projection, which commits its
|
| 609 |
+
signed attestation, full transcript, integration, mapping version, and projected
|
| 610 |
+
trace. It does not make that trace valid V1 evidence. Production issuance still
|
| 611 |
+
requires governance approval of the exact binary/manifest, a live callback fed
|
| 612 |
+
by canonical authority IDs, deployed trust roots, and reproducibility evidence.
|
| 613 |
+
|
| 614 |
+
### Execution modes that must be disabled or rejected initially
|
| 615 |
+
|
| 616 |
+
The first production integration must be deliberately narrow:
|
| 617 |
+
|
| 618 |
+
- Disable CUDA graph capture/replay while PALW is active. A captured sketch
|
| 619 |
+
launch bakes `base_record` and sequence arguments, while a replay skips the
|
| 620 |
+
host dispatcher, so replay would overwrite records. The pinned tree recognizes
|
| 621 |
+
`GGML_CUDA_DISABLE_GRAPHS`, but the patch should make graph enablement return
|
| 622 |
+
false directly when PALW state is active.
|
| 623 |
+
- Disable graph fusion while PALW is active by returning zero from
|
| 624 |
+
`ggml_cuda_try_fuse`. The pinned tree also has `GGML_CUDA_DISABLE_FUSION=1` for
|
| 625 |
+
prototype runs. Fused MUL_MAT paths around lines 3224-3715 bypass the central
|
| 626 |
+
dispatcher hooks.
|
| 627 |
+
- Require `curr_stream_no == 0` and a single CUDA device. The graph optimization
|
| 628 |
+
path can use multiple streams when `GGML_CUDA_GRAPH_OPT=1`; an initial PALW
|
| 629 |
+
request must reject it. Supporting concurrency later requires one context per
|
| 630 |
+
stream plus a separately specified deterministic merge order.
|
| 631 |
+
- Require the initial Rust V2 binding profile's fixed `batch == 1`. The strict
|
| 632 |
+
record decoder and standalone C transport can represent larger batches, but
|
| 633 |
+
`ExpectedCudaLaunchV1` rejects them.
|
| 634 |
+
- Support the exact unfused, single-column MMVQ dense path only. Reject other
|
| 635 |
+
`GGML_OP_MUL_MAT` variants, `GGML_OP_MUL_MAT_ID`, and unexpected CPU/offload
|
| 636 |
+
paths until each has an explicit versioned dispatch descriptor. This is
|
| 637 |
+
suitable for the dense Qwen target, not MoE.
|
| 638 |
+
- For the FA-off runtime, require exact hooks for QK-score GEMM, masked/scaled
|
| 639 |
+
softmax, and PV GEMM under the V3 grouping contract. Never
|
| 640 |
+
claim full attention coverage while any stage is uninstrumented. A separately
|
| 641 |
+
approved FA-on class would require its own exact fused specialization binding.
|
| 642 |
+
|
| 643 |
+
These restrictions are receipt integrity requirements, not performance hints.
|
| 644 |
+
Removing one requires a new tested ordering and coverage contract.
|
| 645 |
+
|
| 646 |
+
## Known limits before production approval
|
| 647 |
+
|
| 648 |
+
- The vendored Q4_K/Q6_K MMVQ hook captures a diagnostic full-K pre-epilogue
|
| 649 |
+
FP32 accumulator. The FA-off QK MMVF, F32 masked/scaled softmax, and PV MMVF
|
| 650 |
+
work paths enqueue the grouped collector on the same stream. The 361-launch
|
| 651 |
+
device E2E and exact release manifest are evidence, but the live callback still
|
| 652 |
+
uses diagnostic rather than authority-provided canonical physical-layout IDs.
|
| 653 |
+
- The launch wrapper checks an exact function pointer and attributes, but CUDA
|
| 654 |
+
cannot derive/attest the release binary digest or semantic accumulator stage
|
| 655 |
+
from that pointer; reviewed source, binary attestation, and manifest binding
|
| 656 |
+
are still required.
|
| 657 |
+
- The 32 public sample positions and integer mixer are deterministic evidence,
|
| 658 |
+
not a cryptographic proof that every output element was computed. Hashing the
|
| 659 |
+
resulting record with SHA3 does not recover unsampled coverage; replication,
|
| 660 |
+
future audit, and an approved sampling/security analysis remain mandatory.
|
| 661 |
+
- Raw or merely bound transcripts cannot establish `KernelSketch` provenance.
|
| 662 |
+
Only the V3 authority typestate may enter Receipt V2; CUDA `KernelSketch`
|
| 663 |
+
remains forbidden in `ComputeReceiptV1`.
|
| 664 |
+
- Cross-architecture and cross-driver reproducibility is unproven.
|
| 665 |
+
- CUDA graph replay, fusion, concurrent streams, multi-GPU merge, MoE
|
| 666 |
+
`MUL_MAT_ID`, and attention variants outside the pinned FA-off QK-score /
|
| 667 |
+
masked-scaled-softmax / PV specializations are intentionally unsupported by
|
| 668 |
+
the proposed first integration.
|
| 669 |
+
- Existing llama.cpp `CUDA_CHECK`/`GGML_ABORT` process-fatal behavior is outside
|
| 670 |
+
this library; a service-grade integration must audit whether those paths need
|
| 671 |
+
conversion to request-scoped errors.
|
| 672 |
+
|
| 673 |
+
R32 remains in progress until the integration proves every accepted event came
|
| 674 |
+
from the exact authority-approved release kernel entry point (or an explicitly
|
| 675 |
+
versioned ordered-kernel-bundle identity) through the live canonical authority
|
| 676 |
+
callback and passes replica/reproducibility gates under deployed trust roots.
|
| 677 |
+
FA-off attention coverage, device E2E, the release manifest, and Receipt V2 are
|
| 678 |
+
complete for the fixed diagnostic profile. The external NVIDIA
|
| 679 |
+
hardware blocker is resolved by the SM89 gate above; the remaining blockers are
|
| 680 |
+
authority/governance integration and production evidence.
|
| 681 |
+
Host-side V2/V3 transport and expected-metadata binding do not satisfy those
|
| 682 |
+
conditions. The production CMake gate and capability macro must not be opened
|
| 683 |
+
before they do.
|
runtime-palw/cuda/abi_contract_test.cpp
ADDED
|
@@ -0,0 +1,723 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "palw_cuda_trace.h"
|
| 2 |
+
|
| 3 |
+
#include <array>
|
| 4 |
+
#include <cstddef>
|
| 5 |
+
#include <cstdint>
|
| 6 |
+
#include <cstdio>
|
| 7 |
+
#include <cstring>
|
| 8 |
+
#include <fstream>
|
| 9 |
+
#include <string>
|
| 10 |
+
#include <type_traits>
|
| 11 |
+
#include <vector>
|
| 12 |
+
|
| 13 |
+
#if !defined(PALW_CUDA_TRACE_GOLDEN_FIXTURE_PATH)
|
| 14 |
+
#error "PALW_CUDA_TRACE_GOLDEN_FIXTURE_PATH is required"
|
| 15 |
+
#endif
|
| 16 |
+
#if !defined(PALW_CUDA_TRACE_GOLDEN_FIXTURE_V3_PATH)
|
| 17 |
+
#error "PALW_CUDA_TRACE_GOLDEN_FIXTURE_V3_PATH is required"
|
| 18 |
+
#endif
|
| 19 |
+
|
| 20 |
+
static_assert(PALW_CUDA_TRACE_ABI_VERSION == 1U);
|
| 21 |
+
static_assert(PALW_CUDA_TRACE_SCHEMA_VERSION == 1U);
|
| 22 |
+
static_assert(PALW_CUDA_TRACE_SCHEMA_VERSION_V1 == 1U);
|
| 23 |
+
static_assert(PALW_CUDA_TRACE_SCHEMA_VERSION_V2 == 2U);
|
| 24 |
+
static_assert(PALW_CUDA_TRACE_SCHEMA_VERSION_V3 == 3U);
|
| 25 |
+
static_assert(PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V1 == 139U);
|
| 26 |
+
static_assert(PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V2 == 184U);
|
| 27 |
+
static_assert(PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V3 == 452U);
|
| 28 |
+
static_assert(PALW_CUDA_TRACE_PRODUCTION_CAPABLE == 0U);
|
| 29 |
+
static_assert(sizeof(palw_cuda_trace_record) == 144U);
|
| 30 |
+
static_assert(alignof(palw_cuda_trace_record) == 8U);
|
| 31 |
+
static_assert(std::is_standard_layout_v<palw_cuda_trace_record>);
|
| 32 |
+
static_assert(std::is_trivial_v<palw_cuda_trace_record>);
|
| 33 |
+
static_assert(offsetof(palw_cuda_trace_record, kernel_sequence) == 0U);
|
| 34 |
+
static_assert(offsetof(palw_cuda_trace_record, sketch) == 72U);
|
| 35 |
+
static_assert(offsetof(palw_cuda_trace_record, layer_id) == 104U);
|
| 36 |
+
static_assert(offsetof(palw_cuda_trace_record, schema_version) == 132U);
|
| 37 |
+
static_assert(offsetof(palw_cuda_trace_record, kind) == 134U);
|
| 38 |
+
static_assert(offsetof(palw_cuda_trace_record, reserved) == 139U);
|
| 39 |
+
static_assert(sizeof(palw_cuda_trace_record_v2) == 192U);
|
| 40 |
+
static_assert(alignof(palw_cuda_trace_record_v2) == 8U);
|
| 41 |
+
static_assert(std::is_standard_layout_v<palw_cuda_trace_record_v2>);
|
| 42 |
+
static_assert(std::is_trivial_v<palw_cuda_trace_record_v2>);
|
| 43 |
+
static_assert(offsetof(palw_cuda_trace_record_v2, base) == 0U);
|
| 44 |
+
static_assert(offsetof(palw_cuda_trace_record_v2, declared_origin) == 144U);
|
| 45 |
+
static_assert(offsetof(palw_cuda_trace_record_v2, accumulator_stage) == 145U);
|
| 46 |
+
static_assert(offsetof(palw_cuda_trace_record_v2, accumulator_dtype) == 146U);
|
| 47 |
+
static_assert(offsetof(palw_cuda_trace_record_v2, sketch_scheme) == 148U);
|
| 48 |
+
static_assert(offsetof(palw_cuda_trace_record_v2, reduction_segment_index) == 152U);
|
| 49 |
+
static_assert(offsetof(palw_cuda_trace_record_v2, reduction_segment_count) == 156U);
|
| 50 |
+
static_assert(offsetof(palw_cuda_trace_record_v2, producer_variant_id) == 160U);
|
| 51 |
+
static_assert(sizeof(palw_cuda_trace_record_v3) == 464U);
|
| 52 |
+
static_assert(alignof(palw_cuda_trace_record_v3) == 8U);
|
| 53 |
+
static_assert(std::is_standard_layout_v<palw_cuda_trace_record_v3>);
|
| 54 |
+
static_assert(std::is_trivial_v<palw_cuda_trace_record_v3>);
|
| 55 |
+
static_assert(offsetof(palw_cuda_trace_record_v3, covered_schedule_index) == 192U);
|
| 56 |
+
static_assert(offsetof(palw_cuda_trace_record_v3, layer_present) == 216U);
|
| 57 |
+
static_assert(offsetof(palw_cuda_trace_record_v3, query_heads) == 220U);
|
| 58 |
+
static_assert(offsetof(palw_cuda_trace_record_v3, grid_x) == 240U);
|
| 59 |
+
static_assert(offsetof(palw_cuda_trace_record_v3, operation_instance_id) == 268U);
|
| 60 |
+
static_assert(offsetof(palw_cuda_trace_record_v3, capture_implementation_id) == 428U);
|
| 61 |
+
static_assert(PALW_CUDA_TRACE_OK == 0);
|
| 62 |
+
static_assert(PALW_CUDA_TRACE_PENDING == 6);
|
| 63 |
+
static_assert(PALW_CUDA_TRACE_INCOMPLETE == 7);
|
| 64 |
+
static_assert(PALW_CUDA_TRACE_IDENTITY_MISMATCH == 8);
|
| 65 |
+
static_assert(PALW_CUDA_TRACE_PRODUCER_FAULT == 9);
|
| 66 |
+
static_assert(PALW_CUDA_TRACE_GEMM == 1);
|
| 67 |
+
static_assert(PALW_CUDA_TRACE_ATTENTION == 2);
|
| 68 |
+
static_assert(PALW_CUDA_TRACE_PREFILL == 0);
|
| 69 |
+
static_assert(PALW_CUDA_TRACE_DECODE == 1);
|
| 70 |
+
static_assert(PALW_CUDA_TRACE_DTYPE_FP32 == 0);
|
| 71 |
+
static_assert(PALW_CUDA_TRACE_DTYPE_INT4 == 4);
|
| 72 |
+
static_assert(PALW_CUDA_TRACE_QUANTIZATION_Q4_K_M == 2);
|
| 73 |
+
static_assert(PALW_CUDA_TRACE_QUANTIZATION_IQ4_XS == 5);
|
| 74 |
+
static_assert(PALW_CUDA_TRACE_QUANTIZATION_Q6_K == 6);
|
| 75 |
+
static_assert(PALW_CUDA_TRACE_ORIGIN_FINAL_OUTPUT == 0);
|
| 76 |
+
static_assert(PALW_CUDA_TRACE_ORIGIN_PRODUCER_ACCUMULATOR == 1);
|
| 77 |
+
static_assert(PALW_CUDA_TRACE_ACCUMULATOR_STAGE_NONE == 0);
|
| 78 |
+
static_assert(PALW_CUDA_TRACE_ACCUMULATOR_STAGE_FULL_K_PRE_EPILOGUE == 2);
|
| 79 |
+
static_assert(PALW_CUDA_TRACE_ACCUMULATOR_DTYPE_FP32 == 0);
|
| 80 |
+
static_assert(PALW_CUDA_TRACE_ACCUMULATOR_DTYPE_NONE == 255);
|
| 81 |
+
static_assert(PALW_CUDA_TRACE_SKETCH_FINAL_OUTPUT_TILE_F32_V1 == 1);
|
| 82 |
+
static_assert(PALW_CUDA_TRACE_SKETCH_SCALAR_ACCUMULATOR_F32_V1 == 2);
|
| 83 |
+
static_assert(PALW_CUDA_TRACE_ATTENTION_STAGE_NONE == 0);
|
| 84 |
+
static_assert(PALW_CUDA_TRACE_ATTENTION_STAGE_EAGER_QK_SCORE_MMVF == 1);
|
| 85 |
+
static_assert(PALW_CUDA_TRACE_ATTENTION_STAGE_EAGER_MASKED_SCALED_SOFTMAX == 2);
|
| 86 |
+
static_assert(PALW_CUDA_TRACE_ATTENTION_STAGE_EAGER_VALUE_AGGREGATION_MMVF == 3);
|
| 87 |
+
|
| 88 |
+
namespace {
|
| 89 |
+
|
| 90 |
+
int fail(const char * message) {
|
| 91 |
+
std::fprintf(stderr, "ABI contract failure: %s\n", message);
|
| 92 |
+
return 1;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
palw_cuda_trace_record make_record() {
|
| 96 |
+
palw_cuda_trace_record record{};
|
| 97 |
+
record.kernel_sequence = 0x0102030405060708ULL;
|
| 98 |
+
record.m = 2;
|
| 99 |
+
record.n = 3;
|
| 100 |
+
record.k = 4;
|
| 101 |
+
record.batch = 1;
|
| 102 |
+
record.sketch[0] = 0x1112131415161718ULL;
|
| 103 |
+
record.sketch[1] = 0x2122232425262728ULL;
|
| 104 |
+
record.sketch[2] = 0x3132333435363738ULL;
|
| 105 |
+
record.sketch[3] = 0x4142434445464748ULL;
|
| 106 |
+
record.layer_id = 7;
|
| 107 |
+
record.tile_rows = 3;
|
| 108 |
+
record.tile_columns = 2;
|
| 109 |
+
record.output_rows = 3;
|
| 110 |
+
record.output_columns = 2;
|
| 111 |
+
record.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION;
|
| 112 |
+
record.kind = PALW_CUDA_TRACE_GEMM;
|
| 113 |
+
record.phase = PALW_CUDA_TRACE_PREFILL;
|
| 114 |
+
record.dtype = PALW_CUDA_TRACE_DTYPE_FP32;
|
| 115 |
+
record.quantization = PALW_CUDA_TRACE_QUANTIZATION_Q4_K_M;
|
| 116 |
+
return record;
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
palw_cuda_trace_record_v2 make_record_v2() {
|
| 120 |
+
palw_cuda_trace_record_v2 record{};
|
| 121 |
+
record.base = make_record();
|
| 122 |
+
record.base.kernel_sequence = 0;
|
| 123 |
+
record.base.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V2;
|
| 124 |
+
record.declared_origin = PALW_CUDA_TRACE_ORIGIN_PRODUCER_ACCUMULATOR;
|
| 125 |
+
record.accumulator_stage = PALW_CUDA_TRACE_ACCUMULATOR_STAGE_FULL_K_PRE_EPILOGUE;
|
| 126 |
+
record.accumulator_dtype = PALW_CUDA_TRACE_ACCUMULATOR_DTYPE_FP32;
|
| 127 |
+
record.sketch_scheme = PALW_CUDA_TRACE_SKETCH_SCALAR_ACCUMULATOR_F32_V1;
|
| 128 |
+
record.reduction_segment_count = 1;
|
| 129 |
+
for (size_t index = 0; index < sizeof(record.producer_variant_id); ++index) {
|
| 130 |
+
record.producer_variant_id[index] = static_cast<uint8_t>(0x80U + index);
|
| 131 |
+
}
|
| 132 |
+
return record;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
void fill_id(uint8_t (&identity)[32], uint8_t seed) {
|
| 136 |
+
for (size_t index = 0; index < 32U; ++index) {
|
| 137 |
+
identity[index] = static_cast<uint8_t>(seed + index);
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
palw_cuda_trace_record_v3 make_record_v3() {
|
| 142 |
+
palw_cuda_trace_record_v3 record{};
|
| 143 |
+
record.base = make_record_v2();
|
| 144 |
+
record.base.base.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V3;
|
| 145 |
+
record.base.base.m = 256U;
|
| 146 |
+
record.base.base.n = 1U;
|
| 147 |
+
record.base.base.k = 128U;
|
| 148 |
+
record.base.base.batch = 32U;
|
| 149 |
+
record.base.base.query_tokens = 1U;
|
| 150 |
+
record.base.base.key_value_tokens = 3U;
|
| 151 |
+
record.base.base.tile_rows = 32U;
|
| 152 |
+
record.base.base.tile_columns = 256U;
|
| 153 |
+
record.base.base.output_rows = 32U;
|
| 154 |
+
record.base.base.output_columns = 256U;
|
| 155 |
+
record.base.base.dtype = PALW_CUDA_TRACE_DTYPE_FP32;
|
| 156 |
+
record.base.base.quantization = PALW_CUDA_TRACE_QUANTIZATION_NONE;
|
| 157 |
+
record.base.base.causal = 1U;
|
| 158 |
+
record.base.declared_origin = PALW_CUDA_TRACE_ORIGIN_FINAL_OUTPUT;
|
| 159 |
+
record.base.accumulator_stage = PALW_CUDA_TRACE_ACCUMULATOR_STAGE_NONE;
|
| 160 |
+
record.base.accumulator_dtype = PALW_CUDA_TRACE_ACCUMULATOR_DTYPE_NONE;
|
| 161 |
+
record.base.sketch_scheme = PALW_CUDA_TRACE_SKETCH_FINAL_OUTPUT_TILE_F32_V1;
|
| 162 |
+
record.base.reduction_segment_count = 0U;
|
| 163 |
+
record.covered_schedule_index = 14U;
|
| 164 |
+
record.attention_owner_schedule_index = 15U;
|
| 165 |
+
record.sublaunch_count = 3U;
|
| 166 |
+
record.layer_present = 1U;
|
| 167 |
+
record.attention_group_present = 1U;
|
| 168 |
+
record.attention_stage = PALW_CUDA_TRACE_ATTENTION_STAGE_EAGER_QK_SCORE_MMVF;
|
| 169 |
+
record.grouping_version = PALW_CUDA_TRACE_GROUPING_VERSION_V1;
|
| 170 |
+
record.query_heads = 32U;
|
| 171 |
+
record.key_value_heads = 8U;
|
| 172 |
+
record.head_dim = 128U;
|
| 173 |
+
record.logical_batch = 1U;
|
| 174 |
+
record.physical_key_value_tokens = 256U;
|
| 175 |
+
record.grid_x = 256U;
|
| 176 |
+
record.grid_y = 32U;
|
| 177 |
+
record.grid_z = 1U;
|
| 178 |
+
record.block_x = 64U;
|
| 179 |
+
record.block_y = 1U;
|
| 180 |
+
record.block_z = 1U;
|
| 181 |
+
record.dynamic_shared_memory_bytes = 128U;
|
| 182 |
+
fill_id(record.operation_instance_id, 0x10U);
|
| 183 |
+
fill_id(record.attention_group_instance_id, 0x30U);
|
| 184 |
+
fill_id(record.decomposition_plan_id, 0x50U);
|
| 185 |
+
fill_id(record.physical_layout_id, 0x70U);
|
| 186 |
+
fill_id(record.work_entry_point_id, 0x90U);
|
| 187 |
+
fill_id(record.capture_implementation_id, 0xb0U);
|
| 188 |
+
return record;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
palw_cuda_trace_record_v3 make_direct_q6_record_v3() {
|
| 192 |
+
palw_cuda_trace_record_v3 record{};
|
| 193 |
+
record.base = make_record_v2();
|
| 194 |
+
record.base.base.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V3;
|
| 195 |
+
record.base.base.layer_id = 0U;
|
| 196 |
+
record.base.base.quantization = PALW_CUDA_TRACE_QUANTIZATION_Q6_K;
|
| 197 |
+
record.covered_schedule_index = 253U;
|
| 198 |
+
record.sublaunch_count = 1U;
|
| 199 |
+
record.grid_x = 2U;
|
| 200 |
+
record.grid_y = 1U;
|
| 201 |
+
record.grid_z = 1U;
|
| 202 |
+
record.block_x = 32U;
|
| 203 |
+
record.block_y = 4U;
|
| 204 |
+
record.block_z = 1U;
|
| 205 |
+
fill_id(record.operation_instance_id, 0x11U);
|
| 206 |
+
fill_id(record.decomposition_plan_id, 0x51U);
|
| 207 |
+
fill_id(record.physical_layout_id, 0x71U);
|
| 208 |
+
fill_id(record.work_entry_point_id, 0x91U);
|
| 209 |
+
fill_id(record.capture_implementation_id, 0xb1U);
|
| 210 |
+
return record;
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
uint8_t hex_nibble(char value) {
|
| 214 |
+
if (value >= '0' && value <= '9') {
|
| 215 |
+
return static_cast<uint8_t>(value - '0');
|
| 216 |
+
}
|
| 217 |
+
if (value >= 'a' && value <= 'f') {
|
| 218 |
+
return static_cast<uint8_t>(value - 'a' + 10);
|
| 219 |
+
}
|
| 220 |
+
return 0xffU;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
std::vector<uint8_t> load_golden_fixture(const char * path) {
|
| 224 |
+
std::ifstream input(path);
|
| 225 |
+
std::string hex;
|
| 226 |
+
input >> hex;
|
| 227 |
+
if (!input || hex.size() % 2U != 0U) {
|
| 228 |
+
return {};
|
| 229 |
+
}
|
| 230 |
+
std::vector<uint8_t> bytes;
|
| 231 |
+
bytes.reserve(hex.size() / 2U);
|
| 232 |
+
for (size_t index = 0; index < hex.size(); index += 2U) {
|
| 233 |
+
const uint8_t high = hex_nibble(hex[index]);
|
| 234 |
+
const uint8_t low = hex_nibble(hex[index + 1U]);
|
| 235 |
+
if (high > 0x0fU || low > 0x0fU) {
|
| 236 |
+
return {};
|
| 237 |
+
}
|
| 238 |
+
bytes.push_back(static_cast<uint8_t>((high << 4U) | low));
|
| 239 |
+
}
|
| 240 |
+
return bytes;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
} // namespace
|
| 244 |
+
|
| 245 |
+
int main() {
|
| 246 |
+
palw_cuda_trace_record first = make_record();
|
| 247 |
+
palw_cuda_trace_record second = first;
|
| 248 |
+
|
| 249 |
+
auto * native_bytes = reinterpret_cast<uint8_t *>(&second);
|
| 250 |
+
for (size_t i = 140; i < sizeof(second); ++i) {
|
| 251 |
+
native_bytes[i] = static_cast<uint8_t>(0xa0U + i);
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
std::array<uint8_t, PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V1> encoded_first{};
|
| 255 |
+
std::array<uint8_t, PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V1> encoded_second{};
|
| 256 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 257 |
+
&first, encoded_first.data(), encoded_first.size()) != PALW_CUDA_TRACE_OK ||
|
| 258 |
+
palw_cuda_trace_encode_record_v1(
|
| 259 |
+
&second, encoded_second.data(), encoded_second.size()) != PALW_CUDA_TRACE_OK) {
|
| 260 |
+
return fail("valid record did not encode");
|
| 261 |
+
}
|
| 262 |
+
if (encoded_first != encoded_second) {
|
| 263 |
+
return fail("native tail padding affected canonical encoding");
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
const std::array<uint8_t, 8> expected_sequence = {1, 2, 3, 4, 5, 6, 7, 8};
|
| 267 |
+
if (std::memcmp(encoded_first.data(), expected_sequence.data(), expected_sequence.size()) != 0) {
|
| 268 |
+
return fail("u64 encoding is not big-endian");
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
second.reserved = 1;
|
| 272 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 273 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 274 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 275 |
+
return fail("nonzero reserved byte was accepted");
|
| 276 |
+
}
|
| 277 |
+
second = first;
|
| 278 |
+
second.dtype = 255;
|
| 279 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 280 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 281 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 282 |
+
return fail("unknown dtype was accepted");
|
| 283 |
+
}
|
| 284 |
+
second = first;
|
| 285 |
+
second.quantization = 255;
|
| 286 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 287 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 288 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 289 |
+
return fail("unknown quantization was accepted");
|
| 290 |
+
}
|
| 291 |
+
second = first;
|
| 292 |
+
second.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V2;
|
| 293 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 294 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 295 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 296 |
+
return fail("V2 schema tag was accepted by the V1 codec");
|
| 297 |
+
}
|
| 298 |
+
second = first;
|
| 299 |
+
second.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V3;
|
| 300 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 301 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 302 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 303 |
+
return fail("V3 schema tag was accepted by the V1 codec");
|
| 304 |
+
}
|
| 305 |
+
second = first;
|
| 306 |
+
second.quantization = PALW_CUDA_TRACE_QUANTIZATION_Q6_K;
|
| 307 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 308 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 309 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 310 |
+
return fail("V3-only Q6_K tag was accepted by the V1 codec");
|
| 311 |
+
}
|
| 312 |
+
second = first;
|
| 313 |
+
second.decode_step = 1;
|
| 314 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 315 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 316 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 317 |
+
return fail("invalid prefill step was accepted");
|
| 318 |
+
}
|
| 319 |
+
second = first;
|
| 320 |
+
second.tile_index = 1;
|
| 321 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 322 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 323 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 324 |
+
return fail("invalid tile index was accepted");
|
| 325 |
+
}
|
| 326 |
+
second = first;
|
| 327 |
+
second.output_columns = 3;
|
| 328 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 329 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 330 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 331 |
+
return fail("invalid GEMM output shape was accepted");
|
| 332 |
+
}
|
| 333 |
+
second = first;
|
| 334 |
+
second.batch = 2;
|
| 335 |
+
second.output_rows = 6;
|
| 336 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 337 |
+
&second, encoded_second.data(), encoded_second.size()) != PALW_CUDA_TRACE_OK) {
|
| 338 |
+
return fail("valid batched GEMM output shape was rejected");
|
| 339 |
+
}
|
| 340 |
+
second = first;
|
| 341 |
+
second.m = static_cast<uint64_t>(UINT32_MAX) + 1U;
|
| 342 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 343 |
+
&second, encoded_second.data(), encoded_second.size()) !=
|
| 344 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 345 |
+
return fail("oversized GEMM dimension was accepted");
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
palw_cuda_trace_record attention = first;
|
| 349 |
+
attention.kernel_sequence = 1;
|
| 350 |
+
attention.m = 2;
|
| 351 |
+
attention.n = 8;
|
| 352 |
+
attention.k = 3;
|
| 353 |
+
attention.query_tokens = 2;
|
| 354 |
+
attention.key_value_tokens = 3;
|
| 355 |
+
attention.tile_rows = 1;
|
| 356 |
+
attention.tile_columns = 4;
|
| 357 |
+
attention.output_rows = 2;
|
| 358 |
+
attention.output_columns = 8;
|
| 359 |
+
attention.kind = PALW_CUDA_TRACE_ATTENTION;
|
| 360 |
+
attention.dtype = PALW_CUDA_TRACE_DTYPE_FP16;
|
| 361 |
+
attention.quantization = PALW_CUDA_TRACE_QUANTIZATION_NONE;
|
| 362 |
+
attention.causal = 1;
|
| 363 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 364 |
+
&attention, encoded_second.data(), encoded_second.size()) != PALW_CUDA_TRACE_OK) {
|
| 365 |
+
return fail("valid attention record did not encode");
|
| 366 |
+
}
|
| 367 |
+
attention.key_value_tokens = 1;
|
| 368 |
+
attention.k = 1;
|
| 369 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 370 |
+
&attention, encoded_second.data(), encoded_second.size()) !=
|
| 371 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 372 |
+
return fail("invalid causal attention shape was accepted");
|
| 373 |
+
}
|
| 374 |
+
attention = first;
|
| 375 |
+
attention.kernel_sequence = 1;
|
| 376 |
+
attention.m = 2;
|
| 377 |
+
attention.n = 8;
|
| 378 |
+
attention.k = 3;
|
| 379 |
+
attention.query_tokens = 2;
|
| 380 |
+
attention.key_value_tokens = 3;
|
| 381 |
+
attention.tile_rows = 1;
|
| 382 |
+
attention.tile_columns = 4;
|
| 383 |
+
attention.output_rows = 2;
|
| 384 |
+
attention.output_columns = 8;
|
| 385 |
+
attention.kind = PALW_CUDA_TRACE_ATTENTION;
|
| 386 |
+
attention.phase = PALW_CUDA_TRACE_DECODE;
|
| 387 |
+
attention.dtype = PALW_CUDA_TRACE_DTYPE_FP16;
|
| 388 |
+
attention.quantization = PALW_CUDA_TRACE_QUANTIZATION_NONE;
|
| 389 |
+
attention.causal = 1;
|
| 390 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 391 |
+
&attention, encoded_second.data(), encoded_second.size()) !=
|
| 392 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 393 |
+
return fail("multi-query-token decode attention was accepted");
|
| 394 |
+
}
|
| 395 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 396 |
+
&first, encoded_first.data(), encoded_first.size() - 1U) !=
|
| 397 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 398 |
+
return fail("short destination was accepted");
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
palw_cuda_trace_record_v2 first_v2 = make_record_v2();
|
| 402 |
+
palw_cuda_trace_record_v2 second_v2 = first_v2;
|
| 403 |
+
auto * native_v2_bytes = reinterpret_cast<uint8_t *>(&second_v2);
|
| 404 |
+
for (size_t index = 140U; index < 144U; ++index) {
|
| 405 |
+
native_v2_bytes[index] = static_cast<uint8_t>(0x50U + index);
|
| 406 |
+
}
|
| 407 |
+
native_v2_bytes[147] = 0xaaU;
|
| 408 |
+
native_v2_bytes[150] = 0xbbU;
|
| 409 |
+
native_v2_bytes[151] = 0xccU;
|
| 410 |
+
|
| 411 |
+
std::array<uint8_t, PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V2> encoded_first_v2{};
|
| 412 |
+
std::array<uint8_t, PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V2> encoded_second_v2{};
|
| 413 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 414 |
+
&first_v2, encoded_first_v2.data(), encoded_first_v2.size()) !=
|
| 415 |
+
PALW_CUDA_TRACE_OK ||
|
| 416 |
+
palw_cuda_trace_encode_record_v2(
|
| 417 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 418 |
+
PALW_CUDA_TRACE_OK) {
|
| 419 |
+
return fail("valid V2 producer-accumulator record did not encode");
|
| 420 |
+
}
|
| 421 |
+
if (encoded_first_v2 != encoded_second_v2) {
|
| 422 |
+
return fail("native V2 padding affected canonical encoding");
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
const std::vector<uint8_t> golden_v2 = load_golden_fixture(PALW_CUDA_TRACE_GOLDEN_FIXTURE_PATH);
|
| 426 |
+
if (golden_v2.size() != encoded_first_v2.size() ||
|
| 427 |
+
std::memcmp(golden_v2.data(), encoded_first_v2.data(), encoded_first_v2.size()) != 0) {
|
| 428 |
+
return fail("V2 canonical encoding did not match the shared golden fixture");
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
second_v2 = first_v2;
|
| 432 |
+
std::memset(second_v2.producer_variant_id, 0, sizeof(second_v2.producer_variant_id));
|
| 433 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 434 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 435 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 436 |
+
return fail("zero V2 producer variant ID was accepted");
|
| 437 |
+
}
|
| 438 |
+
second_v2 = first_v2;
|
| 439 |
+
second_v2.declared_origin = 255U;
|
| 440 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 441 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 442 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 443 |
+
return fail("unknown V2 declared origin was accepted");
|
| 444 |
+
}
|
| 445 |
+
second_v2 = first_v2;
|
| 446 |
+
second_v2.accumulator_stage = PALW_CUDA_TRACE_ACCUMULATOR_STAGE_NONE;
|
| 447 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 448 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 449 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 450 |
+
return fail("producer origin without an accumulator stage was accepted");
|
| 451 |
+
}
|
| 452 |
+
second_v2 = first_v2;
|
| 453 |
+
second_v2.accumulator_dtype = PALW_CUDA_TRACE_ACCUMULATOR_DTYPE_FP16;
|
| 454 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 455 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 456 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 457 |
+
return fail("non-FP32 scalar accumulator scheme was accepted");
|
| 458 |
+
}
|
| 459 |
+
second_v2 = first_v2;
|
| 460 |
+
second_v2.reduction_segment_count = 0U;
|
| 461 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 462 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 463 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 464 |
+
return fail("producer origin without reduction segments was accepted");
|
| 465 |
+
}
|
| 466 |
+
second_v2 = first_v2;
|
| 467 |
+
second_v2.reduction_segment_index = 1U;
|
| 468 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 469 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 470 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 471 |
+
return fail("out-of-range reduction segment was accepted");
|
| 472 |
+
}
|
| 473 |
+
second_v2 = first_v2;
|
| 474 |
+
second_v2.reduction_segment_count = 2U;
|
| 475 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 476 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 477 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 478 |
+
return fail("full-K accumulator was split into multiple reduction segments");
|
| 479 |
+
}
|
| 480 |
+
second_v2 = first_v2;
|
| 481 |
+
second_v2.base.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V1;
|
| 482 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 483 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 484 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 485 |
+
return fail("V1 schema tag was accepted by the V2 codec");
|
| 486 |
+
}
|
| 487 |
+
second_v2 = first_v2;
|
| 488 |
+
second_v2.base.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V3;
|
| 489 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 490 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 491 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 492 |
+
return fail("V3 schema tag was accepted by the V2 codec");
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
second_v2 = first_v2;
|
| 496 |
+
second_v2.declared_origin = PALW_CUDA_TRACE_ORIGIN_FINAL_OUTPUT;
|
| 497 |
+
second_v2.accumulator_stage = PALW_CUDA_TRACE_ACCUMULATOR_STAGE_NONE;
|
| 498 |
+
second_v2.accumulator_dtype = PALW_CUDA_TRACE_ACCUMULATOR_DTYPE_NONE;
|
| 499 |
+
second_v2.sketch_scheme = PALW_CUDA_TRACE_SKETCH_FINAL_OUTPUT_TILE_F32_V1;
|
| 500 |
+
second_v2.reduction_segment_index = 0U;
|
| 501 |
+
second_v2.reduction_segment_count = 0U;
|
| 502 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 503 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 504 |
+
PALW_CUDA_TRACE_OK) {
|
| 505 |
+
return fail("valid V2 final-output declaration did not encode");
|
| 506 |
+
}
|
| 507 |
+
second_v2.reduction_segment_count = 1U;
|
| 508 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 509 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 510 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 511 |
+
return fail("final-output declaration with a reduction segment was accepted");
|
| 512 |
+
}
|
| 513 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 514 |
+
&first_v2, encoded_first_v2.data(), encoded_first_v2.size() - 1U) !=
|
| 515 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 516 |
+
return fail("short V2 destination was accepted");
|
| 517 |
+
}
|
| 518 |
+
|
| 519 |
+
second_v2 = first_v2;
|
| 520 |
+
second_v2.base.quantization = PALW_CUDA_TRACE_QUANTIZATION_Q6_K;
|
| 521 |
+
if (palw_cuda_trace_encode_record_v2(
|
| 522 |
+
&second_v2, encoded_second_v2.data(), encoded_second_v2.size()) !=
|
| 523 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 524 |
+
return fail("V3-only Q6_K tag was accepted by the V2 codec");
|
| 525 |
+
}
|
| 526 |
+
|
| 527 |
+
palw_cuda_trace_record_v3 first_v3 = make_record_v3();
|
| 528 |
+
palw_cuda_trace_record_v3 second_v3 = first_v3;
|
| 529 |
+
std::array<uint8_t, PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V3> encoded_first_v3{};
|
| 530 |
+
std::array<uint8_t, PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V3> encoded_second_v3{};
|
| 531 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 532 |
+
&first_v3, encoded_first_v3.data(), encoded_first_v3.size()) !=
|
| 533 |
+
PALW_CUDA_TRACE_OK) {
|
| 534 |
+
return fail("valid V3 eager-QK record did not encode");
|
| 535 |
+
}
|
| 536 |
+
auto * native_v3_bytes = reinterpret_cast<uint8_t *>(&second_v3);
|
| 537 |
+
for (size_t index = 460U; index < sizeof(second_v3); ++index) {
|
| 538 |
+
native_v3_bytes[index] = static_cast<uint8_t>(0xc0U + index);
|
| 539 |
+
}
|
| 540 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 541 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 542 |
+
PALW_CUDA_TRACE_OK) {
|
| 543 |
+
return fail("valid V3 record with nonzero native tail padding did not encode");
|
| 544 |
+
}
|
| 545 |
+
if (encoded_first_v3 != encoded_second_v3) {
|
| 546 |
+
return fail("native V3 tail padding affected canonical encoding");
|
| 547 |
+
}
|
| 548 |
+
const std::vector<uint8_t> golden_v3 =
|
| 549 |
+
load_golden_fixture(PALW_CUDA_TRACE_GOLDEN_FIXTURE_V3_PATH);
|
| 550 |
+
if (golden_v3.size() != encoded_first_v3.size() ||
|
| 551 |
+
std::memcmp(golden_v3.data(), encoded_first_v3.data(), encoded_first_v3.size()) != 0) {
|
| 552 |
+
return fail("V3 canonical encoding did not match the shared golden fixture");
|
| 553 |
+
}
|
| 554 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 555 |
+
&first_v3, encoded_first_v3.data(), encoded_first_v3.size() - 1U) !=
|
| 556 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 557 |
+
return fail("short V3 destination was accepted");
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
palw_cuda_trace_record_v3 softmax_v3 = first_v3;
|
| 561 |
+
softmax_v3.base.base.kind = PALW_CUDA_TRACE_ATTENTION;
|
| 562 |
+
softmax_v3.base.base.k = 1U;
|
| 563 |
+
softmax_v3.covered_schedule_index = 15U;
|
| 564 |
+
softmax_v3.sublaunch_index = 1U;
|
| 565 |
+
softmax_v3.attention_stage =
|
| 566 |
+
PALW_CUDA_TRACE_ATTENTION_STAGE_EAGER_MASKED_SCALED_SOFTMAX;
|
| 567 |
+
softmax_v3.grid_x = 1U;
|
| 568 |
+
softmax_v3.block_x = 256U;
|
| 569 |
+
softmax_v3.dynamic_shared_memory_bytes = 1152U;
|
| 570 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 571 |
+
&softmax_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 572 |
+
PALW_CUDA_TRACE_OK) {
|
| 573 |
+
return fail("valid V3 eager-softmax record did not encode");
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
palw_cuda_trace_record_v3 kqv_v3 = first_v3;
|
| 577 |
+
kqv_v3.base.base.m = 128U;
|
| 578 |
+
kqv_v3.base.base.k = 256U;
|
| 579 |
+
kqv_v3.base.base.tile_columns = 128U;
|
| 580 |
+
kqv_v3.base.base.output_columns = 128U;
|
| 581 |
+
kqv_v3.covered_schedule_index = 16U;
|
| 582 |
+
kqv_v3.sublaunch_index = 2U;
|
| 583 |
+
kqv_v3.attention_stage =
|
| 584 |
+
PALW_CUDA_TRACE_ATTENTION_STAGE_EAGER_VALUE_AGGREGATION_MMVF;
|
| 585 |
+
kqv_v3.grid_x = 128U;
|
| 586 |
+
kqv_v3.block_x = 128U;
|
| 587 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 588 |
+
&kqv_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 589 |
+
PALW_CUDA_TRACE_OK) {
|
| 590 |
+
return fail("valid V3 eager-KQV record did not encode");
|
| 591 |
+
}
|
| 592 |
+
|
| 593 |
+
palw_cuda_trace_record_v3 direct_q6 = make_direct_q6_record_v3();
|
| 594 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 595 |
+
&direct_q6, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 596 |
+
PALW_CUDA_TRACE_OK) {
|
| 597 |
+
return fail("valid direct Q6_K V3 record did not encode");
|
| 598 |
+
}
|
| 599 |
+
|
| 600 |
+
struct V3IdentityZeroMutation {
|
| 601 |
+
size_t offset;
|
| 602 |
+
const char * failure_message;
|
| 603 |
+
};
|
| 604 |
+
constexpr size_t producer_variant_id_offset =
|
| 605 |
+
offsetof(palw_cuda_trace_record_v3, base) +
|
| 606 |
+
offsetof(palw_cuda_trace_record_v2, producer_variant_id);
|
| 607 |
+
constexpr std::array<V3IdentityZeroMutation, 7> grouped_required_identities{{
|
| 608 |
+
{producer_variant_id_offset, "zero grouped V3 producer variant ID was accepted"},
|
| 609 |
+
{offsetof(palw_cuda_trace_record_v3, operation_instance_id),
|
| 610 |
+
"zero grouped V3 operation instance ID was accepted"},
|
| 611 |
+
{offsetof(palw_cuda_trace_record_v3, attention_group_instance_id),
|
| 612 |
+
"zero grouped V3 attention group instance ID was accepted"},
|
| 613 |
+
{offsetof(palw_cuda_trace_record_v3, decomposition_plan_id),
|
| 614 |
+
"zero grouped V3 decomposition plan ID was accepted"},
|
| 615 |
+
{offsetof(palw_cuda_trace_record_v3, physical_layout_id),
|
| 616 |
+
"zero grouped V3 physical layout ID was accepted"},
|
| 617 |
+
{offsetof(palw_cuda_trace_record_v3, work_entry_point_id),
|
| 618 |
+
"zero grouped V3 work entry-point ID was accepted"},
|
| 619 |
+
{offsetof(palw_cuda_trace_record_v3, capture_implementation_id),
|
| 620 |
+
"zero grouped V3 capture implementation ID was accepted"},
|
| 621 |
+
}};
|
| 622 |
+
for (const V3IdentityZeroMutation & mutation : grouped_required_identities) {
|
| 623 |
+
second_v3 = first_v3;
|
| 624 |
+
std::memset(reinterpret_cast<uint8_t *>(&second_v3) + mutation.offset, 0, 32U);
|
| 625 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 626 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 627 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 628 |
+
return fail(mutation.failure_message);
|
| 629 |
+
}
|
| 630 |
+
}
|
| 631 |
+
|
| 632 |
+
constexpr std::array<V3IdentityZeroMutation, 6> direct_required_identities{{
|
| 633 |
+
{producer_variant_id_offset, "zero direct V3 producer variant ID was accepted"},
|
| 634 |
+
{offsetof(palw_cuda_trace_record_v3, operation_instance_id),
|
| 635 |
+
"zero direct V3 operation instance ID was accepted"},
|
| 636 |
+
{offsetof(palw_cuda_trace_record_v3, decomposition_plan_id),
|
| 637 |
+
"zero direct V3 decomposition plan ID was accepted"},
|
| 638 |
+
{offsetof(palw_cuda_trace_record_v3, physical_layout_id),
|
| 639 |
+
"zero direct V3 physical layout ID was accepted"},
|
| 640 |
+
{offsetof(palw_cuda_trace_record_v3, work_entry_point_id),
|
| 641 |
+
"zero direct V3 work entry-point ID was accepted"},
|
| 642 |
+
{offsetof(palw_cuda_trace_record_v3, capture_implementation_id),
|
| 643 |
+
"zero direct V3 capture implementation ID was accepted"},
|
| 644 |
+
}};
|
| 645 |
+
for (const V3IdentityZeroMutation & mutation : direct_required_identities) {
|
| 646 |
+
second_v3 = direct_q6;
|
| 647 |
+
std::memset(reinterpret_cast<uint8_t *>(&second_v3) + mutation.offset, 0, 32U);
|
| 648 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 649 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 650 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 651 |
+
return fail(mutation.failure_message);
|
| 652 |
+
}
|
| 653 |
+
}
|
| 654 |
+
second_v3 = direct_q6;
|
| 655 |
+
fill_id(second_v3.attention_group_instance_id, 0xd0U);
|
| 656 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 657 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 658 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 659 |
+
return fail("nonzero direct V3 attention group instance ID was accepted");
|
| 660 |
+
}
|
| 661 |
+
|
| 662 |
+
second_v3 = first_v3;
|
| 663 |
+
second_v3.sublaunch_count = 2U;
|
| 664 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 665 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 666 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 667 |
+
return fail("self-declared V3 attention count shrink was accepted");
|
| 668 |
+
}
|
| 669 |
+
second_v3 = first_v3;
|
| 670 |
+
second_v3.attention_stage = PALW_CUDA_TRACE_ATTENTION_STAGE_EAGER_VALUE_AGGREGATION_MMVF;
|
| 671 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 672 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 673 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 674 |
+
return fail("V3 attention role swap was accepted");
|
| 675 |
+
}
|
| 676 |
+
second_v3 = first_v3;
|
| 677 |
+
second_v3.attention_owner_schedule_index = UINT64_MAX;
|
| 678 |
+
second_v3.covered_schedule_index = UINT64_MAX - 1U;
|
| 679 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 680 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 681 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 682 |
+
return fail("uncompletable V3 UINT64_MAX attention owner was accepted");
|
| 683 |
+
}
|
| 684 |
+
second_v3 = first_v3;
|
| 685 |
+
second_v3.key_value_heads = 3U;
|
| 686 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 687 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 688 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 689 |
+
return fail("V3 attention head factorization mutation was accepted");
|
| 690 |
+
}
|
| 691 |
+
second_v3 = first_v3;
|
| 692 |
+
second_v3.physical_key_value_tokens = 512U;
|
| 693 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 694 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 695 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 696 |
+
return fail("V3 logical/physical KV mismatch was accepted");
|
| 697 |
+
}
|
| 698 |
+
second_v3 = first_v3;
|
| 699 |
+
second_v3.block_x = 1U;
|
| 700 |
+
second_v3.block_z = 128U;
|
| 701 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 702 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 703 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 704 |
+
return fail("impossible V3 CUDA block-z dimension was accepted");
|
| 705 |
+
}
|
| 706 |
+
second_v3 = first_v3;
|
| 707 |
+
second_v3.base.base.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V2;
|
| 708 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 709 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 710 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 711 |
+
return fail("V2 schema tag was accepted by the V3 codec");
|
| 712 |
+
}
|
| 713 |
+
second_v3 = first_v3;
|
| 714 |
+
second_v3.base.base.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION_V1;
|
| 715 |
+
if (palw_cuda_trace_encode_record_v3(
|
| 716 |
+
&second_v3, encoded_second_v3.data(), encoded_second_v3.size()) !=
|
| 717 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT) {
|
| 718 |
+
return fail("V1 schema tag was accepted by the V3 codec");
|
| 719 |
+
}
|
| 720 |
+
|
| 721 |
+
std::puts("PALW CUDA trace V1/V2/V3 ABI and canonical codec contract: ok");
|
| 722 |
+
return 0;
|
| 723 |
+
}
|
runtime-palw/cuda/accumulator.cu
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "palw_cuda_trace_internal.cuh"
|
| 2 |
+
|
| 3 |
+
#include <cuda_runtime.h>
|
| 4 |
+
|
| 5 |
+
#include <cstdint>
|
| 6 |
+
#include <limits>
|
| 7 |
+
#include <new>
|
| 8 |
+
|
| 9 |
+
namespace {
|
| 10 |
+
|
| 11 |
+
constexpr uint32_t kMaxGridX = 2147483647U;
|
| 12 |
+
constexpr uint32_t kMaxGridY = 65535U;
|
| 13 |
+
|
| 14 |
+
constexpr uint64_t kSketchSeed[4] = {
|
| 15 |
+
0x243f6a8885a308d3ULL,
|
| 16 |
+
0x13198a2e03707344ULL,
|
| 17 |
+
0xa4093822299f31d0ULL,
|
| 18 |
+
0x082efa98ec4e6c89ULL,
|
| 19 |
+
};
|
| 20 |
+
|
| 21 |
+
__device__ __forceinline__ uint64_t mix64(uint64_t value) {
|
| 22 |
+
value ^= value >> 30;
|
| 23 |
+
value *= 0xbf58476d1ce4e5b9ULL;
|
| 24 |
+
value ^= value >> 27;
|
| 25 |
+
value *= 0x94d049bb133111ebULL;
|
| 26 |
+
return value ^ (value >> 31);
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
__device__ __forceinline__ uint32_t canonical_float_bits(float value) {
|
| 30 |
+
uint32_t bits = __float_as_uint(value);
|
| 31 |
+
const uint32_t magnitude = bits & 0x7fffffffU;
|
| 32 |
+
if (magnitude == 0U) {
|
| 33 |
+
return 0U;
|
| 34 |
+
}
|
| 35 |
+
if ((bits & 0x7f800000U) == 0x7f800000U && (bits & 0x007fffffU) != 0U) {
|
| 36 |
+
return 0x7fc00000U;
|
| 37 |
+
}
|
| 38 |
+
return bits;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
__global__ void accumulator_sketch_f32(
|
| 42 |
+
const float * output,
|
| 43 |
+
uint64_t row_stride,
|
| 44 |
+
palw_cuda_trace_record * records,
|
| 45 |
+
palw_cuda_trace_launch launch) {
|
| 46 |
+
const uint32_t tile_column = blockIdx.x;
|
| 47 |
+
const uint32_t tile_row = blockIdx.y;
|
| 48 |
+
const uint64_t tiles_per_row =
|
| 49 |
+
(static_cast<uint64_t>(launch.output_columns) + launch.tile_columns - 1U) /
|
| 50 |
+
launch.tile_columns;
|
| 51 |
+
const uint64_t tile_index = static_cast<uint64_t>(tile_row) * tiles_per_row + tile_column;
|
| 52 |
+
if (threadIdx.x != 0U || tile_index >= launch.tile_count) {
|
| 53 |
+
return;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
const uint64_t row_begin_64 = static_cast<uint64_t>(tile_row) * launch.tile_rows;
|
| 57 |
+
const uint64_t column_begin_64 = static_cast<uint64_t>(tile_column) * launch.tile_columns;
|
| 58 |
+
const uint64_t row_end_64 = row_begin_64 + launch.tile_rows < launch.output_rows
|
| 59 |
+
? row_begin_64 + launch.tile_rows
|
| 60 |
+
: launch.output_rows;
|
| 61 |
+
const uint64_t column_end_64 = column_begin_64 + launch.tile_columns < launch.output_columns
|
| 62 |
+
? column_begin_64 + launch.tile_columns
|
| 63 |
+
: launch.output_columns;
|
| 64 |
+
const uint32_t row_begin = static_cast<uint32_t>(row_begin_64);
|
| 65 |
+
const uint32_t column_begin = static_cast<uint32_t>(column_begin_64);
|
| 66 |
+
const uint32_t height = static_cast<uint32_t>(row_end_64 - row_begin_64);
|
| 67 |
+
const uint32_t width = static_cast<uint32_t>(column_end_64 - column_begin_64);
|
| 68 |
+
|
| 69 |
+
uint64_t sketch[4] = {kSketchSeed[0], kSketchSeed[1], kSketchSeed[2], kSketchSeed[3]};
|
| 70 |
+
#pragma unroll
|
| 71 |
+
for (uint32_t sample = 0; sample < 32U; ++sample) {
|
| 72 |
+
const uint32_t row = row_begin + ((sample * 13U + 3U) % height);
|
| 73 |
+
const uint32_t column = column_begin + ((sample * 7U + 1U) % width);
|
| 74 |
+
const uint32_t bits = canonical_float_bits(
|
| 75 |
+
output[static_cast<uint64_t>(row) * row_stride + column]);
|
| 76 |
+
const uint64_t tagged =
|
| 77 |
+
mix64(static_cast<uint64_t>(bits) | (static_cast<uint64_t>(sample) << 32)) ^
|
| 78 |
+
mix64(static_cast<uint64_t>(row)) ^
|
| 79 |
+
mix64(static_cast<uint64_t>(column) << 1);
|
| 80 |
+
const uint32_t lane = sample & 3U;
|
| 81 |
+
sketch[lane] = mix64(sketch[lane] ^ tagged);
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
palw_cuda_trace_record record{};
|
| 85 |
+
record.kernel_sequence = launch.kernel_sequence;
|
| 86 |
+
record.tile_index = tile_index;
|
| 87 |
+
record.decode_step = launch.decode_step;
|
| 88 |
+
record.m = launch.m;
|
| 89 |
+
record.n = launch.n;
|
| 90 |
+
record.k = launch.k;
|
| 91 |
+
record.batch = launch.batch;
|
| 92 |
+
record.query_tokens = launch.query_tokens;
|
| 93 |
+
record.key_value_tokens = launch.key_value_tokens;
|
| 94 |
+
#pragma unroll
|
| 95 |
+
for (uint32_t lane = 0; lane < 4U; ++lane) {
|
| 96 |
+
record.sketch[lane] = sketch[lane];
|
| 97 |
+
}
|
| 98 |
+
record.layer_id = launch.layer_id;
|
| 99 |
+
record.tile_row = tile_row;
|
| 100 |
+
record.tile_column = tile_column;
|
| 101 |
+
record.tile_rows = launch.tile_rows;
|
| 102 |
+
record.tile_columns = launch.tile_columns;
|
| 103 |
+
record.output_rows = launch.output_rows;
|
| 104 |
+
record.output_columns = launch.output_columns;
|
| 105 |
+
record.schema_version = PALW_CUDA_TRACE_SCHEMA_VERSION;
|
| 106 |
+
record.kind = launch.kind;
|
| 107 |
+
record.phase = launch.phase;
|
| 108 |
+
record.dtype = launch.dtype;
|
| 109 |
+
record.quantization = launch.quantization;
|
| 110 |
+
record.causal = launch.causal;
|
| 111 |
+
records[launch.base_record + tile_index] = record;
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
void poison_context(palw_cuda_trace_context * context, cudaError_t error) {
|
| 115 |
+
context->poisoned = 1;
|
| 116 |
+
context->last_cuda_error = static_cast<int32_t>(error);
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
palw_cuda_trace_status reject_failed_context(const palw_cuda_trace_context * context) {
|
| 120 |
+
if (context->poisoned != 0) {
|
| 121 |
+
return PALW_CUDA_TRACE_POISONED;
|
| 122 |
+
}
|
| 123 |
+
if (context->overflowed != 0) {
|
| 124 |
+
return PALW_CUDA_TRACE_CAPACITY_EXCEEDED;
|
| 125 |
+
}
|
| 126 |
+
return PALW_CUDA_TRACE_OK;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
bool bind_or_match_stream(palw_cuda_trace_context * context, cudaStream_t stream) {
|
| 130 |
+
if (context->stream_bound != 0) {
|
| 131 |
+
return context->stream == stream;
|
| 132 |
+
}
|
| 133 |
+
context->stream = stream;
|
| 134 |
+
context->stream_bound = 1;
|
| 135 |
+
return true;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
palw_cuda_trace_status consume_pending_cuda_error(palw_cuda_trace_context * context) {
|
| 139 |
+
const cudaError_t error = cudaPeekAtLastError();
|
| 140 |
+
if (error == cudaSuccess) {
|
| 141 |
+
return PALW_CUDA_TRACE_OK;
|
| 142 |
+
}
|
| 143 |
+
(void) cudaGetLastError();
|
| 144 |
+
poison_context(context, error);
|
| 145 |
+
return PALW_CUDA_TRACE_CUDA_ERROR;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
bool valid_address_range(
|
| 149 |
+
const float * output,
|
| 150 |
+
uint32_t output_rows,
|
| 151 |
+
uint32_t output_columns,
|
| 152 |
+
uint64_t row_stride) {
|
| 153 |
+
const uintptr_t base = reinterpret_cast<uintptr_t>(output);
|
| 154 |
+
if ((base % alignof(float)) != 0U) {
|
| 155 |
+
return false;
|
| 156 |
+
}
|
| 157 |
+
const uint64_t row_offset = static_cast<uint64_t>(output_rows - 1U);
|
| 158 |
+
const uint64_t column_offset = static_cast<uint64_t>(output_columns - 1U);
|
| 159 |
+
if (row_offset != 0U && row_stride > (UINT64_MAX - column_offset) / row_offset) {
|
| 160 |
+
return false;
|
| 161 |
+
}
|
| 162 |
+
const uint64_t last_element = row_offset * row_stride + column_offset;
|
| 163 |
+
if (last_element > std::numeric_limits<size_t>::max() / sizeof(float)) {
|
| 164 |
+
return false;
|
| 165 |
+
}
|
| 166 |
+
const uint64_t last_byte_offset = last_element * sizeof(float);
|
| 167 |
+
const uintptr_t pointer_max = std::numeric_limits<uintptr_t>::max();
|
| 168 |
+
return base <= pointer_max - (sizeof(float) - 1U) &&
|
| 169 |
+
last_byte_offset <= pointer_max - base - (sizeof(float) - 1U);
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
} // namespace
|
| 173 |
+
|
| 174 |
+
bool palw_cuda_trace_valid_dtype(uint8_t dtype) {
|
| 175 |
+
return dtype <= PALW_CUDA_TRACE_DTYPE_INT4;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
bool palw_cuda_trace_valid_quantization(uint8_t quantization) {
|
| 179 |
+
return quantization <= PALW_CUDA_TRACE_QUANTIZATION_IQ4_XS;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
bool palw_cuda_trace_valid_phase(uint8_t phase, uint64_t decode_step) {
|
| 183 |
+
if (phase == PALW_CUDA_TRACE_PREFILL) {
|
| 184 |
+
return decode_step == 0U;
|
| 185 |
+
}
|
| 186 |
+
return phase == PALW_CUDA_TRACE_DECODE && decode_step <= UINT32_MAX;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
extern "C" palw_cuda_trace_status palw_cuda_trace_create(
|
| 190 |
+
uint64_t capacity,
|
| 191 |
+
palw_cuda_trace_context ** out_context) {
|
| 192 |
+
if (capacity == 0U || out_context == nullptr ||
|
| 193 |
+
capacity > std::numeric_limits<size_t>::max() / sizeof(palw_cuda_trace_record)) {
|
| 194 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 195 |
+
}
|
| 196 |
+
*out_context = nullptr;
|
| 197 |
+
auto * context = new (std::nothrow) palw_cuda_trace_context{};
|
| 198 |
+
if (context == nullptr) {
|
| 199 |
+
return PALW_CUDA_TRACE_CUDA_ERROR;
|
| 200 |
+
}
|
| 201 |
+
const cudaError_t error = cudaMalloc(
|
| 202 |
+
reinterpret_cast<void **>(&context->device_records),
|
| 203 |
+
static_cast<size_t>(capacity) * sizeof(palw_cuda_trace_record));
|
| 204 |
+
if (error != cudaSuccess) {
|
| 205 |
+
delete context;
|
| 206 |
+
return PALW_CUDA_TRACE_CUDA_ERROR;
|
| 207 |
+
}
|
| 208 |
+
context->capacity = capacity;
|
| 209 |
+
context->last_cuda_error = static_cast<int32_t>(cudaSuccess);
|
| 210 |
+
*out_context = context;
|
| 211 |
+
return PALW_CUDA_TRACE_OK;
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
extern "C" void palw_cuda_trace_destroy(palw_cuda_trace_context * context) {
|
| 215 |
+
if (context != nullptr) {
|
| 216 |
+
(void) cudaFree(context->device_records);
|
| 217 |
+
delete context;
|
| 218 |
+
}
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
extern "C" palw_cuda_trace_status palw_cuda_trace_reset(palw_cuda_trace_context * context) {
|
| 222 |
+
if (context == nullptr) {
|
| 223 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 224 |
+
}
|
| 225 |
+
if (context->poisoned != 0) {
|
| 226 |
+
return PALW_CUDA_TRACE_POISONED;
|
| 227 |
+
}
|
| 228 |
+
if (context->copy_pending != 0 || context->committed_record != context->next_record ||
|
| 229 |
+
context->committed_kernel_sequence != context->next_kernel_sequence) {
|
| 230 |
+
return PALW_CUDA_TRACE_PENDING;
|
| 231 |
+
}
|
| 232 |
+
context->next_record = 0;
|
| 233 |
+
context->committed_record = 0;
|
| 234 |
+
context->next_kernel_sequence = 0;
|
| 235 |
+
context->committed_kernel_sequence = 0;
|
| 236 |
+
context->overflowed = 0;
|
| 237 |
+
context->last_cuda_error = static_cast<int32_t>(cudaSuccess);
|
| 238 |
+
return PALW_CUDA_TRACE_OK;
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
extern "C" uint64_t palw_cuda_trace_count(const palw_cuda_trace_context * context) {
|
| 242 |
+
return context == nullptr ? 0U : context->next_record;
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
extern "C" uint64_t palw_cuda_trace_committed_count(const palw_cuda_trace_context * context) {
|
| 246 |
+
return context == nullptr ? 0U : context->committed_record;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
extern "C" int palw_cuda_trace_overflowed(const palw_cuda_trace_context * context) {
|
| 250 |
+
return context == nullptr ? 1 : context->overflowed;
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
extern "C" int palw_cuda_trace_poisoned(const palw_cuda_trace_context * context) {
|
| 254 |
+
return context == nullptr ? 1 : context->poisoned;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
extern "C" int32_t palw_cuda_trace_last_cuda_error(const palw_cuda_trace_context * context) {
|
| 258 |
+
return context == nullptr ? -1 : context->last_cuda_error;
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
extern "C" palw_cuda_trace_status palw_cuda_trace_synchronize(
|
| 262 |
+
palw_cuda_trace_context * context,
|
| 263 |
+
cudaStream_t stream) {
|
| 264 |
+
if (context == nullptr) {
|
| 265 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 266 |
+
}
|
| 267 |
+
if (context->poisoned != 0) {
|
| 268 |
+
return PALW_CUDA_TRACE_POISONED;
|
| 269 |
+
}
|
| 270 |
+
if (!bind_or_match_stream(context, stream)) {
|
| 271 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 272 |
+
}
|
| 273 |
+
const palw_cuda_trace_status pending_error = consume_pending_cuda_error(context);
|
| 274 |
+
if (pending_error != PALW_CUDA_TRACE_OK) {
|
| 275 |
+
return pending_error;
|
| 276 |
+
}
|
| 277 |
+
const cudaError_t error = cudaStreamSynchronize(stream);
|
| 278 |
+
if (error != cudaSuccess) {
|
| 279 |
+
poison_context(context, error);
|
| 280 |
+
return PALW_CUDA_TRACE_CUDA_ERROR;
|
| 281 |
+
}
|
| 282 |
+
context->committed_record = context->next_record;
|
| 283 |
+
context->committed_kernel_sequence = context->next_kernel_sequence;
|
| 284 |
+
context->copy_pending = 0;
|
| 285 |
+
return PALW_CUDA_TRACE_OK;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
extern "C" palw_cuda_trace_status palw_cuda_trace_copy_async(
|
| 289 |
+
palw_cuda_trace_context * context,
|
| 290 |
+
palw_cuda_trace_record * host_records,
|
| 291 |
+
uint64_t host_capacity,
|
| 292 |
+
cudaStream_t stream) {
|
| 293 |
+
if (context == nullptr || host_records == nullptr) {
|
| 294 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 295 |
+
}
|
| 296 |
+
const palw_cuda_trace_status context_status = reject_failed_context(context);
|
| 297 |
+
if (context_status != PALW_CUDA_TRACE_OK) {
|
| 298 |
+
return context_status;
|
| 299 |
+
}
|
| 300 |
+
if (context->copy_pending != 0) {
|
| 301 |
+
return PALW_CUDA_TRACE_PENDING;
|
| 302 |
+
}
|
| 303 |
+
if (host_capacity < context->next_record || !bind_or_match_stream(context, stream)) {
|
| 304 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 305 |
+
}
|
| 306 |
+
const palw_cuda_trace_status pending_error = consume_pending_cuda_error(context);
|
| 307 |
+
if (pending_error != PALW_CUDA_TRACE_OK) {
|
| 308 |
+
return pending_error;
|
| 309 |
+
}
|
| 310 |
+
const size_t bytes = static_cast<size_t>(context->next_record) * sizeof(palw_cuda_trace_record);
|
| 311 |
+
const cudaError_t error = cudaMemcpyAsync(
|
| 312 |
+
host_records,
|
| 313 |
+
context->device_records,
|
| 314 |
+
bytes,
|
| 315 |
+
cudaMemcpyDeviceToHost,
|
| 316 |
+
stream);
|
| 317 |
+
if (error != cudaSuccess) {
|
| 318 |
+
poison_context(context, error);
|
| 319 |
+
return PALW_CUDA_TRACE_CUDA_ERROR;
|
| 320 |
+
}
|
| 321 |
+
context->copy_pending = 1;
|
| 322 |
+
return PALW_CUDA_TRACE_OK;
|
| 323 |
+
}
|
| 324 |
+
|
| 325 |
+
palw_cuda_trace_status palw_cuda_trace_launch_f32(
|
| 326 |
+
palw_cuda_trace_context * context,
|
| 327 |
+
cudaStream_t stream,
|
| 328 |
+
const float * output,
|
| 329 |
+
uint64_t row_stride,
|
| 330 |
+
const palw_cuda_trace_launch * requested) {
|
| 331 |
+
if (context == nullptr || output == nullptr || requested == nullptr) {
|
| 332 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 333 |
+
}
|
| 334 |
+
const palw_cuda_trace_status context_status = reject_failed_context(context);
|
| 335 |
+
if (context_status != PALW_CUDA_TRACE_OK) {
|
| 336 |
+
return context_status;
|
| 337 |
+
}
|
| 338 |
+
if (context->copy_pending != 0) {
|
| 339 |
+
return PALW_CUDA_TRACE_PENDING;
|
| 340 |
+
}
|
| 341 |
+
if (requested->output_rows == 0U || requested->output_columns == 0U ||
|
| 342 |
+
requested->tile_rows == 0U || requested->tile_columns == 0U ||
|
| 343 |
+
row_stride < requested->output_columns || requested->layer_id > PALW_CUDA_TRACE_MAX_LAYER_ID ||
|
| 344 |
+
!palw_cuda_trace_valid_phase(requested->phase, requested->decode_step) ||
|
| 345 |
+
!palw_cuda_trace_valid_dtype(requested->dtype) ||
|
| 346 |
+
!palw_cuda_trace_valid_quantization(requested->quantization) ||
|
| 347 |
+
requested->kind < PALW_CUDA_TRACE_GEMM || requested->kind > PALW_CUDA_TRACE_ATTENTION ||
|
| 348 |
+
!valid_address_range(output, requested->output_rows, requested->output_columns, row_stride)) {
|
| 349 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 350 |
+
}
|
| 351 |
+
if (requested->kernel_sequence != context->next_kernel_sequence ||
|
| 352 |
+
requested->kernel_sequence == UINT64_MAX) {
|
| 353 |
+
return PALW_CUDA_TRACE_SEQUENCE_MISMATCH;
|
| 354 |
+
}
|
| 355 |
+
/* A wrong stream is invalid and must not make an otherwise-full context overflow-sticky. */
|
| 356 |
+
if (context->stream_bound != 0 && context->stream != stream) {
|
| 357 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
const uint64_t grid_x =
|
| 361 |
+
(static_cast<uint64_t>(requested->output_columns) + requested->tile_columns - 1U) /
|
| 362 |
+
requested->tile_columns;
|
| 363 |
+
const uint64_t grid_y =
|
| 364 |
+
(static_cast<uint64_t>(requested->output_rows) + requested->tile_rows - 1U) /
|
| 365 |
+
requested->tile_rows;
|
| 366 |
+
if (grid_x == 0U || grid_y == 0U || grid_x > kMaxGridX || grid_y > kMaxGridY ||
|
| 367 |
+
grid_y > UINT64_MAX / grid_x) {
|
| 368 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 369 |
+
}
|
| 370 |
+
const uint64_t tile_count = grid_x * grid_y;
|
| 371 |
+
if (tile_count > UINT32_MAX) {
|
| 372 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 373 |
+
}
|
| 374 |
+
if (context->next_record > context->capacity ||
|
| 375 |
+
tile_count > context->capacity - context->next_record) {
|
| 376 |
+
context->overflowed = 1;
|
| 377 |
+
return PALW_CUDA_TRACE_CAPACITY_EXCEEDED;
|
| 378 |
+
}
|
| 379 |
+
if (!bind_or_match_stream(context, stream)) {
|
| 380 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 381 |
+
}
|
| 382 |
+
const palw_cuda_trace_status pending_error = consume_pending_cuda_error(context);
|
| 383 |
+
if (pending_error != PALW_CUDA_TRACE_OK) {
|
| 384 |
+
return pending_error;
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
palw_cuda_trace_launch launch = *requested;
|
| 388 |
+
launch.base_record = context->next_record;
|
| 389 |
+
launch.tile_count = tile_count;
|
| 390 |
+
dim3 launch_grid(static_cast<uint32_t>(grid_x), static_cast<uint32_t>(grid_y), 1U);
|
| 391 |
+
#if defined(PALW_CUDA_TRACE_TESTING)
|
| 392 |
+
if (context->test_force_launch_failure != 0) {
|
| 393 |
+
context->test_force_launch_failure = 0;
|
| 394 |
+
/* A zero-width grid forces a real, immediate CUDA launch-configuration error. */
|
| 395 |
+
launch_grid.x = 0U;
|
| 396 |
+
}
|
| 397 |
+
#endif
|
| 398 |
+
accumulator_sketch_f32<<<
|
| 399 |
+
launch_grid,
|
| 400 |
+
dim3(1U, 1U, 1U),
|
| 401 |
+
0,
|
| 402 |
+
stream>>>(output, row_stride, context->device_records, launch);
|
| 403 |
+
const cudaError_t error = cudaGetLastError();
|
| 404 |
+
if (error != cudaSuccess) {
|
| 405 |
+
poison_context(context, error);
|
| 406 |
+
return PALW_CUDA_TRACE_CUDA_ERROR;
|
| 407 |
+
}
|
| 408 |
+
context->next_record += tile_count;
|
| 409 |
+
context->next_kernel_sequence += 1U;
|
| 410 |
+
return PALW_CUDA_TRACE_OK;
|
| 411 |
+
}
|
runtime-palw/cuda/attention_trace.cu
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "palw_cuda_trace_internal.cuh"
|
| 2 |
+
|
| 3 |
+
extern "C" palw_cuda_trace_status palw_cuda_trace_attention_f32(
|
| 4 |
+
palw_cuda_trace_context * context,
|
| 5 |
+
cudaStream_t stream,
|
| 6 |
+
const float * output,
|
| 7 |
+
uint32_t output_rows,
|
| 8 |
+
uint32_t output_columns,
|
| 9 |
+
uint64_t row_stride,
|
| 10 |
+
uint64_t kernel_sequence,
|
| 11 |
+
uint32_t layer_id,
|
| 12 |
+
uint8_t phase,
|
| 13 |
+
uint64_t decode_step,
|
| 14 |
+
uint64_t query_tokens,
|
| 15 |
+
uint64_t key_value_tokens,
|
| 16 |
+
uint64_t heads,
|
| 17 |
+
uint64_t head_dim,
|
| 18 |
+
uint64_t batch,
|
| 19 |
+
uint8_t dtype,
|
| 20 |
+
uint8_t causal,
|
| 21 |
+
uint32_t tile_rows,
|
| 22 |
+
uint32_t tile_columns) {
|
| 23 |
+
if (context != nullptr && context->poisoned != 0) {
|
| 24 |
+
return PALW_CUDA_TRACE_POISONED;
|
| 25 |
+
}
|
| 26 |
+
if (context != nullptr && context->overflowed != 0) {
|
| 27 |
+
return PALW_CUDA_TRACE_CAPACITY_EXCEEDED;
|
| 28 |
+
}
|
| 29 |
+
if (query_tokens == 0U || key_value_tokens == 0U || heads == 0U || head_dim == 0U ||
|
| 30 |
+
batch == 0U || causal > 1U || query_tokens > UINT32_MAX ||
|
| 31 |
+
key_value_tokens > UINT32_MAX || heads > UINT32_MAX || head_dim > UINT32_MAX ||
|
| 32 |
+
batch > UINT32_MAX || head_dim > UINT64_MAX / heads ||
|
| 33 |
+
query_tokens > UINT64_MAX / batch || query_tokens * batch != output_rows ||
|
| 34 |
+
heads * head_dim != output_columns ||
|
| 35 |
+
(causal != 0U && key_value_tokens < query_tokens) ||
|
| 36 |
+
(phase == PALW_CUDA_TRACE_DECODE && query_tokens != 1U)) {
|
| 37 |
+
return PALW_CUDA_TRACE_INVALID_ARGUMENT;
|
| 38 |
+
}
|
| 39 |
+
palw_cuda_trace_launch launch{};
|
| 40 |
+
launch.kernel_sequence = kernel_sequence;
|
| 41 |
+
launch.decode_step = decode_step;
|
| 42 |
+
launch.m = query_tokens;
|
| 43 |
+
launch.n = heads * head_dim;
|
| 44 |
+
launch.k = key_value_tokens;
|
| 45 |
+
launch.batch = batch;
|
| 46 |
+
launch.query_tokens = query_tokens;
|
| 47 |
+
launch.key_value_tokens = key_value_tokens;
|
| 48 |
+
launch.layer_id = layer_id;
|
| 49 |
+
launch.output_rows = output_rows;
|
| 50 |
+
launch.output_columns = output_columns;
|
| 51 |
+
launch.tile_rows = tile_rows;
|
| 52 |
+
launch.tile_columns = tile_columns;
|
| 53 |
+
launch.kind = PALW_CUDA_TRACE_ATTENTION;
|
| 54 |
+
launch.phase = phase;
|
| 55 |
+
launch.dtype = dtype;
|
| 56 |
+
launch.causal = causal;
|
| 57 |
+
return palw_cuda_trace_launch_f32(context, stream, output, row_stride, &launch);
|
| 58 |
+
}
|
runtime-palw/cuda/cuda_trace_test.cu
ADDED
|
@@ -0,0 +1,522 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "palw_cuda_trace_internal.cuh"
|
| 2 |
+
|
| 3 |
+
#include <cuda_runtime.h>
|
| 4 |
+
|
| 5 |
+
#include <array>
|
| 6 |
+
#include <cstdint>
|
| 7 |
+
#include <cstdio>
|
| 8 |
+
#include <cstring>
|
| 9 |
+
#include <vector>
|
| 10 |
+
|
| 11 |
+
static_assert(PALW_CUDA_TRACE_PRODUCTION_CAPABLE == 0U);
|
| 12 |
+
|
| 13 |
+
namespace {
|
| 14 |
+
|
| 15 |
+
#define REQUIRE(condition, message) \
|
| 16 |
+
do { \
|
| 17 |
+
if (!(condition)) { \
|
| 18 |
+
std::fprintf(stderr, "CUDA trace test failure at line %d: %s\n", __LINE__, message); \
|
| 19 |
+
return false; \
|
| 20 |
+
} \
|
| 21 |
+
} while (false)
|
| 22 |
+
|
| 23 |
+
#define REQUIRE_STATUS(expression, expected) \
|
| 24 |
+
do { \
|
| 25 |
+
const palw_cuda_trace_status actual_status = (expression); \
|
| 26 |
+
if (actual_status != (expected)) { \
|
| 27 |
+
std::fprintf( \
|
| 28 |
+
stderr, \
|
| 29 |
+
"CUDA trace test failure at line %d: status %d, expected %d\n", \
|
| 30 |
+
__LINE__, \
|
| 31 |
+
static_cast<int>(actual_status), \
|
| 32 |
+
static_cast<int>(expected)); \
|
| 33 |
+
return false; \
|
| 34 |
+
} \
|
| 35 |
+
} while (false)
|
| 36 |
+
|
| 37 |
+
class stream_guard {
|
| 38 |
+
public:
|
| 39 |
+
bool create() {
|
| 40 |
+
return cudaStreamCreateWithFlags(&stream_, cudaStreamNonBlocking) == cudaSuccess;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
~stream_guard() {
|
| 44 |
+
if (stream_ != nullptr) {
|
| 45 |
+
(void) cudaStreamDestroy(stream_);
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
cudaStream_t get() const {
|
| 50 |
+
return stream_;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
private:
|
| 54 |
+
cudaStream_t stream_ = nullptr;
|
| 55 |
+
};
|
| 56 |
+
|
| 57 |
+
class device_float_buffer {
|
| 58 |
+
public:
|
| 59 |
+
bool allocate(size_t elements) {
|
| 60 |
+
elements_ = elements;
|
| 61 |
+
return cudaMalloc(reinterpret_cast<void **>(&data_), elements * sizeof(float)) == cudaSuccess;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
~device_float_buffer() {
|
| 65 |
+
if (data_ != nullptr) {
|
| 66 |
+
(void) cudaFree(data_);
|
| 67 |
+
}
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
bool copy_from(const std::vector<float> & values, cudaStream_t stream) {
|
| 71 |
+
return values.size() <= elements_ &&
|
| 72 |
+
cudaMemcpyAsync(
|
| 73 |
+
data_,
|
| 74 |
+
values.data(),
|
| 75 |
+
values.size() * sizeof(float),
|
| 76 |
+
cudaMemcpyHostToDevice,
|
| 77 |
+
stream) == cudaSuccess;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
float * get() const {
|
| 81 |
+
return data_;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
private:
|
| 85 |
+
float * data_ = nullptr;
|
| 86 |
+
size_t elements_ = 0;
|
| 87 |
+
};
|
| 88 |
+
|
| 89 |
+
class pinned_records {
|
| 90 |
+
public:
|
| 91 |
+
bool allocate(size_t count) {
|
| 92 |
+
count_ = count;
|
| 93 |
+
return cudaMallocHost(
|
| 94 |
+
reinterpret_cast<void **>(&records_),
|
| 95 |
+
count * sizeof(palw_cuda_trace_record)) == cudaSuccess;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
~pinned_records() {
|
| 99 |
+
if (records_ != nullptr) {
|
| 100 |
+
(void) cudaFreeHost(records_);
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
palw_cuda_trace_record * get() const {
|
| 105 |
+
return records_;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
uint64_t capacity() const {
|
| 109 |
+
return static_cast<uint64_t>(count_);
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
private:
|
| 113 |
+
palw_cuda_trace_record * records_ = nullptr;
|
| 114 |
+
size_t count_ = 0;
|
| 115 |
+
};
|
| 116 |
+
|
| 117 |
+
class context_guard {
|
| 118 |
+
public:
|
| 119 |
+
bool create(uint64_t capacity) {
|
| 120 |
+
return palw_cuda_trace_create(capacity, &context_) == PALW_CUDA_TRACE_OK;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
~context_guard() {
|
| 124 |
+
palw_cuda_trace_destroy(context_);
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
palw_cuda_trace_context * get() const {
|
| 128 |
+
return context_;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
private:
|
| 132 |
+
palw_cuda_trace_context * context_ = nullptr;
|
| 133 |
+
};
|
| 134 |
+
|
| 135 |
+
using encoded_record = std::array<uint8_t, PALW_CUDA_TRACE_RECORD_ENCODED_SIZE_V1>;
|
| 136 |
+
using sketch = std::array<uint64_t, 4>;
|
| 137 |
+
|
| 138 |
+
palw_cuda_trace_status launch_gemm(
|
| 139 |
+
palw_cuda_trace_context * context,
|
| 140 |
+
cudaStream_t stream,
|
| 141 |
+
const float * output,
|
| 142 |
+
uint64_t sequence,
|
| 143 |
+
uint8_t phase = PALW_CUDA_TRACE_PREFILL,
|
| 144 |
+
uint64_t decode_step = 0,
|
| 145 |
+
uint8_t dtype = PALW_CUDA_TRACE_DTYPE_FP32,
|
| 146 |
+
uint8_t quantization = PALW_CUDA_TRACE_QUANTIZATION_Q4_K_M,
|
| 147 |
+
uint32_t output_rows = 4,
|
| 148 |
+
uint32_t output_columns = 6,
|
| 149 |
+
uint64_t row_stride = 6,
|
| 150 |
+
uint64_t m = 6,
|
| 151 |
+
uint64_t n = 2,
|
| 152 |
+
uint64_t k = 3,
|
| 153 |
+
uint64_t batch = 2,
|
| 154 |
+
uint32_t tile_rows = 2,
|
| 155 |
+
uint32_t tile_columns = 4) {
|
| 156 |
+
return palw_cuda_trace_gemm_f32(
|
| 157 |
+
context,
|
| 158 |
+
stream,
|
| 159 |
+
output,
|
| 160 |
+
output_rows,
|
| 161 |
+
output_columns,
|
| 162 |
+
row_stride,
|
| 163 |
+
sequence,
|
| 164 |
+
5,
|
| 165 |
+
phase,
|
| 166 |
+
decode_step,
|
| 167 |
+
m,
|
| 168 |
+
n,
|
| 169 |
+
k,
|
| 170 |
+
batch,
|
| 171 |
+
dtype,
|
| 172 |
+
quantization,
|
| 173 |
+
tile_rows,
|
| 174 |
+
tile_columns);
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
palw_cuda_trace_status launch_attention(
|
| 178 |
+
palw_cuda_trace_context * context,
|
| 179 |
+
cudaStream_t stream,
|
| 180 |
+
const float * output,
|
| 181 |
+
uint64_t sequence,
|
| 182 |
+
uint8_t phase = PALW_CUDA_TRACE_PREFILL,
|
| 183 |
+
uint64_t decode_step = 0,
|
| 184 |
+
uint64_t query_tokens = 2,
|
| 185 |
+
uint64_t key_value_tokens = 2,
|
| 186 |
+
uint64_t heads = 2,
|
| 187 |
+
uint64_t head_dim = 4,
|
| 188 |
+
uint64_t batch = 1,
|
| 189 |
+
uint8_t dtype = PALW_CUDA_TRACE_DTYPE_FP16,
|
| 190 |
+
uint8_t causal = 1,
|
| 191 |
+
uint32_t output_rows = 2,
|
| 192 |
+
uint32_t output_columns = 8,
|
| 193 |
+
uint64_t row_stride = 8,
|
| 194 |
+
uint32_t tile_rows = 1,
|
| 195 |
+
uint32_t tile_columns = 4) {
|
| 196 |
+
return palw_cuda_trace_attention_f32(
|
| 197 |
+
context,
|
| 198 |
+
stream,
|
| 199 |
+
output,
|
| 200 |
+
output_rows,
|
| 201 |
+
output_columns,
|
| 202 |
+
row_stride,
|
| 203 |
+
sequence,
|
| 204 |
+
5,
|
| 205 |
+
phase,
|
| 206 |
+
decode_step,
|
| 207 |
+
query_tokens,
|
| 208 |
+
key_value_tokens,
|
| 209 |
+
heads,
|
| 210 |
+
head_dim,
|
| 211 |
+
batch,
|
| 212 |
+
dtype,
|
| 213 |
+
causal,
|
| 214 |
+
tile_rows,
|
| 215 |
+
tile_columns);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
bool encode_records(
|
| 219 |
+
const palw_cuda_trace_record * records,
|
| 220 |
+
size_t count,
|
| 221 |
+
std::vector<encoded_record> & encoded) {
|
| 222 |
+
encoded.resize(count);
|
| 223 |
+
for (size_t i = 0; i < count; ++i) {
|
| 224 |
+
if (palw_cuda_trace_encode_record_v1(
|
| 225 |
+
&records[i], encoded[i].data(), encoded[i].size()) != PALW_CUDA_TRACE_OK) {
|
| 226 |
+
return false;
|
| 227 |
+
}
|
| 228 |
+
}
|
| 229 |
+
return true;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
sketch record_sketch(const palw_cuda_trace_record & record) {
|
| 233 |
+
return {record.sketch[0], record.sketch[1], record.sketch[2], record.sketch[3]};
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
float float_from_bits(uint32_t bits) {
|
| 237 |
+
float value = 0.0f;
|
| 238 |
+
std::memcpy(&value, &bits, sizeof(value));
|
| 239 |
+
return value;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
bool run_device_tests() {
|
| 243 |
+
stream_guard stream;
|
| 244 |
+
stream_guard other_stream;
|
| 245 |
+
device_float_buffer output;
|
| 246 |
+
pinned_records records;
|
| 247 |
+
context_guard context;
|
| 248 |
+
context_guard small_context;
|
| 249 |
+
context_guard recovered_context;
|
| 250 |
+
|
| 251 |
+
REQUIRE(stream.create(), "failed to create primary stream");
|
| 252 |
+
REQUIRE(other_stream.create(), "failed to create secondary stream");
|
| 253 |
+
REQUIRE(output.allocate(24), "failed to allocate output");
|
| 254 |
+
REQUIRE(records.allocate(32), "failed to allocate pinned records");
|
| 255 |
+
REQUIRE(context.create(32), "failed to create trace context");
|
| 256 |
+
|
| 257 |
+
std::vector<float> values(24);
|
| 258 |
+
for (size_t i = 0; i < values.size(); ++i) {
|
| 259 |
+
values[i] = static_cast<float>(i + 1U) * 0.25f;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
REQUIRE(output.copy_from(values, stream.get()), "failed to upload baseline output");
|
| 263 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_OK);
|
| 264 |
+
REQUIRE_STATUS(
|
| 265 |
+
launch_attention(context.get(), stream.get(), output.get(), 1),
|
| 266 |
+
PALW_CUDA_TRACE_OK);
|
| 267 |
+
REQUIRE(palw_cuda_trace_count(context.get()) == 8U, "unexpected reserved record count");
|
| 268 |
+
REQUIRE(
|
| 269 |
+
palw_cuda_trace_committed_count(context.get()) == 0U,
|
| 270 |
+
"records committed before synchronization");
|
| 271 |
+
REQUIRE_STATUS(
|
| 272 |
+
palw_cuda_trace_copy_async(context.get(), records.get(), 7, stream.get()),
|
| 273 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 274 |
+
REQUIRE_STATUS(
|
| 275 |
+
palw_cuda_trace_synchronize(context.get(), other_stream.get()),
|
| 276 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 277 |
+
REQUIRE(palw_cuda_trace_count(context.get()) == 8U, "copy/stream rejection changed count");
|
| 278 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(context.get()), PALW_CUDA_TRACE_PENDING);
|
| 279 |
+
REQUIRE_STATUS(
|
| 280 |
+
palw_cuda_trace_copy_async(
|
| 281 |
+
context.get(), records.get(), records.capacity(), stream.get()),
|
| 282 |
+
PALW_CUDA_TRACE_OK);
|
| 283 |
+
REQUIRE_STATUS(
|
| 284 |
+
palw_cuda_trace_copy_async(
|
| 285 |
+
context.get(), records.get(), records.capacity(), stream.get()),
|
| 286 |
+
PALW_CUDA_TRACE_PENDING);
|
| 287 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 2), PALW_CUDA_TRACE_PENDING);
|
| 288 |
+
REQUIRE_STATUS(palw_cuda_trace_synchronize(context.get(), stream.get()), PALW_CUDA_TRACE_OK);
|
| 289 |
+
REQUIRE(
|
| 290 |
+
palw_cuda_trace_committed_count(context.get()) == 8U,
|
| 291 |
+
"successful synchronize did not commit records");
|
| 292 |
+
|
| 293 |
+
for (uint64_t i = 0; i < 4U; ++i) {
|
| 294 |
+
const auto & record = records.get()[i];
|
| 295 |
+
REQUIRE(record.kernel_sequence == 0U, "GEMM sequence mismatch");
|
| 296 |
+
REQUIRE(record.tile_index == i, "GEMM tile index mismatch");
|
| 297 |
+
REQUIRE(record.tile_row == i / 2U && record.tile_column == i % 2U, "GEMM tile order mismatch");
|
| 298 |
+
REQUIRE(record.kind == PALW_CUDA_TRACE_GEMM, "GEMM kind mismatch");
|
| 299 |
+
}
|
| 300 |
+
for (uint64_t i = 0; i < 4U; ++i) {
|
| 301 |
+
const auto & record = records.get()[4U + i];
|
| 302 |
+
REQUIRE(record.kernel_sequence == 1U, "attention sequence mismatch");
|
| 303 |
+
REQUIRE(record.tile_index == i, "attention tile index mismatch");
|
| 304 |
+
REQUIRE(
|
| 305 |
+
record.tile_row == i / 2U && record.tile_column == i % 2U,
|
| 306 |
+
"attention tile order mismatch");
|
| 307 |
+
REQUIRE(record.kind == PALW_CUDA_TRACE_ATTENTION, "attention kind mismatch");
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
std::vector<encoded_record> baseline;
|
| 311 |
+
REQUIRE(encode_records(records.get(), 8, baseline), "failed to encode baseline records");
|
| 312 |
+
std::array<sketch, 4> baseline_gemm_sketches{};
|
| 313 |
+
for (size_t i = 0; i < baseline_gemm_sketches.size(); ++i) {
|
| 314 |
+
baseline_gemm_sketches[i] = record_sketch(records.get()[i]);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(context.get()), PALW_CUDA_TRACE_OK);
|
| 318 |
+
REQUIRE(output.copy_from(values, stream.get()), "failed to restore baseline output");
|
| 319 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_OK);
|
| 320 |
+
REQUIRE_STATUS(
|
| 321 |
+
launch_attention(context.get(), stream.get(), output.get(), 1),
|
| 322 |
+
PALW_CUDA_TRACE_OK);
|
| 323 |
+
REQUIRE_STATUS(
|
| 324 |
+
palw_cuda_trace_copy_async(
|
| 325 |
+
context.get(), records.get(), records.capacity(), stream.get()),
|
| 326 |
+
PALW_CUDA_TRACE_OK);
|
| 327 |
+
REQUIRE_STATUS(palw_cuda_trace_synchronize(context.get(), stream.get()), PALW_CUDA_TRACE_OK);
|
| 328 |
+
std::vector<encoded_record> repeated;
|
| 329 |
+
REQUIRE(encode_records(records.get(), 8, repeated), "failed to encode repeated records");
|
| 330 |
+
REQUIRE(repeated == baseline, "same-stream trace was not repeatable");
|
| 331 |
+
|
| 332 |
+
std::vector<float> canonical_values_a(24);
|
| 333 |
+
std::vector<float> canonical_values_b(24);
|
| 334 |
+
for (size_t i = 0; i < canonical_values_a.size(); ++i) {
|
| 335 |
+
if ((i & 1U) == 0U) {
|
| 336 |
+
canonical_values_a[i] = float_from_bits(0x00000000U);
|
| 337 |
+
canonical_values_b[i] = float_from_bits(0x80000000U);
|
| 338 |
+
} else {
|
| 339 |
+
canonical_values_a[i] = float_from_bits(0x7fc00001U + static_cast<uint32_t>(i));
|
| 340 |
+
canonical_values_b[i] = float_from_bits(0xff800001U + static_cast<uint32_t>(i));
|
| 341 |
+
}
|
| 342 |
+
}
|
| 343 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(context.get()), PALW_CUDA_TRACE_OK);
|
| 344 |
+
REQUIRE(output.copy_from(canonical_values_a, stream.get()), "failed to upload canonical set A");
|
| 345 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_OK);
|
| 346 |
+
REQUIRE_STATUS(
|
| 347 |
+
palw_cuda_trace_copy_async(
|
| 348 |
+
context.get(), records.get(), records.capacity(), stream.get()),
|
| 349 |
+
PALW_CUDA_TRACE_OK);
|
| 350 |
+
REQUIRE_STATUS(palw_cuda_trace_synchronize(context.get(), stream.get()), PALW_CUDA_TRACE_OK);
|
| 351 |
+
std::vector<encoded_record> canonical_a;
|
| 352 |
+
REQUIRE(encode_records(records.get(), 4, canonical_a), "failed to encode canonical set A");
|
| 353 |
+
|
| 354 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(context.get()), PALW_CUDA_TRACE_OK);
|
| 355 |
+
REQUIRE(output.copy_from(canonical_values_b, stream.get()), "failed to upload canonical set B");
|
| 356 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_OK);
|
| 357 |
+
REQUIRE_STATUS(
|
| 358 |
+
palw_cuda_trace_copy_async(
|
| 359 |
+
context.get(), records.get(), records.capacity(), stream.get()),
|
| 360 |
+
PALW_CUDA_TRACE_OK);
|
| 361 |
+
REQUIRE_STATUS(palw_cuda_trace_synchronize(context.get(), stream.get()), PALW_CUDA_TRACE_OK);
|
| 362 |
+
std::vector<encoded_record> canonical_b;
|
| 363 |
+
REQUIRE(encode_records(records.get(), 4, canonical_b), "failed to encode canonical set B");
|
| 364 |
+
REQUIRE(canonical_a == canonical_b, "signed-zero or NaN payload changed a sketch");
|
| 365 |
+
|
| 366 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(context.get()), PALW_CUDA_TRACE_OK);
|
| 367 |
+
values[7] += 17.0f;
|
| 368 |
+
REQUIRE(output.copy_from(values, stream.get()), "failed to upload mutated output");
|
| 369 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_OK);
|
| 370 |
+
REQUIRE_STATUS(
|
| 371 |
+
palw_cuda_trace_copy_async(
|
| 372 |
+
context.get(), records.get(), records.capacity(), stream.get()),
|
| 373 |
+
PALW_CUDA_TRACE_OK);
|
| 374 |
+
REQUIRE_STATUS(palw_cuda_trace_synchronize(context.get(), stream.get()), PALW_CUDA_TRACE_OK);
|
| 375 |
+
REQUIRE(
|
| 376 |
+
record_sketch(records.get()[0]) != baseline_gemm_sketches[0],
|
| 377 |
+
"sampled mutation did not change its tile sketch");
|
| 378 |
+
for (size_t i = 1; i < baseline_gemm_sketches.size(); ++i) {
|
| 379 |
+
REQUIRE(
|
| 380 |
+
record_sketch(records.get()[i]) == baseline_gemm_sketches[i],
|
| 381 |
+
"mutation changed an unrelated tile sketch");
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(context.get()), PALW_CUDA_TRACE_OK);
|
| 385 |
+
REQUIRE_STATUS(
|
| 386 |
+
launch_gemm(
|
| 387 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0, 255),
|
| 388 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 389 |
+
REQUIRE_STATUS(
|
| 390 |
+
launch_gemm(
|
| 391 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 392 |
+
PALW_CUDA_TRACE_DTYPE_FP32, 255),
|
| 393 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 394 |
+
REQUIRE_STATUS(
|
| 395 |
+
launch_gemm(
|
| 396 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 1),
|
| 397 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 398 |
+
REQUIRE_STATUS(
|
| 399 |
+
launch_gemm(
|
| 400 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 401 |
+
PALW_CUDA_TRACE_DTYPE_FP32, PALW_CUDA_TRACE_QUANTIZATION_Q4_K_M, 3),
|
| 402 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 403 |
+
REQUIRE_STATUS(
|
| 404 |
+
launch_gemm(
|
| 405 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 406 |
+
PALW_CUDA_TRACE_DTYPE_FP32, PALW_CUDA_TRACE_QUANTIZATION_Q4_K_M,
|
| 407 |
+
4, 6, 5),
|
| 408 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 409 |
+
REQUIRE_STATUS(
|
| 410 |
+
launch_gemm(
|
| 411 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 412 |
+
PALW_CUDA_TRACE_DTYPE_FP32, PALW_CUDA_TRACE_QUANTIZATION_Q4_K_M,
|
| 413 |
+
4, 6, 6, 6, 2, 3, 2, 0, 4),
|
| 414 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 415 |
+
REQUIRE_STATUS(
|
| 416 |
+
launch_attention(
|
| 417 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_DECODE, 0),
|
| 418 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 419 |
+
REQUIRE_STATUS(
|
| 420 |
+
launch_attention(
|
| 421 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 422 |
+
2, 1),
|
| 423 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 424 |
+
REQUIRE_STATUS(
|
| 425 |
+
launch_attention(
|
| 426 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 427 |
+
2, 2, 2, 4, 1, PALW_CUDA_TRACE_DTYPE_FP16, 1, 3),
|
| 428 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 429 |
+
REQUIRE_STATUS(
|
| 430 |
+
launch_attention(
|
| 431 |
+
context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 432 |
+
2, 2, 2, 4, 1, PALW_CUDA_TRACE_DTYPE_FP16, 2),
|
| 433 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 434 |
+
REQUIRE(palw_cuda_trace_count(context.get()) == 0U, "invalid arguments mutated count");
|
| 435 |
+
REQUIRE(palw_cuda_trace_poisoned(context.get()) == 0, "invalid arguments poisoned context");
|
| 436 |
+
|
| 437 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 1), PALW_CUDA_TRACE_SEQUENCE_MISMATCH);
|
| 438 |
+
REQUIRE(palw_cuda_trace_count(context.get()) == 0U, "sequence mismatch mutated count");
|
| 439 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_OK);
|
| 440 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_SEQUENCE_MISMATCH);
|
| 441 |
+
REQUIRE(palw_cuda_trace_count(context.get()) == 4U, "sequence mismatch changed reserved count");
|
| 442 |
+
REQUIRE_STATUS(palw_cuda_trace_synchronize(context.get(), stream.get()), PALW_CUDA_TRACE_OK);
|
| 443 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(context.get()), PALW_CUDA_TRACE_OK);
|
| 444 |
+
|
| 445 |
+
REQUIRE_STATUS(
|
| 446 |
+
launch_gemm(context.get(), other_stream.get(), output.get(), 0),
|
| 447 |
+
PALW_CUDA_TRACE_INVALID_ARGUMENT);
|
| 448 |
+
REQUIRE(palw_cuda_trace_count(context.get()) == 0U, "wrong stream mutated count");
|
| 449 |
+
|
| 450 |
+
REQUIRE(small_context.create(3), "failed to create small trace context");
|
| 451 |
+
REQUIRE_STATUS(
|
| 452 |
+
launch_gemm(small_context.get(), stream.get(), output.get(), 0),
|
| 453 |
+
PALW_CUDA_TRACE_CAPACITY_EXCEEDED);
|
| 454 |
+
REQUIRE(palw_cuda_trace_overflowed(small_context.get()) == 1, "overflow flag was not sticky");
|
| 455 |
+
REQUIRE(palw_cuda_trace_count(small_context.get()) == 0U, "capacity failure reserved records");
|
| 456 |
+
REQUIRE_STATUS(
|
| 457 |
+
launch_gemm(small_context.get(), stream.get(), output.get(), 0),
|
| 458 |
+
PALW_CUDA_TRACE_CAPACITY_EXCEEDED);
|
| 459 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(small_context.get()), PALW_CUDA_TRACE_OK);
|
| 460 |
+
REQUIRE(palw_cuda_trace_overflowed(small_context.get()) == 0, "reset did not clear overflow");
|
| 461 |
+
REQUIRE_STATUS(
|
| 462 |
+
launch_gemm(
|
| 463 |
+
small_context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 464 |
+
PALW_CUDA_TRACE_DTYPE_FP32, PALW_CUDA_TRACE_QUANTIZATION_Q4_K_M,
|
| 465 |
+
4, 6, 6, 6, 2, 3, 2, 4, 2),
|
| 466 |
+
PALW_CUDA_TRACE_OK);
|
| 467 |
+
REQUIRE(palw_cuda_trace_count(small_context.get()) == 3U, "exact capacity count mismatch");
|
| 468 |
+
REQUIRE_STATUS(
|
| 469 |
+
palw_cuda_trace_synchronize(small_context.get(), stream.get()),
|
| 470 |
+
PALW_CUDA_TRACE_OK);
|
| 471 |
+
|
| 472 |
+
context.get()->test_force_launch_failure = 1;
|
| 473 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_CUDA_ERROR);
|
| 474 |
+
REQUIRE(palw_cuda_trace_poisoned(context.get()) == 1, "launch failure did not poison context");
|
| 475 |
+
REQUIRE(palw_cuda_trace_count(context.get()) == 0U, "failed launch reserved records");
|
| 476 |
+
REQUIRE(palw_cuda_trace_last_cuda_error(context.get()) != 0, "poison lost CUDA error");
|
| 477 |
+
REQUIRE_STATUS(launch_gemm(context.get(), stream.get(), output.get(), 0), PALW_CUDA_TRACE_POISONED);
|
| 478 |
+
REQUIRE_STATUS(
|
| 479 |
+
launch_attention(context.get(), stream.get(), output.get(), 0),
|
| 480 |
+
PALW_CUDA_TRACE_POISONED);
|
| 481 |
+
REQUIRE_STATUS(palw_cuda_trace_reset(context.get()), PALW_CUDA_TRACE_POISONED);
|
| 482 |
+
REQUIRE_STATUS(
|
| 483 |
+
palw_cuda_trace_copy_async(
|
| 484 |
+
context.get(), records.get(), records.capacity(), stream.get()),
|
| 485 |
+
PALW_CUDA_TRACE_POISONED);
|
| 486 |
+
REQUIRE_STATUS(palw_cuda_trace_synchronize(context.get(), stream.get()), PALW_CUDA_TRACE_POISONED);
|
| 487 |
+
|
| 488 |
+
REQUIRE(recovered_context.create(4), "failed to recreate after poison");
|
| 489 |
+
REQUIRE_STATUS(
|
| 490 |
+
launch_gemm(
|
| 491 |
+
recovered_context.get(), stream.get(), output.get(), 0, PALW_CUDA_TRACE_PREFILL, 0,
|
| 492 |
+
PALW_CUDA_TRACE_DTYPE_FP32, PALW_CUDA_TRACE_QUANTIZATION_Q4_K_M,
|
| 493 |
+
4, 6, 6, 6, 2, 3, 2, 2, 4),
|
| 494 |
+
PALW_CUDA_TRACE_OK);
|
| 495 |
+
REQUIRE_STATUS(
|
| 496 |
+
palw_cuda_trace_synchronize(recovered_context.get(), stream.get()),
|
| 497 |
+
PALW_CUDA_TRACE_OK);
|
| 498 |
+
|
| 499 |
+
std::puts("PALW experimental CUDA GEMM/attention transport device gate: ok");
|
| 500 |
+
return true;
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
} // namespace
|
| 504 |
+
|
| 505 |
+
int main() {
|
| 506 |
+
int device_count = 0;
|
| 507 |
+
const cudaError_t count_status = cudaGetDeviceCount(&device_count);
|
| 508 |
+
if (count_status == cudaErrorNoDevice || count_status == cudaErrorInsufficientDriver ||
|
| 509 |
+
(count_status == cudaSuccess && device_count == 0)) {
|
| 510 |
+
std::fprintf(stderr, "SKIP: CUDA trace device gate requires an NVIDIA CUDA device\n");
|
| 511 |
+
return 77;
|
| 512 |
+
}
|
| 513 |
+
if (count_status != cudaSuccess) {
|
| 514 |
+
std::fprintf(stderr, "cudaGetDeviceCount failed: %s\n", cudaGetErrorString(count_status));
|
| 515 |
+
return 1;
|
| 516 |
+
}
|
| 517 |
+
if (cudaSetDevice(0) != cudaSuccess) {
|
| 518 |
+
std::fprintf(stderr, "cudaSetDevice(0) failed\n");
|
| 519 |
+
return 1;
|
| 520 |
+
}
|
| 521 |
+
return run_device_tests() ? 0 : 1;
|
| 522 |
+
}
|