Summary
On Windows, the receipt store appears to use raw receipt IDs such as sha256:... directly as filenames. That breaks receipt persistence because : is not allowed in Windows filenames.
Observed symptom:
receipt store is unreadable: 参数错误。 (os error 87)
This makes receipt-backed runx skill / harness flows fail on Windows even when the skill itself is valid.
Public repro
The repro uses the public hello-world example skill and asserts that a basic receipt-backed skill run should:
- exit successfully
- seal a receipt
- create at least one receipt JSON file in the selected receipt store
Today that test fails on Windows.
Environment
- OS: Windows
- CLI observed:
runx-cli 0.6.1
Reproduction
Example command that reproduces locally on Windows:
runx skill .\hello-world --input 'message=hello' --receipt-dir .\.tmp\receipts --json
Observed output:
{
"error": {
"code": "skill_error",
"message": "receipt store is unreadable: 参数错误。 (os error 87)"
},
"status": "failure"
}
Root cause hypothesis
crates/runx-runtime/src/receipts/store.rs has:
fn receipt_file_name(receipt_id: &str) -> Result<String, ReceiptStoreError> {
if receipt_id.is_empty()
|| receipt_id == "."
|| receipt_id == ".."
|| receipt_id.contains('/')
|| receipt_id.contains('\\')
{
return Err(ReceiptStoreError::InvalidReceiptId {
receipt_id: receipt_id.to_owned(),
});
}
Ok(format!("{receipt_id}.json"))
}
That rejects / and \\, but it does not reject or encode :.
Because receipt IDs commonly look like sha256:..., the store ends up trying to materialize filenames like:
That filename is invalid on Windows.
Expected behavior
Receipt storage should work on Windows, macOS, and Linux.
The storage layer should not use raw receipt IDs as platform path components when they contain OS-invalid characters.
Suggested direction
Map receipt IDs to platform-safe filenames before writing to disk. Examples:
- percent-encoding
- base64url / hex encoding
- hash-based filename with the original receipt ID stored in file contents or index metadata
Green condition
The public repro test should exit 0 on Windows and create at least one .json receipt file under .tmp/receipts/.
Summary
On Windows, the receipt store appears to use raw receipt IDs such as
sha256:...directly as filenames. That breaks receipt persistence because:is not allowed in Windows filenames.Observed symptom:
This makes receipt-backed
runx skill/ harness flows fail on Windows even when the skill itself is valid.Public repro
powershell -ExecutionPolicy Bypass -File .\\test.ps1The repro uses the public
hello-worldexample skill and asserts that a basic receipt-backed skill run should:Today that test fails on Windows.
Environment
runx-cli 0.6.1Reproduction
Example command that reproduces locally on Windows:
Observed output:
{ "error": { "code": "skill_error", "message": "receipt store is unreadable: 参数错误。 (os error 87)" }, "status": "failure" }Root cause hypothesis
crates/runx-runtime/src/receipts/store.rshas:That rejects
/and\\, but it does not reject or encode:.Because receipt IDs commonly look like
sha256:..., the store ends up trying to materialize filenames like:That filename is invalid on Windows.
Expected behavior
Receipt storage should work on Windows, macOS, and Linux.
The storage layer should not use raw receipt IDs as platform path components when they contain OS-invalid characters.
Suggested direction
Map receipt IDs to platform-safe filenames before writing to disk. Examples:
Green condition
The public repro test should exit
0on Windows and create at least one.jsonreceipt file under.tmp/receipts/.