diff --git a/.claude/context/CONTEXT_INDEX.json b/.claude/context/CONTEXT_INDEX.json index 68129451..404fd275 100644 --- a/.claude/context/CONTEXT_INDEX.json +++ b/.claude/context/CONTEXT_INDEX.json @@ -1,16 +1,52 @@ { "schema_version": "2.0", - "latest": "ctx-pcai-gitops-syshard-20260606", + "latest": "ctx-pcai-ci-restoration-20260718", "contexts": [ + { + "id": "ctx-pcai-ci-restoration-20260718", + "file": "pcai-context-20260718-ci-restoration.md", + "created": "2026-07-18T22:00:00Z", + "project": "PC_AI", + "agents_involved": [ + "clippy-lint-fix", + "general-purpose" + ], + "summary": "Re-enabled Actions; root-caused+fixed 7 pre-existing CI gate failures (PR #58). Discovered CI is not a merge gate; 65 pre-existing PS Unit-test failures surfaced (not caused) by Pester fix.", + "status": "active" + }, { "id": "ctx-pcai-gitops-syshard-20260606", "file": "pcai-context-20260606-gitops-and-system-hardening.md", "created": "2026-06-06T21:30:00Z", "project": "PC_AI", - "agents_involved": ["systematic-debugging", "dispatching-parallel-agents", "general-purpose", "Explore", "codex(peer via agent-bus)"], + "agents_involved": [ + "systematic-debugging", + "dispatching-parallel-agents", + "general-purpose", + "Explore", + "codex(peer via agent-bus)" + ], "summary": "Very long multi-arc session. GitOps: SSH-signing standard + dtm-default-protection ruleset on ALL 194 eligible David-Martel repos (PR-only/0-approval self-merge, signed, gh-actions bypass) + non-blocking lefthook push monitors (Watch-WorkflowHealth/Get-UpstreamReviews). Git/GPG/GitHub robustness proposal. Fixed GitHub account-picker (github https->ssh in ~/.gitconfig). Fixed PowerShell .bak shim (created ~/.config/powershell local profile; deleted bak). Input-stack: two independent root causes (PS/2 keyboard vs Sensel SNSL002D I2C touchpad); APPLIED T1 (device power-down off SNSL002D+7E78), T2 (WdfDirectedPowerTransitionEnable 1->0 on 7E78, reboot needed), F3 (MouseKeys hotkey disarm); haptic theory refuted; NVIDIA Ada Code 31 = driver split, two-package manual fix (user-driven). Dep modernization: AI-Media pyproject torch>=2.7+cu128 + requires-python>=3.13 (uv). vLLM->Manual. OneDrive C:\\codedev confirmed not linked. Restore point made. Coordinated w/ Codex on agent-bus throughout.", - "tags": ["gitops", "ssh-signing", "branch-protection", "ruleset", "input-stack", "touchpad", "nvidia-code31", "pytorch-cu128", "python313", "agent-bus", "codex-coordination"], - "artifacts": ["Tools/GitOps/", ".claude/plans/git-gpg-github-agent-robustness-proposal.md", "Reports/system-assessment-20260606/", "Reports/input-stack-investigation-20260606/", "AI-Media/pyproject.toml"], + "tags": [ + "gitops", + "ssh-signing", + "branch-protection", + "ruleset", + "input-stack", + "touchpad", + "nvidia-code31", + "pytorch-cu128", + "python313", + "agent-bus", + "codex-coordination" + ], + "artifacts": [ + "Tools/GitOps/", + ".claude/plans/git-gpg-github-agent-robustness-proposal.md", + "Reports/system-assessment-20260606/", + "Reports/input-stack-investigation-20260606/", + "AI-Media/pyproject.toml" + ], "commit": "pending" }, { @@ -18,10 +54,29 @@ "file": "pcai-context-20260606-input-stack-reinvestigation.md", "created": "2026-06-06T18:30:00Z", "project": "PC_AI", - "agents_involved": ["systematic-debugging", "Explore", "general-purpose"], - "summary": "Re-investigated shift-key + touchpad lockup from scratch. Device topology: Shift=PS/2 LEN0071/i8042 (parent 7E02), Touchpad=Sensel SNSL002D HID-over-I2C (parent 7E78) — DIFFERENT buses = two independent root causes (corrected prior 'Synaptics' mislabel; Synaptics=fingerprint, ELAN=TrackPoint). Verdicts: H1 FilterKeys REFUTED (off+disarmed now), H3 shared-bus REFUTED, H4 ProcessLasso REFUTED (protects input), H6 power SUPPORTS touchpad (MSPower_DeviceEnable=True live on SNSL002D + parent I2C 7E78 x Modern Standby = resume-lockup). Shift has NO OS-layer evidence -> needs Test-KeyInput trace. dwm.exe 62x crash 05-26 cross-links open NVIDIA Code 31. NEW: Watch-InputGlitch.ps1 Gate-C eval harness; touchpad fix T1 (power-down off). Also: CLAUDE.md doc reconciliation (Tools 89->81, +2 workflows, Litho status), doc-tooling eval report (validate-doc-accuracy caught TOOLS.md 31-vs-28 drift; Litho C4 never generated). Cleanup: 44 empty dirs + __pycache__; gitignored eval output + 12.9MB profile dump; surfaced 934MB OneDrive .db for user decision.", - "tags": ["input-stack", "shift-key", "touchpad", "sensel-i2c", "modern-standby", "device-power", "doc-accuracy", "tooling-eval", "gpg-keyboxd"], - "artifacts": ["Reports/input-stack-investigation-20260606/FINDINGS.md", "Tools/InputDiagnostics/Watch-InputGlitch.ps1", "Reports/doc-tooling-evaluation-20260606.md", "machine-reliability.TODO.md"], + "agents_involved": [ + "systematic-debugging", + "Explore", + "general-purpose" + ], + "summary": "Re-investigated shift-key + touchpad lockup from scratch. Device topology: Shift=PS/2 LEN0071/i8042 (parent 7E02), Touchpad=Sensel SNSL002D HID-over-I2C (parent 7E78) \u2014 DIFFERENT buses = two independent root causes (corrected prior 'Synaptics' mislabel; Synaptics=fingerprint, ELAN=TrackPoint). Verdicts: H1 FilterKeys REFUTED (off+disarmed now), H3 shared-bus REFUTED, H4 ProcessLasso REFUTED (protects input), H6 power SUPPORTS touchpad (MSPower_DeviceEnable=True live on SNSL002D + parent I2C 7E78 x Modern Standby = resume-lockup). Shift has NO OS-layer evidence -> needs Test-KeyInput trace. dwm.exe 62x crash 05-26 cross-links open NVIDIA Code 31. NEW: Watch-InputGlitch.ps1 Gate-C eval harness; touchpad fix T1 (power-down off). Also: CLAUDE.md doc reconciliation (Tools 89->81, +2 workflows, Litho status), doc-tooling eval report (validate-doc-accuracy caught TOOLS.md 31-vs-28 drift; Litho C4 never generated). Cleanup: 44 empty dirs + __pycache__; gitignored eval output + 12.9MB profile dump; surfaced 934MB OneDrive .db for user decision.", + "tags": [ + "input-stack", + "shift-key", + "touchpad", + "sensel-i2c", + "modern-standby", + "device-power", + "doc-accuracy", + "tooling-eval", + "gpg-keyboxd" + ], + "artifacts": [ + "Reports/input-stack-investigation-20260606/FINDINGS.md", + "Tools/InputDiagnostics/Watch-InputGlitch.ps1", + "Reports/doc-tooling-evaluation-20260606.md", + "machine-reliability.TODO.md" + ], "commit": "pending" }, { @@ -29,10 +84,28 @@ "file": "input-stack-freeze-context-20260530.md", "created": "2026-05-30T12:54:00Z", "project": "PC_AI", - "agents_involved": ["systematic-debugging", "advisor", "powershell-pro(infra-failed)"], + "agents_involved": [ + "systematic-debugging", + "advisor", + "powershell-pro(infra-failed)" + ], "summary": "Shift/trackpad/fingerprint freeze on DTM-P1GEN7. RESOLVED ROOT CAUSES: Shift = NOT software (stack proven clean; Razer/Logi/PowerToys/accessibility all exonerated) -> ThinkPad EC/keyboard firmware, triggered under eGPU+Terminal+contention load (TrackPoint immune=separate path). Touchpad = Synaptics I2C-HID. eGPU+Terminal+ProcessLasso competition = PL pinned Terminal/pwsh to EcoQoS + forced Terminal render onto eGPU. 5/29 hard-freeze cascade = eGPU(Razer Core X V2/USB4) Thunderbolt link (WHEA PCIe corrected errors). APPLIED+VALIDATED (elevated): USB selective suspend OFF, CrashDumpEnabled=7, per-device power off, PC_AI-HVSockProxy+vtss disabled, PL EcoQoS+GPU-pref optimized (all GPU prefs->auto). Razer uninstalled (not needed for eGPU). 7-script toolkit (Pester 41/41). PENDING USER: sign out/in, EC reset+Test-KeyInput, Lenovo BIOS/EC+Synaptics+NVIDIA driver updates. See machine-reliability.TODO.md + boot.TODO.md.", - "tags": ["input-stack", "freeze", "filterkeys", "usb-selective-suspend", "dpc-latency", "process-lasso", "kernel-power-41", "boot-reliability"], - "artifacts": ["Tools/InputDiagnostics/Invoke-InputStackDiagnostics.ps1", "Tools/InputDiagnostics/Repair-InputStackQuickWins.ps1", "Tools/InputDiagnostics/Start-LoadCapture.ps1", "Tools/InputDiagnostics/README.md"], + "tags": [ + "input-stack", + "freeze", + "filterkeys", + "usb-selective-suspend", + "dpc-latency", + "process-lasso", + "kernel-power-41", + "boot-reliability" + ], + "artifacts": [ + "Tools/InputDiagnostics/Invoke-InputStackDiagnostics.ps1", + "Tools/InputDiagnostics/Repair-InputStackQuickWins.ps1", + "Tools/InputDiagnostics/Start-LoadCapture.ps1", + "Tools/InputDiagnostics/README.md" + ], "commit": "pending" }, { @@ -40,9 +113,18 @@ "file": "pcai-context-20260410-nvidia-option-b.md", "created": "2026-04-10T23:38:00Z", "project": "PC_AI", - "agents_involved": ["general-purpose"], - "summary": "NVIDIA Option B (filtered staged 595.97 Lenovo Enterprise install for DEV_28B8) executed via Tools/Install-InfDriver.ps1 loop. 6 INFs (nvltwi/nvblwi/nvdmwi/nvfmwi/nvmiwi/nvmsowi) installed cleanly, RTX 2000 Ada Code 31 RESOLVED (now OK on 32.0.15.9597, nvidia-smi visible). REGRESSION: RTX 5060 Ti flipped to Code 31 — same WDDM kernel-mismatch pattern, cards swapped. Local recovery exhausted (no GRD on disk newer than 591.86 oem387). Decision pending: reboot, Option C (manual nvidia.com download), or rollback.", - "tags": ["nvidia", "drivers", "pnputil", "WDDM", "split-driver", "decision-pending"], + "agents_involved": [ + "general-purpose" + ], + "summary": "NVIDIA Option B (filtered staged 595.97 Lenovo Enterprise install for DEV_28B8) executed via Tools/Install-InfDriver.ps1 loop. 6 INFs (nvltwi/nvblwi/nvdmwi/nvfmwi/nvmiwi/nvmsowi) installed cleanly, RTX 2000 Ada Code 31 RESOLVED (now OK on 32.0.15.9597, nvidia-smi visible). REGRESSION: RTX 5060 Ti flipped to Code 31 \u2014 same WDDM kernel-mismatch pattern, cards swapped. Local recovery exhausted (no GRD on disk newer than 591.86 oem387). Decision pending: reboot, Option C (manual nvidia.com download), or rollback.", + "tags": [ + "nvidia", + "drivers", + "pnputil", + "WDDM", + "split-driver", + "decision-pending" + ], "commit": "5e7d591" }, { @@ -50,9 +132,15 @@ "file": "pcai-context-20260319-llm-optimization-v2.md", "created": "2026-03-19T07:40:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro", "Explore", "general-purpose"], - "summary": "LLM optimization Phase 2: 36 tok/s (2.0x), critical quality fix (argmax→multinomial), PreAllocKvCache wired, GPU Gumbel sampling, repetition penalty, understanding pipeline fixed, multi-token research complete (Jacobi 1.5-2x next), 235 tests pass, CUDA binaries deployed.", - "supersedes": ["ctx-pcai-20260319-llm-optimization"], + "agents_involved": [ + "rust-pro", + "Explore", + "general-purpose" + ], + "summary": "LLM optimization Phase 2: 36 tok/s (2.0x), critical quality fix (argmax\u2192multinomial), PreAllocKvCache wired, GPU Gumbel sampling, repetition penalty, understanding pipeline fixed, multi-token research complete (Jacobi 1.5-2x next), 235 tests pass, CUDA binaries deployed.", + "supersedes": [ + "ctx-pcai-20260319-llm-optimization" + ], "commit": "98f2009" }, { @@ -60,9 +148,18 @@ "file": "pcai-context-20260319-llm-optimization.md", "created": "2026-03-19T03:00:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro", "search-specialist", "powershell-pro", "deployment-engineer", "Explore", "Jules"], - "summary": "LLM inference optimization: 17.9 → 30 tok/s (1.67x), flash-attn Windows research (Linux-only), cuDNN SDPA as alternative, FunctionGemma flash-attn enabled, Build.ps1 cuda-optimized defaults, ring crate eliminated, 36 commits pushed.", - "supersedes": ["ctx-pcai-20260318-nvidia-complete"], + "agents_involved": [ + "rust-pro", + "search-specialist", + "powershell-pro", + "deployment-engineer", + "Explore", + "Jules" + ], + "summary": "LLM inference optimization: 17.9 \u2192 30 tok/s (1.67x), flash-attn Windows research (Linux-only), cuDNN SDPA as alternative, FunctionGemma flash-attn enabled, Build.ps1 cuda-optimized defaults, ring crate eliminated, 36 commits pushed.", + "supersedes": [ + "ctx-pcai-20260318-nvidia-complete" + ], "commit": "1576f7b" }, { @@ -70,9 +167,18 @@ "file": "pcai-context-20260318-nvidia-complete.md", "created": "2026-03-18T20:00:00Z", "project": "PC_AI", - "agents_involved": ["powershell-pro", "rust-pro", "search-specialist", "team-reviewer", "Explore", "Jules"], + "agents_involved": [ + "powershell-pro", + "rust-pro", + "search-specialist", + "team-reviewer", + "Explore", + "Jules" + ], "summary": "NVIDIA framework complete: PC-AI.Gpu module (19 files, Phases 1-3), NVML Rust GPU monitoring (508 lines), CUDA device fallback, driver auto-discovery, 50 Jules sessions completed via API, RealESRGAN ONNX conversion, PcaiChatTui.Tests, 28 review findings fixed. 15 commits pushed, local/remote synced at 77b0cc7.", - "supersedes": ["ctx-pcai-20260318-media-pipeline"], + "supersedes": [ + "ctx-pcai-20260318-media-pipeline" + ], "commit": "77b0cc7" }, { @@ -80,9 +186,15 @@ "file": "pcai-context-20260318-media-pipeline.md", "created": "2026-03-18T00:00:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro", "powershell-pro", "test-automator"], + "agents_involved": [ + "rust-pro", + "powershell-pro", + "test-automator" + ], "summary": "Media pipeline WIP: 23 modified files across pcai_media/pcai_media_model/pcai_media_server Rust crates + PcaiMedia PowerShell module + 4 test files. Janus-Pro GPU generation (~34 tok/s, ~17s on RTX 2000 Ada). Rust Guidelines enforcement (lefthook, 76 ast-grep rules). Token counting FFI added.", - "supersedes": ["ctx-pcai-20260311-driver-framework"], + "supersedes": [ + "ctx-pcai-20260311-driver-framework" + ], "commit": "pending" }, { @@ -90,9 +202,17 @@ "file": "pcai-context-20260311-driver-framework.md", "created": "2026-03-11T04:45:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro", "csharp-pro", "powershell-pro", "debugger", "architect-reviewer"], + "agents_involved": [ + "rust-pro", + "csharp-pro", + "powershell-pro", + "debugger", + "architect-reviewer" + ], "summary": "Driver update framework: PC-AI.Drivers module, driver-registry.json, Rust PnP driver metadata, pnputil INF installer (Install-InfDriver.ps1), Realtek RTL8156/8157 updated to 1156.21.20.1110/1157.21.20.1110, 5-agent code review with 13 critical/high fixes", - "supersedes": ["ctx-pcai-20260309-rust-toolchain"], + "supersedes": [ + "ctx-pcai-20260309-rust-toolchain" + ], "commit": "pending" }, { @@ -100,31 +220,53 @@ "file": "pcai-context-20260309-rust-toolchain-optimization.md", "created": "2026-03-09T12:00:00Z", "project": "PC_AI", - "agents_involved": ["powershell-pro", "rust-pro"], + "agents_involved": [ + "powershell-pro", + "rust-pro" + ], "summary": "CargoTools v0.10.0: lspmux integration (5 new functions), maturin/PyO3 binding optimization, ConfigFiles bug fixes, stale toolchain cleanup, nightly 1.96.0", - "supersedes": ["ctx-pcai-20260307-commit-cluster-analysis"], + "supersedes": [ + "ctx-pcai-20260307-commit-cluster-analysis" + ], "commit": "pending", - "cross_repo": {"repo": "CargoTools", "path": "C:\\Users\\david\\AppData\\Local\\PowerShell\\Modules\\CargoTools"} + "cross_repo": { + "repo": "CargoTools", + "path": "C:\\Users\\david\\AppData\\Local\\PowerShell\\Modules\\CargoTools" + } }, { "id": "ctx-pcai-20260307-commit-cluster-analysis", "file": "pcai-context-20260307-commit-cluster-analysis.md", "created": "2026-03-07T18:00:00Z", "project": "PC_AI", - "agents_involved": ["claude-md-improver", "commit-cluster", "Explore"], + "agents_involved": [ + "claude-md-improver", + "commit-cluster", + "Explore" + ], "summary": "294-file commit-cluster batch (14 commits to 69f987e), git-cluster-analyzer perf analysis (20 optimizations in optimization.TODO.md committed to git-cluster as 5ea7492), CLAUDE.md audit with 6 targeted edits", - "supersedes": ["ctx-pcai-20260307-claude-md-audit"], + "supersedes": [ + "ctx-pcai-20260307-claude-md-audit" + ], "commit": "69f987e", - "cross_repo": {"repo": "git-cluster", "commit": "5ea7492", "file": "optimization.TODO.md"} + "cross_repo": { + "repo": "git-cluster", + "commit": "5ea7492", + "file": "optimization.TODO.md" + } }, { "id": "ctx-pcai-20260307-claude-md-audit", "file": "pcai-context-20260307-claude-md-audit.md", "created": "2026-03-07T12:00:00Z", "project": "PC_AI", - "agents_involved": ["claude-md-improver"], + "agents_involved": [ + "claude-md-improver" + ], "summary": "CLAUDE.md audit and update: architecture tree updated with 6 Rust crates, AI-Media, PcaiMedia module; Build.ps1 20 components documented; test counts fixed (65+); 22 integration test files; 9 CI workflows; SM 120 Blackwell CUDA target added", - "supersedes": ["ctx-pcai-20260303-toolchain"], + "supersedes": [ + "ctx-pcai-20260303-toolchain" + ], "status": "superseded" }, { @@ -132,9 +274,13 @@ "file": "pcai-context-20260303-toolchain-integration.md", "created": "2026-03-03T12:00:00Z", "project": "PC_AI", - "agents_involved": ["Claude-opus"], + "agents_involved": [ + "Claude-opus" + ], "summary": "CUDA/LLVM toolchain integration: CargoTools GPU/CUDA/MSVC/LLVM/SDK auto-detection, lld-link preferred linker, .cargo/config.toml gitignored with templates, pcai-media pipeline hardened (rand RNG, SigLIP vision, async FFI, RealESRGAN upscale), NativeResolver.cs centralized DLL resolution, 26-file commit a8c2d00", - "supersedes": ["ctx-pcai-20260222b-tdd-cleanup"], + "supersedes": [ + "ctx-pcai-20260222b-tdd-cleanup" + ], "commit": "a8c2d00" }, { @@ -142,9 +288,13 @@ "file": "pcai-context-20260222-tdd-and-cleanup.md", "created": "2026-02-22T18:00:00Z", "project": "PC_AI", - "agents_involved": ["Claude-opus"], + "agents_involved": [ + "Claude-opus" + ], "summary": "42 Rust unit tests (TDD plan complete), CUDA 13.1 now works with updated crate deps, .gitignore/.rgignore updated for alternate target dirs and training checkpoints", - "supersedes": ["ctx-pcai-20260222-ffi-torture"], + "supersedes": [ + "ctx-pcai-20260222-ffi-torture" + ], "commit": "bcfceb4", "status": "superseded" }, @@ -153,9 +303,16 @@ "file": "pcai-context-20260222-ffi-torture-test.md", "created": "2026-02-22T12:00:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro", "csharp-pro", "test-automator", "Claude-opus"], + "agents_involved": [ + "rust-pro", + "csharp-pro", + "test-automator", + "Claude-opus" + ], "summary": "4-phase completion: CUDA fix, FunctionGemma build+train+eval, C# TUI ReAct mode, FFI torture tests (49 tests, 43 pass, 0 fail, 6 skip)", - "supersedes": ["ctx-pcai-20260221-consolidation"], + "supersedes": [ + "ctx-pcai-20260221-consolidation" + ], "commit": "0b9e9ce" }, { @@ -163,9 +320,15 @@ "file": "pcai-context-20260221-functiongemma-consolidation.md", "created": "2026-02-21T12:00:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro", "Explore", "Claude-opus"], + "agents_involved": [ + "rust-pro", + "Explore", + "Claude-opus" + ], "summary": "FunctionGemma cross-crate consolidation complete - 42 tasks, 700+ lines eliminated, unified RuntimeConfig, shared GPU/safetensors/LoRA/prompt utilities in core", - "supersedes": ["ctx-pcai-20260131-ffi"], + "supersedes": [ + "ctx-pcai-20260131-ffi" + ], "commit": "pending" }, { @@ -173,9 +336,14 @@ "file": "pcai-context-2026-01-31.md", "created": "2026-01-31T12:00:00Z", "project": "PC_AI", - "agents_involved": ["Claude", "Explore"], + "agents_involved": [ + "Claude", + "Explore" + ], "summary": "Native inference FFI integration - 22MB mistralrs DLL, C# bindings, PowerShell module fixes, command routing tools", - "supersedes": ["ctx-pcai-20260130-cuda"], + "supersedes": [ + "ctx-pcai-20260130-cuda" + ], "commit": "pending" }, { @@ -183,9 +351,13 @@ "file": "pcai-inference-cuda-build-2026-01-30.md", "created": "2026-01-30T22:30:00Z", "project": "PC_AI", - "agents_involved": ["Claude"], + "agents_involved": [ + "Claude" + ], "summary": "CUDA-enabled llamacpp backend build - CMake/MSVC toolchain fixes, API compatibility (token_to_str), CUDA 12.9 integration", - "supersedes": ["ctx-pcai-20260130-s3"], + "supersedes": [ + "ctx-pcai-20260130-s3" + ], "commit": "pending", "status": "superseded" }, @@ -194,9 +366,15 @@ "file": "pcai-context-2026-01-30.md", "created": "2026-01-30T19:30:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro", "powershell-pro", "test-automator"], + "agents_involved": [ + "rust-pro", + "powershell-pro", + "test-automator" + ], "summary": "Native Rust inference backend (pcai-inference) with llama-cpp-2/mistral.rs dual-backend, CMake/MSVC toolchain, Virtualization module updates", - "supersedes": ["ctx-pcai-20260130-s2"], + "supersedes": [ + "ctx-pcai-20260130-s2" + ], "commit": "ec2b5e1", "status": "superseded" }, @@ -207,7 +385,9 @@ "project": "PC_AI", "agents_involved": [], "summary": "CUDA environment integration for Rust ML training - device detection verified", - "supersedes": ["ctx-pcai-20260130-s1"], + "supersedes": [ + "ctx-pcai-20260130-s1" + ], "commit": "pending", "status": "superseded" }, @@ -218,7 +398,9 @@ "project": "PC_AI", "agents_involved": [], "summary": "Rust compilation fixes, unused import cleanup, 5-group commit clustering", - "supersedes": ["ctx-pcai-20260128-s4"], + "supersedes": [ + "ctx-pcai-20260128-s4" + ], "commit": "e7f815c", "status": "superseded" }, @@ -227,9 +409,14 @@ "file": "pcai-context-20260128-session4.md", "created": "2026-01-29T00:55:49Z", "project": "PC_AI", - "agents_involved": ["Explore", "rust-pro"], + "agents_involved": [ + "Explore", + "rust-pro" + ], "summary": "FunctionGemma runtime OpenAI API compatibility - error handling, validation, usage stats", - "supersedes": ["ctx-pcai-20260128-s3"], + "supersedes": [ + "ctx-pcai-20260128-s3" + ], "commit": "95f9b5e", "status": "superseded" }, @@ -238,9 +425,14 @@ "file": "pcai-context-20260128-session3.md", "created": "2026-01-28T17:30:00Z", "project": "PC_AI", - "agents_involved": ["Explore", "code-reviewer"], + "agents_involved": [ + "Explore", + "code-reviewer" + ], "summary": "Documentation accuracy fixes - 80.1% pollution eliminated", - "supersedes": ["ctx-pcai-20260128-s2"], + "supersedes": [ + "ctx-pcai-20260128-s2" + ], "status": "archived" }, { @@ -248,7 +440,12 @@ "file": "pcai-context-20260128-session2.md", "created": "2026-01-28T19:30:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro", "powershell-pro", "architect-reviewer", "api-documenter"], + "agents_involved": [ + "rust-pro", + "powershell-pro", + "architect-reviewer", + "api-documenter" + ], "summary": "CargoTools critical fixes - mutex, TOCTOU, paths", "status": "archived" }, @@ -257,7 +454,9 @@ "file": "pcai-context-20260128.md", "created": "2026-01-28T00:00:00Z", "project": "PC_AI", - "agents_involved": ["rust-pro"], + "agents_involved": [ + "rust-pro" + ], "summary": "Rust FunctionGemma workspace setup", "status": "archived" }, @@ -277,7 +476,12 @@ "completed": "2026-03-11", "context": "ctx-pcai-20260311-driver-framework", "commit": "pending", - "outputs": ["Modules/PC-AI.Drivers/ (11 files)", "Config/driver-registry.json", "Tools/Install-InfDriver.ps1", "Tools/Update-Drivers.ps1"] + "outputs": [ + "Modules/PC-AI.Drivers/ (11 files)", + "Config/driver-registry.json", + "Tools/Install-InfDriver.ps1", + "Tools/Update-Drivers.ps1" + ] }, { "goal": "Realtek RTL8156/RTL8157 drivers updated to 1156.21.20.1110/1157.21.20.1110 via pnputil INF install", @@ -290,7 +494,10 @@ "completed": "2026-03-11", "context": "ctx-pcai-20260311-driver-framework", "commit": "pending", - "outputs": ["pnp.rs (get_driver_metadata, read_reg_sz)", "HardwareModule.cs (updated P/Invoke)"] + "outputs": [ + "pnp.rs (get_driver_metadata, read_reg_sz)", + "HardwareModule.cs (updated P/Invoke)" + ] }, { "goal": "5-agent code review: 13 critical/high fixes applied (PS, Rust, C#, data, architecture)", @@ -303,7 +510,10 @@ "completed": "2026-03-07", "context": "ctx-pcai-20260307-commit-cluster-analysis", "commit": "69f987e", - "outputs": ["optimization.TODO.md (git-cluster repo, 5ea7492)", "14 semantic commits (a7b5dda..69f987e)"] + "outputs": [ + "optimization.TODO.md (git-cluster repo, 5ea7492)", + "14 semantic commits (a7b5dda..69f987e)" + ] }, { "goal": "CLAUDE.md audit: architecture tree, build components, test counts, CI workflows, CUDA targets", @@ -334,7 +544,12 @@ "completed": "2026-03-03", "context": "ctx-pcai-20260303-toolchain", "commit": "a8c2d00", - "outputs": ["upscale.rs", "NativeResolver.cs", "Install-LlvmFromSource.ps1", ".cargo/config.toml.template (x2)"] + "outputs": [ + "upscale.rs", + "NativeResolver.cs", + "Install-LlvmFromSource.ps1", + ".cargo/config.toml.template (x2)" + ] }, { "goal": "Centralized NativeResolver.cs for DLL path resolution", @@ -365,7 +580,11 @@ "completed": "2026-01-31", "context": "ctx-pcai-20260131-ffi", "commit": "pending", - "outputs": ["pcai_inference.dll (22MB)", "PcaiInference.psm1", "PcaiInterop.cs"] + "outputs": [ + "pcai_inference.dll (22MB)", + "PcaiInference.psm1", + "PcaiInterop.cs" + ] }, { "goal": "Add native inference tools to FunctionGemma routing", @@ -390,7 +609,11 @@ "completed": "2026-01-30", "context": "ctx-pcai-20260130-cuda", "commit": "pending", - "outputs": ["pcai_inference.dll", "ggml-cuda.dll", "llama.dll"] + "outputs": [ + "pcai_inference.dll", + "ggml-cuda.dll", + "llama.dll" + ] }, { "goal": "Fix llama-cpp-2 API compatibility (token_to_str)", @@ -488,7 +711,7 @@ ], "active_blockers": [ { - "blocker": "cuda:auto GPU fallback — RTX 5060 Ti (Blackwell SM 120) init fails", + "blocker": "cuda:auto GPU fallback \u2014 RTX 5060 Ti (Blackwell SM 120) init fails", "severity": "medium", "status": "fix in progress", "notes": "Driver updated to 582.41, toolkit 12.9. cudarc/candle cannot open RTX 5060 Ti; resolve_auto_cuda_device now falls back to next GPU. RTX 2000 Ada (SM 89) works fine.", @@ -524,7 +747,12 @@ "status": "clean", "warnings": 0, "tests": 61, - "features": ["ffi", "llamacpp", "mistralrs-backend", "server"], + "features": [ + "ffi", + "llamacpp", + "mistralrs-backend", + "server" + ], "backends": { "llamacpp": "available (requires CUDA+MSVC toolchain, artifact dir empty)", "mistralrs": "working (deployed, 84MB)" @@ -536,15 +764,25 @@ "llama.dll": "2MB (optional)" }, "ffi_exports": 15, - "deployed_to": ["bin/", ".pcai/build/artifacts/pcai-inference-ffi/"], - "torture_tests": {"total": 49, "pass": 43, "fail": 0, "skip": 6}, + "deployed_to": [ + "bin/", + ".pcai/build/artifacts/pcai-inference-ffi/" + ], + "torture_tests": { + "total": 49, + "pass": 43, + "fail": 0, + "skip": 6 + }, "last_verified": "2026-03-03T12:00:00Z" }, "pcai-media": { "status": "clean", "warnings": 0, "tests": 75, - "features": ["upscale"], + "features": [ + "upscale" + ], "ffi_exports": 16, "last_verified": "2026-03-03T12:00:00Z" }, @@ -590,8 +828,22 @@ "driver_max_cuda": "13.2", "driver_mismatch": false, "gpus": [ - {"name": "NVIDIA RTX 2000 Ada", "vram": "8GB", "compute": "8.9", "sm": "sm_89", "arch": "Ada Lovelace", "role": "inference/runtime (GPU 0)"}, - {"name": "NVIDIA GeForce RTX 5060 Ti", "vram": "16GB", "compute": "12.0", "sm": "sm_120", "arch": "Blackwell", "role": "training/QLoRA (GPU 1)"} + { + "name": "NVIDIA RTX 2000 Ada", + "vram": "8GB", + "compute": "8.9", + "sm": "sm_89", + "arch": "Ada Lovelace", + "role": "inference/runtime (GPU 0)" + }, + { + "name": "NVIDIA GeForce RTX 5060 Ti", + "vram": "16GB", + "compute": "12.0", + "sm": "sm_120", + "arch": "Blackwell", + "role": "training/QLoRA (GPU 1)" + } ], "device_detected": true, "tensor_ops_verified": true, @@ -599,4 +851,4 @@ "linker": "lld-link.exe (LLVM, preferred)", "config_generation": "CargoTools Initialize-ProjectCargoConfig" } -} +} \ No newline at end of file diff --git a/.claude/context/LATEST_CONTEXT.md b/.claude/context/LATEST_CONTEXT.md index 71f3a3cc..83760da4 100644 --- a/.claude/context/LATEST_CONTEXT.md +++ b/.claude/context/LATEST_CONTEXT.md @@ -1,21 +1,22 @@ # LATEST CONTEXT -**Pointer →** [`pcai-context-20260606-gitops-and-system-hardening.md`](pcai-context-20260606-gitops-and-system-hardening.md) -**ID:** `ctx-pcai-gitops-syshard-20260606` · **Date:** 2026-06-06 · **Branch:** main (PR-only ruleset enforced) +**Pointer →** [`pcai-context-20260718-ci-restoration.md`](pcai-context-20260718-ci-restoration.md) +**ID:** `ctx-pcai-ci-restoration-20260718` · **Date:** 2026-07-18 · **Branch:** `fix/ci-gate-pslint-clippy` → PR #58 (`MERGEABLE`, head `15f999a`) ## One-line state -Very long session. Shipped: SSH-signing standard + **194-repo branch protection** (PR-only/signed) + non-blocking -push monitors (`Tools/GitOps/`); GitHub account-picker fix; `.bak` profile-shim fix. Applied input-stack fixes -**T1/T2/F3** (touchpad device + directed power, MouseKeys). Modernized AI-Media deps (torch≥2.7+cu128, Python≥3.13/uv). -`vLLM`→Manual. `C:\codedev` confirmed NOT OneDrive-linked. Coordinated with **Codex** via agent-bus throughout. +Re-enabled GitHub Actions (off ~3 weeks); root-caused and fixed **7 pre-existing CI gate +failures**. Landed WIP (#57), aligned git/QA config + git-guard gate. PR #58 carries the +final two fixes: 19 clippy `-D warnings` lints + Pester `Run.Path`. Both clippy gates +verified exit 0 locally. Ledger: `Reports/ci-restoration-and-techdebt-20260718.md`. -## Resume here -1. **REBOOT** to activate T2; measure touchpad with `Watch-InputGlitch.ps1`. -2. **NVIDIA driver** — two-package manual fix (Enterprise 610.47 + Have-Disk GRD 610.47 for 5060 Ti; WU paused). - USER-DRIVEN — see `Reports/system-assessment-20260606/nvidia-driver-plan.md`. Clears Code 31 + cursor/DWM risk. -3. **Lenovo Vantage** updates: touchpad firmware **ds571229**, BIOS/EC, IR camera (GUI). -4. **Test** AI-Media deps: `cd AI-Media && uv sync`; verify `torch.cuda.get_device_capability()`. -5. **PC-AI CI is RED** (9 failures) + 3 Dependabot rust-openssl alerts — triage. -6. Optional optimizations (power plan / pagefile / Dell / BitLocker / ghost HID) — see context file. +## Resume here (awaiting user go-ahead — nothing auto-merged) +1. **Merge sequence:** #58 → #57 (rebase) → Dependabot safe batch #56/#50/#49/#52 → + #51 tokenizers & #53 windows 0.58→0.62 **gated behind a local `cargo build`**. +2. **65 pre-existing PS Unit-test failures** — surfaced (not caused) by the Pester fix; + attribution proven. Repair as separate `test/repair-unit-contracts` PR, LLM-Logging + first (21/21 broken). NOT started; needs scope confirmation (no silenced tests). +3. **Key fact:** CI is **not** a merge gate (ruleset has no required status checks). +4. **Latent:** `unused manifest key: package.lints` in 3 Cargo.toml; 126 TODO-ledger + items; Gemini/vLLM + google-access integrations remain design-stage backlog. -Full detail: the context file above + `machine-reliability.TODO.md` + `boot.TODO.md`. +Full detail: the context file above + `Reports/ci-restoration-and-techdebt-20260718.md`. diff --git a/.claude/context/pcai-context-20260718-ci-restoration.md b/.claude/context/pcai-context-20260718-ci-restoration.md new file mode 100644 index 00000000..93f88f6b --- /dev/null +++ b/.claude/context/pcai-context-20260718-ci-restoration.md @@ -0,0 +1,45 @@ +# PC-AI Context — CI Restoration & Tech-Debt Ledger + +**ID:** `ctx-pcai-ci-restoration-20260718` · **Date:** 2026-07-18 +**Branch:** `fix/ci-gate-pslint-clippy` → PR #58 (`MERGEABLE`) · **Head:** `15f999a` + +## One-line state +Re-enabled GitHub Actions (off ~3 weeks), root-caused **7 distinct pre-existing CI gate +failures** and fixed all. Landed WIP (PR #57), aligned git/QA config, provisioned +git-guard repo gate. PR #58 carries the final two fixes (19 clippy `-D warnings` lints + +Pester `Run.Path`). Full ledger: `Reports/ci-restoration-and-techdebt-20260718.md`. + +## What shipped (commits on fix/ci-gate-pslint-clippy) +- `67f6467` build: `--locked/--frozen` before cargo `--` separator +- `37993d5` build: route `--`-separated cargo cmds past pwsh -File wrapper +- `7e013fe` lint: PowerShell parse errors (`$var:` interp, malformed foreach) +- `18b6dd3` lint: 21 PSScriptAnalyzer findings (ShouldProcess/IEX/plaintext-pw) +- `ed4251d` qa: `.qa-gate.conf` git-guard repo Rust gate +- `c873fd2` deps: candle-core/transformers/flash-attn 0.9→0.10 (media tree) +- `7515e03` lint: 19 workspace clippy `-D warnings` (both gates exit 0, re-verified) +- `15f999a` test: Pester Run.Path → Tests/Unit,Tests/Integration + +## Verified green locally (exit 0) +- `clippy --all-targets --no-default-features --features server,ffi -- -D warnings` +- `clippy --workspace --all-targets --no-deps -- -D warnings -A clippy::type_complexity` + +## Key discoveries +- **CI is NOT a merge gate.** Ruleset `dtm-default-protection` (id 17356124) = signed + commits + PR (0 approvals), **no required_status_checks**. Red CI ≠ blocked. +- **65 pre-existing PS Unit-test failures** surfaced (not caused) by the Pester fix. + Attribution proven: identical counts repo-root vs Tests/ cwd; all use `$PSScriptRoot`. + Clusters: LLM-Logging 21/21, WSL vsock bridge 13/20, process-idle ~5. Tracked debt. +- **Stray corruption caught:** `Config/llm-config.json` was gutted (37 lines) by an + unknown prior process — reverted; HEAD intact. + +## Resume here (awaiting user go-ahead — nothing auto-merged) +1. **Merge sequence:** #58 → #57 (rebase) → Dependabot safe batch #56/#50/#49/#52 → + #51 tokenizers & #53 windows 0.58→0.62 **gated behind local `cargo build`**. +2. **65-test repair** as separate `test/repair-unit-contracts` PR — start with + LLM-Logging (whole file broken). NOT started; needs scope confirmation (no + reward-hacked/silenced tests). +3. **Latent:** `unused manifest key: package.lints` in 3 Cargo.toml (should be `[lints]`). +4. **Backlog (not started):** 126 TODO-ledger items; Gemini/vLLM + google-access + grand-integration asks remain design-stage. + +Full detail: `Reports/ci-restoration-and-techdebt-20260718.md` diff --git a/.qa-gate.conf b/.qa-gate.conf new file mode 100644 index 00000000..610e43f0 --- /dev/null +++ b/.qa-gate.conf @@ -0,0 +1,29 @@ +# git-guard repo-level QA gate — PC_AI (Rust-heavy Windows workstation agent). +# +# Format: flat KEY=VALUE, one per line, '#' comments (see the global default at +# ~/.git-hooks/common/qa-gate.conf / C:\codedev\git-guard\hooks\common\qa-gate.conf). +# Per-check values: block (refuse commit) | warn (print, proceed) | off (skip). +# A repo-root .qa-gate.conf OVERRIDES the global defaults; unset keys inherit them. +# +# NOTE: this file is INERT until git-guard is installed for the account +# (`sh C:\codedev\git-guard\install.sh` sets the global core.hooksPath). It does +# not change behavior on its own. The authoritative quality gate remains +# .github/workflows/ci.yml (fmt + clippy -D warnings + PS lint + tests); these +# keys mirror that Rust bar at commit time for contributors running git-guard, +# composing with the repo's existing lefthook.yml pre-commit hooks. + +qa.enabled=on + +# --- Rust (this repo is Rust-heavy: pcai_core 7-crate workspace + FunctionGemma) +# Enforce formatting and clippy at commit time. clippy is slower than fmt; relax +# to `warn` if per-commit latency becomes a problem (CI still blocks on it). +rust.fmt=block +rust.clippy=block + +# --- Structural / security rules (ast-grep). The Rust BLOCK trio +# (avoid-static-mut / no-glob-reexport / unsafe-with-panic) always blocks; keep +# the rest advisory to avoid false positives on generated/FFI code. +astgrep=warn + +# --- Filesystem hygiene (NukeNul reserved-name cleanup) stays mandatory. +nul_cleanup=block diff --git a/Build.ps1 b/Build.ps1 index c65ea087..aee88baf 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -801,14 +801,44 @@ function Add-CargoDependencyFlags { return $CargoArgs } - if ($script:DependencyStrategy -eq 'locked') { - return $CargoArgs + @('--locked') + $flag = switch ($script:DependencyStrategy) { + 'locked' { '--locked' } + 'frozen' { '--frozen' } + default { $null } } - if ($script:DependencyStrategy -eq 'frozen') { - return $CargoArgs + @('--frozen') + if (-not $flag) { + return $CargoArgs + } + + # Cargo-level flags MUST precede the '--' separator. Anything after '--' is + # forwarded verbatim to the underlying tool (rustc / clippy-driver), which + # rejects '--locked'/'--frozen' and fails the command in <1s. Commands like + # `clippy ... -- -D warnings` therefore need the flag inserted before '--', + # not appended. (Root cause of the green-CI-blocking Clippy failure.) + $sepIndex = [array]::IndexOf($CargoArgs, '--') + if ($sepIndex -gt 0) { + $before = @($CargoArgs[0..($sepIndex - 1)]) + $after = @($CargoArgs[$sepIndex..($CargoArgs.Count - 1)]) + return $before + @($flag) + $after } - return $CargoArgs + return $CargoArgs + @($flag) +} + +function Write-RustBuildFailureLog { + param([Parameter(Mandatory)][string]$LogFile) + + # cargo output is Tee'd to a log file and suppressed from the console during + # the run. On failure, surface the tail so CI consoles (and local runs) show + # the real compiler/clippy error instead of only "command N failed". + if (Test-Path $LogFile) { + $tail = Get-Content -LiteralPath $LogFile -Tail 60 -ErrorAction SilentlyContinue + if ($tail) { + Write-Host ' ---- cargo output (tail) ----' -ForegroundColor DarkYellow + $tail | ForEach-Object { Write-Host " $_" } + Write-Host " ---- (full log: $LogFile) ----" -ForegroundColor DarkYellow + } + } } function Invoke-RustBuildCommand { @@ -827,7 +857,16 @@ function Invoke-RustBuildCommand { $effectiveCargoArgs = Add-CargoDependencyFlags -CargoArgs $CargoArgs - if (Test-Path $script:RustBuildWrapper) { + # The Invoke-RustBuild.ps1 wrapper is spawned via `pwsh -File`, whose param + # binder consumes a bare `--` as the end-of-parameters token and then fails + # with "parameter name '' is ambiguous". Any cargo command that forwards + # tool args after `--` (e.g. `clippy ... -- -D warnings`) must therefore use + # the direct cargo path below, which splats the args as an array with no + # command-line reparsing. The wrapper's lld/sccache/preflight machinery is + # irrelevant to lint/quality commands anyway. + $hasToolSeparator = $effectiveCargoArgs -contains '--' + + if ((Test-Path $script:RustBuildWrapper) -and -not $hasToolSeparator) { $shellExe = Resolve-PowerShellExecutable $wrapperArgs = @('-NoProfile', '-File', $script:RustBuildWrapper, '-Path', $Path, '-CargoArgs') + $effectiveCargoArgs @@ -842,7 +881,9 @@ function Invoke-RustBuildCommand { } & $shellExe @wrapperArgs 2>&1 | Tee-Object -FilePath $LogFile | Out-Null - return ($LASTEXITCODE -eq 0) + $succeeded = ($LASTEXITCODE -eq 0) + if (-not $succeeded) { Write-RustBuildFailureLog -LogFile $LogFile } + return $succeeded } Push-Location $Path @@ -865,13 +906,16 @@ function Invoke-RustBuildCommand { $effectivePreflightArgs = Add-CargoDependencyFlags -CargoArgs $preflightArgs & cargo @effectivePreflightArgs 2>&1 | Tee-Object -FilePath $LogFile | Out-Null if ($LASTEXITCODE -ne 0) { + Write-RustBuildFailureLog -LogFile $LogFile return $false } } } & cargo @effectiveCargoArgs 2>&1 | Tee-Object -FilePath $LogFile | Out-Null - return ($LASTEXITCODE -eq 0) + $succeeded = ($LASTEXITCODE -eq 0) + if (-not $succeeded) { Write-RustBuildFailureLog -LogFile $LogFile } + return $succeeded } finally { Pop-Location } diff --git a/Native/pcai_core/Cargo.lock b/Native/pcai_core/Cargo.lock index 41113b45..e6eed654 100644 --- a/Native/pcai_core/Cargo.lock +++ b/Native/pcai_core/Cargo.lock @@ -645,6 +645,18 @@ dependencies = [ "half", ] +[[package]] +name = "candle-flash-attn" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12512cf8e706744642e9a8579305a6ed1e44a0c636ce20c416cd5c519de19b7d" +dependencies = [ + "anyhow", + "candle-core 0.10.2", + "cudaforge", + "half", +] + [[package]] name = "candle-flash-attn-build" version = "0.9.2" @@ -723,6 +735,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "candle-transformers" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f59d08c89e9f4af9c464e2f3a8e16199e7cc601e6f34538c2cfbb42b623b1783" +dependencies = [ + "byteorder", + "candle-core 0.10.2", + "candle-nn 0.10.2", + "fancy-regex 0.17.0", + "num-traits", + "rand 0.9.3", + "rayon", + "serde", + "serde_json", + "serde_plain", + "tracing", +] + [[package]] name = "candle-ug" version = "0.9.2" @@ -4236,9 +4267,9 @@ version = "0.1.0" dependencies = [ "anyhow", "axum", - "candle-core 0.9.2", + "candle-core 0.10.2", "candle-nn 0.10.2", - "candle-transformers", + "candle-transformers 0.10.2", "hf-hub 0.5.0", "image", "memmap2 0.9.10", @@ -4262,10 +4293,10 @@ name = "pcai-media-model" version = "0.1.0" dependencies = [ "anyhow", - "candle-core 0.9.2", - "candle-flash-attn", + "candle-core 0.10.2", + "candle-flash-attn 0.10.2", "candle-nn 0.10.2", - "candle-transformers", + "candle-transformers 0.10.2", "serde", "serde_json", ] @@ -5148,9 +5179,9 @@ version = "0.1.0" dependencies = [ "anyhow", "candle-core 0.9.2", - "candle-flash-attn", + "candle-flash-attn 0.9.2", "candle-nn 0.9.2", - "candle-transformers", + "candle-transformers 0.9.2", "cudarc 0.19.4", "minijinja", "qlora-rs", @@ -5168,7 +5199,7 @@ dependencies = [ "anyhow", "candle-core 0.9.2", "candle-nn 0.9.2", - "candle-transformers", + "candle-transformers 0.9.2", "clap", "itertools 0.14.0", "memmap2 0.9.10", @@ -6233,7 +6264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys 0.61.2", diff --git a/Native/pcai_core/pcai_core_lib/src/hash.rs b/Native/pcai_core/pcai_core_lib/src/hash.rs index 6c278208..1fc9065b 100644 --- a/Native/pcai_core/pcai_core_lib/src/hash.rs +++ b/Native/pcai_core/pcai_core_lib/src/hash.rs @@ -126,7 +126,7 @@ pub fn find_duplicates( } // Sort by wasted bytes descending - results.sort_by(|a, b| b.wasted_bytes.cmp(&a.wasted_bytes)); + results.sort_by_key(|r| std::cmp::Reverse(r.wasted_bytes)); Ok(DuplicateResult { status: "Success".to_string(), diff --git a/Native/pcai_core/pcai_core_lib/src/performance/disk.rs b/Native/pcai_core/pcai_core_lib/src/performance/disk.rs index bb01bc73..b12f7c74 100644 --- a/Native/pcai_core/pcai_core_lib/src/performance/disk.rs +++ b/Native/pcai_core/pcai_core_lib/src/performance/disk.rs @@ -275,7 +275,7 @@ pub fn get_disk_usage(root_path: &str, top_n: usize) -> io::Result<(DiskUsageSta }) .collect(); - entries.sort_by(|a, b| b.size_bytes.cmp(&a.size_bytes)); + entries.sort_by_key(|e| std::cmp::Reverse(e.size_bytes)); entries.truncate(top_n); Ok((stats, entries)) diff --git a/Native/pcai_core/pcai_core_lib/src/performance/optimizer.rs b/Native/pcai_core/pcai_core_lib/src/performance/optimizer.rs index ca4ed376..01965b27 100644 --- a/Native/pcai_core/pcai_core_lib/src/performance/optimizer.rs +++ b/Native/pcai_core/pcai_core_lib/src/performance/optimizer.rs @@ -737,8 +737,10 @@ mod tests { #[test] fn test_memory_pressure_to_json_label() { - let mut report = MemoryPressureReport::default(); - report.status = PcaiStatus::Success; + let mut report = MemoryPressureReport { + status: PcaiStatus::Success, + ..Default::default() + }; report.pressure_level = 0; assert_eq!(memory_pressure_to_json(&report).pressure_label, "low"); diff --git a/Native/pcai_core/pcai_core_lib/src/performance/process.rs b/Native/pcai_core/pcai_core_lib/src/performance/process.rs index 0bcb0d7f..7b3fa10a 100644 --- a/Native/pcai_core/pcai_core_lib/src/performance/process.rs +++ b/Native/pcai_core/pcai_core_lib/src/performance/process.rs @@ -263,7 +263,7 @@ pub fn get_top_processes(top_n: usize, sort_by: &str) -> (ProcessStats, Vec processes.sort_by(|a, b| b.memory_bytes.cmp(&a.memory_bytes)), + _ => processes.sort_by_key(|p| std::cmp::Reverse(p.memory_bytes)), } processes.truncate(top_n); diff --git a/Native/pcai_core/pcai_core_lib/src/preflight/vram_audit.rs b/Native/pcai_core/pcai_core_lib/src/preflight/vram_audit.rs index e892f104..1a3887ff 100644 --- a/Native/pcai_core/pcai_core_lib/src/preflight/vram_audit.rs +++ b/Native/pcai_core/pcai_core_lib/src/preflight/vram_audit.rs @@ -140,7 +140,7 @@ pub fn vram_snapshot_all() -> Result> { .collect(); // Sort by VRAM usage descending so top consumers appear first. - processes.sort_by(|a, b| b.used_mb.cmp(&a.used_mb)); + processes.sort_by_key(|p| std::cmp::Reverse(p.used_mb)); snapshots.push(GpuVramSnapshot { index: idx, diff --git a/Native/pcai_core/pcai_inference/src/backends/mod.rs b/Native/pcai_core/pcai_inference/src/backends/mod.rs index 9b5b1ccd..6ee0e2f7 100644 --- a/Native/pcai_core/pcai_inference/src/backends/mod.rs +++ b/Native/pcai_core/pcai_inference/src/backends/mod.rs @@ -207,10 +207,7 @@ mod tests { fn test_backend_type_no_features() { // With no backend features enabled, BackendType has no variants, // so we can't construct one. The enum is effectively empty. - // This test verifies the module compiles correctly without backends. - assert!( - true, - "BackendType correctly has no constructible variants without features" - ); + // This test verifies the module compiles correctly without backends — + // reaching this point at runtime is the assertion. } } diff --git a/Native/pcai_core/pcai_inference/tests/backend_selection_test.rs b/Native/pcai_core/pcai_inference/tests/backend_selection_test.rs index fcf4fbec..5dd5cd02 100644 --- a/Native/pcai_core/pcai_inference/tests/backend_selection_test.rs +++ b/Native/pcai_core/pcai_inference/tests/backend_selection_test.rs @@ -1,6 +1,6 @@ //! Unit tests for backend selection logic -use pcai_inference::backends::{BackendType, FinishReason, GenerateRequest, GenerateResponse}; +use pcai_inference_lib::backends::{FinishReason, GenerateRequest, GenerateResponse}; #[test] fn test_generate_request_defaults() { @@ -61,8 +61,8 @@ fn test_generate_response_creation() { #[cfg(feature = "llamacpp")] mod llamacpp_tests { - use pcai_inference::backends::llamacpp::LlamaCppBackend; - use pcai_inference::backends::InferenceBackend; + use pcai_inference_lib::backends::llamacpp::LlamaCppBackend; + use pcai_inference_lib::backends::InferenceBackend; #[test] fn test_backend_creation() { @@ -80,7 +80,7 @@ mod llamacpp_tests { #[test] fn test_backend_type_creation() { - use pcai_inference::backends::BackendType; + use pcai_inference_lib::backends::BackendType; let backend = BackendType::LlamaCpp.create(); assert!(backend.is_ok(), "Should create llamacpp backend"); @@ -90,8 +90,8 @@ mod llamacpp_tests { #[cfg(feature = "mistralrs-backend")] mod mistralrs_tests { - use pcai_inference::backends::mistralrs::MistralRsBackend; - use pcai_inference::backends::InferenceBackend; + use pcai_inference_lib::backends::mistralrs::MistralRsBackend; + use pcai_inference_lib::backends::InferenceBackend; #[test] fn test_backend_creation() { @@ -102,7 +102,7 @@ mod mistralrs_tests { #[test] fn test_backend_type_creation() { - use pcai_inference::backends::BackendType; + use pcai_inference_lib::backends::BackendType; let backend = BackendType::MistralRs.create(); assert!(backend.is_ok(), "Should create mistralrs backend"); @@ -112,18 +112,17 @@ mod mistralrs_tests { #[test] fn test_backend_trait_object_safety() { - // Verify that InferenceBackend can be used as trait object - use pcai_inference::backends::InferenceBackend; + // Verify that InferenceBackend can be used as a trait object. + // This test passes if it compiles. + use pcai_inference_lib::backends::InferenceBackend; - fn assert_object_safe(_: &dyn InferenceBackend) {} - - // This test passes if it compiles + let _: Option<&dyn InferenceBackend> = None; } #[cfg(all(feature = "llamacpp", feature = "mistralrs-backend"))] #[test] fn test_backend_switching() { - use pcai_inference::backends::BackendType; + use pcai_inference_lib::backends::BackendType; let llamacpp = BackendType::LlamaCpp.create().expect("backend creation should succeed"); let mistralrs = BackendType::MistralRs diff --git a/Native/pcai_core/pcai_inference/tests/common/mod.rs b/Native/pcai_core/pcai_inference/tests/common/mod.rs index 917ff639..e07dc936 100644 --- a/Native/pcai_core/pcai_inference/tests/common/mod.rs +++ b/Native/pcai_core/pcai_inference/tests/common/mod.rs @@ -92,6 +92,10 @@ fn find_gguf_in_dir(dir: &PathBuf) -> Option { /// Get the model path from environment or panic with helpful message /// /// Use this in tests that require a real model file. +// justification: this shared test helper is only called from the feature-gated +// (llamacpp / mistralrs-backend) integration tests, so it reads as dead code +// when the crate is compiled under the default feature set. +#[allow(dead_code, reason = "used only by feature-gated integration tests")] pub fn require_test_model() -> PathBuf { find_test_model().unwrap_or_else(|| { panic!( diff --git a/Native/pcai_core/pcai_inference/tests/ffi/concurrent_access.rs b/Native/pcai_core/pcai_inference/tests/ffi/concurrent_access.rs index 9184e9e2..4b9cd53e 100644 --- a/Native/pcai_core/pcai_inference/tests/ffi/concurrent_access.rs +++ b/Native/pcai_core/pcai_inference/tests/ffi/concurrent_access.rs @@ -10,7 +10,7 @@ use std::ffi::CString; use std::sync::Arc; use std::thread; -use pcai_inference::ffi::{pcai_init, pcai_last_error, pcai_shutdown}; +use pcai_inference_lib::ffi::{pcai_init, pcai_last_error, pcai_shutdown}; /// Test that concurrent shutdown calls don't crash #[test] @@ -118,7 +118,7 @@ fn test_rapid_init_shutdown_cycling() { #[cfg(feature = "llamacpp")] mod llamacpp_concurrent_tests { use super::*; - use pcai_inference::ffi::pcai_generate; + use pcai_inference_lib::ffi::pcai_generate; use std::ffi::CString; use std::ptr; diff --git a/Native/pcai_core/pcai_inference/tests/ffi/error_propagation.rs b/Native/pcai_core/pcai_inference/tests/ffi/error_propagation.rs index e3ddfbe5..67423fcd 100644 --- a/Native/pcai_core/pcai_inference/tests/ffi/error_propagation.rs +++ b/Native/pcai_core/pcai_inference/tests/ffi/error_propagation.rs @@ -10,7 +10,7 @@ use std::ffi::{CStr, CString}; -use pcai_inference::ffi::{ +use pcai_inference_lib::ffi::{ pcai_init, pcai_last_error, pcai_last_error_code, pcai_shutdown, pcai_version, PcaiErrorCode, }; @@ -50,7 +50,7 @@ fn test_not_initialized_error() { #[cfg(feature = "ffi")] { - use pcai_inference::ffi::pcai_load_model; + use pcai_inference_lib::ffi::pcai_load_model; let result = pcai_load_model(path.as_ptr(), 0); assert_eq!(result, -1); @@ -72,7 +72,7 @@ fn test_not_initialized_error() { #[cfg(feature = "llamacpp")] mod llamacpp_error_tests { use super::*; - use pcai_inference::ffi::{pcai_generate, pcai_load_model}; + use pcai_inference_lib::ffi::{pcai_generate, pcai_load_model}; /// Test error for model not found #[test] @@ -251,7 +251,7 @@ fn test_error_codes() { #[cfg(feature = "llamacpp")] mod error_code_tests { use super::*; - use pcai_inference::ffi::{pcai_generate, pcai_load_model}; + use pcai_inference_lib::ffi::{pcai_generate, pcai_load_model}; /// Test NotInitialized error code #[test] @@ -313,7 +313,7 @@ mod error_code_tests { /// Test prompt length validation #[test] fn test_prompt_too_large() { - use pcai_inference::ffi::pcai_generate; + use pcai_inference_lib::ffi::pcai_generate; pcai_shutdown(); diff --git a/Native/pcai_core/pcai_inference/tests/ffi/memory_safety.rs b/Native/pcai_core/pcai_inference/tests/ffi/memory_safety.rs index 04378a8f..c6e2ed17 100644 --- a/Native/pcai_core/pcai_inference/tests/ffi/memory_safety.rs +++ b/Native/pcai_core/pcai_inference/tests/ffi/memory_safety.rs @@ -11,7 +11,7 @@ use std::ffi::{CStr, CString}; use std::ptr; -use pcai_inference::ffi::{pcai_free_string, pcai_init, pcai_last_error, pcai_shutdown, PcaiErrorCode}; +use pcai_inference_lib::ffi::{pcai_free_string, pcai_init, pcai_last_error, pcai_shutdown, PcaiErrorCode}; /// Test that pcai_free_string handles null safely #[test] @@ -118,7 +118,7 @@ fn test_utf8_error_handling() { #[cfg(feature = "llamacpp")] mod llamacpp_memory_tests { use super::*; - use pcai_inference::ffi::{pcai_generate, pcai_load_model}; + use pcai_inference_lib::ffi::{pcai_generate, pcai_load_model}; /// Test that generate with null prompt returns null safely #[test] diff --git a/Native/pcai_core/pcai_inference/tests/integration_test.rs b/Native/pcai_core/pcai_inference/tests/integration_test.rs index 4723df30..475b7d91 100644 --- a/Native/pcai_core/pcai_inference/tests/integration_test.rs +++ b/Native/pcai_core/pcai_inference/tests/integration_test.rs @@ -30,7 +30,7 @@ //! Alternatively, install a model via Ollama or LM Studio, and the tests //! will automatically discover it. -use pcai_inference::{backends::*, config::*, Error, Result}; +use pcai_inference_lib::{backends::*, config::*, Error, Result}; #[cfg(feature = "ffi")] use std::ffi::CString; @@ -44,7 +44,7 @@ mod common; /// Macro to skip tests that require a real model file /// /// Usage: -/// ``` +/// ```ignore /// #[test] /// fn test_with_model() { /// require_model!(); @@ -207,7 +207,7 @@ fn test_error_types() { #[cfg(feature = "llamacpp")] #[test] fn test_llamacpp_backend_creation() { - use pcai_inference::backends::llamacpp::LlamaCppBackend; + use pcai_inference_lib::backends::llamacpp::LlamaCppBackend; let backend = LlamaCppBackend::new(); assert_eq!(backend.backend_name(), "llama.cpp"); @@ -217,7 +217,7 @@ fn test_llamacpp_backend_creation() { #[cfg(feature = "llamacpp")] #[test] fn test_llamacpp_backend_with_config() { - use pcai_inference::backends::llamacpp::LlamaCppBackend; + use pcai_inference_lib::backends::llamacpp::LlamaCppBackend; let backend = LlamaCppBackend::with_config(32, 4096, 512); assert_eq!(backend.backend_name(), "llama.cpp"); @@ -227,7 +227,7 @@ fn test_llamacpp_backend_with_config() { #[cfg(feature = "mistralrs-backend")] #[test] fn test_mistralrs_backend_creation() { - use pcai_inference::backends::mistralrs::MistralRsBackend; + use pcai_inference_lib::backends::mistralrs::MistralRsBackend; let backend = MistralRsBackend::new(); assert_eq!(backend.backend_name(), "mistral.rs"); @@ -321,7 +321,7 @@ async fn test_backend_generate_without_model_fails() { #[cfg(feature = "llamacpp")] #[tokio::test] async fn test_llamacpp_load_nonexistent_file_fails() { - use pcai_inference::backends::llamacpp::LlamaCppBackend; + use pcai_inference_lib::backends::llamacpp::LlamaCppBackend; let mut backend = LlamaCppBackend::new(); let result = backend.load_model("/nonexistent/model.gguf").await; @@ -331,7 +331,7 @@ async fn test_llamacpp_load_nonexistent_file_fails() { #[cfg(feature = "mistralrs-backend")] #[tokio::test] async fn test_mistralrs_load_nonexistent_file_fails() { - use pcai_inference::backends::mistralrs::MistralRsBackend; + use pcai_inference_lib::backends::mistralrs::MistralRsBackend; let mut backend = MistralRsBackend::new(); let result = backend.load_model("/nonexistent/model.gguf").await; @@ -345,7 +345,7 @@ async fn test_mistralrs_load_nonexistent_file_fails() { #[cfg(feature = "llamacpp")] #[tokio::test] async fn test_llamacpp_generate_with_model() { - use pcai_inference::backends::llamacpp::LlamaCppBackend; + use pcai_inference_lib::backends::llamacpp::LlamaCppBackend; require_model!(); @@ -375,7 +375,7 @@ async fn test_llamacpp_generate_with_model() { #[cfg(feature = "mistralrs-backend")] #[tokio::test] async fn test_mistralrs_generate_with_model() { - use pcai_inference::backends::mistralrs::MistralRsBackend; + use pcai_inference_lib::backends::mistralrs::MistralRsBackend; require_model!(); @@ -408,7 +408,7 @@ async fn test_mistralrs_generate_with_model() { #[cfg(feature = "ffi")] mod ffi_tests { use super::*; - use pcai_inference::ffi::*; + use pcai_inference_lib::ffi::*; #[test] fn test_ffi_init_null_backend() { @@ -554,7 +554,7 @@ mod ffi_tests { #[test] fn test_ffi_last_error_no_error() { - use pcai_inference::ffi::pcai_last_error; + use pcai_inference_lib::ffi::pcai_last_error; // Clear any previous errors by calling shutdown pcai_shutdown(); @@ -618,7 +618,7 @@ mod ffi_tests { #[tokio::test] #[ignore] async fn stress_test_sequential_generations() { - use pcai_inference::backends::llamacpp::LlamaCppBackend; + use pcai_inference_lib::backends::llamacpp::LlamaCppBackend; require_model!(); @@ -653,7 +653,7 @@ async fn stress_test_backend_switching() { // Test llamacpp { - use pcai_inference::backends::llamacpp::LlamaCppBackend; + use pcai_inference_lib::backends::llamacpp::LlamaCppBackend; let mut backend = LlamaCppBackend::new(); backend .load_model(&model_path) @@ -674,7 +674,7 @@ async fn stress_test_backend_switching() { // Test mistralrs { - use pcai_inference::backends::mistralrs::MistralRsBackend; + use pcai_inference_lib::backends::mistralrs::MistralRsBackend; let mut backend = MistralRsBackend::new(); backend .load_model(&model_path) diff --git a/Native/pcai_core/pcai_media/Cargo.toml b/Native/pcai_core/pcai_media/Cargo.toml index 05f792d3..389a500d 100644 --- a/Native/pcai_core/pcai_media/Cargo.toml +++ b/Native/pcai_core/pcai_media/Cargo.toml @@ -20,9 +20,9 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tracing = "0.1" -candle-core = { version = "0.9" } +candle-core = { version = "0.10" } candle-nn = "0.10" -candle-transformers = "0.9" +candle-transformers = "0.10" safetensors = "0.7" tokenizers = "0.22" image = "0.25" diff --git a/Native/pcai_core/pcai_media/examples/gen_image.rs b/Native/pcai_core/pcai_media/examples/gen_image.rs index 3b29ee97..f48d79a0 100644 --- a/Native/pcai_core/pcai_media/examples/gen_image.rs +++ b/Native/pcai_core/pcai_media/examples/gen_image.rs @@ -39,6 +39,7 @@ fn main() -> Result<()> { temperature: 1.0, parallel_size: 1, gpu_layers: 0, + ..Default::default() }; // Load model diff --git a/Native/pcai_core/pcai_media/src/generate.rs b/Native/pcai_core/pcai_media/src/generate.rs index a172fd57..32f76777 100644 --- a/Native/pcai_core/pcai_media/src/generate.rs +++ b/Native/pcai_core/pcai_media/src/generate.rs @@ -30,7 +30,7 @@ use anyhow::{Context, Result}; use candle_core::{DType, Device, IndexOp, Tensor}; use candle_nn::{VarBuilder, VarMap}; -use image::{ImageBuffer, Rgb}; +use image::{ImageBuffer, RgbImage}; use std::path::PathBuf; use std::time::Instant; @@ -479,7 +479,7 @@ impl GenerationPipeline { /// # Errors /// /// Returns an error on any tensor operation failure or tokenization error. - pub fn generate(&self, prompt: &str) -> Result, Vec>> { + pub fn generate(&self, prompt: &str) -> Result { self.generate_with_overrides(prompt, None, None) } @@ -526,7 +526,7 @@ impl GenerationPipeline { prompt: &str, cfg_scale: Option, temperature: Option, - ) -> Result<(ImageBuffer, Vec>, GenerationTelemetry)> { + ) -> Result<(RgbImage, GenerationTelemetry)> { self.generate_inner(prompt, cfg_scale, temperature) } @@ -547,7 +547,7 @@ impl GenerationPipeline { prompt: &str, cfg_scale: Option, temperature: Option, - ) -> Result, Vec>> { + ) -> Result { let (image, _telemetry) = self.generate_inner(prompt, cfg_scale, temperature)?; Ok(image) } @@ -562,7 +562,7 @@ impl GenerationPipeline { prompt: &str, cfg_scale: Option, temperature: Option, - ) -> Result<(ImageBuffer, Vec>, GenerationTelemetry)> { + ) -> Result<(RgbImage, GenerationTelemetry)> { let guidance_scale = cfg_scale.unwrap_or(self.config.guidance_scale); let temperature_val = temperature.unwrap_or(self.config.temperature); let parallel_size = self.config.parallel_size; @@ -1163,7 +1163,7 @@ impl GenerationPipeline { // rejected position; it is pushed directly into `generated`. let mut rejection_token: Option<(u32, Tensor)> = None; - 'accept_loop: for j in 0..k { + 'accept_loop: for (j, &draft_tok) in draft_tokens.iter().enumerate().take(k) { // Extract verify hidden at position j: [B, K, H] → [B, H] let verify_hidden_j = verify_hidden_batch .i((.., j, ..)) @@ -1183,7 +1183,7 @@ impl GenerationPipeline { pos + j, )?; - if draft_tokens[j] == verify_tok { + if draft_tok == verify_tok { accept_count += 1; // Keep going — may accept more tokens. } else { @@ -1305,61 +1305,6 @@ impl GenerationPipeline { Ok(tokens[0]) } - /// Greedy (argmax) token selection from a `[B, hidden_size]` hidden state. - /// - /// Used in the verify phase to compare draft tokens against the full-depth - /// model's greedy prediction without stochastic noise. Returns the greedy - /// token for the first batch element after optional CFG blending. - /// - /// # Errors - /// - /// Returns an error on any candle operation failure. - fn greedy_from_hidden( - &self, - hidden: &Tensor, - use_cfg: bool, - batch_size: usize, - guidance_scale: f64, - ) -> Result { - let img_logits = self - .model - .project_to_image_vocab(&hidden.unsqueeze(1).context("greedy_from_hidden: unsqueeze failed")?) - .context("greedy_from_hidden: project_to_image_vocab")? - .squeeze(1) - .context("greedy_from_hidden: squeeze")?; - - let logits = if use_cfg && batch_size >= 2 { - let cond = img_logits - .i(0_usize) - .context("greedy_from_hidden: cond slice")? - .unsqueeze(0) - .context("greedy_from_hidden: cond unsqueeze")?; - let uncond = img_logits - .i(1_usize) - .context("greedy_from_hidden: uncond slice")? - .unsqueeze(0) - .context("greedy_from_hidden: uncond unsqueeze")?; - let diff = (&cond - &uncond).context("greedy_from_hidden: CFG subtract failed")?; - (&uncond + (diff * guidance_scale).context("greedy_from_hidden: CFG scale failed")?) - .context("greedy_from_hidden: CFG add failed")? - } else { - img_logits - .i(0_usize) - .context("greedy_from_hidden: img_logits slice")? - .unsqueeze(0) - .context("greedy_from_hidden: img_logits unsqueeze")? - }; - - let idx = logits - .argmax(candle_core::D::Minus1) - .context("greedy_from_hidden: argmax")? - .i(0_usize) - .context("greedy_from_hidden: extract index")? - .to_scalar::() - .context("greedy_from_hidden: to_scalar")?; - Ok(idx) - } - /// Embed a single image token through `gen_embed` + `gen_aligner`. /// /// Returns a `[batch_size, 1, hidden_size]` tensor on `self.device`. @@ -1398,7 +1343,7 @@ impl GenerationPipeline { /// /// Returns an error if the tensor has wrong number of dimensions, wrong /// channel count, or any candle operation fails. -pub fn tensor_to_image(tensor: &Tensor) -> Result, Vec>> { +pub fn tensor_to_image(tensor: &Tensor) -> Result { // Validate shape [C, H, W]. let dims = tensor.dims(); anyhow::ensure!(dims.len() == 3, "expected 3D tensor [C, H, W], got {}D", dims.len()); @@ -1680,40 +1625,6 @@ mod tests { assert!(tensor_to_image(&tensor).is_err()); } - /// `tensor_to_image` must preserve pixel values during [C, H, W] to [H, W, C] permutation. - #[test] - fn test_tensor_to_image_pixel_content() { - // Create a 3x2x2 [C, H, W] tensor with known values. - let data = vec![ - // Channel 0 (R): - 10u8, 20, 30, 40, // Channel 1 (G): - 50u8, 60, 70, 80, // Channel 2 (B): - 90u8, 100, 110, 120, - ]; - - let tensor = Tensor::from_vec(data, (3_usize, 2_usize, 2_usize), &Device::Cpu).unwrap(); - let img = tensor_to_image(&tensor).expect("tensor_to_image should succeed"); - - assert_eq!(img.width(), 2); - assert_eq!(img.height(), 2); - - // Verify pixel (x, y) = (0, 0) - assert_eq!(img.get_pixel(0, 0).0, [10, 50, 90]); - // Verify pixel (x, y) = (1, 0) - assert_eq!(img.get_pixel(1, 0).0, [20, 60, 100]); - // Verify pixel (x, y) = (0, 1) - assert_eq!(img.get_pixel(0, 1).0, [30, 70, 110]); - // Verify pixel (x, y) = (1, 1) - assert_eq!(img.get_pixel(1, 1).0, [40, 80, 120]); - } - - /// `tensor_to_image` must return an error for non-U8 tensors. - #[test] - fn test_tensor_to_image_wrong_dtype() { - let tensor = Tensor::zeros((3_usize, 8_usize, 8_usize), DType::F32, &Device::Cpu).unwrap(); - assert!(tensor_to_image(&tensor).is_err()); - } - /// `rand_val` must produce values in `[0, 1)`. #[test] fn test_rand_val_range() { @@ -1779,7 +1690,7 @@ mod tests { #[test] fn test_cpu_multinomial_batch() { // 3 rows, 5 vocab elements — uniform distribution. - let data: Vec = vec![0.2_f32, 0.2, 0.2, 0.2, 0.2].repeat(3); + let data: Vec = [0.2_f32, 0.2, 0.2, 0.2, 0.2].repeat(3); let probs = Tensor::from_vec(data, (3_usize, 5_usize), &Device::Cpu).unwrap(); let tokens = cpu_multinomial_sample(&probs).unwrap(); assert_eq!(tokens.len(), 3); diff --git a/Native/pcai_core/pcai_media/src/hub.rs b/Native/pcai_core/pcai_media/src/hub.rs index 8d1a4c73..4cbf3256 100644 --- a/Native/pcai_core/pcai_media/src/hub.rs +++ b/Native/pcai_core/pcai_media/src/hub.rs @@ -405,7 +405,7 @@ mod tests { let mut tensors = HashMap::new(); tensors.insert("dummy_tensor".to_string(), tensor); - safetensors::serialize_to_file(&tensors, &None, &file_path).expect("serialize"); + safetensors::serialize_to_file(&tensors, None, &file_path).expect("serialize"); let archive = open_safetensors(&[file_path]).expect("open_safetensors"); assert!(archive.tensors().iter().any(|(name, _)| name == "dummy_tensor")); @@ -425,13 +425,13 @@ mod tests { let tensor1 = TensorView::new(Dtype::F32, vec![4], &data1).unwrap(); let mut tensors1 = HashMap::new(); tensors1.insert("tensor_part_1".to_string(), tensor1); - safetensors::serialize_to_file(&tensors1, &None, &path1).expect("serialize path1"); + safetensors::serialize_to_file(&tensors1, None, &path1).expect("serialize path1"); let data2: Vec = vec![1; 16]; let tensor2 = TensorView::new(Dtype::F32, vec![4], &data2).unwrap(); let mut tensors2 = HashMap::new(); tensors2.insert("tensor_part_2".to_string(), tensor2); - safetensors::serialize_to_file(&tensors2, &None, &path2).expect("serialize path2"); + safetensors::serialize_to_file(&tensors2, None, &path2).expect("serialize path2"); let archive = open_safetensors(&[path1, path2]).expect("open_safetensors multi"); diff --git a/Native/pcai_core/pcai_media/src/understand.rs b/Native/pcai_core/pcai_media/src/understand.rs index 603476d2..cca46d4e 100644 --- a/Native/pcai_core/pcai_media/src/understand.rs +++ b/Native/pcai_core/pcai_media/src/understand.rs @@ -407,8 +407,6 @@ impl UnderstandingPipeline { .map_err(|e| anyhow::anyhow!("prefill forward_input_embed failed: {e}"))?; // prefill_logits: [1, vocab_size] - let mut pos = combined_len; - // ── 9. Autoregressive text generation ──────────────────────────────── // // Correct decode loop for understanding: @@ -435,7 +433,7 @@ impl UnderstandingPipeline { generated_ids.push(first_token); let mut current_token = first_token; - for step in 1..max_tokens { + for (pos, step) in (combined_len..).zip(1..max_tokens) { // A. Embed the previously sampled token → [1, 1, hidden_size] let token_tensor = Tensor::from_slice(&[current_token], (1_usize, 1_usize), embed_device) .with_context(|| format!("step {step}: failed to build token tensor"))?; @@ -451,7 +449,6 @@ impl UnderstandingPipeline { .llama .forward_input_embed(&token_embed, pos, &mut cache) .map_err(|e| anyhow::anyhow!("step {step}: forward_input_embed failed: {e}"))?; - pos += 1; // C. Apply repetition penalty: reduce logits for previously generated tokens. // This prevents the model from falling into repetition loops (e.g., diff --git a/Native/pcai_core/pcai_media_model/Cargo.toml b/Native/pcai_core/pcai_media_model/Cargo.toml index 76b1e65e..1ca54aa0 100644 --- a/Native/pcai_core/pcai_media_model/Cargo.toml +++ b/Native/pcai_core/pcai_media_model/Cargo.toml @@ -8,10 +8,10 @@ lints.workspace = true [dependencies] anyhow = "1.0" -candle-core = { version = "0.9" } +candle-core = { version = "0.10" } candle-nn = "0.10" -candle-transformers = "0.9" -candle-flash-attn = { version = "0.9", optional = true } +candle-transformers = "0.10" +candle-flash-attn = { version = "0.10", optional = true } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/Native/pcai_core/pcai_media_model/src/janus_llama.rs b/Native/pcai_core/pcai_media_model/src/janus_llama.rs index 1ff5e683..0926a453 100644 --- a/Native/pcai_core/pcai_media_model/src/janus_llama.rs +++ b/Native/pcai_core/pcai_media_model/src/janus_llama.rs @@ -1216,7 +1216,7 @@ mod tests { assert_eq!(cache.seq_len(), 0, "fresh cache should be empty"); // 2 layers × 2 (K+V) × 1 × 4 × 32 × 16 × 4 bytes - let expected = 2 * 2 * 1 * 4 * 32 * 16 * 4; + let expected = 2 * 2 * 4 * 32 * 16 * 4; assert_eq!(cache.allocated_bytes(), expected); } diff --git a/Native/pcai_core/pcai_media_model/src/tensor_utils.rs b/Native/pcai_core/pcai_media_model/src/tensor_utils.rs index 80f47a09..f36654f1 100644 --- a/Native/pcai_core/pcai_media_model/src/tensor_utils.rs +++ b/Native/pcai_core/pcai_media_model/src/tensor_utils.rs @@ -209,14 +209,16 @@ mod tests { assert_eq!(got, expected, "mask[{i}][{j}] expected {expected} got {got}"); } } - // Spot-check: diagonal must be 0. - assert_eq!(data[0 * size + 0], 0); - assert_eq!(data[1 * size + 1], 0); + // Spot-check via a `(row, col)` indexer into the flattened `size × size` mask. + let at = |row: usize, col: usize| data[row * size + col]; + // Diagonal must be 0. + assert_eq!(at(0, 0), 0); + assert_eq!(at(1, 1), 0); // Above diagonal must be 1. - assert_eq!(data[0 * size + 1], 1); - assert_eq!(data[0 * size + 3], 1); + assert_eq!(at(0, 1), 1); + assert_eq!(at(0, 3), 1); // Below diagonal must be 0. - assert_eq!(data[2 * size + 0], 0); - assert_eq!(data[3 * size + 1], 0); + assert_eq!(at(2, 0), 0); + assert_eq!(at(3, 1), 0); } } diff --git a/Native/pcai_core/pcai_ollama_rs/src/main.rs b/Native/pcai_core/pcai_ollama_rs/src/main.rs index cdc092d4..0fa146f8 100644 --- a/Native/pcai_core/pcai_ollama_rs/src/main.rs +++ b/Native/pcai_core/pcai_ollama_rs/src/main.rs @@ -27,8 +27,6 @@ static GLOBAL: MiMalloc = MiMalloc; #[derive(Debug, Deserialize, Default)] struct RootConfig { - #[serde(default, rename = "fallbackOrder")] - fallback_order: Vec, #[serde(default)] ollama: OllamaConfig, #[serde(default)] @@ -61,14 +59,8 @@ struct RouterConfig { #[derive(Debug, Deserialize, Default, Clone)] struct OllamaConfig { - #[serde(default)] - enabled: bool, #[serde(default)] model: String, - #[serde(default, rename = "tool_model")] - tool_model: String, - #[serde(default, rename = "summary_model")] - summary_model: String, #[serde(default, rename = "base_url")] base_url: String, #[serde(default, rename = "timeout_ms")] @@ -109,18 +101,10 @@ struct OllamaConfig { tfs_z: f32, #[serde(default, rename = "seed")] seed: i32, - #[serde(default, rename = "auto_detect_models")] - auto_detect_models: bool, - #[serde(default, rename = "required_models")] - required_models: Vec, - #[serde(default, rename = "warm_models_on_start")] - warm_models_on_start: bool, #[serde(default, rename = "auto_pull_missing_models")] auto_pull_missing_models: bool, #[serde(default, rename = "strict_model_selection")] strict_model_selection: bool, - #[serde(default, rename = "cliSearchPaths")] - cli_search_paths: Vec, #[serde(default, rename = "toolInvokerPath")] tool_invoker_path: String, } @@ -281,21 +265,6 @@ struct TimingSummary { eval_duration_ns: u64, } -#[derive(Debug, Deserialize, Serialize)] -struct ToolCatalog { - tools: Vec, -} - -#[derive(Debug, Deserialize, Serialize)] -struct ConfiguredTool { - function: ConfiguredFunction, -} - -#[derive(Debug, Deserialize, Serialize)] -struct ConfiguredFunction { - name: String, -} - fn read_json_text(path: &Path) -> Result { let content = fs::read_to_string(path).with_context(|| format!("read {}", path.display()))?; Ok(content.trim_start_matches('\u{feff}').to_string()) diff --git a/Reports/ci-restoration-and-techdebt-20260718.md b/Reports/ci-restoration-and-techdebt-20260718.md new file mode 100644 index 00000000..236d74cc --- /dev/null +++ b/Reports/ci-restoration-and-techdebt-20260718.md @@ -0,0 +1,127 @@ +# CI Restoration & Tech-Debt Ledger — 2026-07-18 + +**Branch:** `fix/ci-gate-pslint-clippy` → PR #58 (`MERGEABLE`) +**Context:** GitHub Actions was disabled for ~3 weeks; re-enabling surfaced a stack of +pre-existing CI failures that had accumulated unseen. This report records what was +fixed, what remains as tracked debt, and the merge/dependency sequence to close out. + +--- + +## 1. CI gate restoration (done) + +Actions were re-enabled (free hosted runners, public repo). Root-causing the red gates +turned up **seven distinct pre-existing bugs**, all masked while Actions was off: + +| # | Gate | Root cause | Fix (commit) | +|---|------|-----------|--------------| +| 1 | Rust Check/Clippy | `--locked`/`--frozen` inserted *after* the cargo `--` separator | `67f6467` | +| 2 | Rust build wrapper | `Invoke-RustBuild.ps1` via `pwsh -File` chokes on a bare `--` | `37993d5` | +| 3 | PS Lint | PowerShell parse errors (`$var:` interpolation, malformed `foreach`) | `7e013fe` | +| 4 | PS Lint | 21 PSScriptAnalyzer findings (ShouldProcess, IEX, plaintext-pw) | `18b6dd3` | +| 5 | Media build | candle-core/transformers/flash-attn pinned at 0.9 vs candle-nn 0.10 | `c873fd2` | +| 6 | Clippy `-D warnings` (Cross-Platform + MS Rust Guidelines) | 19 workspace clippy lints | `7515e03` | +| 7 | PS Tests | Pester `Run.Path` bare `('Unit','Integration')` → "No test files found" | `15f999a` | + +Plus `ed4251d`: provisioned `.qa-gate.conf` (git-guard repo-level Rust quality gate). + +**Verified locally green (exit 0):** +- `cargo clippy --all-targets --no-default-features --features server,ffi -- -D warnings` +- `cargo clippy --workspace --all-targets --no-deps -- -D warnings -A clippy::type_complexity` +- Build.ps1 arg-ordering + wrapper routing +- PS Lint (PSScriptAnalyzer) across the workstation tooling + +**CI verdict for #58:** re-triggered on push `15f999a`; authoritative result on the PR checks. + +--- + +## 2. Pre-existing PowerShell Unit-test failures (TRACKED DEBT — not a merge blocker) + +Fixing the Pester `Run.Path` (bug #7 above) made the PS Tests job *actually run* the +suite for the first time, which exposed **65 pre-existing test failures** that were +hidden behind "No test files were found". + +**These are genuine test↔module contract rot, NOT caused by the path fix.** +Attribution proven two ways: +1. Identical pass/fail counts running from repo-root cwd vs `Tests/` cwd. +2. All affected tests resolve their module via `$PSScriptRoot` (cwd-independent). + +**Local baseline:** 759 total → 650 pass / 65 fail / 44 skip (~704 s). + +**Not a merge gate:** ruleset `dtm-default-protection` (id 17356124) requires only +signed commits + PR (0 approvals) and has **no `required_status_checks`** — red CI does +not block merge. These are deferred, not excluded (per the "no reward-hacked tests" rule +they must be fixed *credibly*, not silenced). + +### Failure clusters (representative) + +| Test file | Fail/Total | Symptom | Likely cause | +|-----------|-----------:|---------|--------------| +| `LLM-Logging.Tests.ps1` | 21/21 | Every `Write-LLMLog` / `Log Level Management` assertion fails | `PC-AI.LLM` logging contract changed/broke; module export or JSON shape drifted from tests | +| `Install-WSLVsockBridge.Tests.ps1` | 13/20 | Result-object properties, EnableService/StartService flags, missing-file error entries | `Install-WSLVsockBridge` result schema / mock expectations decayed | +| Process-idle filtering (`*Process*`) | ~5 | `-ExcludeIdle` count/order assertions | process-list helper contract drift | +| Remaining (~26) | — | scattered | to be enumerated on the fix pass | + +**Reproduce full list:** +```powershell +Set-Location C:\codedev\PC_AI +$c = New-PesterConfiguration +$c.Run.Path = 'Tests/Unit'; $c.Run.PassThru = $true; $c.CodeCoverage.Enabled = $false +$c.Output.Verbosity = 'None' +(Invoke-Pester -Configuration $c).Failed | Select Block,Name,@{n='Err';e={($_.ErrorRecord.Exception.Message -split "`n")[0]}} +``` + +**Recommended workstream (separate PR):** a `test/repair-unit-contracts` branch — +fix the module↔test contracts file-by-file, starting with `LLM-Logging` (21/21 = whole +file broken, highest leverage). Est. medium effort; needs the module source read against +each assertion. **Not started — awaiting your scope go-ahead.** + +--- + +## 3. Dependency / Dependabot backlog + +1 open Dependabot alert (moderate, `dependabot/27`). Open dep PRs, by recommended order: + +| PR | Bump | Risk | Recommendation | +|----|------|------|----------------| +| #56 | serde_with 3.16.1 → 3.21.0 | Low (minor) | Merge after #58/#57 — clean | +| #50 | log 0.4.29 → 0.4.33 | Trivial (patch) | Safe batch | +| #49 | memmap2 0.9.10 → 0.9.11 | Trivial (patch) | Safe batch | +| #52 | mimalloc 0.1.50 → 0.1.52 | Trivial (patch) | Safe batch | +| #51 | tokenizers 0.22.2 → 0.23.1 | Medium (minor, API surface) | **Gate behind local `cargo build` of pcai_media/inference** | +| #53 | windows 0.58.0 → 0.62.2 | High (4 majors) | **Gate behind local build; likely needs source edits** to the Windows API call sites | + +**Rule (per CLAUDE.md):** prefer latest compatible, but #51/#53 must build locally +before merge — do not merge on green Dependabot CI alone, since CI does not compile the +`llamacpp`/`mistralrs-backend` cfg-gated blocks where `windows` is used most. + +--- + +## 4. Latent issues noted (not fixed here) + +- **`unused manifest key: package.lints`** — `pcai_core_lib`, `pcai_media_model`, + `pcai_perf_cli` `Cargo.toml` declare `[package.lints]` (should be `[lints]` or a + `[workspace.lints]` + `lints.workspace = true`). Benign (doesn't fail `-D warnings`) + but means those crates' lint tables are silently ignored. One-line fix each; deferred + to avoid touching Cargo.toml on the CI-fix branch. +- **`Config/llm-config.json` stray gutting** — found the working tree with 37 lines + deleted (model/GPU/sampling/adaptive-ctx settings) by an unknown prior process; **not + authored by this work and reverted** (`git checkout`). Flagging so you're aware the + file was briefly corrupted locally; HEAD is intact. + +--- + +## 5. Merge sequence (awaiting your action — not auto-merged) + +1. **#58** (this branch) — merge once CI renders (or now; not gated on CI). +2. **#57** (WIP: vLLM cache pinning, cleanup-archive, workstation profile) — `MERGEABLE`; + rebase on main after #58, then merge. +3. **Dependabot safe batch:** #56 → #50 → #49 → #52. +4. **Dependabot gated:** #51 (tokenizers), #53 (windows) — only after a local + `cargo build --release` of the media + inference trees passes. + +## 6. Longer-horizon backlog (identified, not started) + +126 open TODO items across the repo ledgers — surfaced for prioritization, not executed: +`boot.TODO.md` (33), `CLAUDE.TODO.md` (38), `optimization.TODO.md` (28), +`machine-reliability.TODO.md` (14), `llm.TODO.md` (13). Grand-integration asks +(Gemini/vLLM runtime, google-access) remain design-stage backlog. diff --git a/Tests/PesterConfiguration.psd1 b/Tests/PesterConfiguration.psd1 index 35843323..9ee2d29e 100644 --- a/Tests/PesterConfiguration.psd1 +++ b/Tests/PesterConfiguration.psd1 @@ -1,8 +1,12 @@ @{ Run = @{ + # Paths are resolved from the repo root (the CI working directory and + # the cwd assumed by CodeCoverage.Path './Modules/**' below). Bare + # 'Unit'/'Integration' resolved to ./Unit at the repo root and made + # Pester find zero test files ("No test files were found" -> exit 1). Path = @( - 'Unit' - 'Integration' + 'Tests/Unit' + 'Tests/Integration' ) Exit = $false PassThru = $true diff --git a/Tools/InputDiagnostics/Repair-ProcessLassoTerminalGpu.ps1 b/Tools/InputDiagnostics/Repair-ProcessLassoTerminalGpu.ps1 index 3e6ef9d3..ea60be40 100644 --- a/Tools/InputDiagnostics/Repair-ProcessLassoTerminalGpu.ps1 +++ b/Tools/InputDiagnostics/Repair-ProcessLassoTerminalGpu.ps1 @@ -41,6 +41,8 @@ function Test-IsElevated { ).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) } function Restart-Governor { + [CmdletBinding(SupportsShouldProcess)] + param() $svc = Get-Service -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'ProcessGovernor|Lasso' } | Select-Object -First 1 if ($svc) { if ($PSCmdlet.ShouldProcess($svc.Name, 'Restart Process Governor')) { diff --git a/Tools/InputDiagnostics/Repair-WorkstationInputReliability.ps1 b/Tools/InputDiagnostics/Repair-WorkstationInputReliability.ps1 index fa9f0024..b724f445 100644 --- a/Tools/InputDiagnostics/Repair-WorkstationInputReliability.ps1 +++ b/Tools/InputDiagnostics/Repair-WorkstationInputReliability.ps1 @@ -136,6 +136,7 @@ function Add-Summary { # 2. Helper: run external command with ShouldProcess guard # --------------------------------------------------------------------------- function Invoke-ExternalIfShouldProcess { + [CmdletBinding(SupportsShouldProcess)] param( [string]$Target, [string]$Operation, diff --git a/Tools/Migrate-SystemScriptsIntoRepo.ps1 b/Tools/Migrate-SystemScriptsIntoRepo.ps1 index e21addc6..b053f0c1 100644 --- a/Tools/Migrate-SystemScriptsIntoRepo.ps1 +++ b/Tools/Migrate-SystemScriptsIntoRepo.ps1 @@ -198,6 +198,7 @@ $taskRepoints = @( ) function Move-MigrationItem { + [CmdletBinding(SupportsShouldProcess)] param([Parameter(Mandatory)] $Item) $exists = Test-Path -LiteralPath $Item.Source @@ -251,6 +252,7 @@ function Move-MigrationItem { } function Update-ScheduledTaskActionPath { + [CmdletBinding(SupportsShouldProcess)] param([Parameter(Mandatory)] $TaskSpec) $record = [ordered]@{ @@ -309,6 +311,7 @@ function Update-ScheduledTaskActionPath { } function Remove-EmptyDirectoryTree { + [CmdletBinding(SupportsShouldProcess)] param([Parameter(Mandatory)] [string]$Path) $record = [ordered]@{ diff --git a/Tools/Repair-OneDriveSync.ps1 b/Tools/Repair-OneDriveSync.ps1 index 3e1f06b1..1fecd115 100644 --- a/Tools/Repair-OneDriveSync.ps1 +++ b/Tools/Repair-OneDriveSync.ps1 @@ -289,6 +289,7 @@ function Get-SyncRootInventory { } function Invoke-OneDriveInstaller { + [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [string]$Path, [Parameter(Mandatory)] [object]$Actions @@ -319,6 +320,7 @@ function Invoke-OneDriveInstaller { } function Invoke-OneDriveInteractiveTask { + [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [string]$Executable, [AllowNull()] [string]$Arguments, diff --git a/Tools/SystemScripts/C-Scripts/Archive/wsl2-config-analyzer.ps1 b/Tools/SystemScripts/C-Scripts/Archive/wsl2-config-analyzer.ps1 index 9786b7c7..0321ad8e 100644 --- a/Tools/SystemScripts/C-Scripts/Archive/wsl2-config-analyzer.ps1 +++ b/Tools/SystemScripts/C-Scripts/Archive/wsl2-config-analyzer.ps1 @@ -124,15 +124,15 @@ function Test-HyperVConfiguration { $analysis.Features[$feature] = $status.State if ($status.State -eq "Enabled") { - Write-Host "✓ $feature: Enabled" -ForegroundColor Green + Write-Host "✓ ${feature}: Enabled" -ForegroundColor Green } else { - Write-Host "✗ $feature: $($status.State)" -ForegroundColor Red + Write-Host "✗ ${feature}: $($status.State)" -ForegroundColor Red $analysis.Issues += "$feature is not enabled" } } catch { - Write-Host "? $feature: Unknown" -ForegroundColor Yellow + Write-Host "? ${feature}: Unknown" -ForegroundColor Yellow $analysis.Issues += "Cannot determine status of $feature" } } @@ -147,17 +147,17 @@ function Test-HyperVConfiguration { $analysis.Services[$serviceName] = $service.Status if ($service.Status -eq "Running") { - Write-Host "✓ Service $serviceName: Running" -ForegroundColor Green + Write-Host "✓ Service ${serviceName}: Running" -ForegroundColor Green } else { - Write-Host "⚠ Service $serviceName: $($service.Status)" -ForegroundColor Yellow + Write-Host "⚠ Service ${serviceName}: $($service.Status)" -ForegroundColor Yellow if ($serviceName -eq "vmms") { $analysis.Issues += "Hyper-V Virtual Machine Management service is not running" } } } else { - Write-Host "✗ Service $serviceName: Not found" -ForegroundColor Red + Write-Host "✗ Service ${serviceName}: Not found" -ForegroundColor Red $analysis.Issues += "Service $serviceName is not installed" } } @@ -484,8 +484,10 @@ function Generate-OptimizationReport { Write-Host " ✓ System appears to be well configured" -ForegroundColor Green } else { - foreach ($i, $recommendation in $allRecommendations | ForEach-Object { $i = 0 } { @{ Index = ++$i; Value = $_ } }) { - Write-Host " $($i.Index). $($i.Value)" -ForegroundColor Cyan + $i = 0 + foreach ($recommendation in $allRecommendations) { + $i++ + Write-Host " $i. $recommendation" -ForegroundColor Cyan } } diff --git a/Tools/SystemScripts/C-Scripts/Optimize-Disks.ps1 b/Tools/SystemScripts/C-Scripts/Optimize-Disks.ps1 index f12010d3..e806e0cb 100644 --- a/Tools/SystemScripts/C-Scripts/Optimize-Disks.ps1 +++ b/Tools/SystemScripts/C-Scripts/Optimize-Disks.ps1 @@ -43,9 +43,7 @@ param( ) function Test-Admin { - $isAdmin = ([Security.Principal.WindowsPrincipal] - [Security.Principal.WindowsIdentity]::GetCurrent() - ).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) + $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) if (-not $isAdmin) { throw "This script must be run as Administrator." } } @@ -63,7 +61,7 @@ function Get-VolumeInfo { $_.DriveType -eq 'Fixed' -and $_.FileSystem -in @('NTFS','ReFS') } - foreach ($v in $vols) { + $(foreach ($v in $vols) { $diskNumber = $null; $busType = $null; $mediaType = $null try { if ($v.DriveLetter) { @@ -90,7 +88,7 @@ function Get-VolumeInfo { MediaType = $mediaType IsSsdLike = $isSsdLike } - } | Sort-Object DriveLetter, Path + }) | Sort-Object DriveLetter, Path } function Optimize-OneVolume { @@ -114,7 +112,7 @@ function Optimize-OneVolume { if ($Vol.DriveLetter) { Optimize-Volume -DriveLetter $Vol.DriveLetter -Analyze -Verbose -ErrorAction Stop } else { Optimize-Volume -Path $Vol.Path -Analyze -Verbose -ErrorAction Stop } } catch { - Write-Warning "Analyze failed on $target: $($_.Exception.Message)" + Write-Warning "Analyze failed on ${target}: $($_.Exception.Message)" } } } @@ -131,7 +129,7 @@ function Optimize-OneVolume { if ($Vol.DriveLetter) { Optimize-Volume -DriveLetter $Vol.DriveLetter -Verbose -ErrorAction Stop } else { Optimize-Volume -Path $Vol.Path -Verbose -ErrorAction Stop } } catch { - Write-Error "Optimize failed on $target: $($_.Exception.Message)" + Write-Error "Optimize failed on ${target}: $($_.Exception.Message)" } } } @@ -142,7 +140,7 @@ function Optimize-OneVolume { if ($Vol.DriveLetter) { Optimize-Volume -DriveLetter $Vol.DriveLetter -Verbose -ErrorAction Stop } else { Optimize-Volume -Path $Vol.Path -Verbose -ErrorAction Stop } } catch { - Write-Error "Optimize failed on $target: $($_.Exception.Message)" + Write-Error "Optimize failed on ${target}: $($_.Exception.Message)" } } } diff --git a/Tools/SystemScripts/C-Scripts/Startup/Initialize-BitwardenSession.ps1 b/Tools/SystemScripts/C-Scripts/Startup/Initialize-BitwardenSession.ps1 index d4d348b1..ec948660 100644 --- a/Tools/SystemScripts/C-Scripts/Startup/Initialize-BitwardenSession.ps1 +++ b/Tools/SystemScripts/C-Scripts/Startup/Initialize-BitwardenSession.ps1 @@ -360,6 +360,7 @@ function Invoke-BitwardenUnlock { #> [CmdletBinding(SupportsShouldProcess)] [OutputType([string])] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'Master password originates as plaintext from the BW_PASSWORD env var and must be written to a plaintext temp file for the Bitwarden CLI (bw unlock --passwordfile); SecureString would be round-tripped back to plaintext here and add no protection.')] param( [Parameter(Mandatory)] [string]$MasterPassword diff --git a/Tools/SystemScripts/C-Scripts/Startup/Start-WSLDockerServices.ps1 b/Tools/SystemScripts/C-Scripts/Startup/Start-WSLDockerServices.ps1 index 044156ba..1eb175f6 100644 --- a/Tools/SystemScripts/C-Scripts/Startup/Start-WSLDockerServices.ps1 +++ b/Tools/SystemScripts/C-Scripts/Startup/Start-WSLDockerServices.ps1 @@ -333,7 +333,7 @@ function Start-LxssManager { return $false } catch { - Write-Log "Failed to start $serviceName: $_" -Level ERROR + Write-Log "Failed to start ${serviceName}: $_" -Level ERROR return $false } } diff --git a/Tools/SystemScripts/C-Scripts/Startup/Tests/Sync-RegistryCredentials.Tests.ps1 b/Tools/SystemScripts/C-Scripts/Startup/Tests/Sync-RegistryCredentials.Tests.ps1 index f500b820..4485a8f3 100644 --- a/Tools/SystemScripts/C-Scripts/Startup/Tests/Sync-RegistryCredentials.Tests.ps1 +++ b/Tools/SystemScripts/C-Scripts/Startup/Tests/Sync-RegistryCredentials.Tests.ps1 @@ -22,6 +22,7 @@ BeforeAll { # Mock Bitwarden item structure function New-MockBitwardenItem { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'test fixture, not a real secret')] param( [string]$Name = 'Test Item', [string]$Username = 'testuser', diff --git a/Tools/SystemScripts/HomeRootArchive/Install-KBWithFixes.ps1 b/Tools/SystemScripts/HomeRootArchive/Install-KBWithFixes.ps1 index 6ae813dc..b937b25c 100644 --- a/Tools/SystemScripts/HomeRootArchive/Install-KBWithFixes.ps1 +++ b/Tools/SystemScripts/HomeRootArchive/Install-KBWithFixes.ps1 @@ -59,7 +59,7 @@ function AutoFix-WindowsUpdate { ) foreach ($cmd in $cmds) { Log $cmd - Invoke-Expression $cmd + & cmd.exe /c $cmd } } diff --git a/Tools/SystemScripts/HomeRootArchive/create-priority-repositories.ps1 b/Tools/SystemScripts/HomeRootArchive/create-priority-repositories.ps1 index e8c0f778..d1ad5c83 100644 --- a/Tools/SystemScripts/HomeRootArchive/create-priority-repositories.ps1 +++ b/Tools/SystemScripts/HomeRootArchive/create-priority-repositories.ps1 @@ -186,7 +186,7 @@ Scope: Complete project codebase" return $true } catch { - Write-Warning "❌ Failed to initialize git for $Name: $_" + Write-Warning "❌ Failed to initialize git for ${Name}: $_" return $false } finally { diff --git a/Tools/SystemScripts/HomeRootArchive/invoke-robust-remote.ps1 b/Tools/SystemScripts/HomeRootArchive/invoke-robust-remote.ps1 index d989a3c0..63ad21d2 100644 --- a/Tools/SystemScripts/HomeRootArchive/invoke-robust-remote.ps1 +++ b/Tools/SystemScripts/HomeRootArchive/invoke-robust-remote.ps1 @@ -1,6 +1,7 @@ # invoke-robust-remote.ps1 # Robust remote command execution with automatic fallback +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingInvokeExpression', '', Justification = 'Purpose-built remote command executor: $Command is an arbitrary caller-supplied command line run on the remote host via Invoke-Command; there is no fixed command+args to refactor to the call operator.')] param( [Parameter(Mandatory=$true)] [string]$Command, diff --git a/Tools/SystemScripts/HomeRootArchive/setup-server-winrm.ps1 b/Tools/SystemScripts/HomeRootArchive/setup-server-winrm.ps1 index e347877f..3a01ab04 100644 --- a/Tools/SystemScripts/HomeRootArchive/setup-server-winrm.ps1 +++ b/Tools/SystemScripts/HomeRootArchive/setup-server-winrm.ps1 @@ -369,8 +369,7 @@ function Set-WinRMSettings { foreach ($s in $settings) { try { - $cmd = "winrm set $($s.Path) '@{$($s.Setting)=`"$($s.Value)`"}' 2>&1" - $result = Invoke-Expression $cmd + $result = & winrm set $s.Path "@{$($s.Setting)=`"$($s.Value)`"}" 2>&1 if ($result -match 'cannot be changed.*GPO|controlled by policies') { Write-Status "$($s.Setting) is GPO-controlled - skipped" -Type Warning diff --git a/Tools/SystemScripts/HomeRootArchive/tcp-listener-server.ps1 b/Tools/SystemScripts/HomeRootArchive/tcp-listener-server.ps1 index 774a0bcf..eee7c392 100644 --- a/Tools/SystemScripts/HomeRootArchive/tcp-listener-server.ps1 +++ b/Tools/SystemScripts/HomeRootArchive/tcp-listener-server.ps1 @@ -1,6 +1,7 @@ # tcp-listener-server.ps1 # Run this on the SERVER (10.10.20.214) to enable fallback remote command execution +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingInvokeExpression', '', Justification = 'Purpose-built remote command listener: executes an arbitrary command line received over the IP-allowlisted socket; there is no fixed command+args to refactor to the call operator.')] param( [int]$Port = 9999, [string[]]$AllowedIPs = @("10.10.15.150", "10.10.20.199") diff --git a/Tools/SystemScripts/HomeRootArchive/test_mcp_servers.ps1 b/Tools/SystemScripts/HomeRootArchive/test_mcp_servers.ps1 index 7fd4a1ef..a298dd40 100644 --- a/Tools/SystemScripts/HomeRootArchive/test_mcp_servers.ps1 +++ b/Tools/SystemScripts/HomeRootArchive/test_mcp_servers.ps1 @@ -94,8 +94,7 @@ foreach ($serverName in $servers.PSObject.Properties.Name) { Write-Host "Testing server startup..." -ForegroundColor Yellow try { # Test with timeout using Claude CLI - $testCmd = "claude --mcp-config `"$ConfigPath`" --timeout 10 -p `"Test connectivity to $serverName server only. List available tools.`"" - $testOutput = Invoke-Expression $testCmd 2>&1 + $testOutput = & claude --mcp-config $ConfigPath --timeout 10 -p "Test connectivity to $serverName server only. List available tools." 2>&1 if ($LASTEXITCODE -eq 0) { Write-Host "✓ Server startup test passed" -ForegroundColor Green diff --git a/Tools/SystemScripts/UserBin/Setup-BuildEnvironment.ps1 b/Tools/SystemScripts/UserBin/Setup-BuildEnvironment.ps1 index c181cb51..347eff44 100644 --- a/Tools/SystemScripts/UserBin/Setup-BuildEnvironment.ps1 +++ b/Tools/SystemScripts/UserBin/Setup-BuildEnvironment.ps1 @@ -254,7 +254,7 @@ $tests = @( foreach ($test in $tests) { try { - $output = Invoke-Expression "$($test.Cmd) $($test.Args)" 2>&1 + $output = & $test.Cmd $test.Args 2>&1 $match = $output | Select-String $test.Pattern | Select-Object -First 1 if ($match) { Write-ColoredOutput " ✓ $($test.Name): $match" "Green" diff --git a/Tools/SystemScripts/unifi_api/scripts/udm_boot/Set-UDMSmbBootState.ps1 b/Tools/SystemScripts/unifi_api/scripts/udm_boot/Set-UDMSmbBootState.ps1 index b3c0df84..bdce7794 100644 --- a/Tools/SystemScripts/unifi_api/scripts/udm_boot/Set-UDMSmbBootState.ps1 +++ b/Tools/SystemScripts/unifi_api/scripts/udm_boot/Set-UDMSmbBootState.ps1 @@ -1,3 +1,4 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'Entry-point wrapper: forwards the plaintext SMB password to install_udm_smb_boot.ps1, which passes it to the remote samba setup over SSH; a plaintext value is genuinely required downstream and SecureString would break the pass-through.')] param( [string]$Target = "root@192.168.1.1", [ValidateSet("enable", "disable")] diff --git a/Tools/SystemScripts/unifi_api/scripts/udm_boot/install_udm_smb_boot.ps1 b/Tools/SystemScripts/unifi_api/scripts/udm_boot/install_udm_smb_boot.ps1 index 55e23d54..b4cd2b20 100644 --- a/Tools/SystemScripts/unifi_api/scripts/udm_boot/install_udm_smb_boot.ps1 +++ b/Tools/SystemScripts/unifi_api/scripts/udm_boot/install_udm_smb_boot.ps1 @@ -1,3 +1,4 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'Entry-point installer: the SMB password is passed verbatim as a positional argument to the remote samba setup shell script over SSH; a plaintext value is genuinely required downstream and SecureString would break the pass-through.')] param( [string]$Target = "root@192.168.1.1", [string]$ShareName = "udmpro_data", diff --git a/Tools/SystemScripts/unifi_api/scripts/windows/Start-UDMDriveStack.ps1 b/Tools/SystemScripts/unifi_api/scripts/windows/Start-UDMDriveStack.ps1 index c1478af4..8c7b0301 100644 --- a/Tools/SystemScripts/unifi_api/scripts/windows/Start-UDMDriveStack.ps1 +++ b/Tools/SystemScripts/unifi_api/scripts/windows/Start-UDMDriveStack.ps1 @@ -16,6 +16,7 @@ The long CLI form `--DryRun` is also accepted. .PARAMETER Help Print script help and exit. The aliases `-h` and `--help` are also accepted. #> +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'Entry-point script: the SMB credential user/password are consumed by the native cmdkey /add /user /pass CLI, which requires plaintext values; SecureString cannot be passed to cmdkey. SmbCredentialUser is a username, not a secret.')] param( [string]$TargetHost = "192.168.1.1", [string]$SmbShareName = "udmpro_data", @@ -368,6 +369,7 @@ function Resolve-IdentityFile { } function Test-SmbCredentialAvailable { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'Only tests whether a plaintext SMB password was supplied vs. already stored in Windows Credential Manager; the value flows from the entry-point param that the native cmdkey CLI requires as plaintext.')] param( [string]$HostName, [string]$User, @@ -592,6 +594,7 @@ function Ensure-SmbPathLink { } function Ensure-SmbCredential { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Justification = 'Password is passed to the native cmdkey /add /pass: CLI, which requires a plaintext value; SecureString cannot be supplied to cmdkey.')] param( [string]$TargetHost, [string]$User,