Did the agent run finish—or did the process merely stop?
Offline consistency checks for agent-run records.
Checks the record you provide. Does not independently observe or authenticate the run.
No LLM. No network. No provider account. No runtime dependencies.
Requires Node 24+. No runtime dependencies. The installed runtime-receipt bin runs prebuilt JavaScript (npm run build emits dist/ on pack; Node refuses type stripping for files inside node_modules, so the bin cannot point at the TypeScript source directly).
This package is not published to npm. From a checkout:
npm pack
npm install -g ./runtime-receipt-0.1.0.tgz
runtime-receipt RECEIPT --policy POLICY --now UTC_TIMESTAMP [--json]
Or without installing, from the same checkout (Node 24 executes the erasable TypeScript source directly, no build):
node src/cli.ts RECEIPT --policy POLICY --now UTC_TIMESTAMP [--json]
Programmatic use exposes the same pure check and boundary:
import { verify } from 'runtime-receipt';
const result = verify(receipt, policy, now);
// { schema: 'runtime-receipt-result/v1', status, assurance: 'supplied-evidence-only', diagnostics }
A process can exit 0 after a successful tool event and still be incomplete. RuntimeReceipt requires exactly one successful terminal event (turn.completed) at the end of the supplied record, plus a zero exit code and a matching reviewer policy.
npm run demo:producer:interrupt
# RuntimeReceipt: REJECTED
# TERMINAL_COUNT: Exactly one terminal event is required; tools and exit zero are insufficient.
# exits 1 intentionally
npm run demo:producer
# RuntimeReceipt: VALID (supplied evidence only; not attestation)
Do not chain those commands with &&. The interrupted demo is supposed to exit 1.
Requires Node 24+. No install/build step needed for the CLI: Node executes the TypeScript source using native type stripping.
# 1. Producer writes a run record and a recorded identity (asserted by the producer, not discovered).
node examples/produce.mjs complete /tmp/runtime-receipt.json
# 2. Reviewer supplies expected policy and evaluation time separately.
node src/cli.ts /tmp/runtime-receipt.json \
--policy examples/policy.json \
--now 2026-09-07T12:01:00.000Z
examples/produce.mjs interrupt writes the same process-success record without turn.completed. Dates are fixed synthetic values so the demo is reproducible.
{
"schema": "runtime-receipt-result/v1",
"status": "VALID",
"assurance": "supplied-evidence-only",
"diagnostics": []
}
Use this when you already produce agent-run artifacts and want a small, repeatable check before treating them as coherent execution evidence. Typical callers are an agent integration test or a CI gate.
The producer must write the receipt. The reviewer/CI must keep expected policy and --now outside agent-writable output. This tool does not capture runs, talk to providers, or authorize execution.
Receipt (producer) and policy (reviewer) are separate documents:
{
"schema": "runtime-receipt/v1",
"runId": "demo-run-001",
"identity": { "provider": "fixture", "runtime": "demo-runner", "version": "1.0.0", "model": "synthetic-model" },
"startedAt": "2026-09-07T12:00:00.000Z",
"endedAt": "2026-09-07T12:00:05.000Z",
"exitCode": 0,
"events": [
{ "seq": 0, "runId": "demo-run-001", "at": "2026-09-07T12:00:00.000Z", "type": "run.started" },
{ "seq": 1, "runId": "demo-run-001", "at": "2026-09-07T12:00:03.000Z", "type": "tool.completed" },
{ "seq": 2, "runId": "demo-run-001", "at": "2026-09-07T12:00:05.000Z", "type": "turn.completed" }
]
}
{
"schema": "runtime-receipt-policy/v1",
"runId": "demo-run-001",
"identity": { "provider": "fixture", "runtime": "demo-runner", "version": "1.0.0", "model": "synthetic-model" },
"maxAgeMs": 60000
}
--now is deliberately explicit. In real CI, supply a trusted current UTC timestamp; using the fixture date or an agent-chosen time defeats the freshness check.
npm test
npm run typecheck
Exit 0 = VALID, 1 = REJECTED evidence, 2 = INVALID input/usage.
V0 checks, for the exact supplied documents and evaluation time: structural validity; internally consistent run identity and event ordering; agreement with the expected recorded identity; successful terminal evidence and exit status; process-end freshness under the supplied policy. Output repeats deterministically for the same inputs.
Limitations:
endedAt → --now), not completion-event age. A long-lived process can have an old turn.completed and still be fresh. Replay inside the age window is allowed.verify() function still receives already-parsed objects.See ARCHITECTURE.md for the complete schema and limits.
2 commits
JavaScript
50.8%
TypeScript
49.2%
Did the agent run finish—or did the process merely stop?
Offline consistency checks for agent-run records.
Checks the record you provide. Does not independently observe or authenticate the run.
No LLM. No network. No provider account. No runtime dependencies.
Requires Node 24+. No runtime dependencies. The installed runtime-receipt bin runs prebuilt JavaScript (npm run build emits dist/ on pack; Node refuses type stripping for files inside node_modules, so the bin cannot point at the TypeScript source directly).
This package is not published to npm. From a checkout:
npm pack
npm install -g ./runtime-receipt-0.1.0.tgz
runtime-receipt RECEIPT --policy POLICY --now UTC_TIMESTAMP [--json]
Or without installing, from the same checkout (Node 24 executes the erasable TypeScript source directly, no build):
node src/cli.ts RECEIPT --policy POLICY --now UTC_TIMESTAMP [--json]
Programmatic use exposes the same pure check and boundary:
import { verify } from 'runtime-receipt';
const result = verify(receipt, policy, now);
// { schema: 'runtime-receipt-result/v1', status, assurance: 'supplied-evidence-only', diagnostics }
A process can exit 0 after a successful tool event and still be incomplete. RuntimeReceipt requires exactly one successful terminal event (turn.completed) at the end of the supplied record, plus a zero exit code and a matching reviewer policy.
npm run demo:producer:interrupt
# RuntimeReceipt: REJECTED
# TERMINAL_COUNT: Exactly one terminal event is required; tools and exit zero are insufficient.
# exits 1 intentionally
npm run demo:producer
# RuntimeReceipt: VALID (supplied evidence only; not attestation)
Do not chain those commands with &&. The interrupted demo is supposed to exit 1.
Requires Node 24+. No install/build step needed for the CLI: Node executes the TypeScript source using native type stripping.
# 1. Producer writes a run record and a recorded identity (asserted by the producer, not discovered).
node examples/produce.mjs complete /tmp/runtime-receipt.json
# 2. Reviewer supplies expected policy and evaluation time separately.
node src/cli.ts /tmp/runtime-receipt.json \
--policy examples/policy.json \
--now 2026-09-07T12:01:00.000Z
examples/produce.mjs interrupt writes the same process-success record without turn.completed. Dates are fixed synthetic values so the demo is reproducible.
{
"schema": "runtime-receipt-result/v1",
"status": "VALID",
"assurance": "supplied-evidence-only",
"diagnostics": []
}
Use this when you already produce agent-run artifacts and want a small, repeatable check before treating them as coherent execution evidence. Typical callers are an agent integration test or a CI gate.
The producer must write the receipt. The reviewer/CI must keep expected policy and --now outside agent-writable output. This tool does not capture runs, talk to providers, or authorize execution.
Receipt (producer) and policy (reviewer) are separate documents:
{
"schema": "runtime-receipt/v1",
"runId": "demo-run-001",
"identity": { "provider": "fixture", "runtime": "demo-runner", "version": "1.0.0", "model": "synthetic-model" },
"startedAt": "2026-09-07T12:00:00.000Z",
"endedAt": "2026-09-07T12:00:05.000Z",
"exitCode": 0,
"events": [
{ "seq": 0, "runId": "demo-run-001", "at": "2026-09-07T12:00:00.000Z", "type": "run.started" },
{ "seq": 1, "runId": "demo-run-001", "at": "2026-09-07T12:00:03.000Z", "type": "tool.completed" },
{ "seq": 2, "runId": "demo-run-001", "at": "2026-09-07T12:00:05.000Z", "type": "turn.completed" }
]
}
{
"schema": "runtime-receipt-policy/v1",
"runId": "demo-run-001",
"identity": { "provider": "fixture", "runtime": "demo-runner", "version": "1.0.0", "model": "synthetic-model" },
"maxAgeMs": 60000
}
--now is deliberately explicit. In real CI, supply a trusted current UTC timestamp; using the fixture date or an agent-chosen time defeats the freshness check.
npm test
npm run typecheck
Exit 0 = VALID, 1 = REJECTED evidence, 2 = INVALID input/usage.
V0 checks, for the exact supplied documents and evaluation time: structural validity; internally consistent run identity and event ordering; agreement with the expected recorded identity; successful terminal evidence and exit status; process-end freshness under the supplied policy. Output repeats deterministically for the same inputs.
Limitations:
endedAt → --now), not completion-event age. A long-lived process can have an old turn.completed and still be fresh. Replay inside the age window is allowed.verify() function still receives already-parsed objects.See ARCHITECTURE.md for the complete schema and limits.
2 commits
JavaScript
50.8%
TypeScript
49.2%