Score replay commands

Owner contract verified against commit 153a4e5f54 (2026-10-07). CLI alignment and legacy-builder withdrawal are tracked by PCD-429 in the CLI truth audit sprint. Re-verify the registered tree in Commands/CommandFactory.cs, the options and handlers in Commands/ScoreReplayCommandGroup.cs, client registrations in Program.cs, and the owner contract in src/Scanner/StellaOps.Scanner.WebService/Endpoints/ScoreReplayEndpoints.cs.

The registered score group has four verbs. Replay, bundle metadata and verification call Scanner for an existing scan. Explanation calls Signals for a score digest. These operations use the configured Backend Router (STELLAOPS_BACKEND_URL) and Authority credentials.

CommandRequestClientRequested scope
score replayPOST /api/v1/scans/{scanId}/score/replayScanner.Score.Replayscanner:read scanner:write
score bundleGET /api/v1/scans/{scanId}/score/bundleScanner.Score.Bundlescanner:read
score verifyPOST /api/v1/scans/{scanId}/score/verifyScanner.Score.Verifyscanner:read scanner:write
score explainGET /api/v1/score/explain/{digest}Score.Readscore.read

The Scanner route group requires read authorization; replay and verify additionally require write authorization. The CLI requests both scopes for those operations and propagates the effective tenant through its production authentication pipeline. Transport retains the egress guard. Scanner registers these routes only when score replay is enabled; a source contract does not establish that a selected installation enables or serves them.

Replay a scan

Replay uses the stored scan manifest and asks the Scanner owner to recompute the score.

OptionMeaning
--scan, -sRequired scan identifier
--manifest-hash, -mOptional manifest selection
--freeze, -fOptional ISO 8601 freeze timestamp
--output, -otext (default) or json on standard output
--verboseDiagnostic logging
stella score replay --scan 00000000-0000-0000-0000-000000000123
stella score replay --scan 00000000-0000-0000-0000-000000000123 --manifest-hash sha256:abc123 --output json
stella score replay --scan 00000000-0000-0000-0000-000000000123 --freeze 2026-10-06T00:00:00Z --output json

The request fields are manifestHash and freezeTimestamp. When the timestamp is omitted, the owner derives it from the manifest’s creation time. The response preserves score (0–1), rootHash, bundleUri, manifestHash, manifestDigest, canonicalInputHash, canonicalInputPayload, seedHex, factors, verificationStatus, replayedAt, and deterministic. Each factor carries name, weight, raw, weighted, and source.

deterministic reports the stored manifest flag. Compare repeat-run inputs and results to assess reproducibility. verificationStatus is an owner result; neither field alone proves cryptographic trust or production scoring acceptance.

Read bundle metadata

stella score bundle --scan 00000000-0000-0000-0000-000000000123 --output json

This command requires --scan/-s and accepts --output/-o (text or json) and --verbose. It returns scanId, rootHash, bundleUri, manifestDsseValid, and createdAt. The command retrieves metadata only. bundleUri is a Scanner-side archive path; the CLI does not download that archive. The owner’s optional rootHash query selector is not exposed by this command.

Verify a score bundle

OptionMeaning
--scan, -sRequired scan identifier
--root-hash, -rRequired expected root hash
--canonical-input-hashOptional expected canonical input hash
--canonical-input-payloadOptional path to a UTF-8 JSON file containing the exact canonical input payload
--output, -otext (default) or json on standard output
--verboseDiagnostic logging
stella score verify --scan 00000000-0000-0000-0000-000000000123 --root-hash sha256:def456 --output json
stella score verify --scan 00000000-0000-0000-0000-000000000123 --root-hash sha256:def456 --canonical-input-hash sha256:abc123 --canonical-input-payload canonical-input.json --output json

The request maps these options to expectedRootHash, expectedCanonicalInputHash, and canonicalInputPayload. Scanner verifies only the scan’s stored bundle selected by the root hash; the request names no bundle location. The payload option reads a local file; it does not send the filename or accept a JSON string as the option value. The file is limited to 1 MiB. Unreadable files, invalid UTF-8 and malformed JSON fail before any HTTP request. The CLI preserves the original payload text, including whitespace, newlines and a UTF-8 BOM, because the owner hashes that exact text. Save the response’s canonicalInputPayload string without formatting it or adding a trailing newline.

After a Scanner restart, the owner can require canonical binding supplied by the caller. A root hash alone may then return a valid HTTP response with valid:false. Retain both canonicalInputHash and the exact canonicalInputPayload from replay when preparing a later verification.

The response preserves valid, computedRootHash, expectedRootHash, manifestValid, ledgerValid, canonicalInputHashValid, expectedCanonicalInputHash, canonicalInputHash, verifiedAtUtc, and errorMessage. Inspect the component flags and owner error as well as the overall verdict.

Explain a score digest

stella score explain sha256:abc123 --format json

Explanation accepts a digest argument, --format/-f (table, json, or markdown), optional --server (Backend Router URL), and --verbose. It preserves the separate Signals explanation workflow and its ScoreExitCodes contract.

Failures and evidence limits

For Scanner replay, bundle and verify, success exits 0. A well-formed verification response with valid:false exits 2, including HTTP 200 refusals. Provider, authentication, transport, HTTP and malformed-response failures exit nonzero. In JSON mode, operational failures emit success:false with a sanitized error and no fabricated score, root or verification result. Authentication and backend error guidance identifies the exact required scopes for the operation. HTTP failures also report their numeric status; raw response bodies and credential details are not echoed. Diagnostic logging goes to standard error.

Scanner’s enabled-route tests use a synthetic recorded-measurement scorer for positive contract controls. They do not establish production scoring acceptance. The default proof signing fallback reports IsTrusted=false; route/DTO tests do not establish cryptographic trust. The production scorer refuses unavailable measurements rather than inventing inputs.

The legacy, unregistered ScoreCommandGroup and its command-shape tests were withdrawn under PCD-429 and frozen beneath src/__Obsoleted/Cli/. Its score-ID replay semantics differ from Scanner’s scan-ID replay. Signals still owns the corresponding score-ID APIs; withdrawal of this duplicate CLI builder does not withdraw those owner endpoints. The registered CLI does not provide score compute, history, compare, show, diff, manifest, inputs, or an offline replay flag.

Related: command reference, Scanner score replay runbook, Signals unified score.