NNUE Network Loader¶
RecklessNetworkLoader downloads, verifies, and provisions the Reckless NNUE
evaluation network. It must complete before RecklessEngine is created.
Net must come before engine
RecklessEngine.init(networkDirectory:) returns nil — not a crash, but a
clean failure — when the NNUE net is absent. Always await ensure(in:) first.
The network¶
Reckless v0.9 uses a single NNUE network:
| Property | Value |
|---|---|
| Filename | v54-5478683c.nnue |
| Size | ~60 MB |
| SHA-256 | 5478683cb1bababde29ae8f29468a99846726548fc6a0ed54cac40ab6d38efbf |
| Download source | RecklessNetworks release |
The filename encodes the first 8 hex characters of the SHA-256 (5478683c), the
same convention Stockfish uses. The loader verifies the full SHA-256 digest
after downloading on every supported platform (see
SHA-256 verification).
The network spec is declared as a constant:
public static let network = RecklessNetworkLoader.Network(
filename: "v54-5478683c.nnue",
sha256: "5478683cb1bababde29ae8f29468a99846726548fc6a0ed54cac40ab6d38efbf",
downloadURL: URL(string: "https://github.com/codedeliveryservice/RecklessNetworks/releases/download/networks/v54-5478683c.nnue")!
)
The Network type¶
public struct RecklessNetworkLoader.Network: Sendable {
public let filename: String
public let sha256: String // full SHA-256 hex string
public let downloadURL: URL
public var shaPrefix: String // first 8 hex chars, matches filename segment
}
The loader¶
public struct RecklessNetworkLoader: Sendable {
public init()
@discardableResult
public func ensure(
in directory: URL,
progress: (@Sendable (Progress) -> Void)? = nil
) async throws -> URL
}
ensure(in:progress:):
- Creates
directoryif it does not exist. - Prunes the directory: stale
v…-….nnuenets from a previous Reckless version and orphaned hidden.….nnue.<UUID>.partdownload-staging files from a crashed earlier run are deleted (other files are never touched). Don't pointensure(in:)at a directory holding unrelatedv*-*.nnuefiles you want to keep. - If
v54-5478683c.nnueis already present and passes complete SHA-256 verification, returns immediately — no download, no network access. - If missing or invalid: downloads to a temporary location, verifies the SHA-256 digest (see cross-platform note), and atomically moves the file into place.
- Returns the
URLof the verified network file insidedirectory.
The operation is idempotent. A warm launch with a valid net is a fast checksum-only no-op.
Progress¶
public struct RecklessNetworkLoader.Progress: Sendable {
public let bytesDownloaded: Int64
public let totalBytes: Int64
public var fractionCompleted: Double? // nil when server omits Content-Length
}
The progress closure is invoked on the download task thread. It is only called when
a download is actually in progress. It fires once, at download completion (not
incrementally): bytesDownloaded equals totalBytes on success, or 0 when the
server did not send Content-Length. Do not expect a counting-up live percentage.
try await RecklessNetworkLoader().ensure(in: dir) { p in
if let f = p.fractionCompleted {
print("net: \(Int(f * 100))%")
} else {
print("net: \(p.bytesDownloaded) bytes downloaded")
}
}
Errors¶
public enum RecklessNetworkLoader.LoaderError: Error, Sendable {
case checksumMismatch(String) // complete downloaded digest did not match expected
case downloadFailed(String) // URLSession error
case fileSystem(String) // directory creation or atomic move failed
}
The net is never committed¶
The NNUE network is gitignored across all Fianchetto repositories — *.nnue
and networks/ appear in .gitignore. This mirrors the policy for Stockfish nets in
SwiftStockfish. The rust/networks/ directory (used as the staging path for
cargo test) is also gitignored.
Upgrading the network¶
When Reckless upgrades its evaluation network, update the single constant in
RecklessNetworkLoader.swift:
public static let network = Network(
filename: "<new-filename>.nnue",
sha256: "<new-full-sha256>",
downloadURL: URL(string: "…")!
)
No Rust rebuild is needed — the net is never baked into the compiled crate. The fork
removed upstream's include_bytes! embed specifically to enable this workflow.
SHA-256 verification and cross-platform crypto¶
| Platform | Verification |
|---|---|
| Apple (macOS · iOS · tvOS · watchOS · visionOS) | Full SHA-256 via CryptoKit.SHA256 — the complete 64-hex-char digest is compared against Network.sha256. |
| Linux · Android | Full SHA-256 via swift-crypto's source-compatible Crypto.SHA256. |
The Apple dependency graph is unchanged when building the normal binary arm —
CryptoKit is a system framework, so swift-crypto is resolved only by the
non-Apple/source arm.
See also¶
- Engine API —
RecklessEngine.init(networkDirectory:). - Getting Started — the full lifecycle in context.