Qwen3.6-35B-A3B-PALW-runtime / docs /receipt-implementation-qwen36.md
MISAKA-BTC
sync to MisakaLM3-8B a56c808: search replay, worker, and a build that can start
31ad728
|
Raw
History Blame Contribute Delete
40.8 kB

MISAKA PALW Receipt 実装仕様 — Qwen3.6-35B-A3B (hybrid MoE)

本書は、対象モデルを dense Qwen3-8B から hybrid Qwen3.6-35B-A3B (huihui_ai/Qwen3.6-abliterated:35b-Claude-4.7、abliterated) へ移行した後の ComputeReceiptV1 発行・検証パイプラインの実装仕様である。記述は現行 Rust/C++ ソースを正本とし、実装と本書が一致しない場合は Receipt を発行しない (protocol-v1.md と同じ原則)。本書に無い production 承認・決済連携・ attestation を Receipt から推論してはならない。

対象モデルは linear-attention(state-space / gated-delta-net)層と mixture-of-experts 層を組み合わせた hybrid 構成であり、dense Qwen3-8B 用の厳格な canonical operation mapping では表現できない演算を含む。そのため本移行では (1) pinned llama.cpp への qwen35moe loader/graph 互換修正、**(2)** dense vocabulary に対応の無い演算を output-element 数で committ する generic operation と CU ルールセット v2、**(3)** profile 駆動の hybrid adapter/manifest、を追加した。移行完了後、dense Qwen3-8B 経路(profile / manifest builder / constants / tests)は撤去され、Qwen3.6-35B-A3B が唯一の対象モデルとなった。

行番号 anchor は執筆時点のものであり、正本はソースである。

