From 1a5da828be17b9e9f1f2cc0d0ce941ecd2580e78 Mon Sep 17 00:00:00 2001 From: Noah Gift Date: Tue, 15 Sep 2026 09:58:29 +0200 Subject: [PATCH] =?UTF-8?q?fix(tools):=20pin=20pmat=203.40.1=20=E2=80=94?= =?UTF-8?q?=20the=20fleet=20converged=20on=202026-09-14=20and=20the=20apre?= =?UTF-8?q?nder=20half=20of=20the=20contract=20was=20never=20done;=20CB-20?= =?UTF-8?q?0=20back=20to=20602?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tools.toml's own header: "Bump this file in the SAME commit as the infra forjar.yaml version bump." infra#591 (ba369f9, 2026-09-14 17:53Z) moved intel's stack-tool-pmat to 3.40.1; this file stayed at 3.40.0. Measured on one PR ten minutes apart: main on yoga-build (not yet converged) green, PR 3093 on intel-clean-room-5 `FAIL pmat pinned 3.40.0 found 3.40.1`. The verdict of an aprender PR was a function of which box picked it up. CHANGING THE INSTRUMENT RE-RECORDS THE BASELINES, so both pmat-measured baselines were re-measured under 3.40.1 rather than relabelled: complexity_baseline.txt 679 rows under 3.40.0 -> 679 under 3.40.1 (check_complexity_ratchet.sh --update) cb200_baseline.txt 602 -> 602, but only after the fix below CB-200 was 603 on main. `pmat comply check` under 3.40.1 reads 602 at a0634f7b3 (the commit that banked 602) and 603 at origin/main — same instrument, so the tree moved. Bisected to ad8f98768 (#3004). Roster diff of sub-B definitions between the two trees is one line: crates/aprender-compute/src/registry/wgpu_probe.rs entry B- (72.7) It merged because no required job runs `pmat comply`. `entry` inlined three lookup tables (vendor id, wgpu backend -> transport, device type -> status) plus the unified-memory rule into one constructor. Each is now a named pure function with its own unit test; `entry` is assembly only. Fresh index: entry A+ 98.5, classify A 91.0, transport_name A- 89.5, vendor_name / mem_kind A+; CB-200 `Warn 602 … at the recorded baseline`. Two measurement traps, on the record because both cost a wrong reading: * `pmat comply` reads ~/.cache/paiml-mcp-agent-toolkit/comply/index// context.db and did NOT refresh it after the edit; `pmat query "x"` (dogfood.sh's "index first" step) refreshes .pmat/context.db, a different file. comply reported the OLD `entry` (B-, cx 19) on a tree that no longer contained it. Only moving the comply index aside made it re-measure. Filed against pmat. * min_grade "B" counts B- as below B. 603 reproduces from the index as grade in (B-,C+,C,C-,D+,D,D-,F) minus the [tdg] excludes. Local bashrs on this workstation is 7.3.0, so check_tool_versions.sh and the shell_lint header row FAIL here on bashrs; CI runners carry 7.4.1 and main is green on both. Not this PR's fact. Closes #3300. ont-delta: none — a fleet pin bump and one complexity refactor; no entity type, shape, resolves rule or reason id. Pmat-Ticket: PMAT-3300 Co-Authored-By: Claude Opus 5 (1M context) --- .pmat-gates.toml | 8 +- .../src/registry/wgpu_probe.rs | 128 +++++++++++++++--- docs/roadmaps/roadmap.yaml | 17 +++ scripts/cb200_baseline.txt | 2 +- scripts/complexity_baseline.txt | 2 +- tools.toml | 6 +- 6 files changed, 136 insertions(+), 27 deletions(-) diff --git a/.pmat-gates.toml b/.pmat-gates.toml index b8368b9823..16a4608aaf 100644 --- a/.pmat-gates.toml +++ b/.pmat-gates.toml @@ -95,9 +95,11 @@ exclude = [ [tdg] # CB-200 ratchet: functions below min_grade (pmat comply); the count may only fall. -# 602 measured 2026-09-14 under pmat 3.40.0 (was 609 under 3.39.0, 2026-09-03). -# The tree did not change between those two readings — the instrument did, so this -# is a re-measurement banked at the new floor, not seven functions fixed. +# 602 re-measured 2026-09-15 under pmat 3.40.1 (602 under 3.40.0, 2026-09-14; 609 under +# 3.39.0, 2026-09-03). 3.40.0 -> 3.40.1 read the same tree the same: the instrument moved, +# the count did not. Between those readings #3004 added one B- definition +# (registry/wgpu_probe.rs entry, 603) and merged, because no required job runs +# `pmat comply`; it was split into four graded tables in the pin-bump PR, back to 602. baseline = 602 # CB-200: 21 functions below A are in non-release crates (test-lib, test-cli, train/cuda) # These are complex GPU/inference functions where high cyclomatic complexity is inherent diff --git a/crates/aprender-compute/src/registry/wgpu_probe.rs b/crates/aprender-compute/src/registry/wgpu_probe.rs index e1c7b2c2e6..779bf9b1c5 100644 --- a/crates/aprender-compute/src/registry/wgpu_probe.rs +++ b/crates/aprender-compute/src/registry/wgpu_probe.rs @@ -32,37 +32,67 @@ impl BackendFactory for WgpuFactory { } } -#[allow(clippy::cast_possible_truncation)] -fn entry(i: usize, info: &wgpu::AdapterInfo, limits: &wgpu::Limits) -> BackendEntry { - let vendor = match info.vendor { +/// PCI vendor id -> vendor name. `"unknown"` for anything not in the table. +fn vendor_name(vendor_id: u32) -> &'static str { + match vendor_id { 0x10de => "NVIDIA", 0x1002 => "AMD", 0x8086 => "Intel", 0x106b => "Apple", _ => "unknown", - }; - let transport = match info.backend { + } +} + +/// wgpu backend -> the transport string `apr devices` prints (lane 2). +fn transport_name(backend: wgpu::Backend) -> &'static str { + match backend { wgpu::Backend::Vulkan => "vulkan", wgpu::Backend::Metal => "metal", wgpu::Backend::Dx12 => "dx12", wgpu::Backend::Gl => "gl", wgpu::Backend::BrowserWebGpu => "webgpu", wgpu::Backend::Noop => "noop", - }; - let (device_type, status) = match info.device_type { + } +} + +/// Device type -> (`device_type` string, status). A software rasteriser is +/// `Unavailable(NoBackend)`: listed, never used as a GPU. +fn classify(device_type: wgpu::DeviceType, name: &str) -> (&'static str, Status) { + match device_type { wgpu::DeviceType::DiscreteGpu => ("discrete-gpu", Status::Ready), wgpu::DeviceType::IntegratedGpu => ("integrated-gpu", Status::Ready), wgpu::DeviceType::VirtualGpu => ("virtual-gpu", Status::Ready), wgpu::DeviceType::Cpu => ( "software", Status::Unavailable(Reason::NoBackend { - vendor: format!("software rasteriser ({}) is not a GPU", info.name), + vendor: format!("software rasteriser ({name}) is not a GPU"), }), ), wgpu::DeviceType::Other => ("other", Status::Ready), - }; - let unified = matches!(info.backend, wgpu::Backend::Metal) - || matches!(info.device_type, wgpu::DeviceType::IntegratedGpu); + } +} + +/// Unified memory: Metal, or any integrated part. wgpu exposes no VRAM figure; +/// `max_buffer_size` is an allocation cap, so it is the working-set limit here +/// and `mem_total` stays unknown. +fn mem_kind( + backend: wgpu::Backend, + device_type: wgpu::DeviceType, + limits: &wgpu::Limits, +) -> MemKind { + let unified = matches!(backend, wgpu::Backend::Metal) + || matches!(device_type, wgpu::DeviceType::IntegratedGpu); + if unified { + MemKind::Unified { working_set_limit: Some(limits.max_buffer_size) } + } else { + MemKind::Discrete + } +} + +#[allow(clippy::cast_possible_truncation)] +fn entry(i: usize, info: &wgpu::AdapterInfo, limits: &wgpu::Limits) -> BackendEntry { + let vendor = vendor_name(info.vendor); + let (device_type, status) = classify(info.device_type, &info.name); BackendEntry { kind: BackendKind::Wgpu, api: Api::Wgpu, @@ -72,19 +102,79 @@ fn entry(i: usize, info: &wgpu::AdapterInfo, limits: &wgpu::Limits) -> BackendEn vendor: vendor.to_string(), vendor_id: if vendor == "unknown" { None } else { Some(info.vendor) }, device_type: device_type.to_string(), - // wgpu exposes no VRAM figure; `max_buffer_size` is an allocation cap, not - // memory, so it is reported as a capability string and mem_total stays unknown. mem_total: None, mem_free: None, - mem_kind: if unified { - MemKind::Unified { working_set_limit: Some(limits.max_buffer_size) } - } else { - MemKind::Discrete - }, + mem_kind: mem_kind(info.backend, info.device_type, limits), compute_class: None, caps: vec![format!("max_buffer_size={}", limits.max_buffer_size)], source: Source::CompiledIn, status, - transport: Some(transport.to_string()), + transport: Some(transport_name(info.backend).to_string()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn vendor_table_names_the_four_and_unknown_for_the_rest() { + assert_eq!(vendor_name(0x10de), "NVIDIA"); + assert_eq!(vendor_name(0x1002), "AMD"); + assert_eq!(vendor_name(0x8086), "Intel"); + assert_eq!(vendor_name(0x106b), "Apple"); + assert_eq!(vendor_name(0x0000), "unknown"); + assert_eq!(vendor_name(0xffff), "unknown"); + } + + #[test] + fn transport_table_is_total_over_wgpu_backends() { + assert_eq!(transport_name(wgpu::Backend::Vulkan), "vulkan"); + assert_eq!(transport_name(wgpu::Backend::Metal), "metal"); + assert_eq!(transport_name(wgpu::Backend::Dx12), "dx12"); + assert_eq!(transport_name(wgpu::Backend::Gl), "gl"); + assert_eq!(transport_name(wgpu::Backend::BrowserWebGpu), "webgpu"); + assert_eq!(transport_name(wgpu::Backend::Noop), "noop"); + } + + #[test] + fn software_rasteriser_is_listed_but_never_ready() { + let (ty, status) = classify(wgpu::DeviceType::Cpu, "llvmpipe"); + assert_eq!(ty, "software"); + match status { + Status::Unavailable(Reason::NoBackend { vendor }) => { + assert!(vendor.contains("llvmpipe"), "names the adapter: {vendor}"); + } + other => panic!("software rasteriser must be Unavailable(NoBackend), got {other:?}"), + } + for (dt, want) in [ + (wgpu::DeviceType::DiscreteGpu, "discrete-gpu"), + (wgpu::DeviceType::IntegratedGpu, "integrated-gpu"), + (wgpu::DeviceType::VirtualGpu, "virtual-gpu"), + (wgpu::DeviceType::Other, "other"), + ] { + let (ty, status) = classify(dt, "x"); + assert_eq!(ty, want); + assert!(matches!(status, Status::Ready), "{want} is Ready"); + } + } + + #[test] + fn unified_memory_is_metal_or_integrated_and_carries_the_buffer_cap() { + let mut limits = wgpu::Limits::default(); + limits.max_buffer_size = 4096; + for (b, dt) in [ + (wgpu::Backend::Metal, wgpu::DeviceType::DiscreteGpu), + (wgpu::Backend::Vulkan, wgpu::DeviceType::IntegratedGpu), + ] { + match mem_kind(b, dt, &limits) { + MemKind::Unified { working_set_limit } => assert_eq!(working_set_limit, Some(4096)), + other => panic!("{b:?}/{dt:?} must be Unified, got {other:?}"), + } + } + assert!(matches!( + mem_kind(wgpu::Backend::Vulkan, wgpu::DeviceType::DiscreteGpu, &limits), + MemKind::Discrete + )); } } diff --git a/docs/roadmaps/roadmap.yaml b/docs/roadmaps/roadmap.yaml index f0ce55e20a..20589b119b 100644 --- a/docs/roadmaps/roadmap.yaml +++ b/docs/roadmaps/roadmap.yaml @@ -17801,3 +17801,20 @@ roadmap: - kind:code notes: 'unanchored_but_bindable moves from [U] to 297; contracts_anchored may not rise while pv census is absent, because pv validate accepts entity: by ignoring it' +- id: PMAT-3300 + github_issue: 3300 + item_type: task + title: 'tools.toml pmat 3.40.1: the fleet converged 2026-09-14 and every intel-hosted PR is red' + status: planned + priority: medium + assigned_to: null + created: 2026-09-15T07:58:08Z + updated: 2026-09-15T07:58:08Z + spec: null + acceptance_criteria: [] + phases: [] + subtasks: [] + estimated_effort: null + labels: + - kind:code + notes: null diff --git a/scripts/cb200_baseline.txt b/scripts/cb200_baseline.txt index 3222ad81b3..270043102b 100644 --- a/scripts/cb200_baseline.txt +++ b/scripts/cb200_baseline.txt @@ -1,2 +1,2 @@ -# tool_version=pmat 3.40.0 +# tool_version=pmat 3.40.1 602 diff --git a/scripts/complexity_baseline.txt b/scripts/complexity_baseline.txt index 1be2a59c3f..12dd839e4f 100644 --- a/scripts/complexity_baseline.txt +++ b/scripts/complexity_baseline.txt @@ -2,7 +2,7 @@ # (cyclomatic > 30 or cognitive > 25), as ":: ". # SHRINK-ONLY. Regenerate with: bash scripts/check_complexity_ratchet.sh --update # Owner: scripts/check_complexity_ratchet.sh (PMAT-746). -# tool_version=pmat 3.40.0 +# tool_version=pmat 3.40.1 crates/apr-cli/examples/gpu_chat_inference.rs::run_chat_completion 11 33 crates/apr-cli/src/commands/attn_parity_lint.rs::run 13 26 crates/apr-cli/src/commands/attn_viz_classifier.rs::classify_causal_mask 8 29 diff --git a/tools.toml b/tools.toml index 6d9976252a..5769c33e5f 100644 --- a/tools.toml +++ b/tools.toml @@ -4,8 +4,8 @@ # CI. The fleet installer is infra's forjar pin, applied to every clean-room # runner (paiml/infra, machines/intel/forjar.yaml): # -# stack-tool-pmat (line 784) version: "3.39.0" # infra ef0ec4c, 2026-09-06 -# stack-tool-bashrs (line 811) version: "7.0.4" +# stack-tool-pmat (line 779) version: "3.40.1" # infra ba369f9, 2026-09-14 (#591) +# stack-tool-bashrs version: "7.4.1" # # ALWAYS LATEST (operator rule, 2026-09-14): "we always go latest crates.io on # our stack." This file names that version and check_tool_versions.sh asserts it. @@ -53,7 +53,7 @@ # Bump this file in the SAME commit as the infra forjar.yaml version bump. [pmat] -version = "3.40.0" +version = "3.40.1" [bashrs] version = "7.4.1"