Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .claude/skills/build-deps/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
name: build-deps
description: Install or repair the build prerequisites for this repo (.NET 10 SDK, Node.js/npm, Windows 10 SDK, Git, WebView2). Use when `build.ps1` reports "issue(s) found", when a build fails with a missing SDK/toolchain, or when setting up a fresh Windows checkout.
---

# Build dependencies

This repo already ships the tooling. Do not write new detection or install logic.

- `scripts\setup-dev.ps1` detects and installs prerequisites via winget, refreshes PATH, and trusts the checkout for GitVersion.
- `build.ps1 -CheckOnly` reports prerequisites only. This is what prints `N issue(s) found`.

## Procedure

1. **Diagnose** (never installs, never touches git config):

```powershell
.\scripts\setup-dev.ps1 -CheckOnly
```

2. **Install what is missing.** Report the missing list to the user and confirm before installing, since winget changes machine state and may prompt for elevation.

```powershell
.\scripts\setup-dev.ps1
```

Run this in an elevated PowerShell if winget reports it needs admin. If winget itself is missing, tell the user to install "App Installer" from the Microsoft Store, then rerun.

3. **Refresh PATH, then re-verify.** Newly installed tools are not on the PATH of any shell that was already open, including this session's shell. Pull the current machine and user PATH into the process before re-checking:

```powershell
$env:Path = @(
[Environment]::GetEnvironmentVariable("Path", "Machine"),
[Environment]::GetEnvironmentVariable("Path", "User")
) -join ";"
.\scripts\setup-dev.ps1 -CheckOnly
```

If a tool still is not found after this, the install needs a fresh terminal (or a reboot for the Windows SDK). Say so rather than looping on retries.

4. **Confirm the build works** once the check is clean:

```powershell
.\build.ps1
```

## Package IDs (for reference and manual fallback)

| Missing item | winget id |
| --- | --- |
| .NET SDK / .NET 10 SDK | `Microsoft.DotNet.SDK.10` |
| Node.js (and npm) | `OpenJS.NodeJS.LTS` |
| Windows 10 SDK | `Microsoft.WindowsSDK.10.0.26100` |
| Git | `Git.Git` |
| WebView2 Runtime | `Microsoft.EdgeWebView2Runtime` |

Manual install: `winget install --id <id> -e`.

## Notes

- The Windows SDK can also come from the Visual Studio Installer ("Desktop development with C++" or the standalone SDK component). Detection just looks for a versioned directory under `%ProgramFiles(x86)%\Windows Kits\10\Include`.
- Node.js is required even for the WinUI build: it runs `npm ci` to restore `@microsoft/mxc-sdk` and copy `wxc-exec.exe` into the output.
- Git is required at *build* time, not just for version control, because GitVersion reads repository metadata. `setup-dev.ps1` adds the checkout to `git config --global safe.directory`; pass `-NoTrustRepository` to skip that.
- The .NET version floor is pinned in `global.json` (`10.0.100`, `rollForward: latestFeature`).
- `setup-dev.ps1 -RunValidation` additionally runs the full build plus the shared and tray test projects required by `AGENTS.md` closeout.
- Keep this file free of em dashes: `scripts\validate-docs.ps1` runs during `build.ps1` and fails the build on them.
85 changes: 85 additions & 0 deletions docs/LOCAL_INFERENCE_ASSETS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Local Inference Asset Integrity

Local inference downloads two kinds of executable-adjacent assets at runtime: a
prebuilt `llama.cpp` server for the detected hardware, and GGUF model weights.
Both run on the user's machine with the user's privileges, so both follow the
same fail-closed rules as the audio assets described in
[AUDIO_MODEL_ASSETS.md](AUDIO_MODEL_ASSETS.md).

## Authoritative catalogs

| Asset | Source of truth | Runtime storage |
| --- | --- | --- |
| llama.cpp Windows builds | `LlamaBackendCatalog.Variants` | `<tray-data>\llama\runtimes\<runtime-key>\` |
| GGUF checkpoints | `LocalModelCatalog.Models` | `<tray-data>\llama\models\<model-id>\` |

The source catalogs hold the download URL, pinned SHA-256, and exact size. Do
not duplicate those values here.

## Rules

1. The `llama.cpp` release tag is pinned in `LlamaBackendCatalog.ReleaseTag`.
Only the backend *variant* is chosen at runtime, from detected hardware. We
do not resolve "latest" at runtime: an unpinned binary cannot be
integrity-checked, and an upstream flag change would silently break the
per-model run recipes.
2. Every asset must carry a lowercase 64-character SHA-256 and an HTTPS URL.
An entry missing either is not downloadable
(`LlamaBackendVariant.IsDownloadable` / `LocalModelInfo.IsDownloadable` are
false) and the runtime refuses to fetch it.
3. Downloads stage to a temporary file, verify the hash, and only then move or
extract. A mismatch deletes the partial file and surfaces an error.
4. Archive extraction rejects any entry whose resolved path escapes the
destination directory.

## Provenance

**GGUF checkpoints.** HuggingFace publishes each LFS object's id, which is the
file's SHA-256. The catalog hashes are those published values, read from
`https://huggingface.co/api/models/<repo>/tree/<path>`. Re-read that endpoint to
re-verify rather than trusting a locally computed hash of a file you already
downloaded through the same channel.

**llama.cpp builds.** GitHub does not publish release-asset hashes, so these
must be computed from the downloaded archive:

```powershell
Get-FileHash .\llama-<tag>-bin-win-cuda-12.4-x64.zip -Algorithm SHA256
```

Record the release tag, the date, and who verified it in the change description.

**Current pinning.** Release `b10472`, all nine Windows assets, verified
2026-08-17. Each archive was downloaded from the release URL, its byte length
cross-checked against the size the GitHub releases API reports for that asset,
and its SHA-256 computed from the downloaded bytes. Both the hash and the size
are recorded in `LlamaBackendCatalog`, so a future re-verification that produces
a different length fails before the hash comparison.

Note the limit of that check: the API size and the archive come from the same
origin, so this establishes that the bytes we hashed are the bytes GitHub serves
for that release, not that the release itself is authentic. Independent
provenance for upstream binaries would require a signed upstream manifest, which
llama.cpp does not currently publish.

## Custom local builds

A user may point the app at their own `llama-server.exe` via the custom runtime
path setting. That path bypasses the catalog and the hash check entirely, by
design: the binary is the user's own. The UI must show an explicit "custom build,
not verified" state whenever it is in use, so the bypass is never silent.

## Bumping the pinned release

1. Download every Windows asset listed in `LlamaBackendCatalog.Variants` for the
new tag.
2. Compute and record each SHA-256.
3. Update `ReleaseTag` and all hashes in one commit.
4. Re-verify the run recipes in `LocalModelCatalog` still parse against the new
build. Speculative-decoding flags such as `--spec-type` are the ones most
likely to change.
5. Run `dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --filter Inference`.
6. Launch one real model end to end and confirm a completion.

Re-verify every shipped asset hash before each public release and record the
evidence for release review.
Loading