compute-gate track 更新(2026-07-19、実機検証済み)。 上記 (2) の「generic operation + CU ルールセット v2」は後続の compute-gate track で置換された。現行 receipt は (M1) CU を semantic ルールセット v3 で canonical commit(canonical_compute_units = 41692)、**(M3)** generic 演算を廃止し全 MoE/SSM op を忠実な canonical 演算(ExpertGemm/ExpertRoute/SsmConv/ GatedDeltaNet/L2Norm/Reduction/Elementwise)へ写像、**(M2)** canonical semantic schedule を 再生成・commit、**(M4/#6)** observer が実 MoE routing(ffn_moe_topk)を捕捉し expert_route_root を封緘 bundle へ commit(observer schema v2)、**(M5/#5)** ggml-metal を計装して各 GEMM を実 Metal kernel dispatch + launch geometry へ束縛し trace_evidence=metal_kernel を commit(graph-fallback から昇格、実機で 200/200・411/411 検証)。§0–§2 の一部記述(CU v2 / generic / SCHEMA_VERSION 1 / MUL_MAT_ID=metadata / graph_fallback)は旧版で、現行の正確な値は §10・§11 と receipt-review-remediation.md を参照。6 つの compute gate は 全て実機検証済み。 Metal の kernel-level trace は launch-geometry 束縛であり CUDA V3 相当の intra-kernel accumulator proof ではない(honest labeling、mint は依然不適格)。


0. 全体アーキテクチャとデータフロー

三層構成:

  1. vendor/llama.cpp/(commit 固定 + PALW patch): 推論ランタイムと read-only graph observer llama-palw-observer
  2. runtime-palw/(Rust): adapter、canonical CU、schedule、commitment、manifest、receipt builder/verifier、verification bundle、schema-v4 SQLite。
  3. config/ / patches/: 固定 artifact pin、model profile pin、llama.cpp patch。

Receipt 発行(palw-metal-receipt)のデータフロー:

prompt(stdin)
  │
  ├─ build_qwen36_35b_metal_manifest ─────────► RuntimeManifest(MoE topology, CU v3 semantic)
  │
  ├─ llama-tokenize ──────────────────────────► prompt_token_ids
  │
  ├─ llama-palw-observer --observer sketch ───► JSONL(header/event*/result)
  │       │(read-only graph callback、sketch)
  │       ▼
  │   qwen_adapter(HybridQwen36A3B)
  │       │  header 検証 + op→ComputeOperation 写像 + GEMM sketch
  │       ▼
  │   RuntimeObserver → ExecutionEvidence(schedule + GEMM trace + CU total, ruleset=v3 semantic)
  │
  ├─ build_signed_receipt ────────────────────► ComputeReceiptV1(署名)
  ├─ verify_stateless(cu_rules=v3) ───────────► 自己検証
  ├─ seal_verification_bundle(XChaCha20) ─────► <id>.palw.bundle
  ├─ StateStore(schema v4).accept ────────────► palw-state.sqlite3
  └─ 書き出し: <id>.palw / <id>.json / <id>.palw.bundle / <id>.complete

別 process 検証(palw-verify-bundle)は artifact set・完了 marker を検査し、bundle を復号・ 再検証(verify_bundle_and_restore)して status=local_restored / trust_scope=embedded_local_snapshot を出力する。


1. 対象モデルと固定 artifact

正本: config/runtime-pins.sh(公開識別子のみ、末尾で全て readonly)。

1.1 推論 GGUF(Ollama registry blob)

変数
PALW_GGUF_REGISTRY registry.ollama.ai
PALW_GGUF_REPO_ID huihui_ai/Qwen3.6-abliterated
PALW_GGUF_OLLAMA_TAG 35b-Claude-4.7
PALW_GGUF_REVISION = PALW_GGUF_SHA256 1dc494614bee8a3bc00e79fe5a49da0fc1c36b3b118c4156e223e98e5a0a671b
PALW_GGUF_FILENAME Qwen3.6-abliterated-35b-Claude-4.7-Q4_K_M.gguf
PALW_GGUF_SIZE 23938321728(bytes)

Ollama registry の blob digest は GGUF 本体の SHA-256 に等しいため revision == sha256。 content 検証だけで pin 全体の照合になる。

1.2 base metadata(Hugging Face、7 files)

PALW_BASE_REPO_ID = huihui-ai/Huihui-Qwen3.6-35B-A3B-Claude-4.7-Opus-abliteratedPALW_BASE_REVISION = ac18882735d037f6074a7630eb68d85db8234c25。 files: README.mdchat_template.jinjaconfig.jsonmodel.safetensors.index.jsonprocessor_config.jsontokenizer.jsontokenizer_config.json。 sha256 は config/qwen3.6-35b-a3b-claude-4.7-base-metadata.sha256 および profile pin の base_artifact.files[] と一致する。

1.3 llama.cpp

PALW_LLAMA_COMMIT = 12127defda4f41b7679cb2477a4b0d65ee6a0c8f(build 10015)、 patch = patches/llama.cpp-palw-observer.patchPALW_LLAMA_PATCH_SHA256 = d155a88b7c11ee74f48011760cb1a37773a694c8cab28258ee108c85e2f9e02c。 Metal build は -DGGML_METAL=ON -DGGML_CUDA=OFFarm64、target llama-cli/llama-server/llama-tokenize/llama-palw-observer

1.4 Ollama download 経路(install.sh :: download_gguf_if_needed)

  1. gguf_content_matches(存在 + size + sha256)が成立すれば再利用。
  2. mismatch する既存 file は上書きせず die。
  3. URL = https://$PALW_GGUF_REGISTRY/v2/$PALW_GGUF_REPO_ID/blobs/sha256:$PALW_GGUF_REVISION (OCI/Docker registry の blob-by-digest endpoint)。
  4. curl -fSL -C -(再開可能)で .partial に取得。
  5. size と sha256 を照合してから mv で atomic に確定。
  6. base metadata は従来通り HF(hf_snapshot_download.py、token を strip し Xet を無効化)。

2. 決定論的実行と native observer

正本: vendor/llama.cpp/tools/palw-observer/palw-observer.cpp(以下 OBS)。単一リクエストの 非対話 runner で、public な llama/ggml API のみ使用。versioned JSONL を stdout に、 llama/ggml のログを stderr に書く。

2.1 強制される決定論的実行ポリシー

n_ctx = PALW_CONTEXT_TOKENS = 4096n_batch = n_ubatch = 1n_seq_max = 1n_threads = n_threads_batch = 1、greedy sampler、flash_attn = DISABLEDtype_k = type_v = F16split_mode = NONEuse_mmap = true。context 初期化後に 実 context を読み直し、この不変条件を満たさなければ exit 3。prompt は --prompt-stdin 専用 pipe で渡し(argv に置かない)、prefill/decode とも 1 token ずつ llama_batch_get_one で評価する。prompt_tokens + n_predict > 4096 は context-shift せず失敗。

2.2 model profile gate(validate_qwen36_35b_a3b_profile)

model load 直後に、general.architecture == "qwen35moe"n_layer == 40n_embd == 2048n_vocab == 248320、decoder-only(encoder 無し)のみ受理。不一致は header/result を一切 emit せず exit 3。

2.3 JSONL プロトコル

SCHEMA_NAME = "misaka.palw.runtime_observer"SCHEMA_VERSION = 2(route record 追加)。1 実行は header 1event 0..Nresult 1。各行は個別に flush。

  • header: observer(off/graph/sketch)、trace_variantcuda_kernel_trace:falsemodel{path,description,tensor_size_bytes,parameter_count,file_type,n_ctx_train,n_embd, n_layer,n_head,n_head_kv,n_vocab,rope_type,rope_freq_scale_train,metadata[]}runtime{ggml_version,ggml_commit,system_info,supports_gpu_offload,requested_gpu_layers, devices[]}execution_policy{...上記決定論ポリシー...}observation_policy{read_only:true, graph_metadata_stage:"ask", sketch_bits:256, sketch_probe:"gemm_output_contiguous_prefix_64", raw_activation_values_published:false, tile_variant:"graph_fallback_logical_prefix_v1", kernel_trace_claim:"none"}
  • event: event_seq(単調増加、最終値 = result の event_count)、phase (prefill/decode)、phase_stepstage(ask_metadata / post_compute_sketch)、layer (名前から導出、無ければ null)、categories[]tensor{name,op,type,shape[4],n_bytes}sources[]。MUL_MAT には gemm{variant:"ggml_graph_op_v1",m,n,k,batch_shape}。sketch 時のみ sketch{}/tile{}/kernel_trace{}
  • result: statusstop_reason(n_predict/eog/…)、prompt_token_ids[]generated_token_ids[]output_bytes[](--emit-output-bytes 時のみ非空)、 output_n_bytesevent_count

2.4 observer モードと sketch scheme

  • off: callback 無し、event 0。
  • graph: 各非空 valid node に対し ask_metadata を 1 件 emit。tensor data は一切読まない。
  • sketch: 非 MUL_MAT node は ask_metadataMUL_MAT node のみ post-compute で ggml_backend_tensor_get により先頭最大 64 要素を読み、sign/bucket sketch を採取して post_compute_sketch を emit。

sketch(sign_bucket_256_v1): 各要素を 1 nibble(bit3 = 符号、bit0..2 = 3-bit 絶対値 bucket)にし、64 nibble = 256 bit。bucket 境界は 0, 2⁻⁸, 2⁻⁴, 2⁻², 1, 4, 16, ∞。生の 活性値は決して serialize しない。kernel_trace{available:false, backend:"none", claim:"not_a_cuda_kernel_trace"} を常に付し、graph 観測を CUDA kernel 証拠へ昇格しない。

2.5 observer 側の hybrid 対応(3 点)

  1. is_gemmGGML_OP_MUL_MAT のみに限定GGML_OP_MUL_MAT_ID(indirect expert GEMM)は sketch せず通常の metadata node として emit する。
  2. 0-element(recurrent state cache)tensor を skip。gated-delta-net / SSM 層は初期状態が 空の state cache を gather し、合法な 0-element node を生む。これは compute を伴わないため error にせず skip。
  3. validate_tensor が空 tensor を許容(name/type/op の範囲検査後に短絡)。

2.6 qwen35moe.cpp loader/graph 修正(5 点)

pinned commit 12127defsrc/models/qwen35moe.cpp は本モデルを load/run できないため、 PALW comment 付きで以下を修正(observer patch に同梱):

  1. 3-section mrope zero-pad: rope.dimension_sections を可変配列として読み、size 3 or 4 を 許容して zero-fill+copy。新しい HF→GGUF 変換の [t,h,w](末尾 0 省略)を受理。
  2. ssm_dt bias の suffix 両対応: blk.N.ssm_dt.biasTENSOR_NOT_REQUIRED で試し、 無ければ suffix 無し blk.N.ssm_dt を required で load。
  3. KV 射影幅に n_embd_k_gqa_max(): LLAMA_LOAD_LOCALS は layer 0 から n_embd_k/v_gqa を導出するが、layer 0 は linear-attention 層で n_head_kv==0。full-attention trunk 層と MTP 層の tensor 生成で per-layer 最大値を使う。
  4. sibling tensor(v.* / mtp.*)の計上: Ollama 同梱 GGUF は vision tower と(MTP 未 有効時)MTP sub-model を同梱する。text runtime はこれらを構築しないため、該当 prefix の tensor 分だけ n_created/size_data を調整し done_getting_tensors を通す。存在する tensor のみ 1 回ずつ計上するため、text tensor の欠落は依然として検出される。
  5. build_layer_attn の per-layer n_head(il)/n_head_kv(il): graph base は layer 0 から head 数を初期化するため、full-attention の Q/K/V reshape と RoPE を per-layer 値で shadow。

3. Rust adapter — hybrid 経路

正本: runtime-palw/src/qwen_adapter.rsAdapterProfile { HybridQwen36A3B }(唯一の profile) を NativeParseConfig/NativeRunConfigprofile field で選択し、 parse_native_jsonl_with_stderr が header 検証 / event 変換 / vocab 上限を hybrid 経路で処理する。 旧 dense 経路は撤去済み。

3.1 hybrid 定数と識別子

QWEN36_35B_LAYERS=40QWEN36_35B_VOCAB=248320QWEN36_35B_EMBED=2048QWEN36_35B_CONTEXT=262144QWEN36_35B_PARAMETERS=35_951_822_704QWEN36_ARCHITECTURE="qwen35moe"、共有の Q4_K_M_FILE_TYPE=15QWEN_RUNTIME_CONTEXT=4096

qwen36_adapter_mapping_id_v1() は domain "qwen36-native-observer-mapping/v1"domain_hash。payload は各 op の写像を列挙し cu-ruleset=v2;graph-fallback-only を含む。dense の "qwen-native-observer-mapping/v1"(soft_max=attention)とは別 hash。

3.2 header 検証(validate_header_hybrid)

deterministic execution policy と observation policy は dense と同一の厳格さで検証する。 model-shape だけを MoE 向けに一般化する:

  • parameter_count == 35_951_822_704file_type == 15n_ctx_train == 262144n_embd == 2048n_layer == 40n_vocab == 248320rope_freq_scale_train == 1.0
  • dense と違い n_head/n_head_kv/rope_type は pin しない(MoE は per-layer で可変、 layer-0 KV-head を制約しない)。
  • 必須 metadata: general.architecture=qwen35moegeneral.file_type=15general.quantization_version=2qwen35moe.context_length=262144qwen35moe.embedding_length=2048qwen35moe.block_count=40qwen35moe.expert_count=256qwen35moe.expert_used_count=8。dense と逆に expert metadata を要求する(dense は expert metadata を拒否)。
  • graph/sketch 時は supports_gpu_offload && requested_gpu_layers==999 && GPU device 存在

3.3 op → canonical operation 写像(convert_event_hybrid)

各 ggml op を canonical ComputeOperation へ写像する。dense と異なり、正確な canonical 対応がある演算はそれへ、対応の無い演算は Generic{op_class, elements} へ写す。fail-closed。

ggml op canonical operation
MUL_MAT Gemm(convert_gemm_hybrid、sketch 採取)
RMS_NORM RmsNorm { elements=shape[0], batch=Πshape[1..] }
ROPE Rotary { head_dim=shape[0], heads=shape[1], tokens=Πshape[2..] }
SOFT_MAX Softmax { elements=Πshape }(dense は Attention 再構成)
GLU Silu{elements} + ElementwiseMultiply{elements}
MUL ElementwiseMultiply { elements }
ADD ElementwiseAdd { elements }
GET_ROWS EmbeddingLookup { elements }
SET_ROWS KvCacheWrite { bytes = tensor.n_bytes }
CONT | CPY TensorCopy { bytes = tensor.n_bytes }
VIEW | RESHAPE | PERMUTE | TRANSPOSE layout-only(schedule に載せない)
その他 Generic { op_class=hybrid_generic_op_class(op), elements=Πshape }。未列挙は拒否

hybrid_generic_op_class(不変な op→u32 表): MUL_MAT_ID=1UNARY=2SCALE=3L2_NORM=4SUM_ROWS=5DIV=6CLAMP=7ARGSORT=8SSM_CONV=9GATED_DELTA_NET=10CONCAT=11。これ以外は NoneInvalidEvent(fail-closed)。

3.4 GEMM 変換(convert_gemm_hybrid)

gemm{} metadata の相互整合(m==left.shape[1]n==right.shape[1]k==left.shape[0]left.shape[0]==right.shape[0]、output shape 一致)を検証する。dense と異なり 固定 geometry や dtype allowlist は課さない。quantization は left.kind から q4_K→Q4KMq6_K→Q6K、 その他→None。sketch 時は validate_graph_fallback_sketch(sketch/tile/kernel_trace の値を 厳格検証)後、64 hex を 4 lane の big-endian i64 へ復元し on_gemm_group で trace に記録。 kernel_id domain は "qwen36-graph-fallback-probe/v1"

3.5 GPU offload marker とプライバシ

scan_stderr_markers"offloaded N/N layers to gpu"N が正で左右一致なら任意の N で 検出する(dense 37/37、hybrid 41/41 を model 非依存で受理)。不一致は IncompleteGpuOffload。prompt は OsStr の stdin のみ、error payload は &'static str/数値 のみ、QwenObserverOutputDebug 未実装、zeroize_private_material が prompt/生成 token/QA bytes を zeroize。


4. 正準演算語彙と CU ルールセット

正本: runtime-palw/src/compute_units.rs

4.1 ComputeOperation(canonical serialize discriminant)

0 Gemm(GemmShape)1 Attention2 LayerNorm3 RmsNorm4 Rotary5 ExpertRoute6 KvCacheRead7 KvCacheWrite8 Silu9 ElementwiseMultiply10 Softmax11 ElementwiseAdd12 TensorCopy13 EmbeddingLookup、**14 Generic{op_class:u32, elements:u64}**(本移行で追加)。0..5 は u32 次元、6..13 は単一 u64。追加は additive で 既存 variant の byte は不変。

Generic は「dense に cost 規則の無い演算(gated-delta-net、SSM conv、MoE routing 等)を 意味を歪めず、output 要素数で忠実に committ する」ための variant。op_class は演算種別の 安定 ID、cost は output 要素数のみに依存する。v2 のみが pricing し、v1 は拒否するため 既存 dense receipt と ruleset identity は不変。

4.2 CU ルールセット v1/v2

CU_RULESET_VERSION_V1=1CU_RULESET_VERSION_V2=2ruleset_id()domain_hash("cu-ruleset/vX", X, [payload])。payload の唯一の差分は v2 が ceil;min1 の前に generic=2/4096; を挿入する点(domain も /v2)。よって v1().ruleset_id() != v2().ruleset_id()matching_ruleset_id(&Hash32)[v1(),v2()] から 一致する ruleset を返す(本移行で追加、bundle 経路が使用)。

cost 式(cost()scaled_cost = max(1, ceil(work·units/reference))、全て checked):

op work reference units
Gemm m·n·k·batch 4096³ 120
Attention q·kv·heads·head_dim·batch 4096·4096·32·128 80
LayerNorm/RmsNorm elements·batch 4096 8
Rotary tokens·heads·head_dim 4096 4
ExpertRoute tokens·experts·top_k 4096 16
KvCacheRead/Write/TensorCopy bytes 1 MiB 1
Silu/ElementwiseMultiply/ElementwiseAdd elements 4096 2
Softmax elements 4096 4
EmbeddingLookup elements 4096 1
Generic elements 4096 2 (v2 限定、v1 は UnsupportedOperation)

ComputeUnitCounter.record は cost を checked-add し、overflow 時は state を変えず CostError::Overflow(fail-closed)。


5. Model profile pin と RuntimeManifest 構築

正本: runtime-palw/src/qwen_profile.rsruntime-palw/src/manifest.rsconfig/qwen3.6-35b-a3b-claude-4.7-profile.json

5.1 profile pin(schema v2)

schema = "misaka.palw.model-profile-pin.v2"profile_name = "Qwen3.6-35B-A3B-Claude-4.7-Opus-abliterated-Q4_K_M-Metal-arm64"model{} は MoE の全 shape(architecture Qwen3_5MoeForConditionalGeneration、model_type qwen3_5_moe、gguf_architecture qwen35moe、hidden 2048、heads 16、kv 2、layers 40、 head_dim 256、intermediate 512、expert_count 256、experts_per_token 8、rope_theta 10000000、 vocab 248320、max_pos 262144、bfloat16、Q4_K_M、ほか linear_* 等)を持つ。base_artifact は 7 files(各 sha256)、inference_artifact は Ollama repo/tag/64-hex blob revision/bytes/ sha256、runtime は commit と cmake_cache。deserialize struct は serde deny_unknown_fields (HybridProfilePin/HybridModelPin/HybridInferenceArtifactPin。dense との差は tag field)。

5.2 validate_hybrid_pin

schema/profile_name 一致、model 全 shape 一致、download_scope=="metadata-only"supported_profile=="metal-arm64"targetsllama-palw-observercommit.len()==40base.revision.len()==40、**inference.revision.len()==64**(Ollama blob digest)、 inference.bytes!=0。metadata files は 7 件で各 sha256 を streaming 照合 (verify_base_metadata_hybrid)。

5.3 build_qwen36_35b_metal_manifest

host(arm64、8 field 非空)と environment(LANG/LC_ALL のみ)を検証し、GGUF の size/sha256、 tokenizer(tokenizer.json+tokenizer_config.json の 2 件)を artifact 化する。以下の digest を domain_hash で計算し RuntimeManifest に committ する(dense と domain string が異なる主要点):

  • chat_template_digest(chat-template/v1): chat_template.jinja file bytes (dense は tokenizer_config 内の文字列)。
  • special_tokens_digest(special-token-semantics/v1): tokenizer_config + config.json (generation は Value::Null)。
  • kernel_graph_id(qwen36-35b-llama-graph/v1): commit + qwen36_adapter_mapping_id_v1()
    • ggml_sched_ask_metadata_v1 + prefill/decode 直列。
  • kernel_algorithm_digest(kernel-algorithm-policy/v1): 末尾に ;moe-hybrid;cu-ruleset=v2
  • ほか loaded_libraries_digestbuild_flags_digestdirty_patch_digestenvironment_allowlist_digestruntime_device_digestruntime_program_digestbuild_provenance_digest

ModelProfiletopology = MixtureOfExpertskv_heads=2、**head_dim=256(hidden/heads = 2048/16 = 128 とは decouple)**、rope="Qwen3.5-iMRoPE"native_context_tokens=262144vocabulary=248320RuntimeClass は Q4_K_M、flash-attn off、context_size=4096、batch=1。 RuntimeManifest.cu_ruleset_id = ComputeUnitRules::v2().ruleset_id()

5.4 manifest validator の緩和(hybrid を受理する 2 点)

  • ModelProfile::validate は旧来の head_dim == hidden/heads 検査を削除した。head_dim を 独立 field として committ し cross-check しないため、head_dim=2562048/16=128 が 共存できる。hidden % heads == 0(2048%16)、heads % kv == 0(16%2)は維持。
  • RuntimeManifest::validatecu_ruleset_idv1 または v2 の ruleset_id なら受理する。

6. Receipt body・commitment・署名

正本: runtime-palw/src/receipt.rsruntime-palw/src/builder.rsruntime-palw/src/observer.rs

6.1 ComputeReceiptV1(署名される canonical wire 順)

30 field を固定順で encode し、その byte 列が全 digest(signing_digest/body_id/ receipt_id)の入力になる。主要 field: receipt_version(=1)network_idrequest_commitmentscheduler_job_idsigned_assignment_idreplica_slotmodel_profile_idruntime_class_idruntime_manifest_hashshape_profile_id、 **cu_ruleset_id = evidence.cu_ruleset_id()**、trace_scheme_idtrace_evidenceoperation_schedule_commitmentschedule_event_countcanonical_compute_unitsprefill_tokensdecode_tokensoutput_commitmentgemm_trace_roottrace_event_countowner_commitmentworker_credential_idjob_nullifierexecution_nullifierjob_classevidence_leveltimestampissued_epochexpires_epoch

validate_structure は署名前後で 17 digest の非零、prefill_tokens!=0issued<=expires、job_class ごとの replica_slot 範囲、evidence_level ごとの count 整合 (GemmTraced は schedule/trace/CU が全て非零かつ trace_evidence!=Absent)を検査する。

6.2 build_signed_receipt

manifest.validate、CUDA KernelSketch 拒否、scheduler 署名(request+assignment)検証、worker credential binding、request constraints と manifest ID の一致、evidence↔shape/job binding、 prompt opening と prefill_tokens 一致、output count 一致、を検査後に commitment (commit_prompt_tokens/commit_output/commit_owner/derive_job_nullifier/ derive_execution_nullifier)を計算し、body を Ed25519 署名(signing_digest は network-id salt 付き canonical bytes)。builder は cu_ruleset_idevidence の値そのまま committ する (独自に ruleset を再導出しない)。

6.3 evidence 生成(RuntimeObserverExecutionEvidence)

observer は job_nullifier/shape_profile_id/ComputeUnitRules/EvidenceLevel に束縛される。 schedule = OperationSchedule::new(..., rules.ruleset_id())、trace は GemmTraced 時のみ生成。 状態機械は AwaitingPrefill→Prefill→Decode{step}、decode step は厳密連番、任意の event error で 恒久 poison。finalize_with_generated_tokensgenerated == decode_tokens+1(先頭 token は prefill logits から sample)を要求。GemmTraced 不変条件として schedule の GEMM 数 == trace group 数ExecutionEvidence.cu_ruleset_id = counter.rules().ruleset_id()(本移行では v2)がそのまま receipt へ流れる。


7. Stateless 検証(verify_stateless)

正本: runtime-palw/src/verifier.rsVerificationContext { network_id, current_epoch, manifest, cu_rules, signer_registry, assignment_authorizations } を取り、順に:

  1. validate_structure、network/epoch。
  2. assignment 解決と全 field binding、assignment policy(required_evidence_level==evidence_level)。
  3. signer 解決、owner/worker commitment、Ed25519 署名(weak-key 拒否 + verify_strict)。
  4. manifest.validate、CUDA KernelSketch 拒否。
  5. model_profile_id/runtime_class_id/runtime_manifest_hash/shape_profile_id を manifest から独立再計算して照合。
  6. CU-ruleset triple-bind: body.cu_ruleset_id == context.cu_rules.ruleset_id() かつ == manifest.cu_ruleset_id(不一致は CuRulesetMismatch)。本移行では三者とも v2。
  7. trace_scheme_id bind、job_nullifier/execution_nullifier の再導出照合、verify_shape
  8. verify_execution_evidence: evidence metadata・schedule integrity/commitment 照合後、 context.cu_rules で schedule を最初から再 pricingcanonical_compute_units を 照合(claim を信用しない)。per-entry で layer 範囲、dense topology の expert-route 拒否、 decode phase 順序を検査。GemmTraced は verify_trace(trace binding、capability 一致、 GEMM 数 == trace group 数、per-event の schedule 対応)。
  9. output nonce / prompt opening / output opening / output count。

hybrid では topology が MixtureOfExperts のため expert-route の dense 拒否は発火しない(なお 本 adapter は MUL_MAT_IDGeneric に写すので ExpertRoute op 自体を生成しない)。


8. Verification bundle と ruleset 選択の 3 修正

正本: runtime-palw/src/verification_bundle.rs

8.1 seal_verification_bundle

owner opening を照合し、封印前に receipt を完全に再 stateless 検証する(state-store は 変更しない)。公開部 BundlePublicV1(receipt_binding、receipt_id、verification_epoch、 scheduler-key record、manifest.canonical_bytes()PortableEvidenceV1)は認証済み cleartext。 秘密部 BundlePrivateV1(署名済み request/assignment、signer record、output opening = output_nonce + prompt/output token IDs、owner salt)は XChaCha20-Poly1305 で AEAD 暗号化 (AAD で receipt_binding/public_digest/nonce/public_bytes を束縛、AEAD 鍵は audit key の domain_hash 派生で raw key を直接使わない)。bundle_id は完全な暗号化 envelope 全体の domain_hash

8.2 CU ルールセット選択の 3 修正(v2 対応)

# 位置 修正
1 seal 経路 cu_rules = ComputeUnitRules::matching_ruleset_id(&context.manifest.cu_ruleset_id)(旧: v1 固定)
2 verify_bundle_stateless_inner matching_ruleset_id(&bundle.public.manifest.cu_ruleset_id)(旧: v1 固定)
3 PortableEvidenceV1::encode_canonical ruleset version を evidence に合わせて書く(matching_ruleset_id(evidence.cu_ruleset_id()).map_or(0, version)。旧: v1 固定)。decode は for_version で読む

これらが無いと、v2 evidence が bundle 内で v1 として round-trip し CuRulesetMismatch になる。 併せて manifest.rs の validate が v1|v2 を受理し、matching_ruleset_id を追加した。producing CLI は ComputeUnitRules::v2() を bind する。

8.3 portable evidence の round-trip

encode は version・level・prefill/decode・ruleset version・job_nullifier・shape_profile_id・ schedule entries・trace groups・claimed CU・claimed ruleset を書く。decode は RuntimeObserver で schedule/trace/CU を 再導出(serialize 済み total を信用しない)し、再構成 evidence の canonical_compute_units/cu_ruleset_id が claimed と一致することを要求する。bounds: MAX_EVIDENCE_EVENTS=250000MAX_BUNDLE_BYTES=64MiB


9. 永続化(SQLite schema v4)と CLI 契約

9.1 StateStore(schema v4)

APPLICATION_ID="PALW"SCHEMA_VERSION=4open は parent dir 解決 + SQLITE_OPEN_NOFOLLOWforeign_keys=ONsynchronous=FULLjournal_mode=WAL、application/schema 照合、および sqlite_masterDDL fingerprint(SHA3-256 golden 照合)。acceptBEGIN IMMEDIATE で duplicate receipt / duplicate execution_nullifier / job-class 整合 / slot 充填を強制し、 jobs(PK (network_id,job_nullifier)、WITHOUT ROWID)と receipts(PK receipt_idexecution_nullifier UNIQUE、UNIQUE(network_id,job_nullifier,replica_slot)、FK RESTRICT)へ transaction で insert する。復元経路 restore_accepted は read-only で既存 row を byte 照合する。

9.2 palw-metal-receipt(発行 CLI)

必須: --prompt-stdin--audit-key-file(exact 32 raw bytes、owner-only single-link 0400/0600、output dir 外)、--output-dir(新規/空、owner-only 0700)。任意: --n-predict (1..=1024、default 2)。prompt は UTF-8 非空 ≤1 MiB。run flow は §0 の通り。canonical_source_patchtools/CMakeLists.txtsrc/models/qwen35moe.cpp の modified、tools/palw-observer/ の untracked のみを許容する(他は拒否 = fail-closed)。出力 artifact:

file mode 内容
<id>.palw 0644 署名済み canonical receipt
<id>.json 0644 公開 metadata(misaka.palw.public-receipt.v2、strict field)
<id>.palw.bundle 0600 XChaCha20 暗号化 bundle
palw-state.sqlite3 0600 schema v4 state
<id>.complete 0644 misaka.palw.receipt-set.v2 完了 marker(最後に fsync 付きで作成)

9.3 palw-verify-bundle(検証 CLI)

必須: --receipt/--bundle/--public-json/--audit-key-file/--state-db。artifact set の mode/owner/single-link/同一 private dir、完了 marker の binding、bounded read、decode_strictvalidate_artifact_names(receipt_id は bundle 由来)、verify_bundle_and_restore(§8 の復号・ 再検証・schema-v4 復元)、verify_public_metadata(公開 JSON を authenticated 値と field 単位で 照合)。正常時 status=local_restored / trust_scope=embedded_local_snapshot。この trust scope は bundle 内 registry snapshot による continuity を示すのみで、network authority の代替ではない。


10. E2E 実測(reference receipt)

Apple M1 Max(macOS Metal 4、arm64)。observer は load 時に qwen35moe/40/2048/248320 を検証し offloaded 41/41 layers to GPU。出力健全性: The capital of France is ([760,6511,314,9338,369])→ Paris, a city renowned for its iconic

reference artifact は receipts/final-v7/、evidence 詳細は docs/evidence/metal-hybrid-qwen36-2026-07-19.md。 公開 receipt(misaka.palw.public-receipt.v2)の主要値:

field
receipt_id 8e2dd34b7609d6d7aeec17bff485eb1ae4db31f66dd899a3c3a3e671656053f9
verification_bundle_id f5b8a2968c4ea266b2cbbabf351a171e0fa2581984eff63362de2640fcdcf9db
cu_ruleset_id(v3 semantic) 43a5feef177b389f976361b22ac9d57da65815261282005bc78d1666a37870ce
job_class / evidence_level / trace_evidence self_local / gemm_traced / metal_kernel
prefill_tokens / decode_tokens 5 / 2
prefill_graph_steps / decode_graph_steps 5 / 1
schedule_event_count(= canonical_operations、commitment-only) 13770
trace_event_count(= gemm_events) 2466
canonical_compute_units(v3 semantic、署名 commit) 41692
semantic_compute_units_v3(= canonical_compute_units) 41692
semantic_schedule.commitment / .expert_route_ops e6fc731e… / 80
expert_route.root / .route_event_count(実捕捉) 5e4ea70b… / 240
mint.eligible / mint.weight / mint.mainnet_ready false / 0 / false
mint.ineligible_reasons Metal kernel-launch-bound / 非 network-anchored / 非 bonded の 3 件(generic+graph-fallback は解消)
model_profile_id b6b83a274a889fc5dfa2044b9158111b3849f880a05eb7ebcf560d036515d472
runtime_class_id 8f6f536118a72be70dab2028535c3bb95e3de9a3bac0e9b81cf78677ae902a9c
artifacts.llama_commit / model_bytes 12127def… / 23938321728

privacy: prompt / prompt token IDs / 生成 token IDs / opening / signing key / owner salt は公開 .palw / .json含まれない(全 9 flag が非公開/暗号化)。別 process の palw-verify-bundlestatus=local_restoredtrust_scope=embedded_local_snapshot、receipt_id/bundle_id 一致、 exit 0 で再検証済み。発行は実行ごとに OS CSPRNG で identity を生成するため receipt_id は再現しない。


11. セキュリティ境界・正直な限界

  • この Receipt は mint-grade ではない。 現行の evidence_level=gemm_traced / trace_evidence=graph_fallback強い計算証明ではないruntime-palw/src/mint.rsassess_mint_eligibility が現行 runtime の全 receipt を eligible=false, weight=0, class="local_self_consistent_v0_1" と判定し、公開 JSON の mint ブロックに失格理由と共に 自己申告する(palw-verify-bundle が再構成して照合)。用途は「ローカル自己整合 receipt / testnet 計測 / Self-Local 非報酬」に限られる。mint-grade 化の是正計画は receipt-review-remediation.md を参照。
  • Metal の graph-fallback sketch は CUDA kernel trace ではない
  • 単独ノードが発行する Receipt は、それだけでゼロ知識の計算証明ではない。PALW の不正耐性は runtime/model digest、署名、k=2 replica、future audit、canary、bond/slashing の組み合わせで 成立する。
  • Generic 演算は廃止済み(M3)。 hybrid の全 MoE/SSM op を忠実な canonical 演算へ写像 (MUL_MAT_ID→ExpertGemmARGSORT→ExpertRouteSSM_CONV→SsmConvGATED_DELTA_NET→GatedDeltaNetL2_NORM→L2NormSUM_ROWS→ReductionCONCAT→TensorCopyUNARY/SCALE/DIV/CLAMP→Elementwise)。 実機 receipt の schedule は contains_generic_operation()==false
  • Semantic CU v3 は canonical commitment(M1、mainnet compute measure)。 semantic_cu.rsqwen36_semantic_compute_units(prefill, generated) は CU を observed graph からではなく pinned model 構造 + token 数から算出(active-parameter FLOPs + causal attention 項、丸めは最後に 1 回)。 現行 receipt の canonical_compute_unitsこの semantic 値(41692)を cu_ruleset_id=v3 で署名 commit する(v2 の graph 値ではない)。fragmentation-proof / backend 非依存で、verifier は prefill_tokens/decode_tokens から同値を再計算・照合。
  • canonical semantic schedule(M2、#7 構造半分)。 semantic_schedule.rs が pinned architecture + token 数から canonical op schedule と commitment を決定的に再生成し、公開 JSON semantic_schedule に束縛。verifier が独立再生成して照合。
  • 実 MoE routing の捕捉(M4/#6)。 observer が ffn_moe_topk(I32)を post-compute で読み戻し、 per-token 選択 expert を封緘 bundle の expert_route_root へ commit、公開 JSON expert_route として 発行・再構成。実機で 240 route record を捕捉。
  • kernel-level trace(#5、M5、完了・実機検証済み)。 ggml-metal を計装して各 GEMM を実 Metal kernel dispatch + launch geometry へ束縛(200/200・411/411、0 anomaly)。trace_evidence=metal_kernel (graph-fallback から昇格)、TraceEvidenceKind/TraceCapability::MetalKernel を新設し verifier が照合。 launch-geometry 束縛であり CUDA V3 相当の intra-kernel accumulator proof ではないため KernelSketch とは別 kind で commit(over-claim しない)。mint 失格理由は「Metal kernel-launch-bound sketch, not an intra-kernel accumulator proof」に置換(mint 不適格のまま)。accumulator-level は Metal shader 計装が残件。
  • mainnet-readiness。 assess_mainnet_readiness が compute / network / hardware / model-Genesis の 全 gate を列挙し、外部 gate を Met と偽らない。現状 mint.mainnet_ready=false。mainnet 報酬適格性は deployed network authority / global nullifier / epoch beacon / bond authority / 複数世代実機 / 公式モデル Genesis を要し、この repository の完了範囲外である(remediation の外部ブロック項参照)。
  • 未達 gate R13/R21/R23/R24/R26/R27/R32/R35 は requirements.md の通り In progress。本移行はこれらの production 完了を意味しない。

既知の drift とテスト網羅(2026-07-19 時点)

  • hybrid adapter の専用 unit test は fixture test を追加済み(hybrid_generic_op_class 表、 mapping id 識別、MoE/SSM op 写像、unknown op fail-closed、q6_K trace、dense header 拒否)。 CU fragmentation invariant や公式 Transformers との differential 等の残りは receipt-review-remediation.md の follow-up。
  • validate_hybrid_pin は dense と異なり base_artifact/inference_artifact の repository 文字列を pin せず、deserialize する MoE/linear-attention の追加 dim(linear_*shared_expert_intermediate_sizefull_attention_intervalpartial_rotary_factor_millionths) を committ manifest には使わない(deny_unknown_fields 受理のためだけに存在)。

12. 再現手順

# 1. 導入(GGUF は Ollama registry、base metadata は HF)
./scripts/install.sh

# 2. Rust gate(MSRV 1.85)
cd runtime-palw
cargo +1.85.0 fmt --all -- --check
cargo +1.85.0 clippy --locked --all-targets -- -D warnings
cargo +1.85.0 test --locked --all-targets
cargo +1.85.0 build --release --locked --bin palw-metal-receipt --bin palw-verify-bundle
cd ..

# 3. Receipt 発行(audit key は 32-byte raw、output dir 外に一度だけ作成)
OUT="receipts/manual-$(date +%Y%m%d-%H%M%S)"
AUDIT_KEY="$HOME/.config/misaka-palw/audit-keys/local-audit.key"
install -d -m 700 "$(dirname "$AUDIT_KEY")"; test ! -e "$AUDIT_KEY"
(umask 077 && /usr/bin/openssl rand 32 > "$AUDIT_KEY"); chmod 600 "$AUDIT_KEY"
runtime-palw/target/release/palw-metal-receipt \
  --prompt-stdin --audit-key-file "$AUDIT_KEY" --output-dir "$OUT" --n-predict 2 \
  < /path/to/private-prompt.txt

# 4. 別 process 検証
RECEIPT="$(find "$OUT" -maxdepth 1 -type f -name '*.palw' -print)"; ID="$(basename "$RECEIPT" .palw)"
runtime-palw/target/release/palw-verify-bundle \
  --receipt "$OUT/$ID.palw" --bundle "$OUT/$ID.palw.bundle" \
  --public-json "$OUT/$ID.json" --audit-key-file "$AUDIT_KEY" \
  --state-db "$OUT/palw-state.sqlite3"
# 期待: status=local_restored / trust_scope=embedded_local_snapshot / exit 0

GGUF の SHA-256 を発行前後に 4 回計算するため、1 回の発行は約 5 分要する(24GB × 4)。 これは hang ではない。