Bsibz/runtime-receipt

1

stars

2

commits

JavaScript

primary language

Sep 8, 2026

updated

README

RuntimeReceipt

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.

Install

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 }

Failing run vs completed run

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.

30-second demo

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": []
}

Who should use this

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.

Input example

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.

Tests, exit codes, limitations

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:

  • A fabricated but coherent receipt can pass. This is not authentication, attestation, or independent observation.
  • Tool success, generated code, tests, and business-task correctness are out of scope.
  • Freshness is process-end age (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.
  • CLI ingestion rejects duplicate JSON object keys. The pure verify() function still receives already-parsed objects.
  • Single-turn format. No raw provider-log adapter, cryptographic signatures, trusted wall clock, or multi-turn session completeness.

Architecture

See ARCHITECTURE.md for the complete schema and limits.

Contributors

Bsibz

2 commits

Bsibz/runtime-receipt

1

stars

2

commits

JavaScript

primary language

Sep 8, 2026

updated

README

RuntimeReceipt

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.

Install

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 }

Failing run vs completed run

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.

30-second demo

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": []
}

Who should use this

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.

Input example

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.

Tests, exit codes, limitations

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:

  • A fabricated but coherent receipt can pass. This is not authentication, attestation, or independent observation.
  • Tool success, generated code, tests, and business-task correctness are out of scope.
  • Freshness is process-end age (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.
  • CLI ingestion rejects duplicate JSON object keys. The pure verify() function still receives already-parsed objects.
  • Single-turn format. No raw provider-log adapter, cryptographic signatures, trusted wall clock, or multi-turn session completeness.

Architecture

See ARCHITECTURE.md for the complete schema and limits.

Contributors

Bsibz

2 commits

Languages

JavaScript

50.8%

TypeScript

49.2%