From 90caa73b957c9d32677acb66291edcb62a74c9fe Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 11 Aug 2026 19:54:37 +0000 Subject: [PATCH] feat(runner): wire provider-neutral PRP receipts Add versioned semantic-tool and budget stop receipts with replay parity, conformance fixtures, and normalized adapter evidence. Score eval trace completeness from PRP receipts while preserving the existing live evidence fallback. Co-Authored-By: Paperclip --- packages/paperclip-runner/README.md | 1 + packages/paperclip-runner/docs/index.md | 1 + .../docs/protocol-compatibility.md | 32 ++ .../replay/budget-cost-stop-reason.json | 55 ++ .../budget-cost-stop-reason.snapshot.json | 126 ++++ .../budget-cost-stop-reason.summary.json | 9 + ...tic-tool-artifact-happy-path.snapshot.json | 136 +++++ ...ntic-tool-artifact-happy-path.summary.json | 9 + ...ool-conflict-duplicate-retry.snapshot.json | 172 ++++++ ...tool-conflict-duplicate-retry.summary.json | 9 + ...mantic-tool-denial-redaction.snapshot.json | 137 +++++ ...emantic-tool-denial-redaction.summary.json | 9 + ...tool-governance-wake-monitor.snapshot.json | 139 +++++ ...-tool-governance-wake-monitor.summary.json | 9 + ...ol-unknown-optional-envelope.snapshot.json | 133 +++++ ...ool-unknown-optional-envelope.summary.json | 9 + .../semantic-tool-artifact-happy-path.json | 186 ++++++ ...emantic-tool-conflict-duplicate-retry.json | 120 ++++ .../semantic-tool-denial-redaction.json | 102 ++++ ...semantic-tool-governance-wake-monitor.json | 90 +++ ...mantic-tool-unknown-optional-envelope.json | 72 +++ ...tic-tool-unsupported-required-version.json | 55 ++ .../protocol/schemas/capabilities.schema.json | 39 ++ .../protocol/schemas/event.schema.json | 38 ++ .../schemas/semantic-tool.schema.json | 164 ++++++ .../protocol/schemas/stop-reason.schema.json | 65 +++ .../protocol/schemas/terminal.schema.json | 3 +- .../runner/crates/runner-core/src/replay.rs | 89 +++ .../generate-protocol-schema-module.mjs | 16 +- .../scripts/generate-replay-goldens.mjs | 6 + .../spec/prp-v1-expressiveness-audit.md | 57 +- .../spec/prp-v1-expressiveness-crosswalk.json | 112 +++- .../capability-semantic-conformance.test.ts | 4 + .../capability-semantic-conformance.ts | 98 +++- .../src/conformance/semantic-conformance.ts | 17 + .../src/eval/eval-execution.ts | 151 ++++- .../src/eval/eval-scoring.test.ts | 117 ++++ .../paperclip-runner/src/eval/eval-scoring.ts | 81 ++- packages/paperclip-runner/src/index.ts | 1 + .../src/protocol/generated/schema-bundle.ts | 542 +++++++++++++++++- .../generated/standalone-validators.ts | 3 +- .../prp-v1-expressiveness-crosswalk.test.ts | 9 + .../src/protocol/replay-contract.test.ts | 175 ++++++ .../src/protocol/replay-contract.ts | 118 +++- .../protocol/semantic-tool-receipts.test.ts | 121 ++++ .../src/protocol/semantic-tool-receipts.ts | 239 ++++++++ .../src/reducer/session-reducer.test.ts | 6 + .../helpers/paperclip-semantic-conformance.ts | 8 +- .../paperclip-semantic-conformance.test.ts | 2 + 49 files changed, 3816 insertions(+), 76 deletions(-) create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/budget-cost-stop-reason.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/budget-cost-stop-reason.snapshot.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/budget-cost-stop-reason.summary.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-artifact-happy-path.snapshot.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-artifact-happy-path.summary.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-conflict-duplicate-retry.snapshot.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-conflict-duplicate-retry.summary.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-denial-redaction.snapshot.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-denial-redaction.summary.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-governance-wake-monitor.snapshot.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-governance-wake-monitor.summary.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-unknown-optional-envelope.snapshot.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-unknown-optional-envelope.summary.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-artifact-happy-path.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-conflict-duplicate-retry.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-denial-redaction.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-governance-wake-monitor.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-unknown-optional-envelope.json create mode 100644 packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-unsupported-required-version.json create mode 100644 packages/paperclip-runner/protocol/schemas/semantic-tool.schema.json create mode 100644 packages/paperclip-runner/protocol/schemas/stop-reason.schema.json create mode 100644 packages/paperclip-runner/src/protocol/semantic-tool-receipts.test.ts create mode 100644 packages/paperclip-runner/src/protocol/semantic-tool-receipts.ts diff --git a/packages/paperclip-runner/README.md b/packages/paperclip-runner/README.md index 30377068a9c..54e87d49276 100644 --- a/packages/paperclip-runner/README.md +++ b/packages/paperclip-runner/README.md @@ -164,6 +164,7 @@ and JSON content; see the protocol-server tutorial for direct `curl` examples. - [Capability live runnerd/Codex loop](docs/capability-live-runnerd-codex.md) - [Capability issue-thread UI](docs/capability-issue-thread-ui.md) - [PRP compatibility/versioning policy](docs/protocol-compatibility.md) +- [PRP v1 expressiveness audit](spec/prp-v1-expressiveness-audit.md) - [Cumulative end-to-end tutorial](docs/tutorials/end-to-end.md) - [OKF knowledge bundle](knowledge/) - [Normative native-runner contract](spec/native-runner-contract.md) diff --git a/packages/paperclip-runner/docs/index.md b/packages/paperclip-runner/docs/index.md index db3ea8bbd64..9d7c629b249 100644 --- a/packages/paperclip-runner/docs/index.md +++ b/packages/paperclip-runner/docs/index.md @@ -24,6 +24,7 @@ Each tutorial explains the capability it exercises and the contract it proves. - [Architecture and dependency boundary](architecture.md) - [PRP compatibility and versioning policy](protocol-compatibility.md) +- [PRP v1 expressiveness audit](../spec/prp-v1-expressiveness-audit.md) - [ADR 0001: runner, testing, and eval package boundaries](adr/0001-runner-testing-eval-package-boundaries.md) - [Local protocol and supervision](local-runner.md) - [Durable transport and recovery](durable-recovery.md) diff --git a/packages/paperclip-runner/docs/protocol-compatibility.md b/packages/paperclip-runner/docs/protocol-compatibility.md index 6d521fd8835..b8a1f2d8fea 100644 --- a/packages/paperclip-runner/docs/protocol-compatibility.md +++ b/packages/paperclip-runner/docs/protocol-compatibility.md @@ -21,6 +21,9 @@ production control-plane behavior. | `protocolVersion` | `1` | Required. Negotiate the highest overlapping version; no overlap fails closed. | | `fixtureVersion` | `1` | Required by the conformance corpus. Unknown values fail closed. | | `event.schemaVersion` | `1` | Required on every event. Unknown values fail closed before reduction. | +| `capabilities.semanticTools.schemaVersion` | `1` | Optional advertisement. When present, an unknown required version fails closed. | +| `payload.semantic_tool.schemaVersion` | `1` | Optional on paired semantic tool input/result events. When present, an unknown required version fails closed. | +| `terminal.stopReason.schemaVersion` | `1` | Optional budget/cost receipt. When present, an unknown required version fails closed. | | Typed `schema` discriminators | `*.v1` | Required. Unknown required schema identities fail JSON Schema validation. | Wire protocol versions and fixture-corpus versions are independent. A fixture @@ -45,6 +48,35 @@ The forward-compatibility fixture proves that optional fields survive validation without changing the v1 snapshot. The unsupported-version fixture proves that a required v2 protocol cannot be replayed by this consumer. +## Provider-neutral semantic receipts + +- `capabilities.semanticTools` advertises stable operation IDs, availability, + required claims, and redaction disposition without naming a provider API. +- `mcp_app.tool_input` and `mcp_app.tool_result` may carry paired + `semantic_tool` envelopes. Correlation IDs must match the containing event; + operation ID and idempotency key must match across the pair. +- Content is represented by a canonical SHA-256 digest plus allowlisted typed + references. Raw credentials, provider payloads, and hidden identifiers do not + belong on the wire. +- Result receipts distinguish success, denial, conflict, exact duplicate, + unavailable, and failure. They can name the authorization boundary, safe + revision, artifact/work-product refs, immutable governed targets, and bounded + wake/monitor causality. +- `terminal.stopReason` records budget/cost kind, stable code, retryability, + limit class, safe aggregate, and decision receipt. + +These fields are trace evidence only. The v1 reducer ignores `semantic_tool` +payloads, so adding or extending the optional envelope has no projection +effect. Eval `trace_completeness` treats PRP wire receipts as authoritative when +present and retains the pre-existing scalar fallback for live evidence that has +not yet emitted them. + +Seven conformance fixtures cover artifact success, redacted denial without +fallback, stale conflict plus duplicate retry, governed target and continuation +causality, budget/cost stop, unknown optional fields, and rejection of an +unknown required version. The six accepted fixtures have shared TypeScript and +Rust golden parity summaries. + ## Replay semantics - Events are applied in fixture order and ordered independently by diff --git a/packages/paperclip-runner/protocol/fixtures/replay/budget-cost-stop-reason.json b/packages/paperclip-runner/protocol/fixtures/replay/budget-cost-stop-reason.json new file mode 100644 index 00000000000..2952687c584 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/budget-cost-stop-reason.json @@ -0,0 +1,55 @@ +{ + "schema": "paperclip.prp.fixture.v1", + "fixtureVersion": 1, + "protocolVersion": 1, + "name": "Budget cost stop reason", + "description": "A terminal budget hard stop carries a safe usage aggregate, decision id, and stable stop receipt.", + "identity": { + "schema": "paperclip.prp.identity.v1", "companyId": "company_budget_stop", "issueId": "issue_budget_stop", "runId": "run_budget_stop", + "environmentLeaseId": "lease_budget_stop", "runnerInstanceId": "runner_budget_stop", "normalizedSessionId": "session_budget_stop", "driverSessionId": "driver_budget_stop" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", "sessionReusePolicy": "new_per_run", "driver": { "kind": "provider-neutral", "version": "1.0.0" }, + "steer": false, "interrupt": true, "resume": true, "runtimeRequests": false, "structuredResult": true, "typedEvents": true, "unsupported": [] + }, + "commands": [], + "events": [ + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "budget_stop_01", "sourceSeq": 1, "sourceInstanceId": "runner_budget_stop", + "sourceKind": "runner", "runId": "run_budget_stop", "normalizedSessionId": "session_budget_stop", "turnId": "turn_budget_stop", + "eventType": "run.result.proposed", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:40:00.000Z", + "payload": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "blocked", "summary": "The actor budget reached its hard limit.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": false, "criteria": [], "remainingWork": [{ "description": "The budget owner must raise the limit or wait for reset.", "blocksCompletion": true }] }, + "evidence": [{ "decisionId": "budget_decision_stop" }], + "verification": [{ "commandOrCheck": "budget aggregate receipt", "status": "passed" }], + "blocker": { "reasonCode": "budget_hard_stop", "owner": { "kind": "budget_owner" }, "unblockAction": "Raise the actor budget or wait for the monthly reset.", "scope": "task_wide" }, + "attentionRequests": [], "artifacts": [] + } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "budget_stop_02", "sourceSeq": 2, "sourceInstanceId": "runner_budget_stop", + "sourceKind": "runner", "runId": "run_budget_stop", "normalizedSessionId": "session_budget_stop", "turnId": "turn_budget_stop", + "eventType": "run.terminal", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:40:00.010Z", + "payload": { + "schema": "paperclip.prp.terminal.v1", "turnTerminalState": "cancelled", "runTerminalState": "cancelled", "reportedWorkDisposition": "blocked", + "workAssessmentId": "assessment_budget_stop", "statusDecisionId": "decision_budget_stop", + "stopReason": { + "schema": "paperclip.prp.stop_reason.v1", "schemaVersion": 1, "receiptId": "stop_receipt_budget", "kind": "budget", + "code": "budget_hard_stop", "retryable": true, "decisionId": "budget_decision_stop", "limitClass": "actor_monthly", + "aggregate": { "unit": "cents", "observed": 10000, "limit": 10000, "window": "monthly_utc" }, + "relatedReceiptIds": [] + } + } + } + ], + "requests": [], + "result": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "blocked", "summary": "The actor budget reached its hard limit.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": false, "criteria": [], "remainingWork": [{ "description": "The budget owner must raise the limit or wait for reset.", "blocksCompletion": true }] }, + "evidence": [{ "decisionId": "budget_decision_stop" }], + "verification": [{ "commandOrCheck": "budget aggregate receipt", "status": "passed" }], + "blocker": { "reasonCode": "budget_hard_stop", "owner": { "kind": "budget_owner" }, "unblockAction": "Raise the actor budget or wait for the monthly reset.", "scope": "task_wide" }, + "attentionRequests": [], "artifacts": [] + } +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/budget-cost-stop-reason.snapshot.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/budget-cost-stop-reason.snapshot.json new file mode 100644 index 00000000000..b7d2d329702 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/budget-cost-stop-reason.snapshot.json @@ -0,0 +1,126 @@ +{ + "schema": "paperclip.prp.session-snapshot.v1", + "fixtureName": "Budget cost stop reason", + "identity": { + "schema": "paperclip.prp.identity.v1", + "companyId": "company_budget_stop", + "issueId": "issue_budget_stop", + "runId": "run_budget_stop", + "environmentLeaseId": "lease_budget_stop", + "runnerInstanceId": "runner_budget_stop", + "normalizedSessionId": "session_budget_stop", + "driverSessionId": "driver_budget_stop" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", + "sessionReusePolicy": "new_per_run", + "driver": { + "kind": "provider-neutral", + "version": "1.0.0" + }, + "steer": false, + "interrupt": true, + "resume": true, + "runtimeRequests": false, + "structuredResult": true, + "typedEvents": true, + "unsupported": [] + }, + "runPhase": "terminal", + "sessionState": "not_started", + "turnState": "not_started", + "activeTurnId": null, + "items": [], + "requests": [], + "proposedResult": { + "schema": "paperclip.run_result.v1", + "reportedWorkDisposition": "blocked", + "summary": "The actor budget reached its hard limit.", + "completionClaim": { + "contractRevision": "semantic-receipts-v1", + "objectiveSatisfied": false, + "criteria": [], + "remainingWork": [ + { + "description": "The budget owner must raise the limit or wait for reset.", + "blocksCompletion": true + } + ] + }, + "evidence": [ + { + "decisionId": "budget_decision_stop" + } + ], + "verification": [ + { + "commandOrCheck": "budget aggregate receipt", + "status": "passed" + } + ], + "blocker": { + "reasonCode": "budget_hard_stop", + "owner": { + "kind": "budget_owner" + }, + "unblockAction": "Raise the actor budget or wait for the monthly reset.", + "scope": "task_wide" + }, + "attentionRequests": [], + "artifacts": [] + }, + "terminal": { + "schema": "paperclip.prp.terminal.v1", + "turnTerminalState": "cancelled", + "runTerminalState": "cancelled", + "reportedWorkDisposition": "blocked", + "workAssessmentId": "assessment_budget_stop", + "statusDecisionId": "decision_budget_stop", + "stopReason": { + "schema": "paperclip.prp.stop_reason.v1", + "schemaVersion": 1, + "receiptId": "stop_receipt_budget", + "kind": "budget", + "code": "budget_hard_stop", + "retryable": true, + "decisionId": "budget_decision_stop", + "limitClass": "actor_monthly", + "aggregate": { + "unit": "cents", + "observed": 10000, + "limit": 10000, + "window": "monthly_utc" + }, + "relatedReceiptIds": [] + } + }, + "timeline": [ + { + "position": 1, + "sourceEventId": "budget_stop_01", + "sourceSeq": 1, + "eventType": "run.result.proposed", + "emittedAt": "2026-08-11T10:40:00.000Z", + "summary": "The actor budget reached its hard limit." + }, + { + "position": 2, + "sourceEventId": "budget_stop_02", + "sourceSeq": 2, + "eventType": "run.terminal", + "emittedAt": "2026-08-11T10:40:00.010Z", + "summary": "Run cancelled" + } + ], + "sourceCursors": { + "runner:runner_budget_stop": 2 + }, + "processedEventIds": [ + "budget_stop_01", + "budget_stop_02" + ], + "duplicateEventIds": [], + "outOfOrderEventIds": [], + "gaps": [], + "integrity": "complete" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/budget-cost-stop-reason.summary.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/budget-cost-stop-reason.summary.json new file mode 100644 index 00000000000..074746fba4e --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/budget-cost-stop-reason.summary.json @@ -0,0 +1,9 @@ +{ + "runId": "run_budget_stop", + "integrity": "complete", + "timelineCount": 2, + "duplicateEventIds": [], + "gaps": [], + "turnTerminalState": "cancelled", + "runTerminalState": "cancelled" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-artifact-happy-path.snapshot.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-artifact-happy-path.snapshot.json new file mode 100644 index 00000000000..9ea8e8baa84 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-artifact-happy-path.snapshot.json @@ -0,0 +1,136 @@ +{ + "schema": "paperclip.prp.session-snapshot.v1", + "fixtureName": "Semantic tool artifact happy path", + "identity": { + "schema": "paperclip.prp.identity.v1", + "companyId": "company_semantic_happy", + "issueId": "issue_semantic_happy", + "runId": "run_semantic_happy", + "environmentLeaseId": "lease_semantic_happy", + "runnerInstanceId": "runner_semantic_happy", + "normalizedSessionId": "session_semantic_happy", + "driverSessionId": "driver_semantic_happy" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", + "sessionReusePolicy": "new_per_run", + "driver": { + "kind": "provider-neutral", + "version": "1.0.0" + }, + "steer": true, + "interrupt": true, + "resume": true, + "runtimeRequests": true, + "structuredResult": true, + "typedEvents": true, + "semanticTools": { + "schema": "paperclip.prp.semantic_tools.v1", + "schemaVersion": 1, + "operations": [ + { + "operationId": "register_deliverable", + "version": 1, + "availability": "available", + "redactionDisposition": "digest_only", + "requiredClaims": [] + } + ] + }, + "unsupported": [] + }, + "runPhase": "terminal", + "sessionState": "not_started", + "turnState": "not_started", + "activeTurnId": null, + "items": [], + "requests": [], + "proposedResult": { + "schema": "paperclip.run_result.v1", + "reportedWorkDisposition": "done", + "summary": "The artifact was registered through the semantic tool receipt.", + "completionClaim": { + "contractRevision": "semantic-receipts-v1", + "objectiveSatisfied": true, + "criteria": [], + "remainingWork": [] + }, + "evidence": [ + { + "receiptId": "receipt_semantic_happy" + } + ], + "verification": [ + { + "commandOrCheck": "semantic artifact receipt", + "status": "passed", + "artifactRef": "artifact_semantic_happy" + } + ], + "attentionRequests": [], + "artifacts": [ + { + "kind": "artifact", + "ref": "artifact_semantic_happy", + "title": "Semantic receipt report" + } + ] + }, + "terminal": { + "schema": "paperclip.prp.terminal.v1", + "turnTerminalState": "completed", + "runTerminalState": "succeeded", + "reportedWorkDisposition": "done", + "workAssessmentId": "assessment_semantic_happy", + "statusDecisionId": "decision_semantic_happy" + }, + "timeline": [ + { + "position": 1, + "sourceEventId": "semantic_happy_01", + "sourceSeq": 1, + "eventType": "mcp_app.tool_input", + "emittedAt": "2026-08-11T10:00:00.000Z", + "itemId": "item_semantic_happy", + "summary": "mcp_app tool_input" + }, + { + "position": 2, + "sourceEventId": "semantic_happy_02", + "sourceSeq": 2, + "eventType": "mcp_app.tool_result", + "emittedAt": "2026-08-11T10:00:00.010Z", + "itemId": "item_semantic_happy", + "summary": "mcp_app tool_result" + }, + { + "position": 3, + "sourceEventId": "semantic_happy_03", + "sourceSeq": 3, + "eventType": "run.result.proposed", + "emittedAt": "2026-08-11T10:00:00.020Z", + "summary": "The artifact was registered through the semantic tool receipt." + }, + { + "position": 4, + "sourceEventId": "semantic_happy_04", + "sourceSeq": 4, + "eventType": "run.terminal", + "emittedAt": "2026-08-11T10:00:00.030Z", + "summary": "Run succeeded" + } + ], + "sourceCursors": { + "runner:runner_semantic_happy": 4 + }, + "processedEventIds": [ + "semantic_happy_01", + "semantic_happy_02", + "semantic_happy_03", + "semantic_happy_04" + ], + "duplicateEventIds": [], + "outOfOrderEventIds": [], + "gaps": [], + "integrity": "complete" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-artifact-happy-path.summary.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-artifact-happy-path.summary.json new file mode 100644 index 00000000000..9cddc8ebf6f --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-artifact-happy-path.summary.json @@ -0,0 +1,9 @@ +{ + "runId": "run_semantic_happy", + "integrity": "complete", + "timelineCount": 4, + "duplicateEventIds": [], + "gaps": [], + "turnTerminalState": "completed", + "runTerminalState": "succeeded" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-conflict-duplicate-retry.snapshot.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-conflict-duplicate-retry.snapshot.json new file mode 100644 index 00000000000..0b6121a2e01 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-conflict-duplicate-retry.snapshot.json @@ -0,0 +1,172 @@ +{ + "schema": "paperclip.prp.session-snapshot.v1", + "fixtureName": "Semantic tool conflict and duplicate retry", + "identity": { + "schema": "paperclip.prp.identity.v1", + "companyId": "company_semantic_retry", + "issueId": "issue_semantic_retry", + "runId": "run_semantic_retry", + "environmentLeaseId": "lease_semantic_retry", + "runnerInstanceId": "runner_semantic_retry", + "normalizedSessionId": "session_semantic_retry", + "driverSessionId": "driver_semantic_retry" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", + "sessionReusePolicy": "new_per_run", + "driver": { + "kind": "provider-neutral", + "version": "1.0.0" + }, + "steer": false, + "interrupt": true, + "resume": true, + "runtimeRequests": true, + "structuredResult": true, + "typedEvents": true, + "semanticTools": { + "schema": "paperclip.prp.semantic_tools.v1", + "schemaVersion": 1, + "operations": [ + { + "operationId": "write_document", + "version": 1, + "availability": "available", + "redactionDisposition": "digest_only", + "requiredClaims": [] + } + ] + }, + "unsupported": [] + }, + "runPhase": "terminal", + "sessionState": "not_started", + "turnState": "not_started", + "activeTurnId": null, + "items": [], + "requests": [], + "proposedResult": { + "schema": "paperclip.run_result.v1", + "reportedWorkDisposition": "done", + "summary": "The revision-safe retry committed once.", + "completionClaim": { + "contractRevision": "semantic-receipts-v1", + "objectiveSatisfied": true, + "criteria": [], + "remainingWork": [] + }, + "evidence": [ + { + "receiptId": "receipt_semantic_conflict" + }, + { + "receiptId": "receipt_semantic_document_commit" + } + ], + "verification": [ + { + "commandOrCheck": "conflict then exact duplicate retry", + "status": "passed" + } + ], + "attentionRequests": [], + "artifacts": [] + }, + "terminal": { + "schema": "paperclip.prp.terminal.v1", + "turnTerminalState": "completed", + "runTerminalState": "succeeded", + "reportedWorkDisposition": "done", + "workAssessmentId": "assessment_semantic_retry", + "statusDecisionId": "decision_semantic_retry" + }, + "timeline": [ + { + "position": 1, + "sourceEventId": "semantic_retry_01", + "sourceSeq": 1, + "eventType": "mcp_app.tool_input", + "emittedAt": "2026-08-11T10:20:00.000Z", + "itemId": "item_semantic_conflict", + "summary": "mcp_app tool_input" + }, + { + "position": 2, + "sourceEventId": "semantic_retry_02", + "sourceSeq": 2, + "eventType": "mcp_app.tool_result", + "emittedAt": "2026-08-11T10:20:00.010Z", + "itemId": "item_semantic_conflict", + "summary": "mcp_app tool_result" + }, + { + "position": 3, + "sourceEventId": "semantic_retry_03", + "sourceSeq": 3, + "eventType": "mcp_app.tool_input", + "emittedAt": "2026-08-11T10:20:00.020Z", + "itemId": "item_semantic_fresh", + "summary": "mcp_app tool_input" + }, + { + "position": 4, + "sourceEventId": "semantic_retry_04", + "sourceSeq": 4, + "eventType": "mcp_app.tool_result", + "emittedAt": "2026-08-11T10:20:00.030Z", + "itemId": "item_semantic_fresh", + "summary": "mcp_app tool_result" + }, + { + "position": 5, + "sourceEventId": "semantic_retry_05", + "sourceSeq": 5, + "eventType": "mcp_app.tool_input", + "emittedAt": "2026-08-11T10:20:00.040Z", + "itemId": "item_semantic_duplicate", + "summary": "mcp_app tool_input" + }, + { + "position": 6, + "sourceEventId": "semantic_retry_06", + "sourceSeq": 6, + "eventType": "mcp_app.tool_result", + "emittedAt": "2026-08-11T10:20:00.050Z", + "itemId": "item_semantic_duplicate", + "summary": "mcp_app tool_result" + }, + { + "position": 7, + "sourceEventId": "semantic_retry_07", + "sourceSeq": 7, + "eventType": "run.result.proposed", + "emittedAt": "2026-08-11T10:20:00.060Z", + "summary": "The revision-safe retry committed once." + }, + { + "position": 8, + "sourceEventId": "semantic_retry_08", + "sourceSeq": 8, + "eventType": "run.terminal", + "emittedAt": "2026-08-11T10:20:00.070Z", + "summary": "Run succeeded" + } + ], + "sourceCursors": { + "runner:runner_semantic_retry": 8 + }, + "processedEventIds": [ + "semantic_retry_01", + "semantic_retry_02", + "semantic_retry_03", + "semantic_retry_04", + "semantic_retry_05", + "semantic_retry_06", + "semantic_retry_07", + "semantic_retry_08" + ], + "duplicateEventIds": [], + "outOfOrderEventIds": [], + "gaps": [], + "integrity": "complete" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-conflict-duplicate-retry.summary.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-conflict-duplicate-retry.summary.json new file mode 100644 index 00000000000..ddbb0c594d6 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-conflict-duplicate-retry.summary.json @@ -0,0 +1,9 @@ +{ + "runId": "run_semantic_retry", + "integrity": "complete", + "timelineCount": 8, + "duplicateEventIds": [], + "gaps": [], + "turnTerminalState": "completed", + "runTerminalState": "succeeded" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-denial-redaction.snapshot.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-denial-redaction.snapshot.json new file mode 100644 index 00000000000..be9ad87df4b --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-denial-redaction.snapshot.json @@ -0,0 +1,137 @@ +{ + "schema": "paperclip.prp.session-snapshot.v1", + "fixtureName": "Semantic tool denial and redaction", + "identity": { + "schema": "paperclip.prp.identity.v1", + "companyId": "company_semantic_denied", + "issueId": "issue_semantic_denied", + "runId": "run_semantic_denied", + "environmentLeaseId": "lease_semantic_denied", + "runnerInstanceId": "runner_semantic_denied", + "normalizedSessionId": "session_semantic_denied", + "driverSessionId": "driver_semantic_denied" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", + "sessionReusePolicy": "new_per_run", + "driver": { + "kind": "provider-neutral", + "version": "1.0.0" + }, + "steer": false, + "interrupt": true, + "resume": true, + "runtimeRequests": true, + "structuredResult": true, + "typedEvents": true, + "semanticTools": { + "schema": "paperclip.prp.semantic_tools.v1", + "schemaVersion": 1, + "operations": [ + { + "operationId": "decide_approval", + "version": 1, + "availability": "denied", + "redactionDisposition": "digest_only", + "requiredClaims": [ + "governance:approvals:decide" + ], + "reasonCode": "required_claim_missing" + } + ] + }, + "unsupported": [] + }, + "runPhase": "terminal", + "sessionState": "not_started", + "turnState": "not_started", + "activeTurnId": null, + "items": [], + "requests": [], + "proposedResult": { + "schema": "paperclip.run_result.v1", + "reportedWorkDisposition": "needs_review", + "summary": "The governed action was denied without fallback.", + "completionClaim": { + "contractRevision": "semantic-receipts-v1", + "objectiveSatisfied": false, + "criteria": [], + "remainingWork": [ + { + "description": "An authorized approver must decide.", + "blocksCompletion": true + } + ] + }, + "evidence": [ + { + "receiptId": "receipt_semantic_denied" + } + ], + "verification": [ + { + "commandOrCheck": "no fallback semantic call", + "status": "passed" + } + ], + "attentionRequests": [], + "artifacts": [] + }, + "terminal": { + "schema": "paperclip.prp.terminal.v1", + "turnTerminalState": "completed", + "runTerminalState": "succeeded", + "reportedWorkDisposition": "needs_review", + "workAssessmentId": "assessment_semantic_denied", + "statusDecisionId": "decision_semantic_denied" + }, + "timeline": [ + { + "position": 1, + "sourceEventId": "semantic_denied_01", + "sourceSeq": 1, + "eventType": "mcp_app.tool_input", + "emittedAt": "2026-08-11T10:10:00.000Z", + "itemId": "item_semantic_denied", + "summary": "mcp_app tool_input" + }, + { + "position": 2, + "sourceEventId": "semantic_denied_02", + "sourceSeq": 2, + "eventType": "mcp_app.tool_result", + "emittedAt": "2026-08-11T10:10:00.010Z", + "itemId": "item_semantic_denied", + "summary": "mcp_app tool_result" + }, + { + "position": 3, + "sourceEventId": "semantic_denied_03", + "sourceSeq": 3, + "eventType": "run.result.proposed", + "emittedAt": "2026-08-11T10:10:00.020Z", + "summary": "The governed action was denied without fallback." + }, + { + "position": 4, + "sourceEventId": "semantic_denied_04", + "sourceSeq": 4, + "eventType": "run.terminal", + "emittedAt": "2026-08-11T10:10:00.030Z", + "summary": "Run succeeded" + } + ], + "sourceCursors": { + "runner:runner_semantic_denied": 4 + }, + "processedEventIds": [ + "semantic_denied_01", + "semantic_denied_02", + "semantic_denied_03", + "semantic_denied_04" + ], + "duplicateEventIds": [], + "outOfOrderEventIds": [], + "gaps": [], + "integrity": "complete" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-denial-redaction.summary.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-denial-redaction.summary.json new file mode 100644 index 00000000000..79027b0271c --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-denial-redaction.summary.json @@ -0,0 +1,9 @@ +{ + "runId": "run_semantic_denied", + "integrity": "complete", + "timelineCount": 4, + "duplicateEventIds": [], + "gaps": [], + "turnTerminalState": "completed", + "runTerminalState": "succeeded" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-governance-wake-monitor.snapshot.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-governance-wake-monitor.snapshot.json new file mode 100644 index 00000000000..e5d650b90ae --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-governance-wake-monitor.snapshot.json @@ -0,0 +1,139 @@ +{ + "schema": "paperclip.prp.session-snapshot.v1", + "fixtureName": "Semantic governance target and continuation chain", + "identity": { + "schema": "paperclip.prp.identity.v1", + "companyId": "company_semantic_governance", + "issueId": "issue_semantic_governance", + "runId": "run_semantic_governance", + "environmentLeaseId": "lease_semantic_governance", + "runnerInstanceId": "runner_semantic_governance", + "normalizedSessionId": "session_semantic_governance", + "driverSessionId": "driver_semantic_governance" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", + "sessionReusePolicy": "reuse_per_issue", + "driver": { + "kind": "provider-neutral", + "version": "1.0.0" + }, + "steer": true, + "interrupt": true, + "resume": true, + "runtimeRequests": true, + "structuredResult": true, + "typedEvents": true, + "semanticTools": { + "schema": "paperclip.prp.semantic_tools.v1", + "schemaVersion": 1, + "operations": [ + { + "operationId": "request_human_input", + "version": 1, + "availability": "available", + "redactionDisposition": "digest_only", + "requiredClaims": [] + } + ] + }, + "unsupported": [] + }, + "runPhase": "terminal", + "sessionState": "not_started", + "turnState": "not_started", + "activeTurnId": null, + "items": [], + "requests": [], + "proposedResult": { + "schema": "paperclip.run_result.v1", + "reportedWorkDisposition": "yielded", + "summary": "The immutable decision target is waiting on a bounded monitor continuation.", + "completionClaim": { + "contractRevision": "semantic-receipts-v1", + "objectiveSatisfied": false, + "criteria": [], + "remainingWork": [ + { + "description": "Wait for the interaction response.", + "blocksCompletion": true + } + ] + }, + "evidence": [ + { + "receiptId": "receipt_semantic_governance" + } + ], + "verification": [ + { + "commandOrCheck": "immutable target and causal chain", + "status": "passed" + } + ], + "attentionRequests": [], + "artifacts": [], + "continuation": { + "kind": "monitor", + "summary": "Recheck after the typed response wake.", + "idempotencyKey": "monitor_semantic_governance" + } + }, + "terminal": { + "schema": "paperclip.prp.terminal.v1", + "turnTerminalState": "completed", + "runTerminalState": "succeeded", + "reportedWorkDisposition": "yielded", + "workAssessmentId": "assessment_semantic_governance", + "statusDecisionId": "decision_semantic_governance" + }, + "timeline": [ + { + "position": 1, + "sourceEventId": "semantic_governance_01", + "sourceSeq": 1, + "eventType": "mcp_app.tool_input", + "emittedAt": "2026-08-11T10:30:00.000Z", + "itemId": "item_semantic_governance", + "summary": "mcp_app tool_input" + }, + { + "position": 2, + "sourceEventId": "semantic_governance_02", + "sourceSeq": 2, + "eventType": "mcp_app.tool_result", + "emittedAt": "2026-08-11T10:30:00.010Z", + "itemId": "item_semantic_governance", + "summary": "mcp_app tool_result" + }, + { + "position": 3, + "sourceEventId": "semantic_governance_03", + "sourceSeq": 3, + "eventType": "run.result.proposed", + "emittedAt": "2026-08-11T10:30:00.020Z", + "summary": "The immutable decision target is waiting on a bounded monitor continuation." + }, + { + "position": 4, + "sourceEventId": "semantic_governance_04", + "sourceSeq": 4, + "eventType": "run.terminal", + "emittedAt": "2026-08-11T10:30:00.030Z", + "summary": "Run succeeded" + } + ], + "sourceCursors": { + "runner:runner_semantic_governance": 4 + }, + "processedEventIds": [ + "semantic_governance_01", + "semantic_governance_02", + "semantic_governance_03", + "semantic_governance_04" + ], + "duplicateEventIds": [], + "outOfOrderEventIds": [], + "gaps": [], + "integrity": "complete" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-governance-wake-monitor.summary.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-governance-wake-monitor.summary.json new file mode 100644 index 00000000000..4e380b27978 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-governance-wake-monitor.summary.json @@ -0,0 +1,9 @@ +{ + "runId": "run_semantic_governance", + "integrity": "complete", + "timelineCount": 4, + "duplicateEventIds": [], + "gaps": [], + "turnTerminalState": "completed", + "runTerminalState": "succeeded" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-unknown-optional-envelope.snapshot.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-unknown-optional-envelope.snapshot.json new file mode 100644 index 00000000000..df5576fb66d --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-unknown-optional-envelope.snapshot.json @@ -0,0 +1,133 @@ +{ + "schema": "paperclip.prp.session-snapshot.v1", + "fixtureName": "Semantic tool unknown optional envelope fields", + "identity": { + "schema": "paperclip.prp.identity.v1", + "companyId": "company_semantic_future", + "issueId": "issue_semantic_future", + "runId": "run_semantic_future", + "environmentLeaseId": "lease_semantic_future", + "runnerInstanceId": "runner_semantic_future", + "normalizedSessionId": "session_semantic_future", + "driverSessionId": "driver_semantic_future" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", + "sessionReusePolicy": "new_per_run", + "driver": { + "kind": "provider-neutral", + "version": "1.0.0" + }, + "steer": false, + "interrupt": true, + "resume": true, + "runtimeRequests": false, + "structuredResult": true, + "typedEvents": true, + "semanticTools": { + "schema": "paperclip.prp.semantic_tools.v1", + "schemaVersion": 1, + "operations": [ + { + "operationId": "get_task_context", + "version": 1, + "availability": "available", + "redactionDisposition": "digest_only", + "requiredClaims": [], + "futureAvailabilityHint": "optional" + } + ], + "futureNegotiationHint": { + "safe": true + } + }, + "unsupported": [] + }, + "runPhase": "terminal", + "sessionState": "not_started", + "turnState": "not_started", + "activeTurnId": null, + "items": [], + "requests": [], + "proposedResult": { + "schema": "paperclip.run_result.v1", + "reportedWorkDisposition": "done", + "summary": "Unknown optional receipt fields were ignored by the v1 projection.", + "completionClaim": { + "contractRevision": "semantic-receipts-v1", + "objectiveSatisfied": true, + "criteria": [], + "remainingWork": [] + }, + "evidence": [ + { + "receiptId": "receipt_semantic_future" + } + ], + "verification": [ + { + "commandOrCheck": "optional field projection stability", + "status": "passed" + } + ], + "attentionRequests": [], + "artifacts": [] + }, + "terminal": { + "schema": "paperclip.prp.terminal.v1", + "turnTerminalState": "completed", + "runTerminalState": "succeeded", + "reportedWorkDisposition": "done", + "workAssessmentId": "assessment_semantic_future", + "statusDecisionId": "decision_semantic_future" + }, + "timeline": [ + { + "position": 1, + "sourceEventId": "semantic_future_01", + "sourceSeq": 1, + "eventType": "mcp_app.tool_input", + "emittedAt": "2026-08-11T10:50:00.000Z", + "itemId": "item_semantic_future", + "summary": "mcp_app tool_input" + }, + { + "position": 2, + "sourceEventId": "semantic_future_02", + "sourceSeq": 2, + "eventType": "mcp_app.tool_result", + "emittedAt": "2026-08-11T10:50:00.010Z", + "itemId": "item_semantic_future", + "summary": "mcp_app tool_result" + }, + { + "position": 3, + "sourceEventId": "semantic_future_03", + "sourceSeq": 3, + "eventType": "run.result.proposed", + "emittedAt": "2026-08-11T10:50:00.020Z", + "summary": "Unknown optional receipt fields were ignored by the v1 projection." + }, + { + "position": 4, + "sourceEventId": "semantic_future_04", + "sourceSeq": 4, + "eventType": "run.terminal", + "emittedAt": "2026-08-11T10:50:00.030Z", + "summary": "Run succeeded" + } + ], + "sourceCursors": { + "runner:runner_semantic_future": 4 + }, + "processedEventIds": [ + "semantic_future_01", + "semantic_future_02", + "semantic_future_03", + "semantic_future_04" + ], + "duplicateEventIds": [], + "outOfOrderEventIds": [], + "gaps": [], + "integrity": "complete" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-unknown-optional-envelope.summary.json b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-unknown-optional-envelope.summary.json new file mode 100644 index 00000000000..97efecb1d3d --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/golden/semantic-tool-unknown-optional-envelope.summary.json @@ -0,0 +1,9 @@ +{ + "runId": "run_semantic_future", + "integrity": "complete", + "timelineCount": 4, + "duplicateEventIds": [], + "gaps": [], + "turnTerminalState": "completed", + "runTerminalState": "succeeded" +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-artifact-happy-path.json b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-artifact-happy-path.json new file mode 100644 index 00000000000..d84d3202af9 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-artifact-happy-path.json @@ -0,0 +1,186 @@ +{ + "schema": "paperclip.prp.fixture.v1", + "fixtureVersion": 1, + "protocolVersion": 1, + "name": "Semantic tool artifact happy path", + "description": "A provider-neutral register_deliverable call emits safe input and result receipts linked to the terminal artifact result.", + "identity": { + "schema": "paperclip.prp.identity.v1", + "companyId": "company_semantic_happy", + "issueId": "issue_semantic_happy", + "runId": "run_semantic_happy", + "environmentLeaseId": "lease_semantic_happy", + "runnerInstanceId": "runner_semantic_happy", + "normalizedSessionId": "session_semantic_happy", + "driverSessionId": "driver_semantic_happy" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", + "sessionReusePolicy": "new_per_run", + "driver": { "kind": "provider-neutral", "version": "1.0.0" }, + "steer": true, + "interrupt": true, + "resume": true, + "runtimeRequests": true, + "structuredResult": true, + "typedEvents": true, + "semanticTools": { + "schema": "paperclip.prp.semantic_tools.v1", + "schemaVersion": 1, + "operations": [{ + "operationId": "register_deliverable", + "version": 1, + "availability": "available", + "redactionDisposition": "digest_only", + "requiredClaims": [] + }] + }, + "unsupported": [] + }, + "commands": [], + "events": [ + { + "schema": "paperclip.prp.event.v1", + "sourceEventId": "semantic_happy_01", + "sourceSeq": 1, + "sourceInstanceId": "runner_semantic_happy", + "sourceKind": "runner", + "runId": "run_semantic_happy", + "normalizedSessionId": "session_semantic_happy", + "turnId": "turn_semantic_happy", + "itemId": "item_semantic_happy", + "eventType": "mcp_app.tool_input", + "schemaVersion": 1, + "priority": 1, + "emittedAt": "2026-08-11T10:00:00.000Z", + "payload": { + "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", + "schemaVersion": 1, + "phase": "input", + "operationId": "register_deliverable", + "callId": "call_semantic_happy", + "correlation": { + "runId": "run_semantic_happy", + "normalizedSessionId": "session_semantic_happy", + "turnId": "turn_semantic_happy", + "itemId": "item_semantic_happy" + }, + "idempotencyKey": "artifact_once", + "content": { + "digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "redactionDisposition": "digest_only", + "references": [{ "kind": "task", "id": "issue_semantic_happy" }] + } + } + } + }, + { + "schema": "paperclip.prp.event.v1", + "sourceEventId": "semantic_happy_02", + "sourceSeq": 2, + "sourceInstanceId": "runner_semantic_happy", + "sourceKind": "runner", + "runId": "run_semantic_happy", + "normalizedSessionId": "session_semantic_happy", + "turnId": "turn_semantic_happy", + "itemId": "item_semantic_happy", + "eventType": "mcp_app.tool_result", + "schemaVersion": 1, + "priority": 1, + "emittedAt": "2026-08-11T10:00:00.010Z", + "payload": { + "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", + "schemaVersion": 1, + "phase": "result", + "operationId": "register_deliverable", + "callId": "call_semantic_happy", + "correlation": { + "runId": "run_semantic_happy", + "normalizedSessionId": "session_semantic_happy", + "turnId": "turn_semantic_happy", + "itemId": "item_semantic_happy" + }, + "idempotencyKey": "artifact_once", + "content": { + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "redactionDisposition": "allowlisted_references", + "references": [ + { "kind": "artifact", "id": "artifact_semantic_happy" }, + { "kind": "work_product", "id": "work_product_semantic_happy" } + ] + }, + "outcome": "succeeded", + "code": "ok", + "retryable": false, + "authorizationBoundary": "active_task", + "operationReceiptId": "receipt_semantic_happy", + "auditReceiptId": "audit_semantic_happy", + "currentRevision": 2, + "artifactRefs": [ + { "kind": "artifact", "id": "artifact_semantic_happy" }, + { "kind": "work_product", "id": "work_product_semantic_happy" } + ] + } + } + }, + { + "schema": "paperclip.prp.event.v1", + "sourceEventId": "semantic_happy_03", + "sourceSeq": 3, + "sourceInstanceId": "runner_semantic_happy", + "sourceKind": "runner", + "runId": "run_semantic_happy", + "normalizedSessionId": "session_semantic_happy", + "turnId": "turn_semantic_happy", + "eventType": "run.result.proposed", + "schemaVersion": 1, + "priority": 0, + "emittedAt": "2026-08-11T10:00:00.020Z", + "payload": { + "schema": "paperclip.run_result.v1", + "reportedWorkDisposition": "done", + "summary": "The artifact was registered through the semantic tool receipt.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": true, "criteria": [], "remainingWork": [] }, + "evidence": [{ "receiptId": "receipt_semantic_happy" }], + "verification": [{ "commandOrCheck": "semantic artifact receipt", "status": "passed", "artifactRef": "artifact_semantic_happy" }], + "attentionRequests": [], + "artifacts": [{ "kind": "artifact", "ref": "artifact_semantic_happy", "title": "Semantic receipt report" }] + } + }, + { + "schema": "paperclip.prp.event.v1", + "sourceEventId": "semantic_happy_04", + "sourceSeq": 4, + "sourceInstanceId": "runner_semantic_happy", + "sourceKind": "runner", + "runId": "run_semantic_happy", + "normalizedSessionId": "session_semantic_happy", + "turnId": "turn_semantic_happy", + "eventType": "run.terminal", + "schemaVersion": 1, + "priority": 0, + "emittedAt": "2026-08-11T10:00:00.030Z", + "payload": { + "schema": "paperclip.prp.terminal.v1", + "turnTerminalState": "completed", + "runTerminalState": "succeeded", + "reportedWorkDisposition": "done", + "workAssessmentId": "assessment_semantic_happy", + "statusDecisionId": "decision_semantic_happy" + } + } + ], + "requests": [], + "result": { + "schema": "paperclip.run_result.v1", + "reportedWorkDisposition": "done", + "summary": "The artifact was registered through the semantic tool receipt.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": true, "criteria": [], "remainingWork": [] }, + "evidence": [{ "receiptId": "receipt_semantic_happy" }], + "verification": [{ "commandOrCheck": "semantic artifact receipt", "status": "passed", "artifactRef": "artifact_semantic_happy" }], + "attentionRequests": [], + "artifacts": [{ "kind": "artifact", "ref": "artifact_semantic_happy", "title": "Semantic receipt report" }] + } +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-conflict-duplicate-retry.json b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-conflict-duplicate-retry.json new file mode 100644 index 00000000000..ef3b6a91c11 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-conflict-duplicate-retry.json @@ -0,0 +1,120 @@ +{ + "schema": "paperclip.prp.fixture.v1", + "fixtureVersion": 1, + "protocolVersion": 1, + "name": "Semantic tool conflict and duplicate retry", + "description": "A stale document write conflicts, a fresh retry succeeds, and an exact idempotent retry returns the original operation receipt.", + "identity": { + "schema": "paperclip.prp.identity.v1", "companyId": "company_semantic_retry", "issueId": "issue_semantic_retry", + "runId": "run_semantic_retry", "environmentLeaseId": "lease_semantic_retry", "runnerInstanceId": "runner_semantic_retry", + "normalizedSessionId": "session_semantic_retry", "driverSessionId": "driver_semantic_retry" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", "sessionReusePolicy": "new_per_run", + "driver": { "kind": "provider-neutral", "version": "1.0.0" }, + "steer": false, "interrupt": true, "resume": true, "runtimeRequests": true, "structuredResult": true, "typedEvents": true, + "semanticTools": { "schema": "paperclip.prp.semantic_tools.v1", "schemaVersion": 1, "operations": [{ + "operationId": "write_document", "version": 1, "availability": "available", "redactionDisposition": "digest_only", "requiredClaims": [] + }] }, + "unsupported": [] + }, + "commands": [], + "events": [ + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_retry_01", "sourceSeq": 1, "sourceInstanceId": "runner_semantic_retry", + "sourceKind": "runner", "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", + "itemId": "item_semantic_conflict", "eventType": "mcp_app.tool_input", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:20:00.000Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "input", "operationId": "write_document", "callId": "call_semantic_conflict", + "correlation": { "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", "itemId": "item_semantic_conflict" }, + "idempotencyKey": "write_plan_stale", + "content": { "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111", "redactionDisposition": "digest_only", "references": [{ "kind": "document_revision", "id": "revision_plan_stale" }] } + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_retry_02", "sourceSeq": 2, "sourceInstanceId": "runner_semantic_retry", + "sourceKind": "runner", "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", + "itemId": "item_semantic_conflict", "eventType": "mcp_app.tool_result", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:20:00.010Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "result", "operationId": "write_document", "callId": "call_semantic_conflict", + "correlation": { "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", "itemId": "item_semantic_conflict" }, + "idempotencyKey": "write_plan_stale", + "content": { "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222", "redactionDisposition": "allowlisted_references", "references": [{ "kind": "document_revision", "id": "revision_plan_2" }] }, + "outcome": "conflict", "code": "document_revision_conflict", "retryable": true, "authorizationBoundary": "revision", + "operationReceiptId": "receipt_semantic_conflict", "auditReceiptId": "audit_semantic_conflict", "currentRevision": "revision_plan_2" + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_retry_03", "sourceSeq": 3, "sourceInstanceId": "runner_semantic_retry", + "sourceKind": "runner", "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", + "itemId": "item_semantic_fresh", "eventType": "mcp_app.tool_input", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:20:00.020Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "input", "operationId": "write_document", "callId": "call_semantic_fresh", + "correlation": { "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", "itemId": "item_semantic_fresh" }, + "idempotencyKey": "write_plan_retry", + "content": { "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333", "redactionDisposition": "digest_only", "references": [{ "kind": "document_revision", "id": "revision_plan_2" }] } + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_retry_04", "sourceSeq": 4, "sourceInstanceId": "runner_semantic_retry", + "sourceKind": "runner", "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", + "itemId": "item_semantic_fresh", "eventType": "mcp_app.tool_result", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:20:00.030Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "result", "operationId": "write_document", "callId": "call_semantic_fresh", + "correlation": { "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", "itemId": "item_semantic_fresh" }, + "idempotencyKey": "write_plan_retry", + "content": { "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444", "redactionDisposition": "allowlisted_references", "references": [{ "kind": "document_revision", "id": "revision_plan_3" }] }, + "outcome": "succeeded", "code": "ok", "retryable": false, "authorizationBoundary": "revision", + "operationReceiptId": "receipt_semantic_document_commit", "auditReceiptId": "audit_semantic_document_commit", "currentRevision": "revision_plan_3" + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_retry_05", "sourceSeq": 5, "sourceInstanceId": "runner_semantic_retry", + "sourceKind": "runner", "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", + "itemId": "item_semantic_duplicate", "eventType": "mcp_app.tool_input", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:20:00.040Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "input", "operationId": "write_document", "callId": "call_semantic_duplicate", + "correlation": { "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", "itemId": "item_semantic_duplicate" }, + "idempotencyKey": "write_plan_retry", + "content": { "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333", "redactionDisposition": "digest_only", "references": [{ "kind": "document_revision", "id": "revision_plan_2" }] } + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_retry_06", "sourceSeq": 6, "sourceInstanceId": "runner_semantic_retry", + "sourceKind": "runner", "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", + "itemId": "item_semantic_duplicate", "eventType": "mcp_app.tool_result", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:20:00.050Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "result", "operationId": "write_document", "callId": "call_semantic_duplicate", + "correlation": { "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", "itemId": "item_semantic_duplicate" }, + "idempotencyKey": "write_plan_retry", + "content": { "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444", "redactionDisposition": "allowlisted_references", "references": [{ "kind": "document_revision", "id": "revision_plan_3" }] }, + "outcome": "duplicate", "code": "duplicate", "retryable": false, "authorizationBoundary": "revision", + "operationReceiptId": "receipt_semantic_document_commit", "duplicateOfReceiptId": "receipt_semantic_document_commit", "currentRevision": "revision_plan_3" + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_retry_07", "sourceSeq": 7, "sourceInstanceId": "runner_semantic_retry", + "sourceKind": "runner", "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", + "eventType": "run.result.proposed", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:20:00.060Z", + "payload": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "done", "summary": "The revision-safe retry committed once.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": true, "criteria": [], "remainingWork": [] }, + "evidence": [{ "receiptId": "receipt_semantic_conflict" }, { "receiptId": "receipt_semantic_document_commit" }], + "verification": [{ "commandOrCheck": "conflict then exact duplicate retry", "status": "passed" }], "attentionRequests": [], "artifacts": [] + } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_retry_08", "sourceSeq": 8, "sourceInstanceId": "runner_semantic_retry", + "sourceKind": "runner", "runId": "run_semantic_retry", "normalizedSessionId": "session_semantic_retry", "turnId": "turn_semantic_retry", + "eventType": "run.terminal", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:20:00.070Z", + "payload": { "schema": "paperclip.prp.terminal.v1", "turnTerminalState": "completed", "runTerminalState": "succeeded", "reportedWorkDisposition": "done", "workAssessmentId": "assessment_semantic_retry", "statusDecisionId": "decision_semantic_retry" } + } + ], + "requests": [], + "result": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "done", "summary": "The revision-safe retry committed once.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": true, "criteria": [], "remainingWork": [] }, + "evidence": [{ "receiptId": "receipt_semantic_conflict" }, { "receiptId": "receipt_semantic_document_commit" }], + "verification": [{ "commandOrCheck": "conflict then exact duplicate retry", "status": "passed" }], "attentionRequests": [], "artifacts": [] + } +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-denial-redaction.json b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-denial-redaction.json new file mode 100644 index 00000000000..eab3a516ed8 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-denial-redaction.json @@ -0,0 +1,102 @@ +{ + "schema": "paperclip.prp.fixture.v1", + "fixtureVersion": 1, + "protocolVersion": 1, + "name": "Semantic tool denial and redaction", + "description": "A governed action is denied with digest-only content, a typed authorization boundary, and no fallback semantic call.", + "identity": { + "schema": "paperclip.prp.identity.v1", + "companyId": "company_semantic_denied", + "issueId": "issue_semantic_denied", + "runId": "run_semantic_denied", + "environmentLeaseId": "lease_semantic_denied", + "runnerInstanceId": "runner_semantic_denied", + "normalizedSessionId": "session_semantic_denied", + "driverSessionId": "driver_semantic_denied" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", + "sessionReusePolicy": "new_per_run", + "driver": { "kind": "provider-neutral", "version": "1.0.0" }, + "steer": false, + "interrupt": true, + "resume": true, + "runtimeRequests": true, + "structuredResult": true, + "typedEvents": true, + "semanticTools": { + "schema": "paperclip.prp.semantic_tools.v1", + "schemaVersion": 1, + "operations": [{ + "operationId": "decide_approval", + "version": 1, + "availability": "denied", + "redactionDisposition": "digest_only", + "requiredClaims": ["governance:approvals:decide"], + "reasonCode": "required_claim_missing" + }] + }, + "unsupported": [] + }, + "commands": [], + "events": [ + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_denied_01", "sourceSeq": 1, + "sourceInstanceId": "runner_semantic_denied", "sourceKind": "runner", "runId": "run_semantic_denied", + "normalizedSessionId": "session_semantic_denied", "turnId": "turn_semantic_denied", "itemId": "item_semantic_denied", + "eventType": "mcp_app.tool_input", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:10:00.000Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "input", + "operationId": "decide_approval", "callId": "call_semantic_denied", + "correlation": { "runId": "run_semantic_denied", "normalizedSessionId": "session_semantic_denied", "turnId": "turn_semantic_denied", "itemId": "item_semantic_denied" }, + "idempotencyKey": "denied_once", + "content": { "digest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", "redactionDisposition": "redacted", "references": [] } + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_denied_02", "sourceSeq": 2, + "sourceInstanceId": "runner_semantic_denied", "sourceKind": "runner", "runId": "run_semantic_denied", + "normalizedSessionId": "session_semantic_denied", "turnId": "turn_semantic_denied", "itemId": "item_semantic_denied", + "eventType": "mcp_app.tool_result", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:10:00.010Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "result", + "operationId": "decide_approval", "callId": "call_semantic_denied", + "correlation": { "runId": "run_semantic_denied", "normalizedSessionId": "session_semantic_denied", "turnId": "turn_semantic_denied", "itemId": "item_semantic_denied" }, + "idempotencyKey": "denied_once", + "content": { "digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "redactionDisposition": "redacted", "references": [] }, + "outcome": "denied", "code": "required_claim_missing", "retryable": false, + "authorizationBoundary": "grant", "operationReceiptId": "receipt_semantic_denied", "auditReceiptId": "audit_semantic_denied", "currentRevision": 4 + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_denied_03", "sourceSeq": 3, + "sourceInstanceId": "runner_semantic_denied", "sourceKind": "runner", "runId": "run_semantic_denied", + "normalizedSessionId": "session_semantic_denied", "turnId": "turn_semantic_denied", + "eventType": "run.result.proposed", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:10:00.020Z", + "payload": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "needs_review", + "summary": "The governed action was denied without fallback.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": false, "criteria": [], "remainingWork": [{ "description": "An authorized approver must decide.", "blocksCompletion": true }] }, + "evidence": [{ "receiptId": "receipt_semantic_denied" }], + "verification": [{ "commandOrCheck": "no fallback semantic call", "status": "passed" }], + "attentionRequests": [], "artifacts": [] + } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_denied_04", "sourceSeq": 4, + "sourceInstanceId": "runner_semantic_denied", "sourceKind": "runner", "runId": "run_semantic_denied", + "normalizedSessionId": "session_semantic_denied", "turnId": "turn_semantic_denied", + "eventType": "run.terminal", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:10:00.030Z", + "payload": { "schema": "paperclip.prp.terminal.v1", "turnTerminalState": "completed", "runTerminalState": "succeeded", "reportedWorkDisposition": "needs_review", "workAssessmentId": "assessment_semantic_denied", "statusDecisionId": "decision_semantic_denied" } + } + ], + "requests": [], + "result": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "needs_review", + "summary": "The governed action was denied without fallback.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": false, "criteria": [], "remainingWork": [{ "description": "An authorized approver must decide.", "blocksCompletion": true }] }, + "evidence": [{ "receiptId": "receipt_semantic_denied" }], + "verification": [{ "commandOrCheck": "no fallback semantic call", "status": "passed" }], + "attentionRequests": [], "artifacts": [] + } +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-governance-wake-monitor.json b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-governance-wake-monitor.json new file mode 100644 index 00000000000..98735d3a58b --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-governance-wake-monitor.json @@ -0,0 +1,90 @@ +{ + "schema": "paperclip.prp.fixture.v1", + "fixtureVersion": 1, + "protocolVersion": 1, + "name": "Semantic governance target and continuation chain", + "description": "A semantic result binds immutable interaction and approval targets while carrying only safe wake and monitor causal references.", + "identity": { + "schema": "paperclip.prp.identity.v1", "companyId": "company_semantic_governance", "issueId": "issue_semantic_governance", + "runId": "run_semantic_governance", "environmentLeaseId": "lease_semantic_governance", "runnerInstanceId": "runner_semantic_governance", + "normalizedSessionId": "session_semantic_governance", "driverSessionId": "driver_semantic_governance" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", "sessionReusePolicy": "reuse_per_issue", + "driver": { "kind": "provider-neutral", "version": "1.0.0" }, + "steer": true, "interrupt": true, "resume": true, "runtimeRequests": true, "structuredResult": true, "typedEvents": true, + "semanticTools": { "schema": "paperclip.prp.semantic_tools.v1", "schemaVersion": 1, "operations": [{ + "operationId": "request_human_input", "version": 1, "availability": "available", "redactionDisposition": "digest_only", "requiredClaims": [] + }] }, + "unsupported": [] + }, + "commands": [], + "events": [ + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_governance_01", "sourceSeq": 1, "sourceInstanceId": "runner_semantic_governance", + "sourceKind": "runner", "runId": "run_semantic_governance", "normalizedSessionId": "session_semantic_governance", + "turnId": "turn_semantic_governance", "itemId": "item_semantic_governance", "eventType": "mcp_app.tool_input", + "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:30:00.000Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "input", "operationId": "request_human_input", "callId": "call_semantic_governance", + "correlation": { "runId": "run_semantic_governance", "normalizedSessionId": "session_semantic_governance", "turnId": "turn_semantic_governance", "itemId": "item_semantic_governance", "requestId": "request_semantic_governance" }, + "idempotencyKey": "interaction_once", + "content": { "digest": "sha256:5555555555555555555555555555555555555555555555555555555555555555", "redactionDisposition": "digest_only", "references": [{ "kind": "document_revision", "id": "revision_plan_7" }] } + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_governance_02", "sourceSeq": 2, "sourceInstanceId": "runner_semantic_governance", + "sourceKind": "runner", "runId": "run_semantic_governance", "normalizedSessionId": "session_semantic_governance", + "turnId": "turn_semantic_governance", "itemId": "item_semantic_governance", "eventType": "mcp_app.tool_result", + "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:30:00.010Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "result", "operationId": "request_human_input", "callId": "call_semantic_governance", + "correlation": { "runId": "run_semantic_governance", "normalizedSessionId": "session_semantic_governance", "turnId": "turn_semantic_governance", "itemId": "item_semantic_governance", "requestId": "request_semantic_governance" }, + "idempotencyKey": "interaction_once", + "content": { "digest": "sha256:6666666666666666666666666666666666666666666666666666666666666666", "redactionDisposition": "allowlisted_references", "references": [{ "kind": "interaction", "id": "interaction_semantic_governance" }, { "kind": "wake", "id": "wake_semantic_governance" }, { "kind": "monitor", "id": "monitor_semantic_governance" }] }, + "outcome": "succeeded", "code": "ok", "retryable": false, "authorizationBoundary": "governed_action", + "operationReceiptId": "receipt_semantic_governance", "auditReceiptId": "audit_semantic_governance", "currentRevision": 8, + "targets": [ + { "kind": "interaction", "id": "interaction_semantic_governance", "immutable": true, "revisionId": "revision_plan_7" }, + { "kind": "approval", "id": "approval_semantic_governance", "immutable": true, "decisionId": "decision_approval_semantic_governance" } + ], + "causalRefs": [ + { "kind": "document_revision", "id": "revision_plan_7" }, + { "kind": "interaction", "id": "interaction_semantic_governance" }, + { "kind": "approval", "id": "approval_semantic_governance" }, + { "kind": "decision", "id": "decision_approval_semantic_governance" }, + { "kind": "wake", "id": "wake_semantic_governance" }, + { "kind": "monitor", "id": "monitor_semantic_governance" } + ] + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_governance_03", "sourceSeq": 3, "sourceInstanceId": "runner_semantic_governance", + "sourceKind": "runner", "runId": "run_semantic_governance", "normalizedSessionId": "session_semantic_governance", "turnId": "turn_semantic_governance", + "eventType": "run.result.proposed", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:30:00.020Z", + "payload": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "yielded", "summary": "The immutable decision target is waiting on a bounded monitor continuation.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": false, "criteria": [], "remainingWork": [{ "description": "Wait for the interaction response.", "blocksCompletion": true }] }, + "evidence": [{ "receiptId": "receipt_semantic_governance" }], + "verification": [{ "commandOrCheck": "immutable target and causal chain", "status": "passed" }], + "attentionRequests": [], "artifacts": [], + "continuation": { "kind": "monitor", "summary": "Recheck after the typed response wake.", "idempotencyKey": "monitor_semantic_governance" } + } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_governance_04", "sourceSeq": 4, "sourceInstanceId": "runner_semantic_governance", + "sourceKind": "runner", "runId": "run_semantic_governance", "normalizedSessionId": "session_semantic_governance", "turnId": "turn_semantic_governance", + "eventType": "run.terminal", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:30:00.030Z", + "payload": { "schema": "paperclip.prp.terminal.v1", "turnTerminalState": "completed", "runTerminalState": "succeeded", "reportedWorkDisposition": "yielded", "workAssessmentId": "assessment_semantic_governance", "statusDecisionId": "decision_semantic_governance" } + } + ], + "requests": [], + "result": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "yielded", "summary": "The immutable decision target is waiting on a bounded monitor continuation.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": false, "criteria": [], "remainingWork": [{ "description": "Wait for the interaction response.", "blocksCompletion": true }] }, + "evidence": [{ "receiptId": "receipt_semantic_governance" }], + "verification": [{ "commandOrCheck": "immutable target and causal chain", "status": "passed" }], + "attentionRequests": [], "artifacts": [], + "continuation": { "kind": "monitor", "summary": "Recheck after the typed response wake.", "idempotencyKey": "monitor_semantic_governance" } + } +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-unknown-optional-envelope.json b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-unknown-optional-envelope.json new file mode 100644 index 00000000000..e763dd43ef0 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-unknown-optional-envelope.json @@ -0,0 +1,72 @@ +{ + "schema": "paperclip.prp.fixture.v1", + "fixtureVersion": 1, + "protocolVersion": 1, + "name": "Semantic tool unknown optional envelope fields", + "description": "Unknown additive fields inside typed semantic envelopes validate without changing the existing v1 reducer projection.", + "identity": { + "schema": "paperclip.prp.identity.v1", "companyId": "company_semantic_future", "issueId": "issue_semantic_future", "runId": "run_semantic_future", + "environmentLeaseId": "lease_semantic_future", "runnerInstanceId": "runner_semantic_future", "normalizedSessionId": "session_semantic_future", "driverSessionId": "driver_semantic_future" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", "sessionReusePolicy": "new_per_run", "driver": { "kind": "provider-neutral", "version": "1.0.0" }, + "steer": false, "interrupt": true, "resume": true, "runtimeRequests": false, "structuredResult": true, "typedEvents": true, + "semanticTools": { "schema": "paperclip.prp.semantic_tools.v1", "schemaVersion": 1, "operations": [{ + "operationId": "get_task_context", "version": 1, "availability": "available", "redactionDisposition": "digest_only", "requiredClaims": [], + "futureAvailabilityHint": "optional" + }], "futureNegotiationHint": { "safe": true } }, + "unsupported": [] + }, + "commands": [], + "events": [ + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_future_01", "sourceSeq": 1, "sourceInstanceId": "runner_semantic_future", + "sourceKind": "runner", "runId": "run_semantic_future", "normalizedSessionId": "session_semantic_future", "turnId": "turn_semantic_future", "itemId": "item_semantic_future", + "eventType": "mcp_app.tool_input", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:50:00.000Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "input", "operationId": "get_task_context", "callId": "call_semantic_future", + "correlation": { "runId": "run_semantic_future", "normalizedSessionId": "session_semantic_future", "turnId": "turn_semantic_future", "itemId": "item_semantic_future", "futureCorrelationHint": 1 }, + "idempotencyKey": null, + "content": { "digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777", "redactionDisposition": "digest_only", "references": [], "futureContentHint": "optional" }, + "futureEnvelopeHint": { "version": "1.1-preview" } + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_future_02", "sourceSeq": 2, "sourceInstanceId": "runner_semantic_future", + "sourceKind": "runner", "runId": "run_semantic_future", "normalizedSessionId": "session_semantic_future", "turnId": "turn_semantic_future", "itemId": "item_semantic_future", + "eventType": "mcp_app.tool_result", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T10:50:00.010Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "result", "operationId": "get_task_context", "callId": "call_semantic_future", + "correlation": { "runId": "run_semantic_future", "normalizedSessionId": "session_semantic_future", "turnId": "turn_semantic_future", "itemId": "item_semantic_future", "futureCorrelationHint": 1 }, + "idempotencyKey": null, + "content": { "digest": "sha256:8888888888888888888888888888888888888888888888888888888888888888", "redactionDisposition": "digest_only", "references": [{ "kind": "task", "id": "issue_semantic_future" }], "futureContentHint": "optional" }, + "outcome": "succeeded", "code": "ok", "retryable": false, "authorizationBoundary": "active_task", "operationReceiptId": "receipt_semantic_future", "currentRevision": 1, + "futureEnvelopeHint": { "version": "1.1-preview" } + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_future_03", "sourceSeq": 3, "sourceInstanceId": "runner_semantic_future", + "sourceKind": "runner", "runId": "run_semantic_future", "normalizedSessionId": "session_semantic_future", "turnId": "turn_semantic_future", + "eventType": "run.result.proposed", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:50:00.020Z", + "payload": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "done", "summary": "Unknown optional receipt fields were ignored by the v1 projection.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": true, "criteria": [], "remainingWork": [] }, + "evidence": [{ "receiptId": "receipt_semantic_future" }], "verification": [{ "commandOrCheck": "optional field projection stability", "status": "passed" }], + "attentionRequests": [], "artifacts": [] + } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_future_04", "sourceSeq": 4, "sourceInstanceId": "runner_semantic_future", + "sourceKind": "runner", "runId": "run_semantic_future", "normalizedSessionId": "session_semantic_future", "turnId": "turn_semantic_future", + "eventType": "run.terminal", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T10:50:00.030Z", + "payload": { "schema": "paperclip.prp.terminal.v1", "turnTerminalState": "completed", "runTerminalState": "succeeded", "reportedWorkDisposition": "done", "workAssessmentId": "assessment_semantic_future", "statusDecisionId": "decision_semantic_future" } + } + ], + "requests": [], + "result": { + "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "done", "summary": "Unknown optional receipt fields were ignored by the v1 projection.", + "completionClaim": { "contractRevision": "semantic-receipts-v1", "objectiveSatisfied": true, "criteria": [], "remainingWork": [] }, + "evidence": [{ "receiptId": "receipt_semantic_future" }], "verification": [{ "commandOrCheck": "optional field projection stability", "status": "passed" }], + "attentionRequests": [], "artifacts": [] + } +} diff --git a/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-unsupported-required-version.json b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-unsupported-required-version.json new file mode 100644 index 00000000000..6230b4e4439 --- /dev/null +++ b/packages/paperclip-runner/protocol/fixtures/replay/semantic-tool-unsupported-required-version.json @@ -0,0 +1,55 @@ +{ + "schema": "paperclip.prp.fixture.v1", + "fixtureVersion": 1, + "protocolVersion": 1, + "name": "Unsupported semantic tool envelope version", + "description": "A required semantic_tool v2 envelope must fail closed in a PRP v1 consumer.", + "identity": { + "schema": "paperclip.prp.identity.v1", "companyId": "company_semantic_v2", "issueId": "issue_semantic_v2", "runId": "run_semantic_v2", + "environmentLeaseId": "lease_semantic_v2", "runnerInstanceId": "runner_semantic_v2", "normalizedSessionId": "session_semantic_v2", "driverSessionId": "driver_semantic_v2" + }, + "capabilities": { + "schema": "paperclip.prp.capabilities.v1", "sessionReusePolicy": "new_per_run", "driver": { "kind": "provider-neutral", "version": "1.0.0" }, + "steer": false, "interrupt": true, "resume": true, "runtimeRequests": false, "structuredResult": true, "typedEvents": true, "unsupported": [] + }, + "commands": [], + "events": [ + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_v2_01", "sourceSeq": 1, "sourceInstanceId": "runner_semantic_v2", + "sourceKind": "runner", "runId": "run_semantic_v2", "normalizedSessionId": "session_semantic_v2", "turnId": "turn_semantic_v2", "itemId": "item_semantic_v2", + "eventType": "mcp_app.tool_input", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T11:00:00.000Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v2", "schemaVersion": 2, "phase": "input", "operationId": "get_task_context", "callId": "call_semantic_v2", + "correlation": { "runId": "run_semantic_v2", "normalizedSessionId": "session_semantic_v2", "turnId": "turn_semantic_v2", "itemId": "item_semantic_v2" }, + "idempotencyKey": null, + "content": { "digest": "sha256:9999999999999999999999999999999999999999999999999999999999999999", "redactionDisposition": "digest_only", "references": [] } + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_v2_02", "sourceSeq": 2, "sourceInstanceId": "runner_semantic_v2", + "sourceKind": "runner", "runId": "run_semantic_v2", "normalizedSessionId": "session_semantic_v2", "turnId": "turn_semantic_v2", "itemId": "item_semantic_v2", + "eventType": "mcp_app.tool_result", "schemaVersion": 1, "priority": 1, "emittedAt": "2026-08-11T11:00:00.010Z", + "payload": { "semantic_tool": { + "schema": "paperclip.prp.semantic_tool.v1", "schemaVersion": 1, "phase": "result", "operationId": "get_task_context", "callId": "call_semantic_v2", + "correlation": { "runId": "run_semantic_v2", "normalizedSessionId": "session_semantic_v2", "turnId": "turn_semantic_v2", "itemId": "item_semantic_v2" }, + "idempotencyKey": null, + "content": { "digest": "sha256:0000000000000000000000000000000000000000000000000000000000000000", "redactionDisposition": "digest_only", "references": [] }, + "outcome": "succeeded", "code": "ok", "retryable": false, "authorizationBoundary": "active_task", "operationReceiptId": "receipt_semantic_v2" + } } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_v2_03", "sourceSeq": 3, "sourceInstanceId": "runner_semantic_v2", + "sourceKind": "runner", "runId": "run_semantic_v2", "normalizedSessionId": "session_semantic_v2", "turnId": "turn_semantic_v2", + "eventType": "run.result.proposed", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T11:00:00.020Z", + "payload": { "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "done", "summary": "This result must not replay.", "completionClaim": { "contractRevision": "semantic-receipts-v2", "objectiveSatisfied": true, "criteria": [], "remainingWork": [] }, "evidence": [], "verification": [], "attentionRequests": [], "artifacts": [] } + }, + { + "schema": "paperclip.prp.event.v1", "sourceEventId": "semantic_v2_04", "sourceSeq": 4, "sourceInstanceId": "runner_semantic_v2", + "sourceKind": "runner", "runId": "run_semantic_v2", "normalizedSessionId": "session_semantic_v2", "turnId": "turn_semantic_v2", + "eventType": "run.terminal", "schemaVersion": 1, "priority": 0, "emittedAt": "2026-08-11T11:00:00.030Z", + "payload": { "schema": "paperclip.prp.terminal.v1", "turnTerminalState": "completed", "runTerminalState": "succeeded", "reportedWorkDisposition": "done" } + } + ], + "requests": [], + "result": { "schema": "paperclip.run_result.v1", "reportedWorkDisposition": "done", "summary": "This result must not replay.", "completionClaim": { "contractRevision": "semantic-receipts-v2", "objectiveSatisfied": true, "criteria": [], "remainingWork": [] }, "evidence": [], "verification": [], "attentionRequests": [], "artifacts": [] } +} diff --git a/packages/paperclip-runner/protocol/schemas/capabilities.schema.json b/packages/paperclip-runner/protocol/schemas/capabilities.schema.json index bdf38a2cb33..c9394108360 100644 --- a/packages/paperclip-runner/protocol/schemas/capabilities.schema.json +++ b/packages/paperclip-runner/protocol/schemas/capabilities.schema.json @@ -34,6 +34,45 @@ "runtimeRequests": { "type": "boolean" }, "structuredResult": { "type": "boolean" }, "typedEvents": { "type": "boolean" }, + "semanticTools": { + "type": "object", + "required": ["schema", "schemaVersion", "operations"], + "properties": { + "schema": { "const": "paperclip.prp.semantic_tools.v1" }, + "schemaVersion": { "const": 1 }, + "operations": { + "type": "array", + "items": { + "type": "object", + "required": ["operationId", "version", "availability", "redactionDisposition"], + "properties": { + "operationId": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$" + }, + "version": { "const": 1 }, + "availability": { "enum": ["available", "denied", "unsupported"] }, + "redactionDisposition": { "const": "digest_only" }, + "requiredClaims": { + "type": "array", + "items": { "type": "string", "minLength": 1, "maxLength": 160 }, + "uniqueItems": true + }, + "reasonCode": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^[a-z][a-z0-9_.:-]*$" + } + }, + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, "unsupported": { "type": "array", "items": { "type": "string", "minLength": 1 }, diff --git a/packages/paperclip-runner/protocol/schemas/event.schema.json b/packages/paperclip-runner/protocol/schemas/event.schema.json index 3fe654d1f6c..3b2067c90f5 100644 --- a/packages/paperclip-runner/protocol/schemas/event.schema.json +++ b/packages/paperclip-runner/protocol/schemas/event.schema.json @@ -51,6 +51,44 @@ "debug": { "type": "object", "additionalProperties": true } }, "allOf": [ + { + "if": { "properties": { "eventType": { "const": "mcp_app.tool_input" } } }, + "then": { + "properties": { + "payload": { + "type": "object", + "properties": { + "semantic_tool": { + "allOf": [ + { "$ref": "https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json" }, + { "type": "object", "properties": { "phase": { "const": "input" } } } + ] + } + }, + "additionalProperties": true + } + } + } + }, + { + "if": { "properties": { "eventType": { "const": "mcp_app.tool_result" } } }, + "then": { + "properties": { + "payload": { + "type": "object", + "properties": { + "semantic_tool": { + "allOf": [ + { "$ref": "https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json" }, + { "type": "object", "properties": { "phase": { "const": "result" } } } + ] + } + }, + "additionalProperties": true + } + } + } + }, { "if": { "properties": { "eventType": { "const": "run.terminal" } } }, "then": { diff --git a/packages/paperclip-runner/protocol/schemas/semantic-tool.schema.json b/packages/paperclip-runner/protocol/schemas/semantic-tool.schema.json new file mode 100644 index 00000000000..657a7e4e9f2 --- /dev/null +++ b/packages/paperclip-runner/protocol/schemas/semantic-tool.schema.json @@ -0,0 +1,164 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json", + "title": "PRP provider-neutral semantic tool envelope", + "type": "object", + "required": [ + "schema", + "schemaVersion", + "phase", + "operationId", + "callId", + "correlation", + "idempotencyKey", + "content" + ], + "properties": { + "schema": { "const": "paperclip.prp.semantic_tool.v1" }, + "schemaVersion": { "const": 1 }, + "phase": { "enum": ["input", "result"] }, + "operationId": { "$ref": "#/$defs/stableId" }, + "callId": { "$ref": "#/$defs/stableId" }, + "correlation": { + "type": "object", + "required": ["runId", "normalizedSessionId", "turnId", "itemId"], + "properties": { + "runId": { "$ref": "#/$defs/stableId" }, + "normalizedSessionId": { "$ref": "#/$defs/stableId" }, + "turnId": { "$ref": "#/$defs/stableId" }, + "itemId": { "$ref": "#/$defs/stableId" }, + "requestId": { "$ref": "#/$defs/stableId" } + }, + "additionalProperties": true + }, + "idempotencyKey": { + "type": ["string", "null"], + "minLength": 1, + "maxLength": 240 + }, + "content": { "$ref": "#/$defs/safeContent" }, + "outcome": { + "enum": ["succeeded", "denied", "conflict", "duplicate", "unavailable", "failed"] + }, + "code": { "$ref": "#/$defs/stableCode" }, + "retryable": { "type": "boolean" }, + "authorizationBoundary": { + "enum": ["company", "actor", "active_task", "grant", "governed_action", "lock", "revision"] + }, + "operationReceiptId": { "$ref": "#/$defs/stableId" }, + "auditReceiptId": { "$ref": "#/$defs/stableId" }, + "currentRevision": { + "oneOf": [ + { "type": "integer", "minimum": 0 }, + { "$ref": "#/$defs/stableId" } + ] + }, + "duplicateOfReceiptId": { "$ref": "#/$defs/stableId" }, + "artifactRefs": { + "type": "array", + "items": { + "allOf": [ + { "$ref": "#/$defs/safeReference" }, + { + "type": "object", + "properties": { "kind": { "enum": ["artifact", "work_product"] } } + } + ] + }, + "uniqueItems": true + }, + "targets": { + "type": "array", + "items": { "$ref": "#/$defs/immutableTarget" }, + "uniqueItems": true + }, + "causalRefs": { + "type": "array", + "items": { "$ref": "#/$defs/safeReference" }, + "uniqueItems": true + } + }, + "allOf": [ + { + "if": { "properties": { "phase": { "const": "result" } } }, + "then": { + "required": [ + "outcome", + "code", + "retryable", + "authorizationBoundary", + "operationReceiptId" + ] + } + } + ], + "additionalProperties": true, + "$defs": { + "stableId": { + "type": "string", + "minLength": 1, + "maxLength": 240, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$" + }, + "stableCode": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^[a-z][a-z0-9_.:-]*$" + }, + "safeContent": { + "type": "object", + "required": ["digest", "redactionDisposition", "references"], + "properties": { + "digest": { + "type": "string", + "pattern": "^sha256:[a-f0-9]{64}$" + }, + "redactionDisposition": { + "enum": ["digest_only", "allowlisted_references", "redacted"] + }, + "references": { + "type": "array", + "items": { "$ref": "#/$defs/safeReference" }, + "uniqueItems": true + } + }, + "additionalProperties": true + }, + "safeReference": { + "type": "object", + "required": ["kind", "id"], + "properties": { + "kind": { + "enum": [ + "task", + "document_revision", + "interaction", + "approval", + "decision", + "artifact", + "work_product", + "wake", + "monitor", + "audit", + "operation" + ] + }, + "id": { "$ref": "#/$defs/stableId" } + }, + "additionalProperties": true + }, + "immutableTarget": { + "type": "object", + "required": ["kind", "id", "immutable"], + "properties": { + "kind": { "enum": ["document_revision", "interaction", "approval", "decision"] }, + "id": { "$ref": "#/$defs/stableId" }, + "immutable": { "const": true }, + "revisionId": { "$ref": "#/$defs/stableId" }, + "decisionId": { "$ref": "#/$defs/stableId" } + }, + "additionalProperties": true + } + } +} diff --git a/packages/paperclip-runner/protocol/schemas/stop-reason.schema.json b/packages/paperclip-runner/protocol/schemas/stop-reason.schema.json new file mode 100644 index 00000000000..183615f559b --- /dev/null +++ b/packages/paperclip-runner/protocol/schemas/stop-reason.schema.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperclip.dev/schemas/prp/v1/stop-reason.schema.json", + "title": "PRP terminal stop reason receipt", + "type": "object", + "required": [ + "schema", + "schemaVersion", + "receiptId", + "kind", + "code", + "retryable", + "decisionId", + "limitClass", + "aggregate" + ], + "properties": { + "schema": { "const": "paperclip.prp.stop_reason.v1" }, + "schemaVersion": { "const": 1 }, + "receiptId": { "$ref": "#/$defs/stableId" }, + "kind": { "enum": ["budget", "cost"] }, + "code": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^[a-z][a-z0-9_.:-]*$" + }, + "retryable": { "type": "boolean" }, + "decisionId": { "$ref": "#/$defs/stableId" }, + "limitClass": { + "enum": [ + "company_monthly", + "actor_monthly", + "project_monthly", + "run_cost", + "provider_quota" + ] + }, + "aggregate": { + "type": "object", + "required": ["unit", "observed", "limit", "window"], + "properties": { + "unit": { "enum": ["cents", "usd_micros", "tokens"] }, + "observed": { "type": "integer", "minimum": 0 }, + "limit": { "type": "integer", "minimum": 0 }, + "window": { "enum": ["run", "monthly_utc", "provider_window"] } + }, + "additionalProperties": true + }, + "relatedReceiptIds": { + "type": "array", + "items": { "$ref": "#/$defs/stableId" }, + "uniqueItems": true + } + }, + "additionalProperties": true, + "$defs": { + "stableId": { + "type": "string", + "minLength": 1, + "maxLength": 240, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$" + } + } +} diff --git a/packages/paperclip-runner/protocol/schemas/terminal.schema.json b/packages/paperclip-runner/protocol/schemas/terminal.schema.json index 69397e9c76d..3538d20120d 100644 --- a/packages/paperclip-runner/protocol/schemas/terminal.schema.json +++ b/packages/paperclip-runner/protocol/schemas/terminal.schema.json @@ -19,7 +19,8 @@ "enum": ["done", "blocked", "needs_review", "yielded"] }, "workAssessmentId": { "type": "string", "minLength": 1 }, - "statusDecisionId": { "type": "string", "minLength": 1 } + "statusDecisionId": { "type": "string", "minLength": 1 }, + "stopReason": { "$ref": "https://paperclip.dev/schemas/prp/v1/stop-reason.schema.json" } }, "additionalProperties": true } diff --git a/packages/paperclip-runner/runner/crates/runner-core/src/replay.rs b/packages/paperclip-runner/runner/crates/runner-core/src/replay.rs index fb73b783175..2e3985d7fb9 100644 --- a/packages/paperclip-runner/runner/crates/runner-core/src/replay.rs +++ b/packages/paperclip-runner/runner/crates/runner-core/src/replay.rs @@ -9,6 +9,9 @@ pub const PRP_PROTOCOL_VERSION: u64 = 1; const PRP_FIXTURE_VERSION: u64 = 1; const PRP_FIXTURE_SCHEMA: &str = "paperclip.prp.fixture.v1"; const PRP_EVENT_SCHEMA: &str = "paperclip.prp.event.v1"; +const PRP_SEMANTIC_TOOL_SCHEMA: &str = "paperclip.prp.semantic_tool.v1"; +const PRP_STOP_REASON_SCHEMA: &str = "paperclip.prp.stop_reason.v1"; +const PRP_SEMANTIC_TOOLS_CAPABILITY_SCHEMA: &str = "paperclip.prp.semantic_tools.v1"; #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase")] @@ -17,6 +20,7 @@ struct ReplayFixture { fixture_version: u64, protocol_version: u64, identity: ReplayIdentity, + capabilities: Value, events: Vec, result: Value, } @@ -100,6 +104,11 @@ pub fn reduce_replay_fixture(input: &str) -> Result::new(); for event in &fixture.events { @@ -135,6 +144,16 @@ pub fn reduce_replay_fixture(input: &str) -> Result Result, + expected_schema: &str, + field: &str, +) -> Result<(), ReplayError> { + let Some(envelope) = envelope else { + return Ok(()); + }; + let schema = envelope + .get("schema") + .and_then(Value::as_str) + .unwrap_or("missing"); + if schema != expected_schema { + return Err(ReplayError::invalid(format!( + "unsupported required {field} schema {schema}; expected {expected_schema}" + ))); + } + let version = envelope + .get("schemaVersion") + .and_then(Value::as_u64) + .unwrap_or(0); + if version != 1 { + return Err(ReplayError::invalid(format!( + "unsupported required {field} schemaVersion {version}; expected 1" + ))); + } + Ok(()) +} + #[cfg(test)] mod tests { use super::{reduce_replay_fixture, ReplayParitySummary}; @@ -269,6 +317,36 @@ mod tests { "unknown-optional-fields", "unknown-optional-fields" ); + parity_case!( + replay_fixture_parity_semantic_tool_artifact_happy_path, + "semantic-tool-artifact-happy-path", + "semantic-tool-artifact-happy-path" + ); + parity_case!( + replay_fixture_parity_semantic_tool_denial_redaction, + "semantic-tool-denial-redaction", + "semantic-tool-denial-redaction" + ); + parity_case!( + replay_fixture_parity_semantic_tool_conflict_duplicate_retry, + "semantic-tool-conflict-duplicate-retry", + "semantic-tool-conflict-duplicate-retry" + ); + parity_case!( + replay_fixture_parity_semantic_tool_governance_wake_monitor, + "semantic-tool-governance-wake-monitor", + "semantic-tool-governance-wake-monitor" + ); + parity_case!( + replay_fixture_parity_budget_cost_stop_reason, + "budget-cost-stop-reason", + "budget-cost-stop-reason" + ); + parity_case!( + replay_fixture_parity_semantic_tool_unknown_optional_envelope, + "semantic-tool-unknown-optional-envelope", + "semantic-tool-unknown-optional-envelope" + ); #[test] fn replay_fixture_parity_rejects_unsupported_required_version() { @@ -281,6 +359,17 @@ mod tests { .contains("unsupported required protocolVersion 2")); } + #[test] + fn replay_fixture_parity_rejects_unsupported_semantic_tool_version() { + let error = reduce_replay_fixture(include_str!( + "../../../../protocol/fixtures/replay/semantic-tool-unsupported-required-version.json" + )) + .expect_err("semantic_tool v2 fixture must fail closed"); + assert!(error + .to_string() + .contains("unsupported required semantic_tool schema paperclip.prp.semantic_tool.v2")); + } + #[test] fn replay_fixture_parity_rejects_unsupported_fixture_version() { let fixture = include_str!("../../../../protocol/fixtures/replay/happy-path.json") diff --git a/packages/paperclip-runner/scripts/generate-protocol-schema-module.mjs b/packages/paperclip-runner/scripts/generate-protocol-schema-module.mjs index 3c790298a95..50f7edc640d 100644 --- a/packages/paperclip-runner/scripts/generate-protocol-schema-module.mjs +++ b/packages/paperclip-runner/scripts/generate-protocol-schema-module.mjs @@ -16,6 +16,8 @@ const schemaNames = [ "identity", "capabilities", "command", + "semantic-tool", + "stop-reason", "terminal", "request", "result", @@ -30,10 +32,11 @@ const schemas = await Promise.all( })), ); +const identifier = (name) => name.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase()); const declarations = schemas - .map(({ name, value }) => `export const ${name}Schema = ${JSON.stringify(value, null, 2)} as const;`) + .map(({ name, value }) => `export const ${identifier(name)}Schema = ${JSON.stringify(value, null, 2)} as const;`) .join("\n\n"); -const bundle = schemaNames.map((name) => ` ${name}: ${name}Schema,`).join("\n"); +const bundle = schemaNames.map((name) => ` ${JSON.stringify(name)}: ${identifier(name)}Schema,`).join("\n"); const generated = `// Generated by scripts/generate-protocol-schema-module.mjs. Do not edit.\n\n${declarations}\n\nexport const prpSchemaBundle = {\n${bundle}\n} as const;\n`; const schemaByName = Object.fromEntries(schemas.map(({ name, value }) => [name, value])); @@ -56,11 +59,18 @@ const ucs2RuntimePattern = /const (func\d+) = require\("ajv\/dist\/runtime\/ucs2 if (!ucs2RuntimePattern.test(standaloneValidators)) { throw new Error("Ajv standalone output no longer has the expected ucs2length runtime binding"); } +const equalRuntimePattern = /const (func\d+) = require\("ajv\/dist\/runtime\/equal"\)\.default;/; +if (!equalRuntimePattern.test(standaloneValidators)) { + throw new Error("Ajv standalone output no longer has the expected equal runtime binding"); +} const validators = standaloneValidators.replace( ucs2RuntimePattern, "const $1 = typeof ucs2LengthModule === \"function\" ? ucs2LengthModule : ucs2LengthModule.default;", +).replace( + equalRuntimePattern, + "const $1 = typeof equalModule === \"function\" ? equalModule : equalModule.default;", ); -const generatedValidators = `// Generated by scripts/generate-protocol-schema-module.mjs. Do not edit.\n// @ts-nocheck -- Ajv standalone output is JavaScript compiled from the checked-in schemas.\n\nimport ucs2LengthModule from "ajv/dist/runtime/ucs2length.js";\n\n${validators}\n`; +const generatedValidators = `// Generated by scripts/generate-protocol-schema-module.mjs. Do not edit.\n// @ts-nocheck -- Ajv standalone output is JavaScript compiled from the checked-in schemas.\n\nimport equalModule from "ajv/dist/runtime/equal.js";\nimport ucs2LengthModule from "ajv/dist/runtime/ucs2length.js";\n\n${validators}\n`; if (process.argv.includes("--check")) { const current = await readFile(outputPath, "utf8").catch(() => ""); diff --git a/packages/paperclip-runner/scripts/generate-replay-goldens.mjs b/packages/paperclip-runner/scripts/generate-replay-goldens.mjs index a0ef20bf059..e56e73e8b66 100644 --- a/packages/paperclip-runner/scripts/generate-replay-goldens.mjs +++ b/packages/paperclip-runner/scripts/generate-replay-goldens.mjs @@ -18,6 +18,12 @@ const fixtureNames = [ "duplicate-event", "source-gap", "unknown-optional-fields", + "semantic-tool-artifact-happy-path", + "semantic-tool-denial-redaction", + "semantic-tool-conflict-duplicate-retry", + "semantic-tool-governance-wake-monitor", + "budget-cost-stop-reason", + "semantic-tool-unknown-optional-envelope", ]; const check = process.argv.includes("--check"); const stale = []; diff --git a/packages/paperclip-runner/spec/prp-v1-expressiveness-audit.md b/packages/paperclip-runner/spec/prp-v1-expressiveness-audit.md index 47253cd4b35..385ae0c5220 100644 --- a/packages/paperclip-runner/spec/prp-v1-expressiveness-audit.md +++ b/packages/paperclip-runner/spec/prp-v1-expressiveness-audit.md @@ -4,10 +4,12 @@ PRP v1 is sufficient for runner lifecycle, replay integrity, negotiated runner features, runtime/issue-thread request routing, structured work disposition, -and terminal causality. It is **not** yet sufficient to claim a provider-neutral -semantic-control-plane protocol: tool invocation, authorization denial, -redaction, optimistic concurrency, mutation receipts, and budget stop reasons -are presently represented only by event or request `payload` extension space. +terminal causality, and provider-neutral semantic-control-plane receipts. The +optional `semantic_tool` and `terminal.stopReason` envelopes now type tool +invocation, authorization denial, redaction, optimistic concurrency, mutation +receipts, artifacts, governed targets, causal continuations, and budget stops. +They remain receipts for control-plane-owned operations, not a provider tool +catalog or permission to move control-plane policy into the runner. `prp-v1-expressiveness-crosswalk.json` is the machine-checked source for this verdict. Its Vitest gate rejects an unclassified required fact, a fact justified @@ -39,12 +41,18 @@ coverage row. assessment, and issue-status decision references. Existing golden replay, duplicate-event, unknown-optional-fields, and unsupported-required-version fixtures demonstrate the compatibility boundary. +- `capabilities.semanticTools` advertises versioned, provider-neutral operation + availability and redaction rules. Paired `mcp_app.tool_input` and + `mcp_app.tool_result` events carry one safe `semantic_tool` envelope per call. +- `terminal.stopReason` carries a safe budget/cost aggregate and the decision + receipt that stopped the run. Eval `trace_completeness` reads these PRP wire + receipts when available while retaining the existing live-evidence fallback. -## Required additive v1 envelope +## Landed additive v1 envelope -The smallest correction is one optional, versioned `semantic_tool` envelope -for `mcp_app.tool_input` / `mcp_app.tool_result` (or equivalent new event -types), plus an optional `terminal.stopReason` envelope. It must define: +The correction is one optional, versioned `semantic_tool` envelope for +`mcp_app.tool_input` / `mcp_app.tool_result`, plus an optional +`terminal.stopReason` envelope. It defines: - operation id, call id, correlation ids, idempotency key, outcome, stable code, retryability, and audit/operation receipt id; @@ -58,10 +66,10 @@ types), plus an optional `terminal.stopReason` envelope. It must define: result; immutable interaction/approval document or decision targets; and budget stop reason/aggregate/decision id. -This is additive because existing v1 consumers can ignore the optional typed -envelope. It is not permission to add speculative semantic events: the -crosswalk names the exact facts and the conformance vectors that must land -with any schema change. +This remains additive because existing v1 consumers can ignore the optional +typed envelopes. The reducer intentionally does not project them into session +state; they supply inspectable trace evidence only. Unknown optional fields are +accepted, while an unknown required envelope version fails closed. ## Classification and fixture plan @@ -70,19 +78,20 @@ compositional v1 with a listed invariant, control-plane-local, additive v1, missing fixture/docs, or breaking v2 work. Direct and compositional support is never inferred merely from `additionalProperties: true`. -Before an additive change graduates to direct support, add these fixtures and -golden projections: +The additive change graduated to direct support with these fixtures and golden +projections: -1. semantic tool happy path and artifact registration; -2. denied operation with redaction assertions and no fallback call; -3. stale optimistic write conflict and exact duplicate/retry receipt; -4. immutable interaction/approval target plus wake/monitor causal chain; -5. budget/cost terminal stop reason; -6. unknown optional envelope fields accepted without changing v1 projection; -7. unknown required envelope version rejected fail-closed. +1. `semantic-tool-artifact-happy-path.json` — artifact and work-product receipt; +2. `semantic-tool-denial-redaction.json` — denied/redacted with no fallback; +3. `semantic-tool-conflict-duplicate-retry.json` — stale conflict and exact retry; +4. `semantic-tool-governance-wake-monitor.json` — immutable governed targets and continuation chain; +5. `budget-cost-stop-reason.json` — typed terminal budget/cost stop; +6. `semantic-tool-unknown-optional-envelope.json` — optional fields accepted with unchanged projection; +7. `semantic-tool-unsupported-required-version.json` — required v2 envelope rejected fail-closed. -Each mutation fixture must replay to a golden summary/snapshot and be executed -through mock and real adapters with normalized receipt/state-diff comparison. +The six accepted fixtures replay to TypeScript/Rust parity summaries and golden +snapshots. Shared high-risk semantic vectors compare normalized receipt and +state-diff observations across deterministic mock and production bindings. ## Explicit exclusions @@ -99,4 +108,4 @@ or denied outcomes rather than tunnel those operations through generic payloads. accepted protocol schema/event addition. - A semantic receipt is typed and safe before any surface is marked supported. - Control-plane-local decisions stay out of the semantic tool wire. -- Fixture/document debt is recorded separately from a protocol semantic gap. +- Eval trace scoring consumes wire receipts without changing projection semantics. diff --git a/packages/paperclip-runner/spec/prp-v1-expressiveness-crosswalk.json b/packages/paperclip-runner/spec/prp-v1-expressiveness-crosswalk.json index 041025cdb51..71ae6505fe4 100644 --- a/packages/paperclip-runner/spec/prp-v1-expressiveness-crosswalk.json +++ b/packages/paperclip-runner/spec/prp-v1-expressiveness-crosswalk.json @@ -2,19 +2,103 @@ "$schema": "./prp-v1-expressiveness-crosswalk.schema.json", "version": 1, "facts": [ - {"id":"semantic-tool-exposure","classification":"additive_v1_change","wire":"capabilities.schema.json","evidence":["capabilities.schema.json#/properties/unsupported","spec/capability/capabilities.yaml"],"invariant":"Advertised operations are a typed operation-id set with grant, task-mode, and redaction disposition; generic_api_request never counts as coverage.","correction":{"kind":"additive_schema","target":"capabilities.semanticTools","fixtures":["semantic-tool-denied.json","semantic-tool-unsupported.json"]}}, - {"id":"semantic-tool-call-result","classification":"additive_v1_change","wire":"event.schema.json","evidence":["event.schema.json#/properties/eventType","docs/capability-semantic-tools.md"],"invariant":"Each semantic invocation has one call id, operation id, input digest/redaction disposition, and exactly one typed result receipt.","correction":{"kind":"additive_event","target":"semantic_tool.call|result","fixtures":["semantic-tool-happy-path.json","semantic-tool-duplicate-retry.json"]}}, - {"id":"semantic-tool-denial-and-redaction","classification":"additive_v1_change","wire":"event.schema.json","evidence":["event.schema.json#/properties/eventType","docs/capability-authorization-and-exposure.md"],"invariant":"A denied operation yields a typed safe receipt naming the failed boundary; secret values and hidden identifiers are absent.","correction":{"kind":"additive_schema","target":"semantic_tool.receipt","fixtures":["semantic-tool-denied.json","semantic-tool-redaction.json"]}}, - {"id":"optimistic-write-conflict","classification":"additive_v1_change","wire":"event.schema.json","evidence":["event.schema.json#/properties/eventType","docs/capability-mock-control-plane-port.md"],"invariant":"A mutation receipt carries operation id, idempotency key, outcome, stable code, retryability, and safe current revision when applicable.","correction":{"kind":"additive_schema","target":"semantic_tool.receipt","fixtures":["document-conflict.json","document-duplicate-retry.json"]}}, - {"id":"artifacts-and-deliverables","classification":"compositional_v1_with_invariant","wire":"result.schema.json","evidence":["result.schema.json#/properties/artifacts","protocol/fixtures/replay/happy-path.json"],"invariant":"Every artifact ref is produced by a typed semantic receipt or registered control-plane work product, and is linked to the terminal result by run id."}, - {"id":"governance-links-and-interactions","classification":"compositional_v1_with_invariant","wire":"request.schema.json","evidence":["request.schema.json#/oneOf/1","event.schema.json#/properties/eventType"],"invariant":"Interaction and approval targets are immutable revision/decision references carried in a typed target envelope, not an unconstrained request payload."}, - {"id":"blockers-monitors-and-wakes","classification":"compositional_v1_with_invariant","wire":"result.schema.json","evidence":["result.schema.json#/properties/blocker","result.schema.json#/properties/continuation","event.schema.json#/properties/eventType"],"invariant":"A blocked or yielded result names a bounded owner/action or continuation kind; wake routing remains a control-plane decision and emits only safe causal identifiers."}, - {"id":"budget-cost-stop-reason","classification":"additive_v1_change","wire":"terminal.schema.json","evidence":["terminal.schema.json#/properties/runTerminalState","docs/capability-disposition.md"],"invariant":"A budget/cost stop includes a typed stop reason, observed limit class, safe usage aggregate, and control-plane decision id.","correction":{"kind":"additive_schema","target":"terminal.stopReason","fixtures":["budget-stop.json"]}}, - {"id":"audit-and-idempotency-receipts","classification":"additive_v1_change","wire":"event.schema.json","evidence":["event.schema.json#/required","protocol/fixtures/replay/duplicate-event.json"],"invariant":"Source-event idempotency is already replay-safe; semantic mutation idempotency additionally requires a stable operation receipt/audit ref.","correction":{"kind":"additive_schema","target":"semantic_tool.receipt","fixtures":["semantic-tool-duplicate-retry.json"]}}, - {"id":"capability-negotiation-and-unsupported","classification":"direct_v1","wire":"capabilities.schema.json","evidence":["capabilities.schema.json#/required","capabilities.schema.json#/properties/unsupported","protocol/fixtures/replay/unsupported-required-version.json"],"invariant":"The controller binds behavior to the negotiated typed booleans/version and treats unsupported required versions as fail-closed."}, - {"id":"end-to-end-causality","classification":"compositional_v1_with_invariant","wire":"event.schema.json","evidence":["event.schema.json#/required","terminal.schema.json#/properties/workAssessmentId","protocol/fixtures/replay/golden/happy-path.snapshot.json"],"invariant":"Run, session, turn, item, source-event, work-assessment, status-decision, request, and receipt identifiers form an acyclic trace from command to terminal decision."}, - {"id":"control-plane-local-lifecycle","classification":"control_plane_local","wire":"none","evidence":["docs/capability-disposition.md","spec/capability/capabilities.yaml"],"invariant":"Checkout/release, wake routing, budget enforcement, audit persistence, run persistence/replay, assignment, and monitor management are not runner tool calls and must not be serialized as semantic operations."}, - {"id":"future-cross-company-and-destructive-admin","classification":"breaking_v2_work","wire":"none","evidence":["docs/capability-disposition.md","docs/capability-future-binding-boundary.md"],"invariant":"Cross-company discovery, broad audit access, destructive document lifecycle, and company administration require separately governed product contracts; v1 must reject rather than tunnel them through generic payloads."}, - {"id":"existing-fixture-and-doc-coverage","classification":"missing_fixture_docs","wire":"protocol/fixtures/replay","evidence":["protocol/fixtures/replay/duplicate-event.json","protocol/fixtures/replay/unknown-optional-fields.json","src/protocol/replay-contract.test.ts"],"invariant":"Every accepted additive correction ships a golden replay, duplicate/retry, redaction/denial, and unknown-version fixture before it is called direct support."} + { + "id": "semantic-tool-exposure", + "classification": "direct_v1", + "wire": "capabilities.schema.json", + "evidence": ["capabilities.schema.json#/properties/semanticTools", "protocol/fixtures/replay/semantic-tool-unknown-optional-envelope.json"], + "invariant": "Advertised operations are a typed operation-id set with availability, required claims, and redaction disposition; generic_api_request never counts as coverage." + }, + { + "id": "semantic-tool-call-result", + "classification": "direct_v1", + "wire": "event.schema.json", + "evidence": ["event.schema.json#/allOf", "semantic-tool.schema.json", "protocol/fixtures/replay/semantic-tool-artifact-happy-path.json"], + "invariant": "Each semantic invocation has one call id, operation id, safe input digest, and exactly one typed result receipt." + }, + { + "id": "semantic-tool-denial-and-redaction", + "classification": "direct_v1", + "wire": "semantic-tool.schema.json", + "evidence": ["semantic-tool.schema.json#/properties/authorizationBoundary", "protocol/fixtures/replay/semantic-tool-denial-redaction.json"], + "invariant": "A denied operation yields a typed safe receipt naming the failed boundary; secret values and hidden identifiers are absent." + }, + { + "id": "optimistic-write-conflict", + "classification": "direct_v1", + "wire": "semantic-tool.schema.json", + "evidence": ["semantic-tool.schema.json#/properties/currentRevision", "protocol/fixtures/replay/semantic-tool-conflict-duplicate-retry.json"], + "invariant": "A mutation receipt carries operation id, idempotency key, outcome, stable code, retryability, and safe current revision when applicable." + }, + { + "id": "artifacts-and-deliverables", + "classification": "compositional_v1_with_invariant", + "wire": "semantic-tool.schema.json + result.schema.json", + "evidence": ["semantic-tool.schema.json#/properties/artifactRefs", "result.schema.json#/properties/artifacts", "protocol/fixtures/replay/semantic-tool-artifact-happy-path.json"], + "invariant": "Every artifact ref is produced by a typed semantic receipt or registered work product and remains linked to the terminal result by run id." + }, + { + "id": "governance-links-and-interactions", + "classification": "compositional_v1_with_invariant", + "wire": "semantic-tool.schema.json + request.schema.json", + "evidence": ["semantic-tool.schema.json#/properties/targets", "protocol/fixtures/replay/semantic-tool-governance-wake-monitor.json"], + "invariant": "Interaction and approval targets are immutable revision or decision references carried in a typed target envelope." + }, + { + "id": "blockers-monitors-and-wakes", + "classification": "compositional_v1_with_invariant", + "wire": "semantic-tool.schema.json + result.schema.json", + "evidence": ["semantic-tool.schema.json#/properties/causalRefs", "result.schema.json#/properties/continuation", "protocol/fixtures/replay/semantic-tool-governance-wake-monitor.json"], + "invariant": "A blocked or yielded result names a bounded continuation; wake routing remains a control-plane decision and emits only safe causal identifiers." + }, + { + "id": "budget-cost-stop-reason", + "classification": "direct_v1", + "wire": "terminal.schema.json", + "evidence": ["terminal.schema.json#/properties/stopReason", "stop-reason.schema.json", "protocol/fixtures/replay/budget-cost-stop-reason.json"], + "invariant": "A budget or cost stop includes a typed reason, observed limit class, safe usage aggregate, and control-plane decision id." + }, + { + "id": "audit-and-idempotency-receipts", + "classification": "direct_v1", + "wire": "semantic-tool.schema.json", + "evidence": ["semantic-tool.schema.json#/properties/operationReceiptId", "protocol/fixtures/replay/semantic-tool-conflict-duplicate-retry.json"], + "invariant": "Source-event and semantic mutation idempotency are distinct; an exact semantic retry reuses its stable operation receipt and records the duplicate link." + }, + { + "id": "capability-negotiation-and-unsupported", + "classification": "direct_v1", + "wire": "capabilities.schema.json", + "evidence": ["capabilities.schema.json#/properties/semanticTools", "protocol/fixtures/replay/semantic-tool-unknown-optional-envelope.json", "protocol/fixtures/replay/semantic-tool-unsupported-required-version.json"], + "invariant": "The controller binds behavior to negotiated typed capability versions, accepts optional extensions, and rejects unknown required versions fail-closed." + }, + { + "id": "end-to-end-causality", + "classification": "compositional_v1_with_invariant", + "wire": "event.schema.json + semantic-tool.schema.json + terminal.schema.json", + "evidence": ["event.schema.json#/required", "semantic-tool.schema.json#/properties/correlation", "protocol/fixtures/replay/semantic-tool-governance-wake-monitor.json"], + "invariant": "Run, session, turn, item, source-event, governed-target, wake, monitor, decision, and receipt identifiers form an inspectable trace to terminal disposition." + }, + { + "id": "control-plane-local-lifecycle", + "classification": "control_plane_local", + "wire": "none", + "evidence": ["docs/capability-disposition.md", "spec/capability/capabilities.yaml"], + "invariant": "Checkout and release, wake routing, budget enforcement, audit persistence, run persistence and replay, assignment, and monitor management are not runner tool calls." + }, + { + "id": "future-cross-company-and-destructive-admin", + "classification": "breaking_v2_work", + "wire": "none", + "evidence": ["docs/capability-disposition.md", "docs/capability-future-binding-boundary.md"], + "invariant": "Cross-company discovery, broad audit access, destructive document lifecycle, and company administration require separately governed contracts; v1 rejects rather than tunnels them." + }, + { + "id": "existing-fixture-and-doc-coverage", + "classification": "direct_v1", + "wire": "protocol/fixtures/replay", + "evidence": ["src/protocol/replay-contract.test.ts", "runner/crates/runner-core/src/replay.rs", "docs/protocol-compatibility.md"], + "invariant": "Every accepted additive correction ships golden replay, duplicate and retry, redaction and denial, optional-extension, and unknown-required-version conformance coverage." + } ] } diff --git a/packages/paperclip-runner/src/conformance/capability-semantic-conformance.test.ts b/packages/paperclip-runner/src/conformance/capability-semantic-conformance.test.ts index 1c2d725e3b5..799980e73b6 100644 --- a/packages/paperclip-runner/src/conformance/capability-semantic-conformance.test.ts +++ b/packages/paperclip-runner/src/conformance/capability-semantic-conformance.test.ts @@ -50,5 +50,9 @@ describe("capability semantic conformance vectors", () => { .toMatchObject({ task: { status: "done" } }); expect(report.rows.find((row) => row.vectorId === "terminal-with-dependency")?.observation.state) .toMatchObject({ task: { status: "done" }, dependencies: [expect.any(String)] }); + expect(report.rows.every((row) => row.observation.receipt?.operationReceiptPresent === true)) + .toBe(true); + expect(report.rows.find((row) => row.vectorId === "document-stale-revision")?.observation.receipt) + .toMatchObject({ outcome: "conflict", authorizationBoundary: "revision", retryable: false }); }); }); diff --git a/packages/paperclip-runner/src/conformance/capability-semantic-conformance.ts b/packages/paperclip-runner/src/conformance/capability-semantic-conformance.ts index ea9a9d5cc9e..176a9e502db 100644 --- a/packages/paperclip-runner/src/conformance/capability-semantic-conformance.ts +++ b/packages/paperclip-runner/src/conformance/capability-semantic-conformance.ts @@ -11,6 +11,12 @@ import { type CapabilitySemanticDispatcherOptions, } from "../semantic-tools/dispatcher.js"; import type { CapabilitySemanticToolResult } from "../semantic-tools/types.js"; +import { + createPrpSemanticToolInputEnvelope, + createPrpSemanticToolResultEnvelope, + semanticAuthorizationBoundaryForCode, + semanticOutcomeForCode, +} from "../protocol/semantic-tool-receipts.js"; import type { SemanticConformanceAdapter, SemanticConformanceObservation, @@ -192,7 +198,13 @@ export class CapabilityMockSemanticConformanceAdapter implements SemanticConform input: vector.input, }); const after = world.port.snapshot(); - return normalizeCapabilitySemanticObservation({ result, before, after, taskId: world.taskId }); + return normalizeCapabilitySemanticObservation({ + result, + before, + after, + taskId: world.taskId, + semanticInput: vector.input, + }); } async stop(): Promise { @@ -229,18 +241,77 @@ export function normalizeCapabilitySemanticObservation(input: { readonly before: Readonly; readonly after: Readonly; readonly taskId: string; + readonly semanticInput: unknown; }): SemanticConformanceObservation { const { result, before, after, taskId } = input; + const run = after.runs.find((candidate) => candidate.taskId === taskId); + if (run === undefined) throw new Error(`semantic_conformance_run_missing:${taskId}`); + const idempotencyKey = idempotencyKeyFrom(input.semanticInput); + const disposition = result.ok && isRecord(result.result) ? result.result.disposition : undefined; + const code = result.ok && disposition === "duplicate" + ? "duplicate" + : result.ok + ? "ok" + : result.denial.controlPlaneCode ?? result.denial.code; + const effects = result.ok ? normalizeEffects(result.result) : []; + const authorization = result.ok + ? { outcome: "allowed" as const } + : { + outcome: "denied" as const, + code, + }; + const envelopeBase = { + operationId: result.operationId, + callId: result.callId, + correlation: { + runId: run.id, + normalizedSessionId: run.sessionId, + turnId: `turn:${result.callId}`, + itemId: `item:${result.callId}`, + }, + idempotencyKey, + }; + const inputReceipt = createPrpSemanticToolInputEnvelope({ + ...envelopeBase, + content: input.semanticInput, + }); + const receipt = createPrpSemanticToolResultEnvelope({ + ...envelopeBase, + content: { authorization, effects }, + outcome: semanticOutcomeForCode({ + ok: result.ok, + code, + disposition, + }), + code, + retryable: result.ok ? false : result.denial.retryable, + authorizationBoundary: semanticAuthorizationBoundaryForCode(code), + ...(after.audit.length <= before.audit.length + ? {} + : { auditReceiptId: after.audit.at(-1)?.id }), + currentRevision: result.stateRevision, + }); return Object.freeze({ - authorization: result.ok - ? { outcome: "allowed" as const } - : { - outcome: "denied" as const, - code: result.denial.controlPlaneCode ?? result.denial.code, - }, + authorization, state: projectSemanticState(after, taskId), - effects: result.ok ? normalizeEffects(result.result) : [], + effects, audit: after.audit.length > before.audit.length ? [{ outcome: "recorded" }] : [], + receipt: { + schema: receipt.schema, + schemaVersion: receipt.schemaVersion, + phase: "result", + operationId: receipt.operationId, + callId: receipt.callId, + idempotencyKeyPresent: receipt.idempotencyKey !== null, + outcome: String(receipt.outcome), + code: String(receipt.code), + retryable: receipt.retryable === true, + authorizationBoundary: String(receipt.authorizationBoundary), + operationReceiptPresent: typeof receipt.operationReceiptId === "string", + inputDigestPresent: typeof inputReceipt.content.digest === "string", + outputDigestPresent: typeof receipt.content.digest === "string", + currentRevisionPresent: receipt.currentRevision !== undefined, + }, }); } @@ -293,6 +364,17 @@ function normalizeEffects(result: unknown): readonly unknown[] { }]; } +function idempotencyKeyFrom(value: unknown): string | null { + if (!isRecord(value)) return null; + return typeof value.idempotencyKey === "string" && value.idempotencyKey.length > 0 + ? value.idempotencyKey + : null; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + function mockWorld( id: string, taskId: string, diff --git a/packages/paperclip-runner/src/conformance/semantic-conformance.ts b/packages/paperclip-runner/src/conformance/semantic-conformance.ts index b3f7bfc60b3..817331b3ec5 100644 --- a/packages/paperclip-runner/src/conformance/semantic-conformance.ts +++ b/packages/paperclip-runner/src/conformance/semantic-conformance.ts @@ -17,6 +17,23 @@ export interface SemanticConformanceObservation { readonly state: unknown; readonly effects: readonly unknown[]; readonly audit: readonly unknown[]; + /** Provider-neutral normalized view of the PRP semantic result receipt. */ + readonly receipt?: { + readonly schema: "paperclip.prp.semantic_tool.v1"; + readonly schemaVersion: 1; + readonly phase: "result"; + readonly operationId: string; + readonly callId: string; + readonly idempotencyKeyPresent: boolean; + readonly outcome: string; + readonly code: string; + readonly retryable: boolean; + readonly authorizationBoundary: string; + readonly operationReceiptPresent: boolean; + readonly inputDigestPresent: boolean; + readonly outputDigestPresent: boolean; + readonly currentRevisionPresent: boolean; + }; } export type SemanticConformanceAdapterKind = "mock" | "production_binding"; diff --git a/packages/paperclip-runner/src/eval/eval-execution.ts b/packages/paperclip-runner/src/eval/eval-execution.ts index d222e1f3793..c562b232076 100644 --- a/packages/paperclip-runner/src/eval/eval-execution.ts +++ b/packages/paperclip-runner/src/eval/eval-execution.ts @@ -23,6 +23,13 @@ import { type EvalFaultClass, } from "./eval-bundle.js"; import { scoreEval, type AuthorizationState, type EvalObservation } from "./eval-scoring.js"; +import type { PrpEvent } from "../protocol/replay-contract.js"; +import { + createPrpSemanticToolInputEnvelope, + createPrpSemanticToolResultEnvelope, + semanticAuthorizationBoundaryForCode, + semanticOutcomeForCode, +} from "../protocol/semantic-tool-receipts.js"; export const EVAL_BEHAVIOR_IDS = [ "checkout_context", @@ -579,8 +586,14 @@ async function runBehaviorCase(bundle: EvalBundle, spec: BehaviorCase): Promise< sessionId: SESSION_ID, turnId: `turn-${caseId}`, itemId: `item-${caseId}`, - receiptIds: results.map((result) => result.callId), + receiptIds: [], terminalPresent: true, + wireEvents: evalWireEvents({ + caseId, + invocations: spec.invocations, + results, + authorizationRecords, + }), }, efficiency: { attempts: observedCalls.length }, budget: { maxAttempts: spec.maxAttempts ?? Math.max(1, spec.expectedCalls.length) }, @@ -589,6 +602,142 @@ async function runBehaviorCase(bundle: EvalBundle, spec: BehaviorCase): Promise< return { behavior: spec.behavior, counterpart: spec.counterpart, observation }; } +function evalWireEvents(input: { + caseId: string; + invocations: readonly Invocation[]; + results: readonly CapabilitySemanticToolResult[]; + authorizationRecords: ReturnType; +}): PrpEvent[] { + const events: PrpEvent[] = []; + const turnId = `turn:${input.caseId}`; + const emittedAt = "2026-08-11T00:00:00.000Z"; + const append = ( + eventType: "mcp_app.tool_input" | "mcp_app.tool_result" | "run.terminal", + payload: Record, + itemId?: string, + ): void => { + const sourceSeq = events.length + 1; + events.push({ + schema: "paperclip.prp.event.v1", + sourceEventId: `eval-wire:${input.caseId}:${sourceSeq}`, + sourceSeq, + sourceInstanceId: "eval-wire", + sourceKind: "runner", + runId: RUN_ID, + normalizedSessionId: SESSION_ID, + turnId, + ...(itemId === undefined ? {} : { itemId }), + eventType, + schemaVersion: 1, + priority: eventType === "run.terminal" ? 0 : 1, + emittedAt, + payload, + }); + }; + + input.results.forEach((result, index) => { + const invocation = input.invocations[index]!; + const itemId = `item:${result.callId}`; + const correlation = { runId: RUN_ID, normalizedSessionId: SESSION_ID, turnId, itemId }; + const idempotencyKey = semanticIdempotencyKey(invocation.input); + append("mcp_app.tool_input", { + semantic_tool: createPrpSemanticToolInputEnvelope({ + operationId: result.operationId, + callId: result.callId, + correlation, + idempotencyKey, + content: invocation.input, + }), + }, itemId); + const code = result.ok ? semanticSuccessCode(result.result) : result.denial.controlPlaneCode ?? result.denial.code; + const authorizationRecord = input.authorizationRecords.find( + (record) => record.phase === "invocation" && record.callId === result.callId, + ); + append("mcp_app.tool_result", { + semantic_tool: createPrpSemanticToolResultEnvelope({ + operationId: result.operationId, + callId: result.callId, + correlation, + idempotencyKey, + content: result, + outcome: semanticOutcomeForCode({ + ok: result.ok, + code, + disposition: result.ok && isRecord(result.result) ? result.result.disposition : undefined, + }), + code, + retryable: result.ok ? false : result.denial.retryable, + authorizationBoundary: semanticAuthorizationBoundaryForCode(code), + ...(authorizationRecord === undefined ? {} : { auditReceiptId: authorizationRecord.id }), + currentRevision: result.stateRevision, + artifactRefs: result.ok ? semanticArtifactRefs(result.result) : [], + causalRefs: result.ok ? semanticCausalRefs(result.result) : [], + }), + }, itemId); + }); + append("run.terminal", { + schema: "paperclip.prp.terminal.v1", + turnTerminalState: "completed", + runTerminalState: "succeeded", + reportedWorkDisposition: "done", + }, `item:${input.caseId}`); + return events; +} + +function semanticIdempotencyKey(value: unknown): string | null { + return isRecord(value) && typeof value.idempotencyKey === "string" + ? value.idempotencyKey + : null; +} + +function semanticSuccessCode(value: unknown): string { + return isRecord(value) && value.disposition === "duplicate" ? "duplicate" : "ok"; +} + +function semanticArtifactRefs(value: unknown) { + return semanticRefs(value).filter((reference) => + reference.kind === "artifact" || reference.kind === "work_product", + ); +} + +function semanticCausalRefs(value: unknown) { + return semanticRefs(value).filter((reference) => + ["document_revision", "interaction", "approval", "decision", "wake", "monitor"].includes(reference.kind), + ); +} + +function semanticRefs(value: unknown): Array<{ + kind: "task" | "document_revision" | "interaction" | "approval" | "decision" | "artifact" | "work_product" | "wake" | "monitor" | "audit" | "operation"; + id: string; +}> { + if (!isRecord(value) || !Array.isArray(value.entityRefs)) return []; + const kindMap = { + task: "task", + revision: "document_revision", + interaction: "interaction", + approval: "approval", + decision: "decision", + artifact: "artifact", + "work-product": "work_product", + wake: "wake", + monitor: "monitor", + audit: "audit", + command: "operation", + } as const; + return value.entityRefs.flatMap((entry) => { + if (typeof entry !== "string") return []; + const separator = entry.indexOf(":"); + if (separator < 1) return []; + const kind = kindMap[entry.slice(0, separator) as keyof typeof kindMap]; + const id = entry.slice(separator + 1); + return kind === undefined || id.length === 0 ? [] : [{ kind, id }]; + }); +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + /** * Executes the eight requested behaviors and their red counterparts against the * real deterministic mock authority. The four declared fault classes are not diff --git a/packages/paperclip-runner/src/eval/eval-scoring.test.ts b/packages/paperclip-runner/src/eval/eval-scoring.test.ts index a7caa6a13a0..9cbfcef6f5f 100644 --- a/packages/paperclip-runner/src/eval/eval-scoring.test.ts +++ b/packages/paperclip-runner/src/eval/eval-scoring.test.ts @@ -7,6 +7,11 @@ import { scoreEval, type EvalObservation, } from "./eval-scoring.js"; +import { + createPrpBudgetStopReason, + createPrpSemanticToolResultEnvelope, +} from "../protocol/semantic-tool-receipts.js"; +import type { PrpEvent } from "../protocol/replay-contract.js"; function greenObservation(overrides: Partial = {}): EvalObservation { return { @@ -207,6 +212,59 @@ describe("scoreEval — dimensions are scored separately (red counterparts)", () expect(card.dimensions.trace_completeness.score).toBeCloseTo(5 / 6, 5); }); + it("derives semantic receipt and terminal completeness from PRP wire events", () => { + const card = scoreEval( + greenObservation({ + trace: { + receiptIds: [], + terminalPresent: false, + wireEvents: wireTrace(), + }, + }), + OPTIONS, + ); + expect(card.dimensions.trace_completeness).toMatchObject({ score: 1, passed: true }); + }); + + it("rejects a PRP receipt whose operation does not match the observed call", () => { + const events = wireTrace(); + const payload = events[0]!.payload as Record; + const receipt = payload.semantic_tool as Record; + receipt.operationId = "report_progress"; + const card = scoreEval( + greenObservation({ trace: { receiptIds: ["legacy-must-not-mask-wire"], terminalPresent: true, wireEvents: events } }), + OPTIONS, + ); + expect(card.dimensions.trace_completeness.reasons).toContain("trace missing receipt-per-call"); + }); + + it("requires a receipt and decision id when a terminal advertises a stop reason", () => { + const events = wireTrace(); + const terminal = events[1]!.payload as Record; + terminal.stopReason = createPrpBudgetStopReason({ + receiptId: "stop-receipt-1", + kind: "budget", + code: "budget_hard_stop", + retryable: true, + decisionId: "budget-decision-1", + limitClass: "actor_monthly", + aggregate: { unit: "cents", observed: 5000, limit: 5000, window: "monthly_utc" }, + }); + const card = scoreEval( + greenObservation({ trace: { receiptIds: [], terminalPresent: false, wireEvents: events } }), + OPTIONS, + ); + expect(card.dimensions.trace_completeness).toMatchObject({ score: 1, passed: true }); + + delete (terminal.stopReason as Record).decisionId; + const invalid = scoreEval( + greenObservation({ trace: { receiptIds: [], terminalPresent: false, wireEvents: events } }), + OPTIONS, + ); + expect(invalid.dimensions.trace_completeness.reasons) + .toContain("trace missing stop-reason-receipt"); + }); + it("drops quality_efficiency when a budget is exceeded", () => { const card = scoreEval( greenObservation({ efficiency: { latencyMs: 9000, totalTokens: 400, costUsd: 0.01, attempts: 1 } }), @@ -226,6 +284,65 @@ describe("scoreEval — dimensions are scored separately (red counterparts)", () }); }); +function wireTrace(): PrpEvent[] { + const correlation = { + runId: "run-1", + normalizedSessionId: "session-1", + turnId: "turn-1", + itemId: "item-1", + }; + return [ + { + schema: "paperclip.prp.event.v1", + sourceEventId: "wire-event-1", + sourceSeq: 1, + sourceInstanceId: "wire-test", + sourceKind: "runner", + runId: "run-1", + normalizedSessionId: "session-1", + turnId: "turn-1", + itemId: "item-1", + eventType: "mcp_app.tool_result", + schemaVersion: 1, + priority: 1, + emittedAt: "2026-08-11T00:00:00.000Z", + payload: { + semantic_tool: createPrpSemanticToolResultEnvelope({ + operationId: "finish_task", + callId: "call-1", + correlation, + idempotencyKey: "finish-once", + content: { disposition: "applied" }, + outcome: "succeeded", + code: "ok", + retryable: false, + authorizationBoundary: "active_task", + }), + }, + }, + { + schema: "paperclip.prp.event.v1", + sourceEventId: "wire-event-2", + sourceSeq: 2, + sourceInstanceId: "wire-test", + sourceKind: "runner", + runId: "run-1", + normalizedSessionId: "session-1", + turnId: "turn-1", + eventType: "run.terminal", + schemaVersion: 1, + priority: 0, + emittedAt: "2026-08-11T00:00:01.000Z", + payload: { + schema: "paperclip.prp.terminal.v1", + turnTerminalState: "completed", + runTerminalState: "succeeded", + reportedWorkDisposition: "done", + }, + }, + ]; +} + describe("scoreEval — determinism and weighting", () => { it("is deterministic for identical observations", () => { const obs = greenObservation({ finalState: { expected: "mutated", observed: "unchanged" } }); diff --git a/packages/paperclip-runner/src/eval/eval-scoring.ts b/packages/paperclip-runner/src/eval/eval-scoring.ts index 4a09a8379dc..56d70a65826 100644 --- a/packages/paperclip-runner/src/eval/eval-scoring.ts +++ b/packages/paperclip-runner/src/eval/eval-scoring.ts @@ -2,6 +2,8 @@ import type { CapabilityEvalCaseResult, CapabilityLiveCodexMatrixResult, } from "../conformance/capability-eval-suite.js"; +import type { PrpEvent } from "../protocol/replay-contract.js"; +import { prpSemanticToolResultReceipts } from "../protocol/semantic-tool-receipts.js"; import type { EvalFaultClass } from "./eval-bundle.js"; /** @@ -64,6 +66,11 @@ export interface EvalTraceEvidence { /** One safe receipt/operation id per observed semantic call. */ receiptIds: string[]; terminalPresent: boolean; + /** + * When present, PRP is authoritative for causal ids, semantic receipts, and + * terminal presence. Legacy live snapshots continue to use the scalar fields. + */ + wireEvents?: PrpEvent[]; } export interface EvalEfficiencyEvidence { @@ -200,17 +207,25 @@ function scoreTrajectoryRestraint(obs: EvalObservation): { score: number; reason function scoreTraceCompleteness(obs: EvalObservation): { score: number; reasons: string[] } { const reasons: string[] = []; + const wire = obs.trace.wireEvents === undefined + ? null + : traceEvidenceFromPrpEvents(obs.trace.wireEvents, obs.observedCalls); + const trace = wire ?? obs.trace; const receiptsComplete = - obs.trace.receiptIds.length >= obs.observedCalls.length && - obs.trace.receiptIds.every((id) => id.length > 0); + trace.receiptIds.length >= obs.observedCalls.length && + trace.receiptIds.every((id) => id.length > 0) && + (wire?.semanticReceiptsMatchCalls ?? true); const checks: Array<[string, boolean]> = [ - ["runId", Boolean(obs.trace.runId)], - ["sessionId", Boolean(obs.trace.sessionId)], - ["turnId", Boolean(obs.trace.turnId)], - ["itemId", Boolean(obs.trace.itemId)], - ["terminal", obs.trace.terminalPresent], + ["runId", Boolean(trace.runId)], + ["sessionId", Boolean(trace.sessionId)], + ["turnId", Boolean(trace.turnId)], + ["itemId", Boolean(trace.itemId)], + ["terminal", trace.terminalPresent], ["receipt-per-call", receiptsComplete], ]; + if (wire?.stopReasonPresent) { + checks.push(["stop-reason-receipt", wire.stopReasonReceiptValid]); + } for (const [label, present] of checks) { if (!present) reasons.push(`trace missing ${label}`); } @@ -218,6 +233,58 @@ function scoreTraceCompleteness(obs: EvalObservation): { score: number; reasons: return { score: clamp01(passed / checks.length), reasons }; } +export function traceEvidenceFromPrpEvents( + events: readonly PrpEvent[], + observedCalls: readonly string[] = [], +): EvalTraceEvidence & { + semanticReceiptsMatchCalls: boolean; + stopReasonPresent: boolean; + stopReasonReceiptValid: boolean; +} { + const receipts = prpSemanticToolResultReceipts(events); + const receiptCalls = receipts.map((receipt) => String(receipt.operationId)); + const semanticReceiptsMatchCalls = receiptCalls.length === observedCalls.length + && observedCalls.every((operationId, index) => + receiptCalls[index] === operationId + && typeof receipts[index]?.operationReceiptId === "string" + && String(receipts[index]?.operationReceiptId).length > 0, + ); + const terminal = events.find((event) => event.eventType === "run.terminal"); + const terminalPayload = asRecord(terminal?.payload); + const stopReason = asRecord(terminalPayload?.stopReason); + const stopReasonPresent = stopReason !== null; + const stopReasonReceiptValid = !stopReasonPresent || ( + stopReason?.schema === "paperclip.prp.stop_reason.v1" + && stopReason.schemaVersion === 1 + && typeof stopReason.receiptId === "string" + && stopReason.receiptId.length > 0 + && typeof stopReason.decisionId === "string" + && stopReason.decisionId.length > 0 + ); + const correlated = events.find((event) => event.eventType === "mcp_app.tool_result") + ?? events.find((event) => event.turnId !== undefined); + return { + runId: events[0]?.runId, + sessionId: correlated?.normalizedSessionId, + turnId: correlated?.turnId, + itemId: correlated?.itemId, + receiptIds: receipts.flatMap((receipt) => + typeof receipt.operationReceiptId === "string" ? [receipt.operationReceiptId] : [], + ), + terminalPresent: terminal !== undefined, + wireEvents: [...events], + semanticReceiptsMatchCalls, + stopReasonPresent, + stopReasonReceiptValid, + }; +} + +function asRecord(value: unknown): Record | null { + return typeof value === "object" && value !== null && !Array.isArray(value) + ? value as Record + : null; +} + function scoreQualityEfficiency(obs: EvalObservation): { score: number; reasons: string[] } { const budget = obs.budget; if (!budget || Object.keys(budget).length === 0) { diff --git a/packages/paperclip-runner/src/index.ts b/packages/paperclip-runner/src/index.ts index e8f2fb8c115..0f30d81deaf 100644 --- a/packages/paperclip-runner/src/index.ts +++ b/packages/paperclip-runner/src/index.ts @@ -13,6 +13,7 @@ export * from "./drivers/codex/app-server-transport.js"; export * from "./drivers/codex/codex-app-server-driver.js"; export * from "./protocol/replay-contract.js"; export * from "./protocol/replay-loader.js"; +export * from "./protocol/semantic-tool-receipts.js"; export * from "./reducer/session-reducer.js"; export * from "./generated/capability-contract.js"; export * from "./semantic-tools/index.js"; diff --git a/packages/paperclip-runner/src/protocol/generated/schema-bundle.ts b/packages/paperclip-runner/src/protocol/generated/schema-bundle.ts index 46c62d0e076..bfa59971cc3 100644 --- a/packages/paperclip-runner/src/protocol/generated/schema-bundle.ts +++ b/packages/paperclip-runner/src/protocol/generated/schema-bundle.ts @@ -120,6 +120,72 @@ export const capabilitiesSchema = { "typedEvents": { "type": "boolean" }, + "semanticTools": { + "type": "object", + "required": [ + "schema", + "schemaVersion", + "operations" + ], + "properties": { + "schema": { + "const": "paperclip.prp.semantic_tools.v1" + }, + "schemaVersion": { + "const": 1 + }, + "operations": { + "type": "array", + "items": { + "type": "object", + "required": [ + "operationId", + "version", + "availability", + "redactionDisposition" + ], + "properties": { + "operationId": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$" + }, + "version": { + "const": 1 + }, + "availability": { + "enum": [ + "available", + "denied", + "unsupported" + ] + }, + "redactionDisposition": { + "const": "digest_only" + }, + "requiredClaims": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 160 + }, + "uniqueItems": true + }, + "reasonCode": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^[a-z][a-z0-9_.:-]*$" + } + }, + "additionalProperties": true + } + } + }, + "additionalProperties": true + }, "unsupported": { "type": "array", "items": { @@ -221,6 +287,393 @@ export const commandSchema = { "additionalProperties": true } as const; +export const semanticToolSchema = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json", + "title": "PRP provider-neutral semantic tool envelope", + "type": "object", + "required": [ + "schema", + "schemaVersion", + "phase", + "operationId", + "callId", + "correlation", + "idempotencyKey", + "content" + ], + "properties": { + "schema": { + "const": "paperclip.prp.semantic_tool.v1" + }, + "schemaVersion": { + "const": 1 + }, + "phase": { + "enum": [ + "input", + "result" + ] + }, + "operationId": { + "$ref": "#/$defs/stableId" + }, + "callId": { + "$ref": "#/$defs/stableId" + }, + "correlation": { + "type": "object", + "required": [ + "runId", + "normalizedSessionId", + "turnId", + "itemId" + ], + "properties": { + "runId": { + "$ref": "#/$defs/stableId" + }, + "normalizedSessionId": { + "$ref": "#/$defs/stableId" + }, + "turnId": { + "$ref": "#/$defs/stableId" + }, + "itemId": { + "$ref": "#/$defs/stableId" + }, + "requestId": { + "$ref": "#/$defs/stableId" + } + }, + "additionalProperties": true + }, + "idempotencyKey": { + "type": [ + "string", + "null" + ], + "minLength": 1, + "maxLength": 240 + }, + "content": { + "$ref": "#/$defs/safeContent" + }, + "outcome": { + "enum": [ + "succeeded", + "denied", + "conflict", + "duplicate", + "unavailable", + "failed" + ] + }, + "code": { + "$ref": "#/$defs/stableCode" + }, + "retryable": { + "type": "boolean" + }, + "authorizationBoundary": { + "enum": [ + "company", + "actor", + "active_task", + "grant", + "governed_action", + "lock", + "revision" + ] + }, + "operationReceiptId": { + "$ref": "#/$defs/stableId" + }, + "auditReceiptId": { + "$ref": "#/$defs/stableId" + }, + "currentRevision": { + "oneOf": [ + { + "type": "integer", + "minimum": 0 + }, + { + "$ref": "#/$defs/stableId" + } + ] + }, + "duplicateOfReceiptId": { + "$ref": "#/$defs/stableId" + }, + "artifactRefs": { + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/$defs/safeReference" + }, + { + "type": "object", + "properties": { + "kind": { + "enum": [ + "artifact", + "work_product" + ] + } + } + } + ] + }, + "uniqueItems": true + }, + "targets": { + "type": "array", + "items": { + "$ref": "#/$defs/immutableTarget" + }, + "uniqueItems": true + }, + "causalRefs": { + "type": "array", + "items": { + "$ref": "#/$defs/safeReference" + }, + "uniqueItems": true + } + }, + "allOf": [ + { + "if": { + "properties": { + "phase": { + "const": "result" + } + } + }, + "then": { + "required": [ + "outcome", + "code", + "retryable", + "authorizationBoundary", + "operationReceiptId" + ] + } + } + ], + "additionalProperties": true, + "$defs": { + "stableId": { + "type": "string", + "minLength": 1, + "maxLength": 240, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$" + }, + "stableCode": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^[a-z][a-z0-9_.:-]*$" + }, + "safeContent": { + "type": "object", + "required": [ + "digest", + "redactionDisposition", + "references" + ], + "properties": { + "digest": { + "type": "string", + "pattern": "^sha256:[a-f0-9]{64}$" + }, + "redactionDisposition": { + "enum": [ + "digest_only", + "allowlisted_references", + "redacted" + ] + }, + "references": { + "type": "array", + "items": { + "$ref": "#/$defs/safeReference" + }, + "uniqueItems": true + } + }, + "additionalProperties": true + }, + "safeReference": { + "type": "object", + "required": [ + "kind", + "id" + ], + "properties": { + "kind": { + "enum": [ + "task", + "document_revision", + "interaction", + "approval", + "decision", + "artifact", + "work_product", + "wake", + "monitor", + "audit", + "operation" + ] + }, + "id": { + "$ref": "#/$defs/stableId" + } + }, + "additionalProperties": true + }, + "immutableTarget": { + "type": "object", + "required": [ + "kind", + "id", + "immutable" + ], + "properties": { + "kind": { + "enum": [ + "document_revision", + "interaction", + "approval", + "decision" + ] + }, + "id": { + "$ref": "#/$defs/stableId" + }, + "immutable": { + "const": true + }, + "revisionId": { + "$ref": "#/$defs/stableId" + }, + "decisionId": { + "$ref": "#/$defs/stableId" + } + }, + "additionalProperties": true + } + } +} as const; + +export const stopReasonSchema = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://paperclip.dev/schemas/prp/v1/stop-reason.schema.json", + "title": "PRP terminal stop reason receipt", + "type": "object", + "required": [ + "schema", + "schemaVersion", + "receiptId", + "kind", + "code", + "retryable", + "decisionId", + "limitClass", + "aggregate" + ], + "properties": { + "schema": { + "const": "paperclip.prp.stop_reason.v1" + }, + "schemaVersion": { + "const": 1 + }, + "receiptId": { + "$ref": "#/$defs/stableId" + }, + "kind": { + "enum": [ + "budget", + "cost" + ] + }, + "code": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "pattern": "^[a-z][a-z0-9_.:-]*$" + }, + "retryable": { + "type": "boolean" + }, + "decisionId": { + "$ref": "#/$defs/stableId" + }, + "limitClass": { + "enum": [ + "company_monthly", + "actor_monthly", + "project_monthly", + "run_cost", + "provider_quota" + ] + }, + "aggregate": { + "type": "object", + "required": [ + "unit", + "observed", + "limit", + "window" + ], + "properties": { + "unit": { + "enum": [ + "cents", + "usd_micros", + "tokens" + ] + }, + "observed": { + "type": "integer", + "minimum": 0 + }, + "limit": { + "type": "integer", + "minimum": 0 + }, + "window": { + "enum": [ + "run", + "monthly_utc", + "provider_window" + ] + } + }, + "additionalProperties": true + }, + "relatedReceiptIds": { + "type": "array", + "items": { + "$ref": "#/$defs/stableId" + }, + "uniqueItems": true + } + }, + "additionalProperties": true, + "$defs": { + "stableId": { + "type": "string", + "minLength": 1, + "maxLength": 240, + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$" + } + } +} as const; + export const terminalSchema = { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://paperclip.dev/schemas/prp/v1/terminal.schema.json", @@ -266,6 +719,9 @@ export const terminalSchema = { "statusDecisionId": { "type": "string", "minLength": 1 + }, + "stopReason": { + "$ref": "https://paperclip.dev/schemas/prp/v1/stop-reason.schema.json" } }, "additionalProperties": true @@ -807,6 +1263,74 @@ export const eventSchema = { } }, "allOf": [ + { + "if": { + "properties": { + "eventType": { + "const": "mcp_app.tool_input" + } + } + }, + "then": { + "properties": { + "payload": { + "type": "object", + "properties": { + "semantic_tool": { + "allOf": [ + { + "$ref": "https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json" + }, + { + "type": "object", + "properties": { + "phase": { + "const": "input" + } + } + } + ] + } + }, + "additionalProperties": true + } + } + } + }, + { + "if": { + "properties": { + "eventType": { + "const": "mcp_app.tool_result" + } + } + }, + "then": { + "properties": { + "payload": { + "type": "object", + "properties": { + "semantic_tool": { + "allOf": [ + { + "$ref": "https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json" + }, + { + "type": "object", + "properties": { + "phase": { + "const": "result" + } + } + } + ] + } + }, + "additionalProperties": true + } + } + } + }, { "if": { "properties": { @@ -913,12 +1437,14 @@ export const fixtureSchema = { } as const; export const prpSchemaBundle = { - identity: identitySchema, - capabilities: capabilitiesSchema, - command: commandSchema, - terminal: terminalSchema, - request: requestSchema, - result: resultSchema, - event: eventSchema, - fixture: fixtureSchema, + "identity": identitySchema, + "capabilities": capabilitiesSchema, + "command": commandSchema, + "semantic-tool": semanticToolSchema, + "stop-reason": stopReasonSchema, + "terminal": terminalSchema, + "request": requestSchema, + "result": resultSchema, + "event": eventSchema, + "fixture": fixtureSchema, } as const; diff --git a/packages/paperclip-runner/src/protocol/generated/standalone-validators.ts b/packages/paperclip-runner/src/protocol/generated/standalone-validators.ts index 67043a30e86..0e14c666c29 100644 --- a/packages/paperclip-runner/src/protocol/generated/standalone-validators.ts +++ b/packages/paperclip-runner/src/protocol/generated/standalone-validators.ts @@ -1,6 +1,7 @@ // Generated by scripts/generate-protocol-schema-module.mjs. Do not edit. // @ts-nocheck -- Ajv standalone output is JavaScript compiled from the checked-in schemas. +import equalModule from "ajv/dist/runtime/equal.js"; import ucs2LengthModule from "ajv/dist/runtime/ucs2length.js"; -"use strict";export const fixtureValidator = validate20;const schema31 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/fixture.schema.json","title":"PRP scripted replay fixture","type":"object","required":["schema","fixtureVersion","protocolVersion","name","description","identity","capabilities","commands","events","result"],"properties":{"schema":{"const":"paperclip.prp.fixture.v1"},"fixtureVersion":{"const":1},"protocolVersion":{"const":1},"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","minLength":1,"maxLength":1000},"identity":{"$ref":"https://paperclip.dev/schemas/prp/v1/identity.schema.json"},"capabilities":{"$ref":"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json"},"commands":{"type":"array","items":{"$ref":"https://paperclip.dev/schemas/prp/v1/command.schema.json"}},"events":{"type":"array","minItems":1,"items":{"$ref":"https://paperclip.dev/schemas/prp/v1/event.schema.json"}},"requests":{"type":"array","items":{"$ref":"https://paperclip.dev/schemas/prp/v1/request.schema.json"}},"result":{"$ref":"https://paperclip.dev/schemas/prp/v1/result.schema.json"}},"additionalProperties":true};const schema41 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json","title":"PRP negotiated capabilities","type":"object","required":["schema","sessionReusePolicy","driver","steer","interrupt","resume","runtimeRequests","structuredResult","typedEvents"],"properties":{"schema":{"const":"paperclip.prp.capabilities.v1"},"sessionReusePolicy":{"enum":["new_per_run","reuse_per_issue","reuse_per_workspace"]},"driver":{"type":"object","required":["kind","version"],"properties":{"kind":{"type":"string","minLength":1,"maxLength":80},"version":{"type":"string","minLength":1,"maxLength":80}},"additionalProperties":true},"steer":{"type":"boolean"},"interrupt":{"type":"boolean"},"resume":{"type":"boolean"},"runtimeRequests":{"type":"boolean"},"structuredResult":{"type":"boolean"},"typedEvents":{"type":"boolean"},"unsupported":{"type":"array","items":{"type":"string","minLength":1},"uniqueItems":true}},"additionalProperties":true};const schema42 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/command.schema.json","title":"PRP runner command","type":"object","required":["schema","commandId","controllerSeq","type","issuedAt","payload"],"properties":{"schema":{"const":"paperclip.prp.command.v1"},"commandId":{"type":"string","minLength":1,"maxLength":160},"controllerSeq":{"type":"integer","minimum":1},"type":{"enum":["run.prepare","session.open","turn.start","turn.steer","turn.interrupt","turn.stop","request.resolve","interaction.receipt","session.snapshot","session.close","run.cancel","runner.drain","runner.shutdown"]},"issuedAt":{"type":"string","format":"date-time"},"deadlineAt":{"type":"string","format":"date-time"},"precondition":{"type":"object","properties":{"runnerState":{"type":"array","items":{"type":"string"}},"runState":{"type":"array","items":{"type":"string"}},"sessionState":{"type":"array","items":{"type":"string"}},"activeTurnId":{"type":["string","null"]}},"additionalProperties":true},"payload":{"type":"object","additionalProperties":true}},"additionalProperties":true};const schema46 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/request.schema.json","title":"PRP request","oneOf":[{"type":"object","required":["schema","requestKind","requestId","type","status","prompt"],"properties":{"schema":{"const":"paperclip.runtime_request.v1"},"requestKind":{"const":"runtime"},"requestId":{"type":"string","minLength":1,"maxLength":160},"type":{"enum":["permission","input"]},"status":{"enum":["pending","resolved","expired","cancelled"]},"prompt":{"type":"string","minLength":1,"maxLength":4000},"choices":{"type":"array","items":{"type":"object","required":["key","label"],"properties":{"key":{"type":"string","minLength":1},"label":{"type":"string","minLength":1}},"additionalProperties":true}}},"additionalProperties":true},{"type":"object","required":["schema","requestKind","requestId","kind","blocking","payload"],"properties":{"schema":{"const":"paperclip.interaction_request.v1"},"requestKind":{"const":"issue_thread"},"requestId":{"type":"string","minLength":1,"maxLength":160},"kind":{"enum":["request_confirmation","request_checkbox_confirmation","request_item_verdicts","ask_user_questions","suggest_tasks"]},"blocking":{"type":"boolean"},"payload":{"type":"object","additionalProperties":true}},"additionalProperties":true}]};const schema45 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/result.schema.json","title":"PRP structured run result","type":"object","required":["schema","reportedWorkDisposition","summary","completionClaim","evidence","verification","attentionRequests","artifacts"],"properties":{"schema":{"const":"paperclip.run_result.v1"},"reportedWorkDisposition":{"enum":["done","blocked","needs_review","yielded"]},"summary":{"type":"string","minLength":1,"maxLength":12000},"completionClaim":{"type":"object","required":["contractRevision","objectiveSatisfied","criteria","remainingWork"],"properties":{"contractRevision":{"type":"string","minLength":1},"objectiveSatisfied":{"type":"boolean"},"criteria":{"type":"array","items":{"type":"object","required":["criterionId","status","evidenceRefs"],"properties":{"criterionId":{"type":"string","minLength":1},"status":{"enum":["satisfied","not_satisfied","unknown"]},"evidenceRefs":{"type":"array","items":{"type":"string"}},"explanation":{"type":"string"}},"additionalProperties":true}},"remainingWork":{"type":"array","items":{"type":"object","required":["description","blocksCompletion"],"properties":{"description":{"type":"string","minLength":1},"blocksCompletion":{"type":"boolean"}},"additionalProperties":true}}},"additionalProperties":true},"evidence":{"type":"array","items":{"type":"object"}},"verification":{"type":"array","items":{"type":"object","required":["commandOrCheck","status"],"properties":{"commandOrCheck":{"type":"string","minLength":1},"status":{"enum":["passed","failed","not_run"]},"detail":{"type":"string"},"artifactRef":{"type":"string"}},"additionalProperties":true}},"blocker":{"type":"object","required":["reasonCode","owner","unblockAction","scope"],"properties":{"reasonCode":{"type":"string","minLength":1},"owner":{"type":"object","additionalProperties":true},"unblockAction":{"type":"string","minLength":1},"scope":{"enum":["current_track","task_wide"]}},"additionalProperties":true},"attentionRequests":{"type":"array","items":{"type":"object"}},"artifacts":{"type":"array","items":{"type":"object","required":["kind","ref"],"properties":{"kind":{"type":"string","minLength":1},"ref":{"type":"string","minLength":1},"title":{"type":"string"}},"additionalProperties":true}},"continuation":{"type":"object","required":["kind","summary","idempotencyKey"],"properties":{"kind":{"enum":["same_agent","retry","delegated_issue","response_wake","monitor"]},"summary":{"type":"string","minLength":1},"idempotencyKey":{"type":"string","minLength":1}},"additionalProperties":true}},"allOf":[{"if":{"properties":{"reportedWorkDisposition":{"const":"blocked"}}},"then":{"required":["blocker"]}},{"if":{"properties":{"reportedWorkDisposition":{"const":"yielded"}}},"then":{"required":["continuation"]}}],"additionalProperties":true};const func1 = typeof ucs2LengthModule === "function" ? ucs2LengthModule : ucs2LengthModule.default;const schema32 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/identity.schema.json","title":"PRP identity graph","type":"object","required":["schema","companyId","issueId","runId","environmentLeaseId","runnerInstanceId","normalizedSessionId","driverSessionId"],"properties":{"schema":{"const":"paperclip.prp.identity.v1"},"companyId":{"$ref":"#/$defs/stableId"},"issueId":{"$ref":"#/$defs/stableId"},"runId":{"$ref":"#/$defs/stableId"},"environmentLeaseId":{"$ref":"#/$defs/stableId"},"runnerInstanceId":{"$ref":"#/$defs/stableId"},"normalizedSessionId":{"$ref":"#/$defs/stableId"},"driverSessionId":{"$ref":"#/$defs/stableId"},"providerSessionId":{"$ref":"#/$defs/stableId"}},"additionalProperties":true,"$defs":{"stableId":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$"}}};const schema33 = {"type":"string","minLength":1,"maxLength":160,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$"};const pattern4 = new RegExp("^[A-Za-z0-9][A-Za-z0-9._:-]*$", "u");function validate21(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://paperclip.dev/schemas/prp/v1/identity.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate21.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.schema === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.companyId === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "companyId"},message:"must have required property '"+"companyId"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.issueId === undefined){const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "issueId"},message:"must have required property '"+"issueId"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.runId === undefined){const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "runId"},message:"must have required property '"+"runId"+"'"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(data.environmentLeaseId === undefined){const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "environmentLeaseId"},message:"must have required property '"+"environmentLeaseId"+"'"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(data.runnerInstanceId === undefined){const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "runnerInstanceId"},message:"must have required property '"+"runnerInstanceId"+"'"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}if(data.normalizedSessionId === undefined){const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "normalizedSessionId"},message:"must have required property '"+"normalizedSessionId"+"'"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}if(data.driverSessionId === undefined){const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "driverSessionId"},message:"must have required property '"+"driverSessionId"+"'"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}if(data.schema !== undefined){if("paperclip.prp.identity.v1" !== data.schema){const err8 = {instancePath:instancePath+"/schema",schemaPath:"#/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.identity.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}}if(data.companyId !== undefined){let data1 = data.companyId;if(typeof data1 === "string"){if(func1(data1) > 160){const err9 = {instancePath:instancePath+"/companyId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}if(func1(data1) < 1){const err10 = {instancePath:instancePath+"/companyId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}if(!pattern4.test(data1)){const err11 = {instancePath:instancePath+"/companyId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}}else {const err12 = {instancePath:instancePath+"/companyId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}}if(data.issueId !== undefined){let data2 = data.issueId;if(typeof data2 === "string"){if(func1(data2) > 160){const err13 = {instancePath:instancePath+"/issueId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}if(func1(data2) < 1){const err14 = {instancePath:instancePath+"/issueId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}if(!pattern4.test(data2)){const err15 = {instancePath:instancePath+"/issueId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}}else {const err16 = {instancePath:instancePath+"/issueId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}}if(data.runId !== undefined){let data3 = data.runId;if(typeof data3 === "string"){if(func1(data3) > 160){const err17 = {instancePath:instancePath+"/runId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}if(func1(data3) < 1){const err18 = {instancePath:instancePath+"/runId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}if(!pattern4.test(data3)){const err19 = {instancePath:instancePath+"/runId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}}else {const err20 = {instancePath:instancePath+"/runId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}}if(data.environmentLeaseId !== undefined){let data4 = data.environmentLeaseId;if(typeof data4 === "string"){if(func1(data4) > 160){const err21 = {instancePath:instancePath+"/environmentLeaseId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(func1(data4) < 1){const err22 = {instancePath:instancePath+"/environmentLeaseId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(!pattern4.test(data4)){const err23 = {instancePath:instancePath+"/environmentLeaseId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}}else {const err24 = {instancePath:instancePath+"/environmentLeaseId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}}if(data.runnerInstanceId !== undefined){let data5 = data.runnerInstanceId;if(typeof data5 === "string"){if(func1(data5) > 160){const err25 = {instancePath:instancePath+"/runnerInstanceId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}if(func1(data5) < 1){const err26 = {instancePath:instancePath+"/runnerInstanceId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}if(!pattern4.test(data5)){const err27 = {instancePath:instancePath+"/runnerInstanceId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}}else {const err28 = {instancePath:instancePath+"/runnerInstanceId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}}if(data.normalizedSessionId !== undefined){let data6 = data.normalizedSessionId;if(typeof data6 === "string"){if(func1(data6) > 160){const err29 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}if(func1(data6) < 1){const err30 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}if(!pattern4.test(data6)){const err31 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}}else {const err32 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}}if(data.driverSessionId !== undefined){let data7 = data.driverSessionId;if(typeof data7 === "string"){if(func1(data7) > 160){const err33 = {instancePath:instancePath+"/driverSessionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}if(func1(data7) < 1){const err34 = {instancePath:instancePath+"/driverSessionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}if(!pattern4.test(data7)){const err35 = {instancePath:instancePath+"/driverSessionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}}else {const err36 = {instancePath:instancePath+"/driverSessionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}}if(data.providerSessionId !== undefined){let data8 = data.providerSessionId;if(typeof data8 === "string"){if(func1(data8) > 160){const err37 = {instancePath:instancePath+"/providerSessionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}if(func1(data8) < 1){const err38 = {instancePath:instancePath+"/providerSessionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}if(!pattern4.test(data8)){const err39 = {instancePath:instancePath+"/providerSessionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err39];}else {vErrors.push(err39);}errors++;}}else {const err40 = {instancePath:instancePath+"/providerSessionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err40];}else {vErrors.push(err40);}errors++;}}}else {const err41 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err41];}else {vErrors.push(err41);}errors++;}validate21.errors = vErrors;return errors === 0;}validate21.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};const schema43 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/event.schema.json","title":"PRP native event","type":"object","required":["schema","sourceEventId","sourceSeq","sourceInstanceId","sourceKind","runId","eventType","schemaVersion","priority","emittedAt","payload"],"properties":{"schema":{"const":"paperclip.prp.event.v1"},"sourceEventId":{"type":"string","minLength":1,"maxLength":160},"sourceSeq":{"type":"integer","minimum":1},"sourceInstanceId":{"type":"string","minLength":1,"maxLength":160},"sourceKind":{"enum":["runner","control_plane"]},"runId":{"type":"string","minLength":1,"maxLength":160},"normalizedSessionId":{"type":"string","minLength":1,"maxLength":160},"turnId":{"type":"string","minLength":1,"maxLength":160},"itemId":{"type":"string","minLength":1,"maxLength":160},"eventType":{"enum":["runner.connected","runner.reconnected","runner.disconnected","runner.draining","runner.diagnostic","runtime.phase.changed","sandbox.metric","workspace.ready","harness.starting","harness.ready","harness.exited","harness.diagnostic","session.starting","session.started","session.resuming","session.resumed","session.reconciled","session.closed","session.failed","turn.submitted","turn.accepted","turn.started","turn.completed","turn.failed","turn.interrupted","turn.cancelled","item.started","item.delta","item.completed","item.failed","mcp_app.discovered","mcp_app.resource.resolved","mcp_app.initializing","mcp_app.ready","mcp_app.tool_input","mcp_app.tool_result","mcp_app.action.requested","mcp_app.action.resolved","mcp_app.host_context.changed","mcp_app.failed","mcp_app.teardown","runtime_request.created","runtime_request.resolved","runtime_request.expired","runtime_request.cancelled","interaction.request.proposed","interaction.request.materialized","interaction.request.rejected","interaction.response.progressed","interaction.response.resolved","interaction.response.delivered","run.result.proposed","run.result.accepted","run.result.rejected","attention.request.proposed","attention.request.routed","attention.request.resolved","attention.request.expired","attention.request.superseded","work.assessment.recorded","issue.status.decision.recorded","issue.status.decision.applied","issue.status.decision.rejected","issue.status.decision.superseded","run.terminal"]},"schemaVersion":{"const":1},"priority":{"enum":[0,1,2]},"emittedAt":{"type":"string","format":"date-time"},"observedAt":{"type":"string","format":"date-time"},"payload":{"type":"object","additionalProperties":true},"debug":{"type":"object","additionalProperties":true}},"allOf":[{"if":{"properties":{"eventType":{"const":"run.terminal"}}},"then":{"properties":{"payload":{"$ref":"https://paperclip.dev/schemas/prp/v1/terminal.schema.json"}}}},{"if":{"properties":{"eventType":{"const":"run.result.proposed"}}},"then":{"properties":{"payload":{"$ref":"https://paperclip.dev/schemas/prp/v1/result.schema.json"}}}}],"additionalProperties":true};const schema44 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/terminal.schema.json","title":"PRP run terminal state","type":"object","required":["schema","turnTerminalState","runTerminalState","reportedWorkDisposition"],"properties":{"schema":{"const":"paperclip.prp.terminal.v1"},"turnTerminalState":{"enum":["completed","failed","interrupted","cancelled"]},"runTerminalState":{"enum":["succeeded","failed","cancelled"]},"reportedWorkDisposition":{"enum":["done","blocked","needs_review","yielded"]},"workAssessmentId":{"type":"string","minLength":1},"statusDecisionId":{"type":"string","minLength":1}},"additionalProperties":true};const formats0 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;function validate23(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://paperclip.dev/schemas/prp/v1/event.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate23.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}const _errs2 = errors;let valid1 = true;const _errs3 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.eventType !== undefined){if("run.terminal" !== data.eventType){const err0 = {};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}}}var _valid0 = _errs3 === errors;errors = _errs2;if(vErrors !== null){if(_errs2){vErrors.length = _errs2;}else {vErrors = null;}}if(_valid0){const _errs5 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.payload !== undefined){let data1 = data.payload;if(data1 && typeof data1 == "object" && !Array.isArray(data1)){if(data1.schema === undefined){const err1 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data1.turnTerminalState === undefined){const err2 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/required",keyword:"required",params:{missingProperty: "turnTerminalState"},message:"must have required property '"+"turnTerminalState"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data1.runTerminalState === undefined){const err3 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/required",keyword:"required",params:{missingProperty: "runTerminalState"},message:"must have required property '"+"runTerminalState"+"'"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(data1.reportedWorkDisposition === undefined){const err4 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/required",keyword:"required",params:{missingProperty: "reportedWorkDisposition"},message:"must have required property '"+"reportedWorkDisposition"+"'"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(data1.schema !== undefined){if("paperclip.prp.terminal.v1" !== data1.schema){const err5 = {instancePath:instancePath+"/payload/schema",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.terminal.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}}if(data1.turnTerminalState !== undefined){let data3 = data1.turnTerminalState;if(!((((data3 === "completed") || (data3 === "failed")) || (data3 === "interrupted")) || (data3 === "cancelled"))){const err6 = {instancePath:instancePath+"/payload/turnTerminalState",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/properties/turnTerminalState/enum",keyword:"enum",params:{allowedValues: schema44.properties.turnTerminalState.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}}if(data1.runTerminalState !== undefined){let data4 = data1.runTerminalState;if(!(((data4 === "succeeded") || (data4 === "failed")) || (data4 === "cancelled"))){const err7 = {instancePath:instancePath+"/payload/runTerminalState",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/properties/runTerminalState/enum",keyword:"enum",params:{allowedValues: schema44.properties.runTerminalState.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}}if(data1.reportedWorkDisposition !== undefined){let data5 = data1.reportedWorkDisposition;if(!((((data5 === "done") || (data5 === "blocked")) || (data5 === "needs_review")) || (data5 === "yielded"))){const err8 = {instancePath:instancePath+"/payload/reportedWorkDisposition",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/properties/reportedWorkDisposition/enum",keyword:"enum",params:{allowedValues: schema44.properties.reportedWorkDisposition.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}}if(data1.workAssessmentId !== undefined){let data6 = data1.workAssessmentId;if(typeof data6 === "string"){if(func1(data6) < 1){const err9 = {instancePath:instancePath+"/payload/workAssessmentId",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/properties/workAssessmentId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}}else {const err10 = {instancePath:instancePath+"/payload/workAssessmentId",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/properties/workAssessmentId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}}if(data1.statusDecisionId !== undefined){let data7 = data1.statusDecisionId;if(typeof data7 === "string"){if(func1(data7) < 1){const err11 = {instancePath:instancePath+"/payload/statusDecisionId",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/properties/statusDecisionId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}}else {const err12 = {instancePath:instancePath+"/payload/statusDecisionId",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/properties/statusDecisionId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}}}else {const err13 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/terminal.schema.json/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}}}var _valid0 = _errs5 === errors;valid1 = _valid0;if(valid1){var props0 = {};props0.payload = true;props0.eventType = true;}}if(!valid1){const err14 = {instancePath,schemaPath:"#/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}const _errs19 = errors;let valid6 = true;const _errs20 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.eventType !== undefined){if("run.result.proposed" !== data.eventType){const err15 = {};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}}}var _valid1 = _errs20 === errors;errors = _errs19;if(vErrors !== null){if(_errs19){vErrors.length = _errs19;}else {vErrors = null;}}if(_valid1){const _errs22 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.payload !== undefined){let data9 = data.payload;const _errs27 = errors;let valid11 = true;const _errs28 = errors;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.reportedWorkDisposition !== undefined){if("blocked" !== data9.reportedWorkDisposition){const err16 = {};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}}}var _valid2 = _errs28 === errors;errors = _errs27;if(vErrors !== null){if(_errs27){vErrors.length = _errs27;}else {vErrors = null;}}if(_valid2){const _errs30 = errors;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.blocker === undefined){const err17 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/0/then/required",keyword:"required",params:{missingProperty: "blocker"},message:"must have required property '"+"blocker"+"'"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}}var _valid2 = _errs30 === errors;valid11 = _valid2;}if(!valid11){const err18 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}const _errs32 = errors;let valid13 = true;const _errs33 = errors;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.reportedWorkDisposition !== undefined){if("yielded" !== data9.reportedWorkDisposition){const err19 = {};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}}}var _valid3 = _errs33 === errors;errors = _errs32;if(vErrors !== null){if(_errs32){vErrors.length = _errs32;}else {vErrors = null;}}if(_valid3){const _errs35 = errors;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.continuation === undefined){const err20 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/1/then/required",keyword:"required",params:{missingProperty: "continuation"},message:"must have required property '"+"continuation"+"'"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}}var _valid3 = _errs35 === errors;valid13 = _valid3;}if(!valid13){const err21 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/1/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.schema === undefined){const err22 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(data9.reportedWorkDisposition === undefined){const err23 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "reportedWorkDisposition"},message:"must have required property '"+"reportedWorkDisposition"+"'"};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}if(data9.summary === undefined){const err24 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "summary"},message:"must have required property '"+"summary"+"'"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}if(data9.completionClaim === undefined){const err25 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "completionClaim"},message:"must have required property '"+"completionClaim"+"'"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}if(data9.evidence === undefined){const err26 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "evidence"},message:"must have required property '"+"evidence"+"'"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}if(data9.verification === undefined){const err27 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "verification"},message:"must have required property '"+"verification"+"'"};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}if(data9.attentionRequests === undefined){const err28 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "attentionRequests"},message:"must have required property '"+"attentionRequests"+"'"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}if(data9.artifacts === undefined){const err29 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "artifacts"},message:"must have required property '"+"artifacts"+"'"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}if(data9.schema !== undefined){if("paperclip.run_result.v1" !== data9.schema){const err30 = {instancePath:instancePath+"/payload/schema",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.run_result.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}}if(data9.reportedWorkDisposition !== undefined){let data13 = data9.reportedWorkDisposition;if(!((((data13 === "done") || (data13 === "blocked")) || (data13 === "needs_review")) || (data13 === "yielded"))){const err31 = {instancePath:instancePath+"/payload/reportedWorkDisposition",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/reportedWorkDisposition/enum",keyword:"enum",params:{allowedValues: schema45.properties.reportedWorkDisposition.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}}if(data9.summary !== undefined){let data14 = data9.summary;if(typeof data14 === "string"){if(func1(data14) > 12000){const err32 = {instancePath:instancePath+"/payload/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/maxLength",keyword:"maxLength",params:{limit: 12000},message:"must NOT have more than 12000 characters"};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}if(func1(data14) < 1){const err33 = {instancePath:instancePath+"/payload/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}}else {const err34 = {instancePath:instancePath+"/payload/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}}if(data9.completionClaim !== undefined){let data15 = data9.completionClaim;if(data15 && typeof data15 == "object" && !Array.isArray(data15)){if(data15.contractRevision === undefined){const err35 = {instancePath:instancePath+"/payload/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "contractRevision"},message:"must have required property '"+"contractRevision"+"'"};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}if(data15.objectiveSatisfied === undefined){const err36 = {instancePath:instancePath+"/payload/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "objectiveSatisfied"},message:"must have required property '"+"objectiveSatisfied"+"'"};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}if(data15.criteria === undefined){const err37 = {instancePath:instancePath+"/payload/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "criteria"},message:"must have required property '"+"criteria"+"'"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}if(data15.remainingWork === undefined){const err38 = {instancePath:instancePath+"/payload/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "remainingWork"},message:"must have required property '"+"remainingWork"+"'"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}if(data15.contractRevision !== undefined){let data16 = data15.contractRevision;if(typeof data16 === "string"){if(func1(data16) < 1){const err39 = {instancePath:instancePath+"/payload/completionClaim/contractRevision",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/contractRevision/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err39];}else {vErrors.push(err39);}errors++;}}else {const err40 = {instancePath:instancePath+"/payload/completionClaim/contractRevision",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/contractRevision/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err40];}else {vErrors.push(err40);}errors++;}}if(data15.objectiveSatisfied !== undefined){if(typeof data15.objectiveSatisfied !== "boolean"){const err41 = {instancePath:instancePath+"/payload/completionClaim/objectiveSatisfied",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/objectiveSatisfied/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err41];}else {vErrors.push(err41);}errors++;}}if(data15.criteria !== undefined){let data18 = data15.criteria;if(Array.isArray(data18)){const len0 = data18.length;for(let i0=0; i0 160){const err117 = {instancePath:instancePath+"/sourceEventId",schemaPath:"#/properties/sourceEventId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err117];}else {vErrors.push(err117);}errors++;}if(func1(data54) < 1){const err118 = {instancePath:instancePath+"/sourceEventId",schemaPath:"#/properties/sourceEventId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err118];}else {vErrors.push(err118);}errors++;}}else {const err119 = {instancePath:instancePath+"/sourceEventId",schemaPath:"#/properties/sourceEventId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err119];}else {vErrors.push(err119);}errors++;}}if(data.sourceSeq !== undefined){let data55 = data.sourceSeq;if(!(((typeof data55 == "number") && (!(data55 % 1) && !isNaN(data55))) && (isFinite(data55)))){const err120 = {instancePath:instancePath+"/sourceSeq",schemaPath:"#/properties/sourceSeq/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err120];}else {vErrors.push(err120);}errors++;}if((typeof data55 == "number") && (isFinite(data55))){if(data55 < 1 || isNaN(data55)){const err121 = {instancePath:instancePath+"/sourceSeq",schemaPath:"#/properties/sourceSeq/minimum",keyword:"minimum",params:{comparison: ">=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err121];}else {vErrors.push(err121);}errors++;}}}if(data.sourceInstanceId !== undefined){let data56 = data.sourceInstanceId;if(typeof data56 === "string"){if(func1(data56) > 160){const err122 = {instancePath:instancePath+"/sourceInstanceId",schemaPath:"#/properties/sourceInstanceId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err122];}else {vErrors.push(err122);}errors++;}if(func1(data56) < 1){const err123 = {instancePath:instancePath+"/sourceInstanceId",schemaPath:"#/properties/sourceInstanceId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err123];}else {vErrors.push(err123);}errors++;}}else {const err124 = {instancePath:instancePath+"/sourceInstanceId",schemaPath:"#/properties/sourceInstanceId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err124];}else {vErrors.push(err124);}errors++;}}if(data.sourceKind !== undefined){let data57 = data.sourceKind;if(!((data57 === "runner") || (data57 === "control_plane"))){const err125 = {instancePath:instancePath+"/sourceKind",schemaPath:"#/properties/sourceKind/enum",keyword:"enum",params:{allowedValues: schema43.properties.sourceKind.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err125];}else {vErrors.push(err125);}errors++;}}if(data.runId !== undefined){let data58 = data.runId;if(typeof data58 === "string"){if(func1(data58) > 160){const err126 = {instancePath:instancePath+"/runId",schemaPath:"#/properties/runId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err126];}else {vErrors.push(err126);}errors++;}if(func1(data58) < 1){const err127 = {instancePath:instancePath+"/runId",schemaPath:"#/properties/runId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err127];}else {vErrors.push(err127);}errors++;}}else {const err128 = {instancePath:instancePath+"/runId",schemaPath:"#/properties/runId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err128];}else {vErrors.push(err128);}errors++;}}if(data.normalizedSessionId !== undefined){let data59 = data.normalizedSessionId;if(typeof data59 === "string"){if(func1(data59) > 160){const err129 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/properties/normalizedSessionId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err129];}else {vErrors.push(err129);}errors++;}if(func1(data59) < 1){const err130 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/properties/normalizedSessionId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err130];}else {vErrors.push(err130);}errors++;}}else {const err131 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/properties/normalizedSessionId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err131];}else {vErrors.push(err131);}errors++;}}if(data.turnId !== undefined){let data60 = data.turnId;if(typeof data60 === "string"){if(func1(data60) > 160){const err132 = {instancePath:instancePath+"/turnId",schemaPath:"#/properties/turnId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err132];}else {vErrors.push(err132);}errors++;}if(func1(data60) < 1){const err133 = {instancePath:instancePath+"/turnId",schemaPath:"#/properties/turnId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err133];}else {vErrors.push(err133);}errors++;}}else {const err134 = {instancePath:instancePath+"/turnId",schemaPath:"#/properties/turnId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err134];}else {vErrors.push(err134);}errors++;}}if(data.itemId !== undefined){let data61 = data.itemId;if(typeof data61 === "string"){if(func1(data61) > 160){const err135 = {instancePath:instancePath+"/itemId",schemaPath:"#/properties/itemId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err135];}else {vErrors.push(err135);}errors++;}if(func1(data61) < 1){const err136 = {instancePath:instancePath+"/itemId",schemaPath:"#/properties/itemId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err136];}else {vErrors.push(err136);}errors++;}}else {const err137 = {instancePath:instancePath+"/itemId",schemaPath:"#/properties/itemId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err137];}else {vErrors.push(err137);}errors++;}}if(data.eventType !== undefined){let data62 = data.eventType;if(!(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((data62 === "runner.connected") || (data62 === "runner.reconnected")) || (data62 === "runner.disconnected")) || (data62 === "runner.draining")) || (data62 === "runner.diagnostic")) || (data62 === "runtime.phase.changed")) || (data62 === "sandbox.metric")) || (data62 === "workspace.ready")) || (data62 === "harness.starting")) || (data62 === "harness.ready")) || (data62 === "harness.exited")) || (data62 === "harness.diagnostic")) || (data62 === "session.starting")) || (data62 === "session.started")) || (data62 === "session.resuming")) || (data62 === "session.resumed")) || (data62 === "session.reconciled")) || (data62 === "session.closed")) || (data62 === "session.failed")) || (data62 === "turn.submitted")) || (data62 === "turn.accepted")) || (data62 === "turn.started")) || (data62 === "turn.completed")) || (data62 === "turn.failed")) || (data62 === "turn.interrupted")) || (data62 === "turn.cancelled")) || (data62 === "item.started")) || (data62 === "item.delta")) || (data62 === "item.completed")) || (data62 === "item.failed")) || (data62 === "mcp_app.discovered")) || (data62 === "mcp_app.resource.resolved")) || (data62 === "mcp_app.initializing")) || (data62 === "mcp_app.ready")) || (data62 === "mcp_app.tool_input")) || (data62 === "mcp_app.tool_result")) || (data62 === "mcp_app.action.requested")) || (data62 === "mcp_app.action.resolved")) || (data62 === "mcp_app.host_context.changed")) || (data62 === "mcp_app.failed")) || (data62 === "mcp_app.teardown")) || (data62 === "runtime_request.created")) || (data62 === "runtime_request.resolved")) || (data62 === "runtime_request.expired")) || (data62 === "runtime_request.cancelled")) || (data62 === "interaction.request.proposed")) || (data62 === "interaction.request.materialized")) || (data62 === "interaction.request.rejected")) || (data62 === "interaction.response.progressed")) || (data62 === "interaction.response.resolved")) || (data62 === "interaction.response.delivered")) || (data62 === "run.result.proposed")) || (data62 === "run.result.accepted")) || (data62 === "run.result.rejected")) || (data62 === "attention.request.proposed")) || (data62 === "attention.request.routed")) || (data62 === "attention.request.resolved")) || (data62 === "attention.request.expired")) || (data62 === "attention.request.superseded")) || (data62 === "work.assessment.recorded")) || (data62 === "issue.status.decision.recorded")) || (data62 === "issue.status.decision.applied")) || (data62 === "issue.status.decision.rejected")) || (data62 === "issue.status.decision.superseded")) || (data62 === "run.terminal"))){const err138 = {instancePath:instancePath+"/eventType",schemaPath:"#/properties/eventType/enum",keyword:"enum",params:{allowedValues: schema43.properties.eventType.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err138];}else {vErrors.push(err138);}errors++;}}if(data.schemaVersion !== undefined){if(1 !== data.schemaVersion){const err139 = {instancePath:instancePath+"/schemaVersion",schemaPath:"#/properties/schemaVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err139];}else {vErrors.push(err139);}errors++;}}if(data.priority !== undefined){let data64 = data.priority;if(!(((data64 === 0) || (data64 === 1)) || (data64 === 2))){const err140 = {instancePath:instancePath+"/priority",schemaPath:"#/properties/priority/enum",keyword:"enum",params:{allowedValues: schema43.properties.priority.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err140];}else {vErrors.push(err140);}errors++;}}if(data.emittedAt !== undefined){let data65 = data.emittedAt;if(typeof data65 === "string"){if(!(formats0.test(data65))){const err141 = {instancePath:instancePath+"/emittedAt",schemaPath:"#/properties/emittedAt/format",keyword:"format",params:{format: "date-time"},message:"must match format \""+"date-time"+"\""};if(vErrors === null){vErrors = [err141];}else {vErrors.push(err141);}errors++;}}else {const err142 = {instancePath:instancePath+"/emittedAt",schemaPath:"#/properties/emittedAt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err142];}else {vErrors.push(err142);}errors++;}}if(data.observedAt !== undefined){let data66 = data.observedAt;if(typeof data66 === "string"){if(!(formats0.test(data66))){const err143 = {instancePath:instancePath+"/observedAt",schemaPath:"#/properties/observedAt/format",keyword:"format",params:{format: "date-time"},message:"must match format \""+"date-time"+"\""};if(vErrors === null){vErrors = [err143];}else {vErrors.push(err143);}errors++;}}else {const err144 = {instancePath:instancePath+"/observedAt",schemaPath:"#/properties/observedAt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err144];}else {vErrors.push(err144);}errors++;}}if(data.payload !== undefined){let data67 = data.payload;if(data67 && typeof data67 == "object" && !Array.isArray(data67)){}else {const err145 = {instancePath:instancePath+"/payload",schemaPath:"#/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err145];}else {vErrors.push(err145);}errors++;}}if(data.debug !== undefined){let data68 = data.debug;if(data68 && typeof data68 == "object" && !Array.isArray(data68)){}else {const err146 = {instancePath:instancePath+"/debug",schemaPath:"#/properties/debug/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err146];}else {vErrors.push(err146);}errors++;}}}else {const err147 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err147];}else {vErrors.push(err147);}errors++;}validate23.errors = vErrors;return errors === 0;}validate23.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};function validate20(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://paperclip.dev/schemas/prp/v1/fixture.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate20.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.schema === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.fixtureVersion === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "fixtureVersion"},message:"must have required property '"+"fixtureVersion"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.protocolVersion === undefined){const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "protocolVersion"},message:"must have required property '"+"protocolVersion"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.name === undefined){const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(data.description === undefined){const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(data.identity === undefined){const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "identity"},message:"must have required property '"+"identity"+"'"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}if(data.capabilities === undefined){const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}if(data.commands === undefined){const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "commands"},message:"must have required property '"+"commands"+"'"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}if(data.events === undefined){const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "events"},message:"must have required property '"+"events"+"'"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}if(data.result === undefined){const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "result"},message:"must have required property '"+"result"+"'"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}if(data.schema !== undefined){if("paperclip.prp.fixture.v1" !== data.schema){const err10 = {instancePath:instancePath+"/schema",schemaPath:"#/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.fixture.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}}if(data.fixtureVersion !== undefined){if(1 !== data.fixtureVersion){const err11 = {instancePath:instancePath+"/fixtureVersion",schemaPath:"#/properties/fixtureVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}}if(data.protocolVersion !== undefined){if(1 !== data.protocolVersion){const err12 = {instancePath:instancePath+"/protocolVersion",schemaPath:"#/properties/protocolVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}}if(data.name !== undefined){let data3 = data.name;if(typeof data3 === "string"){if(func1(data3) > 120){const err13 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/maxLength",keyword:"maxLength",params:{limit: 120},message:"must NOT have more than 120 characters"};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}if(func1(data3) < 1){const err14 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}}else {const err15 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}}if(data.description !== undefined){let data4 = data.description;if(typeof data4 === "string"){if(func1(data4) > 1000){const err16 = {instancePath:instancePath+"/description",schemaPath:"#/properties/description/maxLength",keyword:"maxLength",params:{limit: 1000},message:"must NOT have more than 1000 characters"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}if(func1(data4) < 1){const err17 = {instancePath:instancePath+"/description",schemaPath:"#/properties/description/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}}else {const err18 = {instancePath:instancePath+"/description",schemaPath:"#/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}}if(data.identity !== undefined){if(!(validate21(data.identity, {instancePath:instancePath+"/identity",parentData:data,parentDataProperty:"identity",rootData,dynamicAnchors}))){vErrors = vErrors === null ? validate21.errors : vErrors.concat(validate21.errors);errors = vErrors.length;}}if(data.capabilities !== undefined){let data6 = data.capabilities;if(data6 && typeof data6 == "object" && !Array.isArray(data6)){if(data6.schema === undefined){const err19 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}if(data6.sessionReusePolicy === undefined){const err20 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "sessionReusePolicy"},message:"must have required property '"+"sessionReusePolicy"+"'"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}if(data6.driver === undefined){const err21 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "driver"},message:"must have required property '"+"driver"+"'"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(data6.steer === undefined){const err22 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "steer"},message:"must have required property '"+"steer"+"'"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(data6.interrupt === undefined){const err23 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "interrupt"},message:"must have required property '"+"interrupt"+"'"};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}if(data6.resume === undefined){const err24 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "resume"},message:"must have required property '"+"resume"+"'"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}if(data6.runtimeRequests === undefined){const err25 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "runtimeRequests"},message:"must have required property '"+"runtimeRequests"+"'"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}if(data6.structuredResult === undefined){const err26 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "structuredResult"},message:"must have required property '"+"structuredResult"+"'"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}if(data6.typedEvents === undefined){const err27 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "typedEvents"},message:"must have required property '"+"typedEvents"+"'"};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}if(data6.schema !== undefined){if("paperclip.prp.capabilities.v1" !== data6.schema){const err28 = {instancePath:instancePath+"/capabilities/schema",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.capabilities.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}}if(data6.sessionReusePolicy !== undefined){let data8 = data6.sessionReusePolicy;if(!(((data8 === "new_per_run") || (data8 === "reuse_per_issue")) || (data8 === "reuse_per_workspace"))){const err29 = {instancePath:instancePath+"/capabilities/sessionReusePolicy",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/sessionReusePolicy/enum",keyword:"enum",params:{allowedValues: schema41.properties.sessionReusePolicy.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}}if(data6.driver !== undefined){let data9 = data6.driver;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.kind === undefined){const err30 = {instancePath:instancePath+"/capabilities/driver",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}if(data9.version === undefined){const err31 = {instancePath:instancePath+"/capabilities/driver",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}if(data9.kind !== undefined){let data10 = data9.kind;if(typeof data10 === "string"){if(func1(data10) > 80){const err32 = {instancePath:instancePath+"/capabilities/driver/kind",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/kind/maxLength",keyword:"maxLength",params:{limit: 80},message:"must NOT have more than 80 characters"};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}if(func1(data10) < 1){const err33 = {instancePath:instancePath+"/capabilities/driver/kind",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/kind/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}}else {const err34 = {instancePath:instancePath+"/capabilities/driver/kind",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}}if(data9.version !== undefined){let data11 = data9.version;if(typeof data11 === "string"){if(func1(data11) > 80){const err35 = {instancePath:instancePath+"/capabilities/driver/version",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/version/maxLength",keyword:"maxLength",params:{limit: 80},message:"must NOT have more than 80 characters"};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}if(func1(data11) < 1){const err36 = {instancePath:instancePath+"/capabilities/driver/version",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/version/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}}else {const err37 = {instancePath:instancePath+"/capabilities/driver/version",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}}}else {const err38 = {instancePath:instancePath+"/capabilities/driver",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}}if(data6.steer !== undefined){if(typeof data6.steer !== "boolean"){const err39 = {instancePath:instancePath+"/capabilities/steer",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/steer/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err39];}else {vErrors.push(err39);}errors++;}}if(data6.interrupt !== undefined){if(typeof data6.interrupt !== "boolean"){const err40 = {instancePath:instancePath+"/capabilities/interrupt",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/interrupt/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err40];}else {vErrors.push(err40);}errors++;}}if(data6.resume !== undefined){if(typeof data6.resume !== "boolean"){const err41 = {instancePath:instancePath+"/capabilities/resume",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/resume/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err41];}else {vErrors.push(err41);}errors++;}}if(data6.runtimeRequests !== undefined){if(typeof data6.runtimeRequests !== "boolean"){const err42 = {instancePath:instancePath+"/capabilities/runtimeRequests",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/runtimeRequests/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err42];}else {vErrors.push(err42);}errors++;}}if(data6.structuredResult !== undefined){if(typeof data6.structuredResult !== "boolean"){const err43 = {instancePath:instancePath+"/capabilities/structuredResult",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/structuredResult/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err43];}else {vErrors.push(err43);}errors++;}}if(data6.typedEvents !== undefined){if(typeof data6.typedEvents !== "boolean"){const err44 = {instancePath:instancePath+"/capabilities/typedEvents",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/typedEvents/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err44];}else {vErrors.push(err44);}errors++;}}if(data6.unsupported !== undefined){let data18 = data6.unsupported;if(Array.isArray(data18)){const len0 = data18.length;for(let i0=0; i0 1){const indices0 = {};for(;i1--;){let item0 = data18[i1];if(typeof item0 !== "string"){continue;}if(typeof indices0[item0] == "number"){j0 = indices0[item0];const err47 = {instancePath:instancePath+"/capabilities/unsupported",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/unsupported/uniqueItems",keyword:"uniqueItems",params:{i: i1, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i1+" are identical)"};if(vErrors === null){vErrors = [err47];}else {vErrors.push(err47);}errors++;break;}indices0[item0] = i1;}}}else {const err48 = {instancePath:instancePath+"/capabilities/unsupported",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/unsupported/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err48];}else {vErrors.push(err48);}errors++;}}}else {const err49 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err49];}else {vErrors.push(err49);}errors++;}}if(data.commands !== undefined){let data20 = data.commands;if(Array.isArray(data20)){const len1 = data20.length;for(let i2=0; i2 160){const err57 = {instancePath:instancePath+"/commands/" + i2+"/commandId",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/commandId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err57];}else {vErrors.push(err57);}errors++;}if(func1(data23) < 1){const err58 = {instancePath:instancePath+"/commands/" + i2+"/commandId",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/commandId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err58];}else {vErrors.push(err58);}errors++;}}else {const err59 = {instancePath:instancePath+"/commands/" + i2+"/commandId",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/commandId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err59];}else {vErrors.push(err59);}errors++;}}if(data21.controllerSeq !== undefined){let data24 = data21.controllerSeq;if(!(((typeof data24 == "number") && (!(data24 % 1) && !isNaN(data24))) && (isFinite(data24)))){const err60 = {instancePath:instancePath+"/commands/" + i2+"/controllerSeq",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/controllerSeq/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err60];}else {vErrors.push(err60);}errors++;}if((typeof data24 == "number") && (isFinite(data24))){if(data24 < 1 || isNaN(data24)){const err61 = {instancePath:instancePath+"/commands/" + i2+"/controllerSeq",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/controllerSeq/minimum",keyword:"minimum",params:{comparison: ">=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err61];}else {vErrors.push(err61);}errors++;}}}if(data21.type !== undefined){let data25 = data21.type;if(!(((((((((((((data25 === "run.prepare") || (data25 === "session.open")) || (data25 === "turn.start")) || (data25 === "turn.steer")) || (data25 === "turn.interrupt")) || (data25 === "turn.stop")) || (data25 === "request.resolve")) || (data25 === "interaction.receipt")) || (data25 === "session.snapshot")) || (data25 === "session.close")) || (data25 === "run.cancel")) || (data25 === "runner.drain")) || (data25 === "runner.shutdown"))){const err62 = {instancePath:instancePath+"/commands/" + i2+"/type",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/type/enum",keyword:"enum",params:{allowedValues: schema42.properties.type.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err62];}else {vErrors.push(err62);}errors++;}}if(data21.issuedAt !== undefined){let data26 = data21.issuedAt;if(typeof data26 === "string"){if(!(formats0.test(data26))){const err63 = {instancePath:instancePath+"/commands/" + i2+"/issuedAt",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/issuedAt/format",keyword:"format",params:{format: "date-time"},message:"must match format \""+"date-time"+"\""};if(vErrors === null){vErrors = [err63];}else {vErrors.push(err63);}errors++;}}else {const err64 = {instancePath:instancePath+"/commands/" + i2+"/issuedAt",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/issuedAt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err64];}else {vErrors.push(err64);}errors++;}}if(data21.deadlineAt !== undefined){let data27 = data21.deadlineAt;if(typeof data27 === "string"){if(!(formats0.test(data27))){const err65 = {instancePath:instancePath+"/commands/" + i2+"/deadlineAt",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/deadlineAt/format",keyword:"format",params:{format: "date-time"},message:"must match format \""+"date-time"+"\""};if(vErrors === null){vErrors = [err65];}else {vErrors.push(err65);}errors++;}}else {const err66 = {instancePath:instancePath+"/commands/" + i2+"/deadlineAt",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/deadlineAt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err66];}else {vErrors.push(err66);}errors++;}}if(data21.precondition !== undefined){let data28 = data21.precondition;if(data28 && typeof data28 == "object" && !Array.isArray(data28)){if(data28.runnerState !== undefined){let data29 = data28.runnerState;if(Array.isArray(data29)){const len2 = data29.length;for(let i3=0; i3 160){const err88 = {instancePath:instancePath+"/requests/" + i7+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/requestId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err88];}else {vErrors.push(err88);}errors++;}if(func1(data43) < 1){const err89 = {instancePath:instancePath+"/requests/" + i7+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/requestId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err89];}else {vErrors.push(err89);}errors++;}}else {const err90 = {instancePath:instancePath+"/requests/" + i7+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/requestId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err90];}else {vErrors.push(err90);}errors++;}}if(data40.type !== undefined){let data44 = data40.type;if(!((data44 === "permission") || (data44 === "input"))){const err91 = {instancePath:instancePath+"/requests/" + i7+"/type",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/type/enum",keyword:"enum",params:{allowedValues: schema46.oneOf[0].properties.type.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err91];}else {vErrors.push(err91);}errors++;}}if(data40.status !== undefined){let data45 = data40.status;if(!((((data45 === "pending") || (data45 === "resolved")) || (data45 === "expired")) || (data45 === "cancelled"))){const err92 = {instancePath:instancePath+"/requests/" + i7+"/status",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/status/enum",keyword:"enum",params:{allowedValues: schema46.oneOf[0].properties.status.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err92];}else {vErrors.push(err92);}errors++;}}if(data40.prompt !== undefined){let data46 = data40.prompt;if(typeof data46 === "string"){if(func1(data46) > 4000){const err93 = {instancePath:instancePath+"/requests/" + i7+"/prompt",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/prompt/maxLength",keyword:"maxLength",params:{limit: 4000},message:"must NOT have more than 4000 characters"};if(vErrors === null){vErrors = [err93];}else {vErrors.push(err93);}errors++;}if(func1(data46) < 1){const err94 = {instancePath:instancePath+"/requests/" + i7+"/prompt",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/prompt/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err94];}else {vErrors.push(err94);}errors++;}}else {const err95 = {instancePath:instancePath+"/requests/" + i7+"/prompt",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err95];}else {vErrors.push(err95);}errors++;}}if(data40.choices !== undefined){let data47 = data40.choices;if(Array.isArray(data47)){const len7 = data47.length;for(let i8=0; i8 160){const err113 = {instancePath:instancePath+"/requests/" + i7+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/requestId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err113];}else {vErrors.push(err113);}errors++;}if(func1(data53) < 1){const err114 = {instancePath:instancePath+"/requests/" + i7+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/requestId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err114];}else {vErrors.push(err114);}errors++;}}else {const err115 = {instancePath:instancePath+"/requests/" + i7+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/requestId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err115];}else {vErrors.push(err115);}errors++;}}if(data40.kind !== undefined){let data54 = data40.kind;if(!(((((data54 === "request_confirmation") || (data54 === "request_checkbox_confirmation")) || (data54 === "request_item_verdicts")) || (data54 === "ask_user_questions")) || (data54 === "suggest_tasks"))){const err116 = {instancePath:instancePath+"/requests/" + i7+"/kind",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/kind/enum",keyword:"enum",params:{allowedValues: schema46.oneOf[1].properties.kind.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err116];}else {vErrors.push(err116);}errors++;}}if(data40.blocking !== undefined){if(typeof data40.blocking !== "boolean"){const err117 = {instancePath:instancePath+"/requests/" + i7+"/blocking",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/blocking/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err117];}else {vErrors.push(err117);}errors++;}}if(data40.payload !== undefined){let data56 = data40.payload;if(data56 && typeof data56 == "object" && !Array.isArray(data56)){}else {const err118 = {instancePath:instancePath+"/requests/" + i7+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err118];}else {vErrors.push(err118);}errors++;}}}else {const err119 = {instancePath:instancePath+"/requests/" + i7,schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err119];}else {vErrors.push(err119);}errors++;}var _valid0 = _errs103 === errors;if(_valid0 && valid23){valid23 = false;passing0 = [passing0, 1];}else {if(_valid0){valid23 = true;passing0 = 1;if(props0 !== true){props0 = true;}}}if(!valid23){const err120 = {instancePath:instancePath+"/requests/" + i7,schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf",keyword:"oneOf",params:{passingSchemas: passing0},message:"must match exactly one schema in oneOf"};if(vErrors === null){vErrors = [err120];}else {vErrors.push(err120);}errors++;}else {errors = _errs82;if(vErrors !== null){if(_errs82){vErrors.length = _errs82;}else {vErrors = null;}}}}}else {const err121 = {instancePath:instancePath+"/requests",schemaPath:"#/properties/requests/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err121];}else {vErrors.push(err121);}errors++;}}if(data.result !== undefined){let data57 = data.result;const _errs120 = errors;let valid31 = true;const _errs121 = errors;if(data57 && typeof data57 == "object" && !Array.isArray(data57)){if(data57.reportedWorkDisposition !== undefined){if("blocked" !== data57.reportedWorkDisposition){const err122 = {};if(vErrors === null){vErrors = [err122];}else {vErrors.push(err122);}errors++;}}}var _valid1 = _errs121 === errors;errors = _errs120;if(vErrors !== null){if(_errs120){vErrors.length = _errs120;}else {vErrors = null;}}if(_valid1){const _errs123 = errors;if(data57 && typeof data57 == "object" && !Array.isArray(data57)){if(data57.blocker === undefined){const err123 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/0/then/required",keyword:"required",params:{missingProperty: "blocker"},message:"must have required property '"+"blocker"+"'"};if(vErrors === null){vErrors = [err123];}else {vErrors.push(err123);}errors++;}}var _valid1 = _errs123 === errors;valid31 = _valid1;}if(!valid31){const err124 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err124];}else {vErrors.push(err124);}errors++;}const _errs125 = errors;let valid33 = true;const _errs126 = errors;if(data57 && typeof data57 == "object" && !Array.isArray(data57)){if(data57.reportedWorkDisposition !== undefined){if("yielded" !== data57.reportedWorkDisposition){const err125 = {};if(vErrors === null){vErrors = [err125];}else {vErrors.push(err125);}errors++;}}}var _valid2 = _errs126 === errors;errors = _errs125;if(vErrors !== null){if(_errs125){vErrors.length = _errs125;}else {vErrors = null;}}if(_valid2){const _errs128 = errors;if(data57 && typeof data57 == "object" && !Array.isArray(data57)){if(data57.continuation === undefined){const err126 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/1/then/required",keyword:"required",params:{missingProperty: "continuation"},message:"must have required property '"+"continuation"+"'"};if(vErrors === null){vErrors = [err126];}else {vErrors.push(err126);}errors++;}}var _valid2 = _errs128 === errors;valid33 = _valid2;}if(!valid33){const err127 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/1/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err127];}else {vErrors.push(err127);}errors++;}if(data57 && typeof data57 == "object" && !Array.isArray(data57)){if(data57.schema === undefined){const err128 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err128];}else {vErrors.push(err128);}errors++;}if(data57.reportedWorkDisposition === undefined){const err129 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "reportedWorkDisposition"},message:"must have required property '"+"reportedWorkDisposition"+"'"};if(vErrors === null){vErrors = [err129];}else {vErrors.push(err129);}errors++;}if(data57.summary === undefined){const err130 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "summary"},message:"must have required property '"+"summary"+"'"};if(vErrors === null){vErrors = [err130];}else {vErrors.push(err130);}errors++;}if(data57.completionClaim === undefined){const err131 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "completionClaim"},message:"must have required property '"+"completionClaim"+"'"};if(vErrors === null){vErrors = [err131];}else {vErrors.push(err131);}errors++;}if(data57.evidence === undefined){const err132 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "evidence"},message:"must have required property '"+"evidence"+"'"};if(vErrors === null){vErrors = [err132];}else {vErrors.push(err132);}errors++;}if(data57.verification === undefined){const err133 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "verification"},message:"must have required property '"+"verification"+"'"};if(vErrors === null){vErrors = [err133];}else {vErrors.push(err133);}errors++;}if(data57.attentionRequests === undefined){const err134 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "attentionRequests"},message:"must have required property '"+"attentionRequests"+"'"};if(vErrors === null){vErrors = [err134];}else {vErrors.push(err134);}errors++;}if(data57.artifacts === undefined){const err135 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "artifacts"},message:"must have required property '"+"artifacts"+"'"};if(vErrors === null){vErrors = [err135];}else {vErrors.push(err135);}errors++;}if(data57.schema !== undefined){if("paperclip.run_result.v1" !== data57.schema){const err136 = {instancePath:instancePath+"/result/schema",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.run_result.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err136];}else {vErrors.push(err136);}errors++;}}if(data57.reportedWorkDisposition !== undefined){let data61 = data57.reportedWorkDisposition;if(!((((data61 === "done") || (data61 === "blocked")) || (data61 === "needs_review")) || (data61 === "yielded"))){const err137 = {instancePath:instancePath+"/result/reportedWorkDisposition",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/reportedWorkDisposition/enum",keyword:"enum",params:{allowedValues: schema45.properties.reportedWorkDisposition.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err137];}else {vErrors.push(err137);}errors++;}}if(data57.summary !== undefined){let data62 = data57.summary;if(typeof data62 === "string"){if(func1(data62) > 12000){const err138 = {instancePath:instancePath+"/result/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/maxLength",keyword:"maxLength",params:{limit: 12000},message:"must NOT have more than 12000 characters"};if(vErrors === null){vErrors = [err138];}else {vErrors.push(err138);}errors++;}if(func1(data62) < 1){const err139 = {instancePath:instancePath+"/result/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err139];}else {vErrors.push(err139);}errors++;}}else {const err140 = {instancePath:instancePath+"/result/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err140];}else {vErrors.push(err140);}errors++;}}if(data57.completionClaim !== undefined){let data63 = data57.completionClaim;if(data63 && typeof data63 == "object" && !Array.isArray(data63)){if(data63.contractRevision === undefined){const err141 = {instancePath:instancePath+"/result/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "contractRevision"},message:"must have required property '"+"contractRevision"+"'"};if(vErrors === null){vErrors = [err141];}else {vErrors.push(err141);}errors++;}if(data63.objectiveSatisfied === undefined){const err142 = {instancePath:instancePath+"/result/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "objectiveSatisfied"},message:"must have required property '"+"objectiveSatisfied"+"'"};if(vErrors === null){vErrors = [err142];}else {vErrors.push(err142);}errors++;}if(data63.criteria === undefined){const err143 = {instancePath:instancePath+"/result/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "criteria"},message:"must have required property '"+"criteria"+"'"};if(vErrors === null){vErrors = [err143];}else {vErrors.push(err143);}errors++;}if(data63.remainingWork === undefined){const err144 = {instancePath:instancePath+"/result/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "remainingWork"},message:"must have required property '"+"remainingWork"+"'"};if(vErrors === null){vErrors = [err144];}else {vErrors.push(err144);}errors++;}if(data63.contractRevision !== undefined){let data64 = data63.contractRevision;if(typeof data64 === "string"){if(func1(data64) < 1){const err145 = {instancePath:instancePath+"/result/completionClaim/contractRevision",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/contractRevision/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err145];}else {vErrors.push(err145);}errors++;}}else {const err146 = {instancePath:instancePath+"/result/completionClaim/contractRevision",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/contractRevision/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err146];}else {vErrors.push(err146);}errors++;}}if(data63.objectiveSatisfied !== undefined){if(typeof data63.objectiveSatisfied !== "boolean"){const err147 = {instancePath:instancePath+"/result/completionClaim/objectiveSatisfied",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/objectiveSatisfied/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err147];}else {vErrors.push(err147);}errors++;}}if(data63.criteria !== undefined){let data66 = data63.criteria;if(Array.isArray(data66)){const len8 = data66.length;for(let i9=0; i9 12000){const err16 = {instancePath:instancePath+"/summary",schemaPath:"#/properties/summary/maxLength",keyword:"maxLength",params:{limit: 12000},message:"must NOT have more than 12000 characters"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}if(func1(data4) < 1){const err17 = {instancePath:instancePath+"/summary",schemaPath:"#/properties/summary/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}}else {const err18 = {instancePath:instancePath+"/summary",schemaPath:"#/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}}if(data.completionClaim !== undefined){let data5 = data.completionClaim;if(data5 && typeof data5 == "object" && !Array.isArray(data5)){if(data5.contractRevision === undefined){const err19 = {instancePath:instancePath+"/completionClaim",schemaPath:"#/properties/completionClaim/required",keyword:"required",params:{missingProperty: "contractRevision"},message:"must have required property '"+"contractRevision"+"'"};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}if(data5.objectiveSatisfied === undefined){const err20 = {instancePath:instancePath+"/completionClaim",schemaPath:"#/properties/completionClaim/required",keyword:"required",params:{missingProperty: "objectiveSatisfied"},message:"must have required property '"+"objectiveSatisfied"+"'"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}if(data5.criteria === undefined){const err21 = {instancePath:instancePath+"/completionClaim",schemaPath:"#/properties/completionClaim/required",keyword:"required",params:{missingProperty: "criteria"},message:"must have required property '"+"criteria"+"'"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(data5.remainingWork === undefined){const err22 = {instancePath:instancePath+"/completionClaim",schemaPath:"#/properties/completionClaim/required",keyword:"required",params:{missingProperty: "remainingWork"},message:"must have required property '"+"remainingWork"+"'"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(data5.contractRevision !== undefined){let data6 = data5.contractRevision;if(typeof data6 === "string"){if(func1(data6) < 1){const err23 = {instancePath:instancePath+"/completionClaim/contractRevision",schemaPath:"#/properties/completionClaim/properties/contractRevision/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}}else {const err24 = {instancePath:instancePath+"/completionClaim/contractRevision",schemaPath:"#/properties/completionClaim/properties/contractRevision/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}}if(data5.objectiveSatisfied !== undefined){if(typeof data5.objectiveSatisfied !== "boolean"){const err25 = {instancePath:instancePath+"/completionClaim/objectiveSatisfied",schemaPath:"#/properties/completionClaim/properties/objectiveSatisfied/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}}if(data5.criteria !== undefined){let data8 = data5.criteria;if(Array.isArray(data8)){const len0 = data8.length;for(let i0=0; i0 160){const err9 = {instancePath:instancePath+"/companyId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}if(func1(data1) < 1){const err10 = {instancePath:instancePath+"/companyId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}if(!pattern4.test(data1)){const err11 = {instancePath:instancePath+"/companyId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}}else {const err12 = {instancePath:instancePath+"/companyId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}}if(data.issueId !== undefined){let data2 = data.issueId;if(typeof data2 === "string"){if(func1(data2) > 160){const err13 = {instancePath:instancePath+"/issueId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}if(func1(data2) < 1){const err14 = {instancePath:instancePath+"/issueId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}if(!pattern4.test(data2)){const err15 = {instancePath:instancePath+"/issueId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}}else {const err16 = {instancePath:instancePath+"/issueId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}}if(data.runId !== undefined){let data3 = data.runId;if(typeof data3 === "string"){if(func1(data3) > 160){const err17 = {instancePath:instancePath+"/runId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}if(func1(data3) < 1){const err18 = {instancePath:instancePath+"/runId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}if(!pattern4.test(data3)){const err19 = {instancePath:instancePath+"/runId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}}else {const err20 = {instancePath:instancePath+"/runId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}}if(data.environmentLeaseId !== undefined){let data4 = data.environmentLeaseId;if(typeof data4 === "string"){if(func1(data4) > 160){const err21 = {instancePath:instancePath+"/environmentLeaseId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(func1(data4) < 1){const err22 = {instancePath:instancePath+"/environmentLeaseId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(!pattern4.test(data4)){const err23 = {instancePath:instancePath+"/environmentLeaseId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}}else {const err24 = {instancePath:instancePath+"/environmentLeaseId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}}if(data.runnerInstanceId !== undefined){let data5 = data.runnerInstanceId;if(typeof data5 === "string"){if(func1(data5) > 160){const err25 = {instancePath:instancePath+"/runnerInstanceId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}if(func1(data5) < 1){const err26 = {instancePath:instancePath+"/runnerInstanceId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}if(!pattern4.test(data5)){const err27 = {instancePath:instancePath+"/runnerInstanceId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}}else {const err28 = {instancePath:instancePath+"/runnerInstanceId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}}if(data.normalizedSessionId !== undefined){let data6 = data.normalizedSessionId;if(typeof data6 === "string"){if(func1(data6) > 160){const err29 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}if(func1(data6) < 1){const err30 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}if(!pattern4.test(data6)){const err31 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}}else {const err32 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}}if(data.driverSessionId !== undefined){let data7 = data.driverSessionId;if(typeof data7 === "string"){if(func1(data7) > 160){const err33 = {instancePath:instancePath+"/driverSessionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}if(func1(data7) < 1){const err34 = {instancePath:instancePath+"/driverSessionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}if(!pattern4.test(data7)){const err35 = {instancePath:instancePath+"/driverSessionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}}else {const err36 = {instancePath:instancePath+"/driverSessionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}}if(data.providerSessionId !== undefined){let data8 = data.providerSessionId;if(typeof data8 === "string"){if(func1(data8) > 160){const err37 = {instancePath:instancePath+"/providerSessionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}if(func1(data8) < 1){const err38 = {instancePath:instancePath+"/providerSessionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}if(!pattern4.test(data8)){const err39 = {instancePath:instancePath+"/providerSessionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err39];}else {vErrors.push(err39);}errors++;}}else {const err40 = {instancePath:instancePath+"/providerSessionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err40];}else {vErrors.push(err40);}errors++;}}}else {const err41 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err41];}else {vErrors.push(err41);}errors++;}validate21.errors = vErrors;return errors === 0;}validate21.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};const schema43 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/event.schema.json","title":"PRP native event","type":"object","required":["schema","sourceEventId","sourceSeq","sourceInstanceId","sourceKind","runId","eventType","schemaVersion","priority","emittedAt","payload"],"properties":{"schema":{"const":"paperclip.prp.event.v1"},"sourceEventId":{"type":"string","minLength":1,"maxLength":160},"sourceSeq":{"type":"integer","minimum":1},"sourceInstanceId":{"type":"string","minLength":1,"maxLength":160},"sourceKind":{"enum":["runner","control_plane"]},"runId":{"type":"string","minLength":1,"maxLength":160},"normalizedSessionId":{"type":"string","minLength":1,"maxLength":160},"turnId":{"type":"string","minLength":1,"maxLength":160},"itemId":{"type":"string","minLength":1,"maxLength":160},"eventType":{"enum":["runner.connected","runner.reconnected","runner.disconnected","runner.draining","runner.diagnostic","runtime.phase.changed","sandbox.metric","workspace.ready","harness.starting","harness.ready","harness.exited","harness.diagnostic","session.starting","session.started","session.resuming","session.resumed","session.reconciled","session.closed","session.failed","turn.submitted","turn.accepted","turn.started","turn.completed","turn.failed","turn.interrupted","turn.cancelled","item.started","item.delta","item.completed","item.failed","mcp_app.discovered","mcp_app.resource.resolved","mcp_app.initializing","mcp_app.ready","mcp_app.tool_input","mcp_app.tool_result","mcp_app.action.requested","mcp_app.action.resolved","mcp_app.host_context.changed","mcp_app.failed","mcp_app.teardown","runtime_request.created","runtime_request.resolved","runtime_request.expired","runtime_request.cancelled","interaction.request.proposed","interaction.request.materialized","interaction.request.rejected","interaction.response.progressed","interaction.response.resolved","interaction.response.delivered","run.result.proposed","run.result.accepted","run.result.rejected","attention.request.proposed","attention.request.routed","attention.request.resolved","attention.request.expired","attention.request.superseded","work.assessment.recorded","issue.status.decision.recorded","issue.status.decision.applied","issue.status.decision.rejected","issue.status.decision.superseded","run.terminal"]},"schemaVersion":{"const":1},"priority":{"enum":[0,1,2]},"emittedAt":{"type":"string","format":"date-time"},"observedAt":{"type":"string","format":"date-time"},"payload":{"type":"object","additionalProperties":true},"debug":{"type":"object","additionalProperties":true}},"allOf":[{"if":{"properties":{"eventType":{"const":"mcp_app.tool_input"}}},"then":{"properties":{"payload":{"type":"object","properties":{"semantic_tool":{"allOf":[{"$ref":"https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json"},{"type":"object","properties":{"phase":{"const":"input"}}}]}},"additionalProperties":true}}}},{"if":{"properties":{"eventType":{"const":"mcp_app.tool_result"}}},"then":{"properties":{"payload":{"type":"object","properties":{"semantic_tool":{"allOf":[{"$ref":"https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json"},{"type":"object","properties":{"phase":{"const":"result"}}}]}},"additionalProperties":true}}}},{"if":{"properties":{"eventType":{"const":"run.terminal"}}},"then":{"properties":{"payload":{"$ref":"https://paperclip.dev/schemas/prp/v1/terminal.schema.json"}}}},{"if":{"properties":{"eventType":{"const":"run.result.proposed"}}},"then":{"properties":{"payload":{"$ref":"https://paperclip.dev/schemas/prp/v1/result.schema.json"}}}}],"additionalProperties":true};const schema44 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json","title":"PRP provider-neutral semantic tool envelope","type":"object","required":["schema","schemaVersion","phase","operationId","callId","correlation","idempotencyKey","content"],"properties":{"schema":{"const":"paperclip.prp.semantic_tool.v1"},"schemaVersion":{"const":1},"phase":{"enum":["input","result"]},"operationId":{"$ref":"#/$defs/stableId"},"callId":{"$ref":"#/$defs/stableId"},"correlation":{"type":"object","required":["runId","normalizedSessionId","turnId","itemId"],"properties":{"runId":{"$ref":"#/$defs/stableId"},"normalizedSessionId":{"$ref":"#/$defs/stableId"},"turnId":{"$ref":"#/$defs/stableId"},"itemId":{"$ref":"#/$defs/stableId"},"requestId":{"$ref":"#/$defs/stableId"}},"additionalProperties":true},"idempotencyKey":{"type":["string","null"],"minLength":1,"maxLength":240},"content":{"$ref":"#/$defs/safeContent"},"outcome":{"enum":["succeeded","denied","conflict","duplicate","unavailable","failed"]},"code":{"$ref":"#/$defs/stableCode"},"retryable":{"type":"boolean"},"authorizationBoundary":{"enum":["company","actor","active_task","grant","governed_action","lock","revision"]},"operationReceiptId":{"$ref":"#/$defs/stableId"},"auditReceiptId":{"$ref":"#/$defs/stableId"},"currentRevision":{"oneOf":[{"type":"integer","minimum":0},{"$ref":"#/$defs/stableId"}]},"duplicateOfReceiptId":{"$ref":"#/$defs/stableId"},"artifactRefs":{"type":"array","items":{"allOf":[{"$ref":"#/$defs/safeReference"},{"type":"object","properties":{"kind":{"enum":["artifact","work_product"]}}}]},"uniqueItems":true},"targets":{"type":"array","items":{"$ref":"#/$defs/immutableTarget"},"uniqueItems":true},"causalRefs":{"type":"array","items":{"$ref":"#/$defs/safeReference"},"uniqueItems":true}},"allOf":[{"if":{"properties":{"phase":{"const":"result"}}},"then":{"required":["outcome","code","retryable","authorizationBoundary","operationReceiptId"]}}],"additionalProperties":true,"$defs":{"stableId":{"type":"string","minLength":1,"maxLength":240,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$"},"stableCode":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[a-z][a-z0-9_.:-]*$"},"safeContent":{"type":"object","required":["digest","redactionDisposition","references"],"properties":{"digest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"redactionDisposition":{"enum":["digest_only","allowlisted_references","redacted"]},"references":{"type":"array","items":{"$ref":"#/$defs/safeReference"},"uniqueItems":true}},"additionalProperties":true},"safeReference":{"type":"object","required":["kind","id"],"properties":{"kind":{"enum":["task","document_revision","interaction","approval","decision","artifact","work_product","wake","monitor","audit","operation"]},"id":{"$ref":"#/$defs/stableId"}},"additionalProperties":true},"immutableTarget":{"type":"object","required":["kind","id","immutable"],"properties":{"kind":{"enum":["document_revision","interaction","approval","decision"]},"id":{"$ref":"#/$defs/stableId"},"immutable":{"const":true},"revisionId":{"$ref":"#/$defs/stableId"},"decisionId":{"$ref":"#/$defs/stableId"}},"additionalProperties":true}}};const schema45 = {"type":"string","minLength":1,"maxLength":240,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$"};const schema55 = {"type":"string","minLength":1,"maxLength":160,"pattern":"^[a-z][a-z0-9_.:-]*$"};const func0 = typeof equalModule === "function" ? equalModule : equalModule.default;const pattern13 = new RegExp("^[a-z][a-z0-9_.:-]*$", "u");const schema52 = {"type":"object","required":["digest","redactionDisposition","references"],"properties":{"digest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"redactionDisposition":{"enum":["digest_only","allowlisted_references","redacted"]},"references":{"type":"array","items":{"$ref":"#/$defs/safeReference"},"uniqueItems":true}},"additionalProperties":true};const pattern21 = new RegExp("^sha256:[a-f0-9]{64}$", "u");const schema53 = {"type":"object","required":["kind","id"],"properties":{"kind":{"enum":["task","document_revision","interaction","approval","decision","artifact","work_product","wake","monitor","audit","operation"]},"id":{"$ref":"#/$defs/stableId"}},"additionalProperties":true};function validate26(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){let vErrors = null;let errors = 0;const evaluated0 = validate26.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.kind === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.id === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.kind !== undefined){let data0 = data.kind;if(!(((((((((((data0 === "task") || (data0 === "document_revision")) || (data0 === "interaction")) || (data0 === "approval")) || (data0 === "decision")) || (data0 === "artifact")) || (data0 === "work_product")) || (data0 === "wake")) || (data0 === "monitor")) || (data0 === "audit")) || (data0 === "operation"))){const err2 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/enum",keyword:"enum",params:{allowedValues: schema53.properties.kind.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}}if(data.id !== undefined){let data1 = data.id;if(typeof data1 === "string"){if(func1(data1) > 240){const err3 = {instancePath:instancePath+"/id",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(func1(data1) < 1){const err4 = {instancePath:instancePath+"/id",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(!pattern4.test(data1)){const err5 = {instancePath:instancePath+"/id",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}}else {const err6 = {instancePath:instancePath+"/id",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}}}else {const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}validate26.errors = vErrors;return errors === 0;}validate26.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};function validate25(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){let vErrors = null;let errors = 0;const evaluated0 = validate25.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.digest === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.redactionDisposition === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "redactionDisposition"},message:"must have required property '"+"redactionDisposition"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.references === undefined){const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "references"},message:"must have required property '"+"references"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.digest !== undefined){let data0 = data.digest;if(typeof data0 === "string"){if(!pattern21.test(data0)){const err3 = {instancePath:instancePath+"/digest",schemaPath:"#/properties/digest/pattern",keyword:"pattern",params:{pattern: "^sha256:[a-f0-9]{64}$"},message:"must match pattern \""+"^sha256:[a-f0-9]{64}$"+"\""};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}}else {const err4 = {instancePath:instancePath+"/digest",schemaPath:"#/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}}if(data.redactionDisposition !== undefined){let data1 = data.redactionDisposition;if(!(((data1 === "digest_only") || (data1 === "allowlisted_references")) || (data1 === "redacted"))){const err5 = {instancePath:instancePath+"/redactionDisposition",schemaPath:"#/properties/redactionDisposition/enum",keyword:"enum",params:{allowedValues: schema52.properties.redactionDisposition.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}}if(data.references !== undefined){let data2 = data.references;if(Array.isArray(data2)){const len0 = data2.length;for(let i0=0; i0 1){outer0:for(;i1--;){for(j0 = i1; j0--;){if(func0(data2[i1], data2[j0])){const err6 = {instancePath:instancePath+"/references",schemaPath:"#/properties/references/uniqueItems",keyword:"uniqueItems",params:{i: i1, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i1+" are identical)"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;break outer0;}}}}}else {const err7 = {instancePath:instancePath+"/references",schemaPath:"#/properties/references/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}}}else {const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}validate25.errors = vErrors;return errors === 0;}validate25.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};const schema60 = {"type":"object","required":["kind","id","immutable"],"properties":{"kind":{"enum":["document_revision","interaction","approval","decision"]},"id":{"$ref":"#/$defs/stableId"},"immutable":{"const":true},"revisionId":{"$ref":"#/$defs/stableId"},"decisionId":{"$ref":"#/$defs/stableId"}},"additionalProperties":true};function validate30(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){let vErrors = null;let errors = 0;const evaluated0 = validate30.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.kind === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.id === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.immutable === undefined){const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "immutable"},message:"must have required property '"+"immutable"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.kind !== undefined){let data0 = data.kind;if(!((((data0 === "document_revision") || (data0 === "interaction")) || (data0 === "approval")) || (data0 === "decision"))){const err3 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/enum",keyword:"enum",params:{allowedValues: schema60.properties.kind.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}}if(data.id !== undefined){let data1 = data.id;if(typeof data1 === "string"){if(func1(data1) > 240){const err4 = {instancePath:instancePath+"/id",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(func1(data1) < 1){const err5 = {instancePath:instancePath+"/id",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}if(!pattern4.test(data1)){const err6 = {instancePath:instancePath+"/id",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}}else {const err7 = {instancePath:instancePath+"/id",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}}if(data.immutable !== undefined){if(true !== data.immutable){const err8 = {instancePath:instancePath+"/immutable",schemaPath:"#/properties/immutable/const",keyword:"const",params:{allowedValue: true},message:"must be equal to constant"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}}if(data.revisionId !== undefined){let data3 = data.revisionId;if(typeof data3 === "string"){if(func1(data3) > 240){const err9 = {instancePath:instancePath+"/revisionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}if(func1(data3) < 1){const err10 = {instancePath:instancePath+"/revisionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}if(!pattern4.test(data3)){const err11 = {instancePath:instancePath+"/revisionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}}else {const err12 = {instancePath:instancePath+"/revisionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}}if(data.decisionId !== undefined){let data4 = data.decisionId;if(typeof data4 === "string"){if(func1(data4) > 240){const err13 = {instancePath:instancePath+"/decisionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}if(func1(data4) < 1){const err14 = {instancePath:instancePath+"/decisionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}if(!pattern4.test(data4)){const err15 = {instancePath:instancePath+"/decisionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}}else {const err16 = {instancePath:instancePath+"/decisionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}}}else {const err17 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}validate30.errors = vErrors;return errors === 0;}validate30.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};function validate24(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://paperclip.dev/schemas/prp/v1/semantic-tool.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate24.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}const _errs2 = errors;let valid1 = true;const _errs3 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.phase !== undefined){if("result" !== data.phase){const err0 = {};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}}}var _valid0 = _errs3 === errors;errors = _errs2;if(vErrors !== null){if(_errs2){vErrors.length = _errs2;}else {vErrors = null;}}if(_valid0){const _errs5 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.outcome === undefined){const err1 = {instancePath,schemaPath:"#/allOf/0/then/required",keyword:"required",params:{missingProperty: "outcome"},message:"must have required property '"+"outcome"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.code === undefined){const err2 = {instancePath,schemaPath:"#/allOf/0/then/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.retryable === undefined){const err3 = {instancePath,schemaPath:"#/allOf/0/then/required",keyword:"required",params:{missingProperty: "retryable"},message:"must have required property '"+"retryable"+"'"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(data.authorizationBoundary === undefined){const err4 = {instancePath,schemaPath:"#/allOf/0/then/required",keyword:"required",params:{missingProperty: "authorizationBoundary"},message:"must have required property '"+"authorizationBoundary"+"'"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(data.operationReceiptId === undefined){const err5 = {instancePath,schemaPath:"#/allOf/0/then/required",keyword:"required",params:{missingProperty: "operationReceiptId"},message:"must have required property '"+"operationReceiptId"+"'"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}}var _valid0 = _errs5 === errors;valid1 = _valid0;}if(!valid1){const err6 = {instancePath,schemaPath:"#/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.schema === undefined){const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}if(data.schemaVersion === undefined){const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schemaVersion"},message:"must have required property '"+"schemaVersion"+"'"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}if(data.phase === undefined){const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "phase"},message:"must have required property '"+"phase"+"'"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}if(data.operationId === undefined){const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operationId"},message:"must have required property '"+"operationId"+"'"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}if(data.callId === undefined){const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "callId"},message:"must have required property '"+"callId"+"'"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}if(data.correlation === undefined){const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "correlation"},message:"must have required property '"+"correlation"+"'"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}if(data.idempotencyKey === undefined){const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "idempotencyKey"},message:"must have required property '"+"idempotencyKey"+"'"};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}if(data.content === undefined){const err14 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}if(data.schema !== undefined){if("paperclip.prp.semantic_tool.v1" !== data.schema){const err15 = {instancePath:instancePath+"/schema",schemaPath:"#/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.semantic_tool.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}}if(data.schemaVersion !== undefined){if(1 !== data.schemaVersion){const err16 = {instancePath:instancePath+"/schemaVersion",schemaPath:"#/properties/schemaVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}}if(data.phase !== undefined){let data3 = data.phase;if(!((data3 === "input") || (data3 === "result"))){const err17 = {instancePath:instancePath+"/phase",schemaPath:"#/properties/phase/enum",keyword:"enum",params:{allowedValues: schema44.properties.phase.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}}if(data.operationId !== undefined){let data4 = data.operationId;if(typeof data4 === "string"){if(func1(data4) > 240){const err18 = {instancePath:instancePath+"/operationId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}if(func1(data4) < 1){const err19 = {instancePath:instancePath+"/operationId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}if(!pattern4.test(data4)){const err20 = {instancePath:instancePath+"/operationId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}}else {const err21 = {instancePath:instancePath+"/operationId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}}if(data.callId !== undefined){let data5 = data.callId;if(typeof data5 === "string"){if(func1(data5) > 240){const err22 = {instancePath:instancePath+"/callId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(func1(data5) < 1){const err23 = {instancePath:instancePath+"/callId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}if(!pattern4.test(data5)){const err24 = {instancePath:instancePath+"/callId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}}else {const err25 = {instancePath:instancePath+"/callId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}}if(data.correlation !== undefined){let data6 = data.correlation;if(data6 && typeof data6 == "object" && !Array.isArray(data6)){if(data6.runId === undefined){const err26 = {instancePath:instancePath+"/correlation",schemaPath:"#/properties/correlation/required",keyword:"required",params:{missingProperty: "runId"},message:"must have required property '"+"runId"+"'"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}if(data6.normalizedSessionId === undefined){const err27 = {instancePath:instancePath+"/correlation",schemaPath:"#/properties/correlation/required",keyword:"required",params:{missingProperty: "normalizedSessionId"},message:"must have required property '"+"normalizedSessionId"+"'"};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}if(data6.turnId === undefined){const err28 = {instancePath:instancePath+"/correlation",schemaPath:"#/properties/correlation/required",keyword:"required",params:{missingProperty: "turnId"},message:"must have required property '"+"turnId"+"'"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}if(data6.itemId === undefined){const err29 = {instancePath:instancePath+"/correlation",schemaPath:"#/properties/correlation/required",keyword:"required",params:{missingProperty: "itemId"},message:"must have required property '"+"itemId"+"'"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}if(data6.runId !== undefined){let data7 = data6.runId;if(typeof data7 === "string"){if(func1(data7) > 240){const err30 = {instancePath:instancePath+"/correlation/runId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}if(func1(data7) < 1){const err31 = {instancePath:instancePath+"/correlation/runId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}if(!pattern4.test(data7)){const err32 = {instancePath:instancePath+"/correlation/runId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}}else {const err33 = {instancePath:instancePath+"/correlation/runId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}}if(data6.normalizedSessionId !== undefined){let data8 = data6.normalizedSessionId;if(typeof data8 === "string"){if(func1(data8) > 240){const err34 = {instancePath:instancePath+"/correlation/normalizedSessionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}if(func1(data8) < 1){const err35 = {instancePath:instancePath+"/correlation/normalizedSessionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}if(!pattern4.test(data8)){const err36 = {instancePath:instancePath+"/correlation/normalizedSessionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}}else {const err37 = {instancePath:instancePath+"/correlation/normalizedSessionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}}if(data6.turnId !== undefined){let data9 = data6.turnId;if(typeof data9 === "string"){if(func1(data9) > 240){const err38 = {instancePath:instancePath+"/correlation/turnId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}if(func1(data9) < 1){const err39 = {instancePath:instancePath+"/correlation/turnId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err39];}else {vErrors.push(err39);}errors++;}if(!pattern4.test(data9)){const err40 = {instancePath:instancePath+"/correlation/turnId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err40];}else {vErrors.push(err40);}errors++;}}else {const err41 = {instancePath:instancePath+"/correlation/turnId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err41];}else {vErrors.push(err41);}errors++;}}if(data6.itemId !== undefined){let data10 = data6.itemId;if(typeof data10 === "string"){if(func1(data10) > 240){const err42 = {instancePath:instancePath+"/correlation/itemId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err42];}else {vErrors.push(err42);}errors++;}if(func1(data10) < 1){const err43 = {instancePath:instancePath+"/correlation/itemId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err43];}else {vErrors.push(err43);}errors++;}if(!pattern4.test(data10)){const err44 = {instancePath:instancePath+"/correlation/itemId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err44];}else {vErrors.push(err44);}errors++;}}else {const err45 = {instancePath:instancePath+"/correlation/itemId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err45];}else {vErrors.push(err45);}errors++;}}if(data6.requestId !== undefined){let data11 = data6.requestId;if(typeof data11 === "string"){if(func1(data11) > 240){const err46 = {instancePath:instancePath+"/correlation/requestId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err46];}else {vErrors.push(err46);}errors++;}if(func1(data11) < 1){const err47 = {instancePath:instancePath+"/correlation/requestId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err47];}else {vErrors.push(err47);}errors++;}if(!pattern4.test(data11)){const err48 = {instancePath:instancePath+"/correlation/requestId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err48];}else {vErrors.push(err48);}errors++;}}else {const err49 = {instancePath:instancePath+"/correlation/requestId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err49];}else {vErrors.push(err49);}errors++;}}}else {const err50 = {instancePath:instancePath+"/correlation",schemaPath:"#/properties/correlation/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err50];}else {vErrors.push(err50);}errors++;}}if(data.idempotencyKey !== undefined){let data12 = data.idempotencyKey;if((typeof data12 !== "string") && (data12 !== null)){const err51 = {instancePath:instancePath+"/idempotencyKey",schemaPath:"#/properties/idempotencyKey/type",keyword:"type",params:{type: schema44.properties.idempotencyKey.type},message:"must be string,null"};if(vErrors === null){vErrors = [err51];}else {vErrors.push(err51);}errors++;}if(typeof data12 === "string"){if(func1(data12) > 240){const err52 = {instancePath:instancePath+"/idempotencyKey",schemaPath:"#/properties/idempotencyKey/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err52];}else {vErrors.push(err52);}errors++;}if(func1(data12) < 1){const err53 = {instancePath:instancePath+"/idempotencyKey",schemaPath:"#/properties/idempotencyKey/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err53];}else {vErrors.push(err53);}errors++;}}}if(data.content !== undefined){if(!(validate25(data.content, {instancePath:instancePath+"/content",parentData:data,parentDataProperty:"content",rootData,dynamicAnchors}))){vErrors = vErrors === null ? validate25.errors : vErrors.concat(validate25.errors);errors = vErrors.length;}}if(data.outcome !== undefined){let data14 = data.outcome;if(!((((((data14 === "succeeded") || (data14 === "denied")) || (data14 === "conflict")) || (data14 === "duplicate")) || (data14 === "unavailable")) || (data14 === "failed"))){const err54 = {instancePath:instancePath+"/outcome",schemaPath:"#/properties/outcome/enum",keyword:"enum",params:{allowedValues: schema44.properties.outcome.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err54];}else {vErrors.push(err54);}errors++;}}if(data.code !== undefined){let data15 = data.code;if(typeof data15 === "string"){if(func1(data15) > 160){const err55 = {instancePath:instancePath+"/code",schemaPath:"#/$defs/stableCode/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err55];}else {vErrors.push(err55);}errors++;}if(func1(data15) < 1){const err56 = {instancePath:instancePath+"/code",schemaPath:"#/$defs/stableCode/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err56];}else {vErrors.push(err56);}errors++;}if(!pattern13.test(data15)){const err57 = {instancePath:instancePath+"/code",schemaPath:"#/$defs/stableCode/pattern",keyword:"pattern",params:{pattern: "^[a-z][a-z0-9_.:-]*$"},message:"must match pattern \""+"^[a-z][a-z0-9_.:-]*$"+"\""};if(vErrors === null){vErrors = [err57];}else {vErrors.push(err57);}errors++;}}else {const err58 = {instancePath:instancePath+"/code",schemaPath:"#/$defs/stableCode/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err58];}else {vErrors.push(err58);}errors++;}}if(data.retryable !== undefined){if(typeof data.retryable !== "boolean"){const err59 = {instancePath:instancePath+"/retryable",schemaPath:"#/properties/retryable/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err59];}else {vErrors.push(err59);}errors++;}}if(data.authorizationBoundary !== undefined){let data17 = data.authorizationBoundary;if(!(((((((data17 === "company") || (data17 === "actor")) || (data17 === "active_task")) || (data17 === "grant")) || (data17 === "governed_action")) || (data17 === "lock")) || (data17 === "revision"))){const err60 = {instancePath:instancePath+"/authorizationBoundary",schemaPath:"#/properties/authorizationBoundary/enum",keyword:"enum",params:{allowedValues: schema44.properties.authorizationBoundary.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err60];}else {vErrors.push(err60);}errors++;}}if(data.operationReceiptId !== undefined){let data18 = data.operationReceiptId;if(typeof data18 === "string"){if(func1(data18) > 240){const err61 = {instancePath:instancePath+"/operationReceiptId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err61];}else {vErrors.push(err61);}errors++;}if(func1(data18) < 1){const err62 = {instancePath:instancePath+"/operationReceiptId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err62];}else {vErrors.push(err62);}errors++;}if(!pattern4.test(data18)){const err63 = {instancePath:instancePath+"/operationReceiptId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err63];}else {vErrors.push(err63);}errors++;}}else {const err64 = {instancePath:instancePath+"/operationReceiptId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err64];}else {vErrors.push(err64);}errors++;}}if(data.auditReceiptId !== undefined){let data19 = data.auditReceiptId;if(typeof data19 === "string"){if(func1(data19) > 240){const err65 = {instancePath:instancePath+"/auditReceiptId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err65];}else {vErrors.push(err65);}errors++;}if(func1(data19) < 1){const err66 = {instancePath:instancePath+"/auditReceiptId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err66];}else {vErrors.push(err66);}errors++;}if(!pattern4.test(data19)){const err67 = {instancePath:instancePath+"/auditReceiptId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err67];}else {vErrors.push(err67);}errors++;}}else {const err68 = {instancePath:instancePath+"/auditReceiptId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err68];}else {vErrors.push(err68);}errors++;}}if(data.currentRevision !== undefined){let data20 = data.currentRevision;const _errs51 = errors;let valid15 = false;let passing0 = null;const _errs52 = errors;if(!(((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20))) && (isFinite(data20)))){const err69 = {instancePath:instancePath+"/currentRevision",schemaPath:"#/properties/currentRevision/oneOf/0/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err69];}else {vErrors.push(err69);}errors++;}if((typeof data20 == "number") && (isFinite(data20))){if(data20 < 0 || isNaN(data20)){const err70 = {instancePath:instancePath+"/currentRevision",schemaPath:"#/properties/currentRevision/oneOf/0/minimum",keyword:"minimum",params:{comparison: ">=", limit: 0},message:"must be >= 0"};if(vErrors === null){vErrors = [err70];}else {vErrors.push(err70);}errors++;}}var _valid1 = _errs52 === errors;if(_valid1){valid15 = true;passing0 = 0;}const _errs54 = errors;if(typeof data20 === "string"){if(func1(data20) > 240){const err71 = {instancePath:instancePath+"/currentRevision",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err71];}else {vErrors.push(err71);}errors++;}if(func1(data20) < 1){const err72 = {instancePath:instancePath+"/currentRevision",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err72];}else {vErrors.push(err72);}errors++;}if(!pattern4.test(data20)){const err73 = {instancePath:instancePath+"/currentRevision",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err73];}else {vErrors.push(err73);}errors++;}}else {const err74 = {instancePath:instancePath+"/currentRevision",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err74];}else {vErrors.push(err74);}errors++;}var _valid1 = _errs54 === errors;if(_valid1 && valid15){valid15 = false;passing0 = [passing0, 1];}else {if(_valid1){valid15 = true;passing0 = 1;}}if(!valid15){const err75 = {instancePath:instancePath+"/currentRevision",schemaPath:"#/properties/currentRevision/oneOf",keyword:"oneOf",params:{passingSchemas: passing0},message:"must match exactly one schema in oneOf"};if(vErrors === null){vErrors = [err75];}else {vErrors.push(err75);}errors++;}else {errors = _errs51;if(vErrors !== null){if(_errs51){vErrors.length = _errs51;}else {vErrors = null;}}}}if(data.duplicateOfReceiptId !== undefined){let data21 = data.duplicateOfReceiptId;if(typeof data21 === "string"){if(func1(data21) > 240){const err76 = {instancePath:instancePath+"/duplicateOfReceiptId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err76];}else {vErrors.push(err76);}errors++;}if(func1(data21) < 1){const err77 = {instancePath:instancePath+"/duplicateOfReceiptId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err77];}else {vErrors.push(err77);}errors++;}if(!pattern4.test(data21)){const err78 = {instancePath:instancePath+"/duplicateOfReceiptId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err78];}else {vErrors.push(err78);}errors++;}}else {const err79 = {instancePath:instancePath+"/duplicateOfReceiptId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err79];}else {vErrors.push(err79);}errors++;}}if(data.artifactRefs !== undefined){let data22 = data.artifactRefs;if(Array.isArray(data22)){const len0 = data22.length;for(let i0=0; i0 1){outer0:for(;i1--;){for(j0 = i1; j0--;){if(func0(data22[i1], data22[j0])){const err82 = {instancePath:instancePath+"/artifactRefs",schemaPath:"#/properties/artifactRefs/uniqueItems",keyword:"uniqueItems",params:{i: i1, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i1+" are identical)"};if(vErrors === null){vErrors = [err82];}else {vErrors.push(err82);}errors++;break outer0;}}}}}else {const err83 = {instancePath:instancePath+"/artifactRefs",schemaPath:"#/properties/artifactRefs/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err83];}else {vErrors.push(err83);}errors++;}}if(data.targets !== undefined){let data25 = data.targets;if(Array.isArray(data25)){const len1 = data25.length;for(let i2=0; i2 1){outer1:for(;i3--;){for(j1 = i3; j1--;){if(func0(data25[i3], data25[j1])){const err84 = {instancePath:instancePath+"/targets",schemaPath:"#/properties/targets/uniqueItems",keyword:"uniqueItems",params:{i: i3, j: j1},message:"must NOT have duplicate items (items ## "+j1+" and "+i3+" are identical)"};if(vErrors === null){vErrors = [err84];}else {vErrors.push(err84);}errors++;break outer1;}}}}}else {const err85 = {instancePath:instancePath+"/targets",schemaPath:"#/properties/targets/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err85];}else {vErrors.push(err85);}errors++;}}if(data.causalRefs !== undefined){let data27 = data.causalRefs;if(Array.isArray(data27)){const len2 = data27.length;for(let i4=0; i4 1){outer2:for(;i5--;){for(j2 = i5; j2--;){if(func0(data27[i5], data27[j2])){const err86 = {instancePath:instancePath+"/causalRefs",schemaPath:"#/properties/causalRefs/uniqueItems",keyword:"uniqueItems",params:{i: i5, j: j2},message:"must NOT have duplicate items (items ## "+j2+" and "+i5+" are identical)"};if(vErrors === null){vErrors = [err86];}else {vErrors.push(err86);}errors++;break outer2;}}}}}else {const err87 = {instancePath:instancePath+"/causalRefs",schemaPath:"#/properties/causalRefs/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err87];}else {vErrors.push(err87);}errors++;}}}else {const err88 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err88];}else {vErrors.push(err88);}errors++;}validate24.errors = vErrors;return errors === 0;}validate24.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};const schema64 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/terminal.schema.json","title":"PRP run terminal state","type":"object","required":["schema","turnTerminalState","runTerminalState","reportedWorkDisposition"],"properties":{"schema":{"const":"paperclip.prp.terminal.v1"},"turnTerminalState":{"enum":["completed","failed","interrupted","cancelled"]},"runTerminalState":{"enum":["succeeded","failed","cancelled"]},"reportedWorkDisposition":{"enum":["done","blocked","needs_review","yielded"]},"workAssessmentId":{"type":"string","minLength":1},"statusDecisionId":{"type":"string","minLength":1},"stopReason":{"$ref":"https://paperclip.dev/schemas/prp/v1/stop-reason.schema.json"}},"additionalProperties":true};const schema65 = {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://paperclip.dev/schemas/prp/v1/stop-reason.schema.json","title":"PRP terminal stop reason receipt","type":"object","required":["schema","schemaVersion","receiptId","kind","code","retryable","decisionId","limitClass","aggregate"],"properties":{"schema":{"const":"paperclip.prp.stop_reason.v1"},"schemaVersion":{"const":1},"receiptId":{"$ref":"#/$defs/stableId"},"kind":{"enum":["budget","cost"]},"code":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[a-z][a-z0-9_.:-]*$"},"retryable":{"type":"boolean"},"decisionId":{"$ref":"#/$defs/stableId"},"limitClass":{"enum":["company_monthly","actor_monthly","project_monthly","run_cost","provider_quota"]},"aggregate":{"type":"object","required":["unit","observed","limit","window"],"properties":{"unit":{"enum":["cents","usd_micros","tokens"]},"observed":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":0},"window":{"enum":["run","monthly_utc","provider_window"]}},"additionalProperties":true},"relatedReceiptIds":{"type":"array","items":{"$ref":"#/$defs/stableId"},"uniqueItems":true}},"additionalProperties":true,"$defs":{"stableId":{"type":"string","minLength":1,"maxLength":240,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$"}}};const schema66 = {"type":"string","minLength":1,"maxLength":240,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$"};function validate36(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://paperclip.dev/schemas/prp/v1/stop-reason.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate36.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.schema === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.schemaVersion === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schemaVersion"},message:"must have required property '"+"schemaVersion"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.receiptId === undefined){const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "receiptId"},message:"must have required property '"+"receiptId"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.kind === undefined){const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(data.code === undefined){const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(data.retryable === undefined){const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "retryable"},message:"must have required property '"+"retryable"+"'"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}if(data.decisionId === undefined){const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "decisionId"},message:"must have required property '"+"decisionId"+"'"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}if(data.limitClass === undefined){const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limitClass"},message:"must have required property '"+"limitClass"+"'"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}if(data.aggregate === undefined){const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "aggregate"},message:"must have required property '"+"aggregate"+"'"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}if(data.schema !== undefined){if("paperclip.prp.stop_reason.v1" !== data.schema){const err9 = {instancePath:instancePath+"/schema",schemaPath:"#/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.stop_reason.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}}if(data.schemaVersion !== undefined){if(1 !== data.schemaVersion){const err10 = {instancePath:instancePath+"/schemaVersion",schemaPath:"#/properties/schemaVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}}if(data.receiptId !== undefined){let data2 = data.receiptId;if(typeof data2 === "string"){if(func1(data2) > 240){const err11 = {instancePath:instancePath+"/receiptId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}if(func1(data2) < 1){const err12 = {instancePath:instancePath+"/receiptId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}if(!pattern4.test(data2)){const err13 = {instancePath:instancePath+"/receiptId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}}else {const err14 = {instancePath:instancePath+"/receiptId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}}if(data.kind !== undefined){let data3 = data.kind;if(!((data3 === "budget") || (data3 === "cost"))){const err15 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/enum",keyword:"enum",params:{allowedValues: schema65.properties.kind.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}}if(data.code !== undefined){let data4 = data.code;if(typeof data4 === "string"){if(func1(data4) > 160){const err16 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}if(func1(data4) < 1){const err17 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}if(!pattern13.test(data4)){const err18 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/pattern",keyword:"pattern",params:{pattern: "^[a-z][a-z0-9_.:-]*$"},message:"must match pattern \""+"^[a-z][a-z0-9_.:-]*$"+"\""};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}}else {const err19 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}}if(data.retryable !== undefined){if(typeof data.retryable !== "boolean"){const err20 = {instancePath:instancePath+"/retryable",schemaPath:"#/properties/retryable/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}}if(data.decisionId !== undefined){let data6 = data.decisionId;if(typeof data6 === "string"){if(func1(data6) > 240){const err21 = {instancePath:instancePath+"/decisionId",schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(func1(data6) < 1){const err22 = {instancePath:instancePath+"/decisionId",schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(!pattern4.test(data6)){const err23 = {instancePath:instancePath+"/decisionId",schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}}else {const err24 = {instancePath:instancePath+"/decisionId",schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}}if(data.limitClass !== undefined){let data7 = data.limitClass;if(!(((((data7 === "company_monthly") || (data7 === "actor_monthly")) || (data7 === "project_monthly")) || (data7 === "run_cost")) || (data7 === "provider_quota"))){const err25 = {instancePath:instancePath+"/limitClass",schemaPath:"#/properties/limitClass/enum",keyword:"enum",params:{allowedValues: schema65.properties.limitClass.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}}if(data.aggregate !== undefined){let data8 = data.aggregate;if(data8 && typeof data8 == "object" && !Array.isArray(data8)){if(data8.unit === undefined){const err26 = {instancePath:instancePath+"/aggregate",schemaPath:"#/properties/aggregate/required",keyword:"required",params:{missingProperty: "unit"},message:"must have required property '"+"unit"+"'"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}if(data8.observed === undefined){const err27 = {instancePath:instancePath+"/aggregate",schemaPath:"#/properties/aggregate/required",keyword:"required",params:{missingProperty: "observed"},message:"must have required property '"+"observed"+"'"};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}if(data8.limit === undefined){const err28 = {instancePath:instancePath+"/aggregate",schemaPath:"#/properties/aggregate/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}if(data8.window === undefined){const err29 = {instancePath:instancePath+"/aggregate",schemaPath:"#/properties/aggregate/required",keyword:"required",params:{missingProperty: "window"},message:"must have required property '"+"window"+"'"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}if(data8.unit !== undefined){let data9 = data8.unit;if(!(((data9 === "cents") || (data9 === "usd_micros")) || (data9 === "tokens"))){const err30 = {instancePath:instancePath+"/aggregate/unit",schemaPath:"#/properties/aggregate/properties/unit/enum",keyword:"enum",params:{allowedValues: schema65.properties.aggregate.properties.unit.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}}if(data8.observed !== undefined){let data10 = data8.observed;if(!(((typeof data10 == "number") && (!(data10 % 1) && !isNaN(data10))) && (isFinite(data10)))){const err31 = {instancePath:instancePath+"/aggregate/observed",schemaPath:"#/properties/aggregate/properties/observed/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}if((typeof data10 == "number") && (isFinite(data10))){if(data10 < 0 || isNaN(data10)){const err32 = {instancePath:instancePath+"/aggregate/observed",schemaPath:"#/properties/aggregate/properties/observed/minimum",keyword:"minimum",params:{comparison: ">=", limit: 0},message:"must be >= 0"};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}}}if(data8.limit !== undefined){let data11 = data8.limit;if(!(((typeof data11 == "number") && (!(data11 % 1) && !isNaN(data11))) && (isFinite(data11)))){const err33 = {instancePath:instancePath+"/aggregate/limit",schemaPath:"#/properties/aggregate/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}if((typeof data11 == "number") && (isFinite(data11))){if(data11 < 0 || isNaN(data11)){const err34 = {instancePath:instancePath+"/aggregate/limit",schemaPath:"#/properties/aggregate/properties/limit/minimum",keyword:"minimum",params:{comparison: ">=", limit: 0},message:"must be >= 0"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}}}if(data8.window !== undefined){let data12 = data8.window;if(!(((data12 === "run") || (data12 === "monthly_utc")) || (data12 === "provider_window"))){const err35 = {instancePath:instancePath+"/aggregate/window",schemaPath:"#/properties/aggregate/properties/window/enum",keyword:"enum",params:{allowedValues: schema65.properties.aggregate.properties.window.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}}}else {const err36 = {instancePath:instancePath+"/aggregate",schemaPath:"#/properties/aggregate/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}}if(data.relatedReceiptIds !== undefined){let data13 = data.relatedReceiptIds;if(Array.isArray(data13)){const len0 = data13.length;for(let i0=0; i0 240){const err37 = {instancePath:instancePath+"/relatedReceiptIds/" + i0,schemaPath:"#/$defs/stableId/maxLength",keyword:"maxLength",params:{limit: 240},message:"must NOT have more than 240 characters"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}if(func1(data14) < 1){const err38 = {instancePath:instancePath+"/relatedReceiptIds/" + i0,schemaPath:"#/$defs/stableId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}if(!pattern4.test(data14)){const err39 = {instancePath:instancePath+"/relatedReceiptIds/" + i0,schemaPath:"#/$defs/stableId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err39];}else {vErrors.push(err39);}errors++;}}else {const err40 = {instancePath:instancePath+"/relatedReceiptIds/" + i0,schemaPath:"#/$defs/stableId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err40];}else {vErrors.push(err40);}errors++;}}let i1 = data13.length;let j0;if(i1 > 1){outer0:for(;i1--;){for(j0 = i1; j0--;){if(func0(data13[i1], data13[j0])){const err41 = {instancePath:instancePath+"/relatedReceiptIds",schemaPath:"#/properties/relatedReceiptIds/uniqueItems",keyword:"uniqueItems",params:{i: i1, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i1+" are identical)"};if(vErrors === null){vErrors = [err41];}else {vErrors.push(err41);}errors++;break outer0;}}}}}else {const err42 = {instancePath:instancePath+"/relatedReceiptIds",schemaPath:"#/properties/relatedReceiptIds/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err42];}else {vErrors.push(err42);}errors++;}}}else {const err43 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err43];}else {vErrors.push(err43);}errors++;}validate36.errors = vErrors;return errors === 0;}validate36.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};function validate35(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://paperclip.dev/schemas/prp/v1/terminal.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate35.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.schema === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.turnTerminalState === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turnTerminalState"},message:"must have required property '"+"turnTerminalState"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.runTerminalState === undefined){const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "runTerminalState"},message:"must have required property '"+"runTerminalState"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.reportedWorkDisposition === undefined){const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reportedWorkDisposition"},message:"must have required property '"+"reportedWorkDisposition"+"'"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(data.schema !== undefined){if("paperclip.prp.terminal.v1" !== data.schema){const err4 = {instancePath:instancePath+"/schema",schemaPath:"#/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.terminal.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}}if(data.turnTerminalState !== undefined){let data1 = data.turnTerminalState;if(!((((data1 === "completed") || (data1 === "failed")) || (data1 === "interrupted")) || (data1 === "cancelled"))){const err5 = {instancePath:instancePath+"/turnTerminalState",schemaPath:"#/properties/turnTerminalState/enum",keyword:"enum",params:{allowedValues: schema64.properties.turnTerminalState.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}}if(data.runTerminalState !== undefined){let data2 = data.runTerminalState;if(!(((data2 === "succeeded") || (data2 === "failed")) || (data2 === "cancelled"))){const err6 = {instancePath:instancePath+"/runTerminalState",schemaPath:"#/properties/runTerminalState/enum",keyword:"enum",params:{allowedValues: schema64.properties.runTerminalState.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}}if(data.reportedWorkDisposition !== undefined){let data3 = data.reportedWorkDisposition;if(!((((data3 === "done") || (data3 === "blocked")) || (data3 === "needs_review")) || (data3 === "yielded"))){const err7 = {instancePath:instancePath+"/reportedWorkDisposition",schemaPath:"#/properties/reportedWorkDisposition/enum",keyword:"enum",params:{allowedValues: schema64.properties.reportedWorkDisposition.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}}if(data.workAssessmentId !== undefined){let data4 = data.workAssessmentId;if(typeof data4 === "string"){if(func1(data4) < 1){const err8 = {instancePath:instancePath+"/workAssessmentId",schemaPath:"#/properties/workAssessmentId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}}else {const err9 = {instancePath:instancePath+"/workAssessmentId",schemaPath:"#/properties/workAssessmentId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}}if(data.statusDecisionId !== undefined){let data5 = data.statusDecisionId;if(typeof data5 === "string"){if(func1(data5) < 1){const err10 = {instancePath:instancePath+"/statusDecisionId",schemaPath:"#/properties/statusDecisionId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}}else {const err11 = {instancePath:instancePath+"/statusDecisionId",schemaPath:"#/properties/statusDecisionId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}}if(data.stopReason !== undefined){if(!(validate36(data.stopReason, {instancePath:instancePath+"/stopReason",parentData:data,parentDataProperty:"stopReason",rootData,dynamicAnchors}))){vErrors = vErrors === null ? validate36.errors : vErrors.concat(validate36.errors);errors = vErrors.length;}}}else {const err12 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}validate35.errors = vErrors;return errors === 0;}validate35.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};const formats0 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;function validate23(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://paperclip.dev/schemas/prp/v1/event.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate23.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}const _errs2 = errors;let valid1 = true;const _errs3 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.eventType !== undefined){if("mcp_app.tool_input" !== data.eventType){const err0 = {};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}}}var _valid0 = _errs3 === errors;errors = _errs2;if(vErrors !== null){if(_errs2){vErrors.length = _errs2;}else {vErrors = null;}}if(_valid0){const _errs5 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.payload !== undefined){let data1 = data.payload;if(data1 && typeof data1 == "object" && !Array.isArray(data1)){if(data1.semantic_tool !== undefined){let data2 = data1.semantic_tool;if(!(validate24(data2, {instancePath:instancePath+"/payload/semantic_tool",parentData:data1,parentDataProperty:"semantic_tool",rootData,dynamicAnchors}))){vErrors = vErrors === null ? validate24.errors : vErrors.concat(validate24.errors);errors = vErrors.length;}if(data2 && typeof data2 == "object" && !Array.isArray(data2)){if(data2.phase !== undefined){if("input" !== data2.phase){const err1 = {instancePath:instancePath+"/payload/semantic_tool/phase",schemaPath:"#/allOf/0/then/properties/payload/properties/semantic_tool/allOf/1/properties/phase/const",keyword:"const",params:{allowedValue: "input"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}}}else {const err2 = {instancePath:instancePath+"/payload/semantic_tool",schemaPath:"#/allOf/0/then/properties/payload/properties/semantic_tool/allOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}}}else {const err3 = {instancePath:instancePath+"/payload",schemaPath:"#/allOf/0/then/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}}}var _valid0 = _errs5 === errors;valid1 = _valid0;if(valid1){var props0 = {};props0.payload = true;props0.eventType = true;}}if(!valid1){const err4 = {instancePath,schemaPath:"#/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}const _errs15 = errors;let valid7 = true;const _errs16 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.eventType !== undefined){if("mcp_app.tool_result" !== data.eventType){const err5 = {};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}}}var _valid1 = _errs16 === errors;errors = _errs15;if(vErrors !== null){if(_errs15){vErrors.length = _errs15;}else {vErrors = null;}}if(_valid1){const _errs18 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.payload !== undefined){let data5 = data.payload;if(data5 && typeof data5 == "object" && !Array.isArray(data5)){if(data5.semantic_tool !== undefined){let data6 = data5.semantic_tool;if(!(validate24(data6, {instancePath:instancePath+"/payload/semantic_tool",parentData:data5,parentDataProperty:"semantic_tool",rootData,dynamicAnchors}))){vErrors = vErrors === null ? validate24.errors : vErrors.concat(validate24.errors);errors = vErrors.length;}if(data6 && typeof data6 == "object" && !Array.isArray(data6)){if(data6.phase !== undefined){if("result" !== data6.phase){const err6 = {instancePath:instancePath+"/payload/semantic_tool/phase",schemaPath:"#/allOf/1/then/properties/payload/properties/semantic_tool/allOf/1/properties/phase/const",keyword:"const",params:{allowedValue: "result"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}}}else {const err7 = {instancePath:instancePath+"/payload/semantic_tool",schemaPath:"#/allOf/1/then/properties/payload/properties/semantic_tool/allOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}}}else {const err8 = {instancePath:instancePath+"/payload",schemaPath:"#/allOf/1/then/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}}}var _valid1 = _errs18 === errors;valid7 = _valid1;if(valid7){var props1 = {};props1.payload = true;props1.eventType = true;}}if(!valid7){const err9 = {instancePath,schemaPath:"#/allOf/1/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}if(props0 !== true && props1 !== undefined){if(props1 === true){props0 = true;}else {props0 = props0 || {};Object.assign(props0, props1);}}const _errs28 = errors;let valid13 = true;const _errs29 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.eventType !== undefined){if("run.terminal" !== data.eventType){const err10 = {};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}}}var _valid2 = _errs29 === errors;errors = _errs28;if(vErrors !== null){if(_errs28){vErrors.length = _errs28;}else {vErrors = null;}}if(_valid2){const _errs31 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.payload !== undefined){if(!(validate35(data.payload, {instancePath:instancePath+"/payload",parentData:data,parentDataProperty:"payload",rootData,dynamicAnchors}))){vErrors = vErrors === null ? validate35.errors : vErrors.concat(validate35.errors);errors = vErrors.length;}}}var _valid2 = _errs31 === errors;valid13 = _valid2;if(valid13){var props2 = {};props2.payload = true;props2.eventType = true;}}if(!valid13){const err11 = {instancePath,schemaPath:"#/allOf/2/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}if(props0 !== true && props2 !== undefined){if(props2 === true){props0 = true;}else {props0 = props0 || {};Object.assign(props0, props2);}}const _errs34 = errors;let valid16 = true;const _errs35 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.eventType !== undefined){if("run.result.proposed" !== data.eventType){const err12 = {};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}}}var _valid3 = _errs35 === errors;errors = _errs34;if(vErrors !== null){if(_errs34){vErrors.length = _errs34;}else {vErrors = null;}}if(_valid3){const _errs37 = errors;if(data && typeof data == "object" && !Array.isArray(data)){if(data.payload !== undefined){let data11 = data.payload;const _errs42 = errors;let valid21 = true;const _errs43 = errors;if(data11 && typeof data11 == "object" && !Array.isArray(data11)){if(data11.reportedWorkDisposition !== undefined){if("blocked" !== data11.reportedWorkDisposition){const err13 = {};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}}}var _valid4 = _errs43 === errors;errors = _errs42;if(vErrors !== null){if(_errs42){vErrors.length = _errs42;}else {vErrors = null;}}if(_valid4){const _errs45 = errors;if(data11 && typeof data11 == "object" && !Array.isArray(data11)){if(data11.blocker === undefined){const err14 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/0/then/required",keyword:"required",params:{missingProperty: "blocker"},message:"must have required property '"+"blocker"+"'"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}}var _valid4 = _errs45 === errors;valid21 = _valid4;}if(!valid21){const err15 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}const _errs47 = errors;let valid23 = true;const _errs48 = errors;if(data11 && typeof data11 == "object" && !Array.isArray(data11)){if(data11.reportedWorkDisposition !== undefined){if("yielded" !== data11.reportedWorkDisposition){const err16 = {};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}}}var _valid5 = _errs48 === errors;errors = _errs47;if(vErrors !== null){if(_errs47){vErrors.length = _errs47;}else {vErrors = null;}}if(_valid5){const _errs50 = errors;if(data11 && typeof data11 == "object" && !Array.isArray(data11)){if(data11.continuation === undefined){const err17 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/1/then/required",keyword:"required",params:{missingProperty: "continuation"},message:"must have required property '"+"continuation"+"'"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}}var _valid5 = _errs50 === errors;valid23 = _valid5;}if(!valid23){const err18 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/1/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}if(data11 && typeof data11 == "object" && !Array.isArray(data11)){if(data11.schema === undefined){const err19 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}if(data11.reportedWorkDisposition === undefined){const err20 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "reportedWorkDisposition"},message:"must have required property '"+"reportedWorkDisposition"+"'"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}if(data11.summary === undefined){const err21 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "summary"},message:"must have required property '"+"summary"+"'"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(data11.completionClaim === undefined){const err22 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "completionClaim"},message:"must have required property '"+"completionClaim"+"'"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(data11.evidence === undefined){const err23 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "evidence"},message:"must have required property '"+"evidence"+"'"};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}if(data11.verification === undefined){const err24 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "verification"},message:"must have required property '"+"verification"+"'"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}if(data11.attentionRequests === undefined){const err25 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "attentionRequests"},message:"must have required property '"+"attentionRequests"+"'"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}if(data11.artifacts === undefined){const err26 = {instancePath:instancePath+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "artifacts"},message:"must have required property '"+"artifacts"+"'"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}if(data11.schema !== undefined){if("paperclip.run_result.v1" !== data11.schema){const err27 = {instancePath:instancePath+"/payload/schema",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.run_result.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}}if(data11.reportedWorkDisposition !== undefined){let data15 = data11.reportedWorkDisposition;if(!((((data15 === "done") || (data15 === "blocked")) || (data15 === "needs_review")) || (data15 === "yielded"))){const err28 = {instancePath:instancePath+"/payload/reportedWorkDisposition",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/reportedWorkDisposition/enum",keyword:"enum",params:{allowedValues: schema69.properties.reportedWorkDisposition.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}}if(data11.summary !== undefined){let data16 = data11.summary;if(typeof data16 === "string"){if(func1(data16) > 12000){const err29 = {instancePath:instancePath+"/payload/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/maxLength",keyword:"maxLength",params:{limit: 12000},message:"must NOT have more than 12000 characters"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}if(func1(data16) < 1){const err30 = {instancePath:instancePath+"/payload/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}}else {const err31 = {instancePath:instancePath+"/payload/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}}if(data11.completionClaim !== undefined){let data17 = data11.completionClaim;if(data17 && typeof data17 == "object" && !Array.isArray(data17)){if(data17.contractRevision === undefined){const err32 = {instancePath:instancePath+"/payload/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "contractRevision"},message:"must have required property '"+"contractRevision"+"'"};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}if(data17.objectiveSatisfied === undefined){const err33 = {instancePath:instancePath+"/payload/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "objectiveSatisfied"},message:"must have required property '"+"objectiveSatisfied"+"'"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}if(data17.criteria === undefined){const err34 = {instancePath:instancePath+"/payload/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "criteria"},message:"must have required property '"+"criteria"+"'"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}if(data17.remainingWork === undefined){const err35 = {instancePath:instancePath+"/payload/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "remainingWork"},message:"must have required property '"+"remainingWork"+"'"};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}if(data17.contractRevision !== undefined){let data18 = data17.contractRevision;if(typeof data18 === "string"){if(func1(data18) < 1){const err36 = {instancePath:instancePath+"/payload/completionClaim/contractRevision",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/contractRevision/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}}else {const err37 = {instancePath:instancePath+"/payload/completionClaim/contractRevision",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/contractRevision/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}}if(data17.objectiveSatisfied !== undefined){if(typeof data17.objectiveSatisfied !== "boolean"){const err38 = {instancePath:instancePath+"/payload/completionClaim/objectiveSatisfied",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/objectiveSatisfied/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}}if(data17.criteria !== undefined){let data20 = data17.criteria;if(Array.isArray(data20)){const len0 = data20.length;for(let i0=0; i0 160){const err114 = {instancePath:instancePath+"/sourceEventId",schemaPath:"#/properties/sourceEventId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err114];}else {vErrors.push(err114);}errors++;}if(func1(data56) < 1){const err115 = {instancePath:instancePath+"/sourceEventId",schemaPath:"#/properties/sourceEventId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err115];}else {vErrors.push(err115);}errors++;}}else {const err116 = {instancePath:instancePath+"/sourceEventId",schemaPath:"#/properties/sourceEventId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err116];}else {vErrors.push(err116);}errors++;}}if(data.sourceSeq !== undefined){let data57 = data.sourceSeq;if(!(((typeof data57 == "number") && (!(data57 % 1) && !isNaN(data57))) && (isFinite(data57)))){const err117 = {instancePath:instancePath+"/sourceSeq",schemaPath:"#/properties/sourceSeq/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err117];}else {vErrors.push(err117);}errors++;}if((typeof data57 == "number") && (isFinite(data57))){if(data57 < 1 || isNaN(data57)){const err118 = {instancePath:instancePath+"/sourceSeq",schemaPath:"#/properties/sourceSeq/minimum",keyword:"minimum",params:{comparison: ">=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err118];}else {vErrors.push(err118);}errors++;}}}if(data.sourceInstanceId !== undefined){let data58 = data.sourceInstanceId;if(typeof data58 === "string"){if(func1(data58) > 160){const err119 = {instancePath:instancePath+"/sourceInstanceId",schemaPath:"#/properties/sourceInstanceId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err119];}else {vErrors.push(err119);}errors++;}if(func1(data58) < 1){const err120 = {instancePath:instancePath+"/sourceInstanceId",schemaPath:"#/properties/sourceInstanceId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err120];}else {vErrors.push(err120);}errors++;}}else {const err121 = {instancePath:instancePath+"/sourceInstanceId",schemaPath:"#/properties/sourceInstanceId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err121];}else {vErrors.push(err121);}errors++;}}if(data.sourceKind !== undefined){let data59 = data.sourceKind;if(!((data59 === "runner") || (data59 === "control_plane"))){const err122 = {instancePath:instancePath+"/sourceKind",schemaPath:"#/properties/sourceKind/enum",keyword:"enum",params:{allowedValues: schema43.properties.sourceKind.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err122];}else {vErrors.push(err122);}errors++;}}if(data.runId !== undefined){let data60 = data.runId;if(typeof data60 === "string"){if(func1(data60) > 160){const err123 = {instancePath:instancePath+"/runId",schemaPath:"#/properties/runId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err123];}else {vErrors.push(err123);}errors++;}if(func1(data60) < 1){const err124 = {instancePath:instancePath+"/runId",schemaPath:"#/properties/runId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err124];}else {vErrors.push(err124);}errors++;}}else {const err125 = {instancePath:instancePath+"/runId",schemaPath:"#/properties/runId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err125];}else {vErrors.push(err125);}errors++;}}if(data.normalizedSessionId !== undefined){let data61 = data.normalizedSessionId;if(typeof data61 === "string"){if(func1(data61) > 160){const err126 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/properties/normalizedSessionId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err126];}else {vErrors.push(err126);}errors++;}if(func1(data61) < 1){const err127 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/properties/normalizedSessionId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err127];}else {vErrors.push(err127);}errors++;}}else {const err128 = {instancePath:instancePath+"/normalizedSessionId",schemaPath:"#/properties/normalizedSessionId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err128];}else {vErrors.push(err128);}errors++;}}if(data.turnId !== undefined){let data62 = data.turnId;if(typeof data62 === "string"){if(func1(data62) > 160){const err129 = {instancePath:instancePath+"/turnId",schemaPath:"#/properties/turnId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err129];}else {vErrors.push(err129);}errors++;}if(func1(data62) < 1){const err130 = {instancePath:instancePath+"/turnId",schemaPath:"#/properties/turnId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err130];}else {vErrors.push(err130);}errors++;}}else {const err131 = {instancePath:instancePath+"/turnId",schemaPath:"#/properties/turnId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err131];}else {vErrors.push(err131);}errors++;}}if(data.itemId !== undefined){let data63 = data.itemId;if(typeof data63 === "string"){if(func1(data63) > 160){const err132 = {instancePath:instancePath+"/itemId",schemaPath:"#/properties/itemId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err132];}else {vErrors.push(err132);}errors++;}if(func1(data63) < 1){const err133 = {instancePath:instancePath+"/itemId",schemaPath:"#/properties/itemId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err133];}else {vErrors.push(err133);}errors++;}}else {const err134 = {instancePath:instancePath+"/itemId",schemaPath:"#/properties/itemId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err134];}else {vErrors.push(err134);}errors++;}}if(data.eventType !== undefined){let data64 = data.eventType;if(!(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((data64 === "runner.connected") || (data64 === "runner.reconnected")) || (data64 === "runner.disconnected")) || (data64 === "runner.draining")) || (data64 === "runner.diagnostic")) || (data64 === "runtime.phase.changed")) || (data64 === "sandbox.metric")) || (data64 === "workspace.ready")) || (data64 === "harness.starting")) || (data64 === "harness.ready")) || (data64 === "harness.exited")) || (data64 === "harness.diagnostic")) || (data64 === "session.starting")) || (data64 === "session.started")) || (data64 === "session.resuming")) || (data64 === "session.resumed")) || (data64 === "session.reconciled")) || (data64 === "session.closed")) || (data64 === "session.failed")) || (data64 === "turn.submitted")) || (data64 === "turn.accepted")) || (data64 === "turn.started")) || (data64 === "turn.completed")) || (data64 === "turn.failed")) || (data64 === "turn.interrupted")) || (data64 === "turn.cancelled")) || (data64 === "item.started")) || (data64 === "item.delta")) || (data64 === "item.completed")) || (data64 === "item.failed")) || (data64 === "mcp_app.discovered")) || (data64 === "mcp_app.resource.resolved")) || (data64 === "mcp_app.initializing")) || (data64 === "mcp_app.ready")) || (data64 === "mcp_app.tool_input")) || (data64 === "mcp_app.tool_result")) || (data64 === "mcp_app.action.requested")) || (data64 === "mcp_app.action.resolved")) || (data64 === "mcp_app.host_context.changed")) || (data64 === "mcp_app.failed")) || (data64 === "mcp_app.teardown")) || (data64 === "runtime_request.created")) || (data64 === "runtime_request.resolved")) || (data64 === "runtime_request.expired")) || (data64 === "runtime_request.cancelled")) || (data64 === "interaction.request.proposed")) || (data64 === "interaction.request.materialized")) || (data64 === "interaction.request.rejected")) || (data64 === "interaction.response.progressed")) || (data64 === "interaction.response.resolved")) || (data64 === "interaction.response.delivered")) || (data64 === "run.result.proposed")) || (data64 === "run.result.accepted")) || (data64 === "run.result.rejected")) || (data64 === "attention.request.proposed")) || (data64 === "attention.request.routed")) || (data64 === "attention.request.resolved")) || (data64 === "attention.request.expired")) || (data64 === "attention.request.superseded")) || (data64 === "work.assessment.recorded")) || (data64 === "issue.status.decision.recorded")) || (data64 === "issue.status.decision.applied")) || (data64 === "issue.status.decision.rejected")) || (data64 === "issue.status.decision.superseded")) || (data64 === "run.terminal"))){const err135 = {instancePath:instancePath+"/eventType",schemaPath:"#/properties/eventType/enum",keyword:"enum",params:{allowedValues: schema43.properties.eventType.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err135];}else {vErrors.push(err135);}errors++;}}if(data.schemaVersion !== undefined){if(1 !== data.schemaVersion){const err136 = {instancePath:instancePath+"/schemaVersion",schemaPath:"#/properties/schemaVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err136];}else {vErrors.push(err136);}errors++;}}if(data.priority !== undefined){let data66 = data.priority;if(!(((data66 === 0) || (data66 === 1)) || (data66 === 2))){const err137 = {instancePath:instancePath+"/priority",schemaPath:"#/properties/priority/enum",keyword:"enum",params:{allowedValues: schema43.properties.priority.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err137];}else {vErrors.push(err137);}errors++;}}if(data.emittedAt !== undefined){let data67 = data.emittedAt;if(typeof data67 === "string"){if(!(formats0.test(data67))){const err138 = {instancePath:instancePath+"/emittedAt",schemaPath:"#/properties/emittedAt/format",keyword:"format",params:{format: "date-time"},message:"must match format \""+"date-time"+"\""};if(vErrors === null){vErrors = [err138];}else {vErrors.push(err138);}errors++;}}else {const err139 = {instancePath:instancePath+"/emittedAt",schemaPath:"#/properties/emittedAt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err139];}else {vErrors.push(err139);}errors++;}}if(data.observedAt !== undefined){let data68 = data.observedAt;if(typeof data68 === "string"){if(!(formats0.test(data68))){const err140 = {instancePath:instancePath+"/observedAt",schemaPath:"#/properties/observedAt/format",keyword:"format",params:{format: "date-time"},message:"must match format \""+"date-time"+"\""};if(vErrors === null){vErrors = [err140];}else {vErrors.push(err140);}errors++;}}else {const err141 = {instancePath:instancePath+"/observedAt",schemaPath:"#/properties/observedAt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err141];}else {vErrors.push(err141);}errors++;}}if(data.payload !== undefined){let data69 = data.payload;if(data69 && typeof data69 == "object" && !Array.isArray(data69)){}else {const err142 = {instancePath:instancePath+"/payload",schemaPath:"#/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err142];}else {vErrors.push(err142);}errors++;}}if(data.debug !== undefined){let data70 = data.debug;if(data70 && typeof data70 == "object" && !Array.isArray(data70)){}else {const err143 = {instancePath:instancePath+"/debug",schemaPath:"#/properties/debug/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err143];}else {vErrors.push(err143);}errors++;}}}else {const err144 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err144];}else {vErrors.push(err144);}errors++;}validate23.errors = vErrors;return errors === 0;}validate23.evaluated = {"props":true,"dynamicProps":false,"dynamicItems":false};function validate20(data, {instancePath="", parentData, parentDataProperty, rootData=data, dynamicAnchors={}}={}){/*# sourceURL="https://paperclip.dev/schemas/prp/v1/fixture.schema.json" */;let vErrors = null;let errors = 0;const evaluated0 = validate20.evaluated;if(evaluated0.dynamicProps){evaluated0.props = undefined;}if(evaluated0.dynamicItems){evaluated0.items = undefined;}if(data && typeof data == "object" && !Array.isArray(data)){if(data.schema === undefined){const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(data.fixtureVersion === undefined){const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "fixtureVersion"},message:"must have required property '"+"fixtureVersion"+"'"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}if(data.protocolVersion === undefined){const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "protocolVersion"},message:"must have required property '"+"protocolVersion"+"'"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(data.name === undefined){const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}if(data.description === undefined){const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(data.identity === undefined){const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "identity"},message:"must have required property '"+"identity"+"'"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}if(data.capabilities === undefined){const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}if(data.commands === undefined){const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "commands"},message:"must have required property '"+"commands"+"'"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}if(data.events === undefined){const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "events"},message:"must have required property '"+"events"+"'"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}if(data.result === undefined){const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "result"},message:"must have required property '"+"result"+"'"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}if(data.schema !== undefined){if("paperclip.prp.fixture.v1" !== data.schema){const err10 = {instancePath:instancePath+"/schema",schemaPath:"#/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.fixture.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}}if(data.fixtureVersion !== undefined){if(1 !== data.fixtureVersion){const err11 = {instancePath:instancePath+"/fixtureVersion",schemaPath:"#/properties/fixtureVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}}if(data.protocolVersion !== undefined){if(1 !== data.protocolVersion){const err12 = {instancePath:instancePath+"/protocolVersion",schemaPath:"#/properties/protocolVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;}}if(data.name !== undefined){let data3 = data.name;if(typeof data3 === "string"){if(func1(data3) > 120){const err13 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/maxLength",keyword:"maxLength",params:{limit: 120},message:"must NOT have more than 120 characters"};if(vErrors === null){vErrors = [err13];}else {vErrors.push(err13);}errors++;}if(func1(data3) < 1){const err14 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err14];}else {vErrors.push(err14);}errors++;}}else {const err15 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err15];}else {vErrors.push(err15);}errors++;}}if(data.description !== undefined){let data4 = data.description;if(typeof data4 === "string"){if(func1(data4) > 1000){const err16 = {instancePath:instancePath+"/description",schemaPath:"#/properties/description/maxLength",keyword:"maxLength",params:{limit: 1000},message:"must NOT have more than 1000 characters"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}if(func1(data4) < 1){const err17 = {instancePath:instancePath+"/description",schemaPath:"#/properties/description/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}}else {const err18 = {instancePath:instancePath+"/description",schemaPath:"#/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}}if(data.identity !== undefined){if(!(validate21(data.identity, {instancePath:instancePath+"/identity",parentData:data,parentDataProperty:"identity",rootData,dynamicAnchors}))){vErrors = vErrors === null ? validate21.errors : vErrors.concat(validate21.errors);errors = vErrors.length;}}if(data.capabilities !== undefined){let data6 = data.capabilities;if(data6 && typeof data6 == "object" && !Array.isArray(data6)){if(data6.schema === undefined){const err19 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}if(data6.sessionReusePolicy === undefined){const err20 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "sessionReusePolicy"},message:"must have required property '"+"sessionReusePolicy"+"'"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}if(data6.driver === undefined){const err21 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "driver"},message:"must have required property '"+"driver"+"'"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(data6.steer === undefined){const err22 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "steer"},message:"must have required property '"+"steer"+"'"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(data6.interrupt === undefined){const err23 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "interrupt"},message:"must have required property '"+"interrupt"+"'"};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}if(data6.resume === undefined){const err24 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "resume"},message:"must have required property '"+"resume"+"'"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}if(data6.runtimeRequests === undefined){const err25 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "runtimeRequests"},message:"must have required property '"+"runtimeRequests"+"'"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}if(data6.structuredResult === undefined){const err26 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "structuredResult"},message:"must have required property '"+"structuredResult"+"'"};if(vErrors === null){vErrors = [err26];}else {vErrors.push(err26);}errors++;}if(data6.typedEvents === undefined){const err27 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/required",keyword:"required",params:{missingProperty: "typedEvents"},message:"must have required property '"+"typedEvents"+"'"};if(vErrors === null){vErrors = [err27];}else {vErrors.push(err27);}errors++;}if(data6.schema !== undefined){if("paperclip.prp.capabilities.v1" !== data6.schema){const err28 = {instancePath:instancePath+"/capabilities/schema",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.capabilities.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err28];}else {vErrors.push(err28);}errors++;}}if(data6.sessionReusePolicy !== undefined){let data8 = data6.sessionReusePolicy;if(!(((data8 === "new_per_run") || (data8 === "reuse_per_issue")) || (data8 === "reuse_per_workspace"))){const err29 = {instancePath:instancePath+"/capabilities/sessionReusePolicy",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/sessionReusePolicy/enum",keyword:"enum",params:{allowedValues: schema41.properties.sessionReusePolicy.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err29];}else {vErrors.push(err29);}errors++;}}if(data6.driver !== undefined){let data9 = data6.driver;if(data9 && typeof data9 == "object" && !Array.isArray(data9)){if(data9.kind === undefined){const err30 = {instancePath:instancePath+"/capabilities/driver",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"};if(vErrors === null){vErrors = [err30];}else {vErrors.push(err30);}errors++;}if(data9.version === undefined){const err31 = {instancePath:instancePath+"/capabilities/driver",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"};if(vErrors === null){vErrors = [err31];}else {vErrors.push(err31);}errors++;}if(data9.kind !== undefined){let data10 = data9.kind;if(typeof data10 === "string"){if(func1(data10) > 80){const err32 = {instancePath:instancePath+"/capabilities/driver/kind",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/kind/maxLength",keyword:"maxLength",params:{limit: 80},message:"must NOT have more than 80 characters"};if(vErrors === null){vErrors = [err32];}else {vErrors.push(err32);}errors++;}if(func1(data10) < 1){const err33 = {instancePath:instancePath+"/capabilities/driver/kind",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/kind/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err33];}else {vErrors.push(err33);}errors++;}}else {const err34 = {instancePath:instancePath+"/capabilities/driver/kind",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err34];}else {vErrors.push(err34);}errors++;}}if(data9.version !== undefined){let data11 = data9.version;if(typeof data11 === "string"){if(func1(data11) > 80){const err35 = {instancePath:instancePath+"/capabilities/driver/version",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/version/maxLength",keyword:"maxLength",params:{limit: 80},message:"must NOT have more than 80 characters"};if(vErrors === null){vErrors = [err35];}else {vErrors.push(err35);}errors++;}if(func1(data11) < 1){const err36 = {instancePath:instancePath+"/capabilities/driver/version",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/version/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err36];}else {vErrors.push(err36);}errors++;}}else {const err37 = {instancePath:instancePath+"/capabilities/driver/version",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err37];}else {vErrors.push(err37);}errors++;}}}else {const err38 = {instancePath:instancePath+"/capabilities/driver",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/driver/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err38];}else {vErrors.push(err38);}errors++;}}if(data6.steer !== undefined){if(typeof data6.steer !== "boolean"){const err39 = {instancePath:instancePath+"/capabilities/steer",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/steer/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err39];}else {vErrors.push(err39);}errors++;}}if(data6.interrupt !== undefined){if(typeof data6.interrupt !== "boolean"){const err40 = {instancePath:instancePath+"/capabilities/interrupt",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/interrupt/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err40];}else {vErrors.push(err40);}errors++;}}if(data6.resume !== undefined){if(typeof data6.resume !== "boolean"){const err41 = {instancePath:instancePath+"/capabilities/resume",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/resume/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err41];}else {vErrors.push(err41);}errors++;}}if(data6.runtimeRequests !== undefined){if(typeof data6.runtimeRequests !== "boolean"){const err42 = {instancePath:instancePath+"/capabilities/runtimeRequests",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/runtimeRequests/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err42];}else {vErrors.push(err42);}errors++;}}if(data6.structuredResult !== undefined){if(typeof data6.structuredResult !== "boolean"){const err43 = {instancePath:instancePath+"/capabilities/structuredResult",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/structuredResult/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err43];}else {vErrors.push(err43);}errors++;}}if(data6.typedEvents !== undefined){if(typeof data6.typedEvents !== "boolean"){const err44 = {instancePath:instancePath+"/capabilities/typedEvents",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/typedEvents/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err44];}else {vErrors.push(err44);}errors++;}}if(data6.semanticTools !== undefined){let data18 = data6.semanticTools;if(data18 && typeof data18 == "object" && !Array.isArray(data18)){if(data18.schema === undefined){const err45 = {instancePath:instancePath+"/capabilities/semanticTools",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err45];}else {vErrors.push(err45);}errors++;}if(data18.schemaVersion === undefined){const err46 = {instancePath:instancePath+"/capabilities/semanticTools",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/required",keyword:"required",params:{missingProperty: "schemaVersion"},message:"must have required property '"+"schemaVersion"+"'"};if(vErrors === null){vErrors = [err46];}else {vErrors.push(err46);}errors++;}if(data18.operations === undefined){const err47 = {instancePath:instancePath+"/capabilities/semanticTools",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"};if(vErrors === null){vErrors = [err47];}else {vErrors.push(err47);}errors++;}if(data18.schema !== undefined){if("paperclip.prp.semantic_tools.v1" !== data18.schema){const err48 = {instancePath:instancePath+"/capabilities/semanticTools/schema",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.prp.semantic_tools.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err48];}else {vErrors.push(err48);}errors++;}}if(data18.schemaVersion !== undefined){if(1 !== data18.schemaVersion){const err49 = {instancePath:instancePath+"/capabilities/semanticTools/schemaVersion",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/schemaVersion/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err49];}else {vErrors.push(err49);}errors++;}}if(data18.operations !== undefined){let data21 = data18.operations;if(Array.isArray(data21)){const len0 = data21.length;for(let i0=0; i0 160){const err54 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/operationId",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/operationId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err54];}else {vErrors.push(err54);}errors++;}if(func1(data23) < 1){const err55 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/operationId",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/operationId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err55];}else {vErrors.push(err55);}errors++;}if(!pattern4.test(data23)){const err56 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/operationId",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/operationId/pattern",keyword:"pattern",params:{pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},message:"must match pattern \""+"^[A-Za-z0-9][A-Za-z0-9._:-]*$"+"\""};if(vErrors === null){vErrors = [err56];}else {vErrors.push(err56);}errors++;}}else {const err57 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/operationId",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/operationId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err57];}else {vErrors.push(err57);}errors++;}}if(data22.version !== undefined){if(1 !== data22.version){const err58 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/version",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/version/const",keyword:"const",params:{allowedValue: 1},message:"must be equal to constant"};if(vErrors === null){vErrors = [err58];}else {vErrors.push(err58);}errors++;}}if(data22.availability !== undefined){let data25 = data22.availability;if(!(((data25 === "available") || (data25 === "denied")) || (data25 === "unsupported"))){const err59 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/availability",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/availability/enum",keyword:"enum",params:{allowedValues: schema41.properties.semanticTools.properties.operations.items.properties.availability.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err59];}else {vErrors.push(err59);}errors++;}}if(data22.redactionDisposition !== undefined){if("digest_only" !== data22.redactionDisposition){const err60 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/redactionDisposition",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/redactionDisposition/const",keyword:"const",params:{allowedValue: "digest_only"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err60];}else {vErrors.push(err60);}errors++;}}if(data22.requiredClaims !== undefined){let data27 = data22.requiredClaims;if(Array.isArray(data27)){const len1 = data27.length;for(let i1=0; i1 160){const err61 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/requiredClaims/" + i1,schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/requiredClaims/items/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err61];}else {vErrors.push(err61);}errors++;}if(func1(data28) < 1){const err62 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/requiredClaims/" + i1,schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/requiredClaims/items/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err62];}else {vErrors.push(err62);}errors++;}}else {const err63 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/requiredClaims/" + i1,schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/requiredClaims/items/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err63];}else {vErrors.push(err63);}errors++;}}let i2 = data27.length;let j0;if(i2 > 1){const indices0 = {};for(;i2--;){let item0 = data27[i2];if(typeof item0 !== "string"){continue;}if(typeof indices0[item0] == "number"){j0 = indices0[item0];const err64 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/requiredClaims",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/requiredClaims/uniqueItems",keyword:"uniqueItems",params:{i: i2, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i2+" are identical)"};if(vErrors === null){vErrors = [err64];}else {vErrors.push(err64);}errors++;break;}indices0[item0] = i2;}}}else {const err65 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/requiredClaims",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/requiredClaims/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err65];}else {vErrors.push(err65);}errors++;}}if(data22.reasonCode !== undefined){let data29 = data22.reasonCode;if(typeof data29 === "string"){if(func1(data29) > 160){const err66 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/reasonCode",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/reasonCode/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err66];}else {vErrors.push(err66);}errors++;}if(func1(data29) < 1){const err67 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/reasonCode",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/reasonCode/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err67];}else {vErrors.push(err67);}errors++;}if(!pattern13.test(data29)){const err68 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/reasonCode",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/reasonCode/pattern",keyword:"pattern",params:{pattern: "^[a-z][a-z0-9_.:-]*$"},message:"must match pattern \""+"^[a-z][a-z0-9_.:-]*$"+"\""};if(vErrors === null){vErrors = [err68];}else {vErrors.push(err68);}errors++;}}else {const err69 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0+"/reasonCode",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/properties/reasonCode/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err69];}else {vErrors.push(err69);}errors++;}}}else {const err70 = {instancePath:instancePath+"/capabilities/semanticTools/operations/" + i0,schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/items/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err70];}else {vErrors.push(err70);}errors++;}}}else {const err71 = {instancePath:instancePath+"/capabilities/semanticTools/operations",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/properties/operations/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err71];}else {vErrors.push(err71);}errors++;}}}else {const err72 = {instancePath:instancePath+"/capabilities/semanticTools",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/semanticTools/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err72];}else {vErrors.push(err72);}errors++;}}if(data6.unsupported !== undefined){let data30 = data6.unsupported;if(Array.isArray(data30)){const len2 = data30.length;for(let i3=0; i3 1){const indices1 = {};for(;i4--;){let item1 = data30[i4];if(typeof item1 !== "string"){continue;}if(typeof indices1[item1] == "number"){j1 = indices1[item1];const err75 = {instancePath:instancePath+"/capabilities/unsupported",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/unsupported/uniqueItems",keyword:"uniqueItems",params:{i: i4, j: j1},message:"must NOT have duplicate items (items ## "+j1+" and "+i4+" are identical)"};if(vErrors === null){vErrors = [err75];}else {vErrors.push(err75);}errors++;break;}indices1[item1] = i4;}}}else {const err76 = {instancePath:instancePath+"/capabilities/unsupported",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/properties/unsupported/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err76];}else {vErrors.push(err76);}errors++;}}}else {const err77 = {instancePath:instancePath+"/capabilities",schemaPath:"https://paperclip.dev/schemas/prp/v1/capabilities.schema.json/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err77];}else {vErrors.push(err77);}errors++;}}if(data.commands !== undefined){let data32 = data.commands;if(Array.isArray(data32)){const len3 = data32.length;for(let i5=0; i5 160){const err85 = {instancePath:instancePath+"/commands/" + i5+"/commandId",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/commandId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err85];}else {vErrors.push(err85);}errors++;}if(func1(data35) < 1){const err86 = {instancePath:instancePath+"/commands/" + i5+"/commandId",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/commandId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err86];}else {vErrors.push(err86);}errors++;}}else {const err87 = {instancePath:instancePath+"/commands/" + i5+"/commandId",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/commandId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err87];}else {vErrors.push(err87);}errors++;}}if(data33.controllerSeq !== undefined){let data36 = data33.controllerSeq;if(!(((typeof data36 == "number") && (!(data36 % 1) && !isNaN(data36))) && (isFinite(data36)))){const err88 = {instancePath:instancePath+"/commands/" + i5+"/controllerSeq",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/controllerSeq/type",keyword:"type",params:{type: "integer"},message:"must be integer"};if(vErrors === null){vErrors = [err88];}else {vErrors.push(err88);}errors++;}if((typeof data36 == "number") && (isFinite(data36))){if(data36 < 1 || isNaN(data36)){const err89 = {instancePath:instancePath+"/commands/" + i5+"/controllerSeq",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/controllerSeq/minimum",keyword:"minimum",params:{comparison: ">=", limit: 1},message:"must be >= 1"};if(vErrors === null){vErrors = [err89];}else {vErrors.push(err89);}errors++;}}}if(data33.type !== undefined){let data37 = data33.type;if(!(((((((((((((data37 === "run.prepare") || (data37 === "session.open")) || (data37 === "turn.start")) || (data37 === "turn.steer")) || (data37 === "turn.interrupt")) || (data37 === "turn.stop")) || (data37 === "request.resolve")) || (data37 === "interaction.receipt")) || (data37 === "session.snapshot")) || (data37 === "session.close")) || (data37 === "run.cancel")) || (data37 === "runner.drain")) || (data37 === "runner.shutdown"))){const err90 = {instancePath:instancePath+"/commands/" + i5+"/type",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/type/enum",keyword:"enum",params:{allowedValues: schema42.properties.type.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err90];}else {vErrors.push(err90);}errors++;}}if(data33.issuedAt !== undefined){let data38 = data33.issuedAt;if(typeof data38 === "string"){if(!(formats0.test(data38))){const err91 = {instancePath:instancePath+"/commands/" + i5+"/issuedAt",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/issuedAt/format",keyword:"format",params:{format: "date-time"},message:"must match format \""+"date-time"+"\""};if(vErrors === null){vErrors = [err91];}else {vErrors.push(err91);}errors++;}}else {const err92 = {instancePath:instancePath+"/commands/" + i5+"/issuedAt",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/issuedAt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err92];}else {vErrors.push(err92);}errors++;}}if(data33.deadlineAt !== undefined){let data39 = data33.deadlineAt;if(typeof data39 === "string"){if(!(formats0.test(data39))){const err93 = {instancePath:instancePath+"/commands/" + i5+"/deadlineAt",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/deadlineAt/format",keyword:"format",params:{format: "date-time"},message:"must match format \""+"date-time"+"\""};if(vErrors === null){vErrors = [err93];}else {vErrors.push(err93);}errors++;}}else {const err94 = {instancePath:instancePath+"/commands/" + i5+"/deadlineAt",schemaPath:"https://paperclip.dev/schemas/prp/v1/command.schema.json/properties/deadlineAt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err94];}else {vErrors.push(err94);}errors++;}}if(data33.precondition !== undefined){let data40 = data33.precondition;if(data40 && typeof data40 == "object" && !Array.isArray(data40)){if(data40.runnerState !== undefined){let data41 = data40.runnerState;if(Array.isArray(data41)){const len4 = data41.length;for(let i6=0; i6 160){const err116 = {instancePath:instancePath+"/requests/" + i10+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/requestId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err116];}else {vErrors.push(err116);}errors++;}if(func1(data55) < 1){const err117 = {instancePath:instancePath+"/requests/" + i10+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/requestId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err117];}else {vErrors.push(err117);}errors++;}}else {const err118 = {instancePath:instancePath+"/requests/" + i10+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/requestId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err118];}else {vErrors.push(err118);}errors++;}}if(data52.type !== undefined){let data56 = data52.type;if(!((data56 === "permission") || (data56 === "input"))){const err119 = {instancePath:instancePath+"/requests/" + i10+"/type",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/type/enum",keyword:"enum",params:{allowedValues: schema70.oneOf[0].properties.type.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err119];}else {vErrors.push(err119);}errors++;}}if(data52.status !== undefined){let data57 = data52.status;if(!((((data57 === "pending") || (data57 === "resolved")) || (data57 === "expired")) || (data57 === "cancelled"))){const err120 = {instancePath:instancePath+"/requests/" + i10+"/status",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/status/enum",keyword:"enum",params:{allowedValues: schema70.oneOf[0].properties.status.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err120];}else {vErrors.push(err120);}errors++;}}if(data52.prompt !== undefined){let data58 = data52.prompt;if(typeof data58 === "string"){if(func1(data58) > 4000){const err121 = {instancePath:instancePath+"/requests/" + i10+"/prompt",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/prompt/maxLength",keyword:"maxLength",params:{limit: 4000},message:"must NOT have more than 4000 characters"};if(vErrors === null){vErrors = [err121];}else {vErrors.push(err121);}errors++;}if(func1(data58) < 1){const err122 = {instancePath:instancePath+"/requests/" + i10+"/prompt",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/prompt/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err122];}else {vErrors.push(err122);}errors++;}}else {const err123 = {instancePath:instancePath+"/requests/" + i10+"/prompt",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/0/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err123];}else {vErrors.push(err123);}errors++;}}if(data52.choices !== undefined){let data59 = data52.choices;if(Array.isArray(data59)){const len9 = data59.length;for(let i11=0; i11 160){const err141 = {instancePath:instancePath+"/requests/" + i10+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/requestId/maxLength",keyword:"maxLength",params:{limit: 160},message:"must NOT have more than 160 characters"};if(vErrors === null){vErrors = [err141];}else {vErrors.push(err141);}errors++;}if(func1(data65) < 1){const err142 = {instancePath:instancePath+"/requests/" + i10+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/requestId/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err142];}else {vErrors.push(err142);}errors++;}}else {const err143 = {instancePath:instancePath+"/requests/" + i10+"/requestId",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/requestId/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err143];}else {vErrors.push(err143);}errors++;}}if(data52.kind !== undefined){let data66 = data52.kind;if(!(((((data66 === "request_confirmation") || (data66 === "request_checkbox_confirmation")) || (data66 === "request_item_verdicts")) || (data66 === "ask_user_questions")) || (data66 === "suggest_tasks"))){const err144 = {instancePath:instancePath+"/requests/" + i10+"/kind",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/kind/enum",keyword:"enum",params:{allowedValues: schema70.oneOf[1].properties.kind.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err144];}else {vErrors.push(err144);}errors++;}}if(data52.blocking !== undefined){if(typeof data52.blocking !== "boolean"){const err145 = {instancePath:instancePath+"/requests/" + i10+"/blocking",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/blocking/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err145];}else {vErrors.push(err145);}errors++;}}if(data52.payload !== undefined){let data68 = data52.payload;if(data68 && typeof data68 == "object" && !Array.isArray(data68)){}else {const err146 = {instancePath:instancePath+"/requests/" + i10+"/payload",schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err146];}else {vErrors.push(err146);}errors++;}}}else {const err147 = {instancePath:instancePath+"/requests/" + i10,schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"};if(vErrors === null){vErrors = [err147];}else {vErrors.push(err147);}errors++;}var _valid0 = _errs124 === errors;if(_valid0 && valid30){valid30 = false;passing0 = [passing0, 1];}else {if(_valid0){valid30 = true;passing0 = 1;if(props0 !== true){props0 = true;}}}if(!valid30){const err148 = {instancePath:instancePath+"/requests/" + i10,schemaPath:"https://paperclip.dev/schemas/prp/v1/request.schema.json/oneOf",keyword:"oneOf",params:{passingSchemas: passing0},message:"must match exactly one schema in oneOf"};if(vErrors === null){vErrors = [err148];}else {vErrors.push(err148);}errors++;}else {errors = _errs103;if(vErrors !== null){if(_errs103){vErrors.length = _errs103;}else {vErrors = null;}}}}}else {const err149 = {instancePath:instancePath+"/requests",schemaPath:"#/properties/requests/type",keyword:"type",params:{type: "array"},message:"must be array"};if(vErrors === null){vErrors = [err149];}else {vErrors.push(err149);}errors++;}}if(data.result !== undefined){let data69 = data.result;const _errs141 = errors;let valid38 = true;const _errs142 = errors;if(data69 && typeof data69 == "object" && !Array.isArray(data69)){if(data69.reportedWorkDisposition !== undefined){if("blocked" !== data69.reportedWorkDisposition){const err150 = {};if(vErrors === null){vErrors = [err150];}else {vErrors.push(err150);}errors++;}}}var _valid1 = _errs142 === errors;errors = _errs141;if(vErrors !== null){if(_errs141){vErrors.length = _errs141;}else {vErrors = null;}}if(_valid1){const _errs144 = errors;if(data69 && typeof data69 == "object" && !Array.isArray(data69)){if(data69.blocker === undefined){const err151 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/0/then/required",keyword:"required",params:{missingProperty: "blocker"},message:"must have required property '"+"blocker"+"'"};if(vErrors === null){vErrors = [err151];}else {vErrors.push(err151);}errors++;}}var _valid1 = _errs144 === errors;valid38 = _valid1;}if(!valid38){const err152 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/0/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err152];}else {vErrors.push(err152);}errors++;}const _errs146 = errors;let valid40 = true;const _errs147 = errors;if(data69 && typeof data69 == "object" && !Array.isArray(data69)){if(data69.reportedWorkDisposition !== undefined){if("yielded" !== data69.reportedWorkDisposition){const err153 = {};if(vErrors === null){vErrors = [err153];}else {vErrors.push(err153);}errors++;}}}var _valid2 = _errs147 === errors;errors = _errs146;if(vErrors !== null){if(_errs146){vErrors.length = _errs146;}else {vErrors = null;}}if(_valid2){const _errs149 = errors;if(data69 && typeof data69 == "object" && !Array.isArray(data69)){if(data69.continuation === undefined){const err154 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/1/then/required",keyword:"required",params:{missingProperty: "continuation"},message:"must have required property '"+"continuation"+"'"};if(vErrors === null){vErrors = [err154];}else {vErrors.push(err154);}errors++;}}var _valid2 = _errs149 === errors;valid40 = _valid2;}if(!valid40){const err155 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/allOf/1/if",keyword:"if",params:{failingKeyword: "then"},message:"must match \"then\" schema"};if(vErrors === null){vErrors = [err155];}else {vErrors.push(err155);}errors++;}if(data69 && typeof data69 == "object" && !Array.isArray(data69)){if(data69.schema === undefined){const err156 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "schema"},message:"must have required property '"+"schema"+"'"};if(vErrors === null){vErrors = [err156];}else {vErrors.push(err156);}errors++;}if(data69.reportedWorkDisposition === undefined){const err157 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "reportedWorkDisposition"},message:"must have required property '"+"reportedWorkDisposition"+"'"};if(vErrors === null){vErrors = [err157];}else {vErrors.push(err157);}errors++;}if(data69.summary === undefined){const err158 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "summary"},message:"must have required property '"+"summary"+"'"};if(vErrors === null){vErrors = [err158];}else {vErrors.push(err158);}errors++;}if(data69.completionClaim === undefined){const err159 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "completionClaim"},message:"must have required property '"+"completionClaim"+"'"};if(vErrors === null){vErrors = [err159];}else {vErrors.push(err159);}errors++;}if(data69.evidence === undefined){const err160 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "evidence"},message:"must have required property '"+"evidence"+"'"};if(vErrors === null){vErrors = [err160];}else {vErrors.push(err160);}errors++;}if(data69.verification === undefined){const err161 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "verification"},message:"must have required property '"+"verification"+"'"};if(vErrors === null){vErrors = [err161];}else {vErrors.push(err161);}errors++;}if(data69.attentionRequests === undefined){const err162 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "attentionRequests"},message:"must have required property '"+"attentionRequests"+"'"};if(vErrors === null){vErrors = [err162];}else {vErrors.push(err162);}errors++;}if(data69.artifacts === undefined){const err163 = {instancePath:instancePath+"/result",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/required",keyword:"required",params:{missingProperty: "artifacts"},message:"must have required property '"+"artifacts"+"'"};if(vErrors === null){vErrors = [err163];}else {vErrors.push(err163);}errors++;}if(data69.schema !== undefined){if("paperclip.run_result.v1" !== data69.schema){const err164 = {instancePath:instancePath+"/result/schema",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/schema/const",keyword:"const",params:{allowedValue: "paperclip.run_result.v1"},message:"must be equal to constant"};if(vErrors === null){vErrors = [err164];}else {vErrors.push(err164);}errors++;}}if(data69.reportedWorkDisposition !== undefined){let data73 = data69.reportedWorkDisposition;if(!((((data73 === "done") || (data73 === "blocked")) || (data73 === "needs_review")) || (data73 === "yielded"))){const err165 = {instancePath:instancePath+"/result/reportedWorkDisposition",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/reportedWorkDisposition/enum",keyword:"enum",params:{allowedValues: schema69.properties.reportedWorkDisposition.enum},message:"must be equal to one of the allowed values"};if(vErrors === null){vErrors = [err165];}else {vErrors.push(err165);}errors++;}}if(data69.summary !== undefined){let data74 = data69.summary;if(typeof data74 === "string"){if(func1(data74) > 12000){const err166 = {instancePath:instancePath+"/result/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/maxLength",keyword:"maxLength",params:{limit: 12000},message:"must NOT have more than 12000 characters"};if(vErrors === null){vErrors = [err166];}else {vErrors.push(err166);}errors++;}if(func1(data74) < 1){const err167 = {instancePath:instancePath+"/result/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err167];}else {vErrors.push(err167);}errors++;}}else {const err168 = {instancePath:instancePath+"/result/summary",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err168];}else {vErrors.push(err168);}errors++;}}if(data69.completionClaim !== undefined){let data75 = data69.completionClaim;if(data75 && typeof data75 == "object" && !Array.isArray(data75)){if(data75.contractRevision === undefined){const err169 = {instancePath:instancePath+"/result/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "contractRevision"},message:"must have required property '"+"contractRevision"+"'"};if(vErrors === null){vErrors = [err169];}else {vErrors.push(err169);}errors++;}if(data75.objectiveSatisfied === undefined){const err170 = {instancePath:instancePath+"/result/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "objectiveSatisfied"},message:"must have required property '"+"objectiveSatisfied"+"'"};if(vErrors === null){vErrors = [err170];}else {vErrors.push(err170);}errors++;}if(data75.criteria === undefined){const err171 = {instancePath:instancePath+"/result/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "criteria"},message:"must have required property '"+"criteria"+"'"};if(vErrors === null){vErrors = [err171];}else {vErrors.push(err171);}errors++;}if(data75.remainingWork === undefined){const err172 = {instancePath:instancePath+"/result/completionClaim",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/required",keyword:"required",params:{missingProperty: "remainingWork"},message:"must have required property '"+"remainingWork"+"'"};if(vErrors === null){vErrors = [err172];}else {vErrors.push(err172);}errors++;}if(data75.contractRevision !== undefined){let data76 = data75.contractRevision;if(typeof data76 === "string"){if(func1(data76) < 1){const err173 = {instancePath:instancePath+"/result/completionClaim/contractRevision",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/contractRevision/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err173];}else {vErrors.push(err173);}errors++;}}else {const err174 = {instancePath:instancePath+"/result/completionClaim/contractRevision",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/contractRevision/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err174];}else {vErrors.push(err174);}errors++;}}if(data75.objectiveSatisfied !== undefined){if(typeof data75.objectiveSatisfied !== "boolean"){const err175 = {instancePath:instancePath+"/result/completionClaim/objectiveSatisfied",schemaPath:"https://paperclip.dev/schemas/prp/v1/result.schema.json/properties/completionClaim/properties/objectiveSatisfied/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err175];}else {vErrors.push(err175);}errors++;}}if(data75.criteria !== undefined){let data78 = data75.criteria;if(Array.isArray(data78)){const len10 = data78.length;for(let i12=0; i12 12000){const err16 = {instancePath:instancePath+"/summary",schemaPath:"#/properties/summary/maxLength",keyword:"maxLength",params:{limit: 12000},message:"must NOT have more than 12000 characters"};if(vErrors === null){vErrors = [err16];}else {vErrors.push(err16);}errors++;}if(func1(data4) < 1){const err17 = {instancePath:instancePath+"/summary",schemaPath:"#/properties/summary/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err17];}else {vErrors.push(err17);}errors++;}}else {const err18 = {instancePath:instancePath+"/summary",schemaPath:"#/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err18];}else {vErrors.push(err18);}errors++;}}if(data.completionClaim !== undefined){let data5 = data.completionClaim;if(data5 && typeof data5 == "object" && !Array.isArray(data5)){if(data5.contractRevision === undefined){const err19 = {instancePath:instancePath+"/completionClaim",schemaPath:"#/properties/completionClaim/required",keyword:"required",params:{missingProperty: "contractRevision"},message:"must have required property '"+"contractRevision"+"'"};if(vErrors === null){vErrors = [err19];}else {vErrors.push(err19);}errors++;}if(data5.objectiveSatisfied === undefined){const err20 = {instancePath:instancePath+"/completionClaim",schemaPath:"#/properties/completionClaim/required",keyword:"required",params:{missingProperty: "objectiveSatisfied"},message:"must have required property '"+"objectiveSatisfied"+"'"};if(vErrors === null){vErrors = [err20];}else {vErrors.push(err20);}errors++;}if(data5.criteria === undefined){const err21 = {instancePath:instancePath+"/completionClaim",schemaPath:"#/properties/completionClaim/required",keyword:"required",params:{missingProperty: "criteria"},message:"must have required property '"+"criteria"+"'"};if(vErrors === null){vErrors = [err21];}else {vErrors.push(err21);}errors++;}if(data5.remainingWork === undefined){const err22 = {instancePath:instancePath+"/completionClaim",schemaPath:"#/properties/completionClaim/required",keyword:"required",params:{missingProperty: "remainingWork"},message:"must have required property '"+"remainingWork"+"'"};if(vErrors === null){vErrors = [err22];}else {vErrors.push(err22);}errors++;}if(data5.contractRevision !== undefined){let data6 = data5.contractRevision;if(typeof data6 === "string"){if(func1(data6) < 1){const err23 = {instancePath:instancePath+"/completionClaim/contractRevision",schemaPath:"#/properties/completionClaim/properties/contractRevision/minLength",keyword:"minLength",params:{limit: 1},message:"must NOT have fewer than 1 characters"};if(vErrors === null){vErrors = [err23];}else {vErrors.push(err23);}errors++;}}else {const err24 = {instancePath:instancePath+"/completionClaim/contractRevision",schemaPath:"#/properties/completionClaim/properties/contractRevision/type",keyword:"type",params:{type: "string"},message:"must be string"};if(vErrors === null){vErrors = [err24];}else {vErrors.push(err24);}errors++;}}if(data5.objectiveSatisfied !== undefined){if(typeof data5.objectiveSatisfied !== "boolean"){const err25 = {instancePath:instancePath+"/completionClaim/objectiveSatisfied",schemaPath:"#/properties/completionClaim/properties/objectiveSatisfied/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"};if(vErrors === null){vErrors = [err25];}else {vErrors.push(err25);}errors++;}}if(data5.criteria !== undefined){let data8 = data5.criteria;if(Array.isArray(data8)){const len0 = data8.length;for(let i0=0; i0 { } } }); + + it("has no unlanded additive receipt or fixture/document gap", () => { + expect( + crosswalk.facts.filter((fact) => + fact.classification === "additive_v1_change" + || fact.classification === "missing_fixture_docs", + ), + ).toEqual([]); + }); }); diff --git a/packages/paperclip-runner/src/protocol/replay-contract.test.ts b/packages/paperclip-runner/src/protocol/replay-contract.test.ts index 43f02f1826d..ca45657e3e6 100644 --- a/packages/paperclip-runner/src/protocol/replay-contract.test.ts +++ b/packages/paperclip-runner/src/protocol/replay-contract.test.ts @@ -7,6 +7,7 @@ import { parsePrpFixtureText, PRP_PROTOCOL_VERSION, } from "./replay-contract.js"; +import { reducePrpFixture } from "../reducer/session-reducer.js"; const fixtureDirectory = new URL("../../protocol/fixtures/replay/", import.meta.url); const validFixtures = [ @@ -16,6 +17,12 @@ const validFixtures = [ "duplicate-event.json", "source-gap.json", "unknown-optional-fields.json", + "semantic-tool-artifact-happy-path.json", + "semantic-tool-denial-redaction.json", + "semantic-tool-conflict-duplicate-retry.json", + "semantic-tool-governance-wake-monitor.json", + "budget-cost-stop-reason.json", + "semantic-tool-unknown-optional-envelope.json", ]; async function readFixture(name = "happy-path.json"): Promise> { @@ -62,6 +69,174 @@ describe("PRP v1 JSON Schema contract", () => { }); }); + it("fails closed on an unsupported required semantic-tool version", async () => { + const result = parsePrpFixtureText( + await readFile( + new URL("semantic-tool-unsupported-required-version.json", fixtureDirectory), + "utf8", + ), + ); + expect(result).toMatchObject({ + ok: false, + issues: [ + { + code: "unsupported_required_version", + path: "/events/0/payload/semantic_tool/schemaVersion", + }, + ], + }); + }); + + it("records an artifact receipt without projecting semantic-tool payload", async () => { + const result = parsePrpFixtureText( + await readFile( + new URL("semantic-tool-artifact-happy-path.json", fixtureDirectory), + "utf8", + ), + ); + expect(result.ok).toBe(true); + if (!result.ok) return; + const semantic = result.fixture.events[1]?.payload.semantic_tool; + expect(semantic).toMatchObject({ + phase: "result", + operationId: "register_deliverable", + outcome: "succeeded", + operationReceiptId: "receipt_semantic_happy", + artifactRefs: [ + { kind: "artifact", id: "artifact_semantic_happy" }, + { kind: "work_product", id: "work_product_semantic_happy" }, + ], + }); + }); + + it("records a redacted denial with no fallback semantic call", async () => { + const result = parsePrpFixtureText( + await readFile( + new URL("semantic-tool-denial-redaction.json", fixtureDirectory), + "utf8", + ), + ); + expect(result.ok).toBe(true); + if (!result.ok) return; + const semanticEvents = result.fixture.events.filter( + (event) => event.payload.semantic_tool !== undefined, + ); + expect(semanticEvents).toHaveLength(2); + expect(semanticEvents.map((event) => event.payload.semantic_tool?.operationId)).toEqual([ + "decide_approval", + "decide_approval", + ]); + expect(semanticEvents[1]?.payload.semantic_tool).toMatchObject({ + outcome: "denied", + code: "required_claim_missing", + authorizationBoundary: "grant", + content: { redactionDisposition: "redacted" }, + }); + expect(JSON.stringify(semanticEvents)).not.toContain("Bearer "); + }); + + it("links a stale conflict to an exact duplicate retry receipt", async () => { + const result = parsePrpFixtureText( + await readFile( + new URL("semantic-tool-conflict-duplicate-retry.json", fixtureDirectory), + "utf8", + ), + ); + expect(result.ok).toBe(true); + if (!result.ok) return; + const receipts = result.fixture.events + .filter((event) => event.eventType === "mcp_app.tool_result") + .map((event) => event.payload.semantic_tool); + expect(receipts[0]).toMatchObject({ + outcome: "conflict", + currentRevision: "revision_plan_2", + retryable: true, + }); + expect(receipts[2]).toMatchObject({ + outcome: "duplicate", + operationReceiptId: receipts[1]?.operationReceiptId, + duplicateOfReceiptId: receipts[1]?.operationReceiptId, + }); + }); + + it("deduplicates an at-least-once semantic source delivery before pair binding", async () => { + const fixture = await readFixture("semantic-tool-artifact-happy-path.json"); + const events = fixture.events as Array>; + events.splice(1, 0, structuredClone(events[0]!)); + expect(parsePrpFixtureText(JSON.stringify(fixture))).toMatchObject({ ok: true }); + }); + + it("binds immutable interaction and approval targets to a wake/monitor chain", async () => { + const result = parsePrpFixtureText( + await readFile( + new URL("semantic-tool-governance-wake-monitor.json", fixtureDirectory), + "utf8", + ), + ); + expect(result.ok).toBe(true); + if (!result.ok) return; + const receipt = result.fixture.events[1]?.payload.semantic_tool; + expect(receipt?.targets).toEqual([ + { + kind: "interaction", + id: "interaction_semantic_governance", + immutable: true, + revisionId: "revision_plan_7", + }, + { + kind: "approval", + id: "approval_semantic_governance", + immutable: true, + decisionId: "decision_approval_semantic_governance", + }, + ]); + expect(receipt?.causalRefs?.map((reference) => reference.kind)).toEqual([ + "document_revision", + "interaction", + "approval", + "decision", + "wake", + "monitor", + ]); + }); + + it("carries a budget/cost stop receipt on the terminal event", async () => { + const result = parsePrpFixtureText( + await readFile(new URL("budget-cost-stop-reason.json", fixtureDirectory), "utf8"), + ); + expect(result.ok).toBe(true); + if (!result.ok) return; + const terminal = result.fixture.events.find( + (event) => event.eventType === "run.terminal", + ); + expect(terminal?.payload.stopReason).toMatchObject({ + kind: "budget", + code: "budget_hard_stop", + decisionId: "budget_decision_stop", + aggregate: { unit: "cents", observed: 10000, limit: 10000 }, + }); + }); + + it("accepts unknown optional semantic fields without changing projection", async () => { + const result = parsePrpFixtureText( + await readFile( + new URL("semantic-tool-unknown-optional-envelope.json", fixtureDirectory), + "utf8", + ), + ); + expect(result.ok).toBe(true); + if (!result.ok) return; + expect(result.fixture.events[0]?.payload.semantic_tool?.futureEnvelopeHint).toEqual({ + version: "1.1-preview", + }); + + const withoutEnvelope = structuredClone(result.fixture); + for (const event of withoutEnvelope.events) { + delete event.payload.semantic_tool; + } + expect(reducePrpFixture(result.fixture)).toEqual(reducePrpFixture(withoutEnvelope)); + }); + it("fails closed on unsupported nested required schema versions", async () => { const fixture = await readFixture(); const events = fixture.events as Array>; diff --git a/packages/paperclip-runner/src/protocol/replay-contract.ts b/packages/paperclip-runner/src/protocol/replay-contract.ts index c1a651b5065..744560aa7b6 100644 --- a/packages/paperclip-runner/src/protocol/replay-contract.ts +++ b/packages/paperclip-runner/src/protocol/replay-contract.ts @@ -8,6 +8,8 @@ import { identitySchema, requestSchema, resultSchema, + semanticToolSchema, + stopReasonSchema, terminalSchema, } from "./generated/schema-bundle.js"; import { @@ -20,11 +22,22 @@ export const PRP_PROTOCOL_NAME = "paperclip.runner"; export const PRP_PROTOCOL_VERSION = 1; export const PRP_FIXTURE_SCHEMA = "paperclip.prp.fixture.v1"; -type EventReferences = [typeof terminalSchema, typeof resultSchema]; +type TerminalReferences = [typeof stopReasonSchema]; +type EventReferences = [ + typeof semanticToolSchema, + typeof stopReasonSchema, + typeof terminalSchema, + typeof resultSchema, +]; export type PrpIdentity = FromSchema; export type PrpCapabilities = FromSchema; export type PrpCommand = FromSchema; -export type PrpTerminalState = FromSchema; +export type PrpSemanticToolEnvelope = FromSchema; +export type PrpStopReason = FromSchema; +export type PrpTerminalState = FromSchema< + typeof terminalSchema, + { references: TerminalReferences } +>; export type PrpRequest = FromSchema; export type PrpStructuredRunResult = FromSchema; export type PrpEvent = FromSchema< @@ -127,6 +140,35 @@ function versionIssues(value: unknown): ProtocolValidationIssue[] { message: `event schemaVersion ${actual} is unsupported; this implementation requires 1`, }); } + const payload = asRecord(event?.payload); + const semanticTool = asRecord(payload?.semantic_tool); + const semanticToolVersion = semanticTool?.schemaVersion; + if (typeof semanticToolVersion === "number" && semanticToolVersion !== 1) { + issues.push({ + code: "unsupported_required_version", + path: `/events/${index}/payload/semantic_tool/schemaVersion`, + message: `semantic_tool schemaVersion ${semanticToolVersion} is unsupported; this implementation requires 1`, + }); + } + const stopReason = asRecord(payload?.stopReason); + const stopReasonVersion = stopReason?.schemaVersion; + if (typeof stopReasonVersion === "number" && stopReasonVersion !== 1) { + issues.push({ + code: "unsupported_required_version", + path: `/events/${index}/payload/stopReason/schemaVersion`, + message: `stopReason schemaVersion ${stopReasonVersion} is unsupported; this implementation requires 1`, + }); + } + }); + } + const capabilities = asRecord(fixture.capabilities); + const semanticTools = asRecord(capabilities?.semanticTools); + const semanticToolsVersion = semanticTools?.schemaVersion; + if (typeof semanticToolsVersion === "number" && semanticToolsVersion !== 1) { + issues.push({ + code: "unsupported_required_version", + path: "/capabilities/semanticTools/schemaVersion", + message: `semanticTools schemaVersion ${semanticToolsVersion} is unsupported; this implementation requires 1`, }); } return issues; @@ -143,6 +185,10 @@ function ajvIssue(error: ErrorObject): ProtocolValidationIssue { function bindingIssues(fixture: PrpFixture): ProtocolValidationIssue[] { const issues: ProtocolValidationIssue[] = []; const uniqueEvents = new Map(); + const semanticCalls = new Map< + string, + { input?: { envelope: PrpSemanticToolEnvelope; index: number }; result?: { envelope: PrpSemanticToolEnvelope; index: number } } + >(); fixture.events.forEach((event, index) => { if (event.runId !== fixture.identity.runId) { issues.push({ @@ -164,15 +210,71 @@ function bindingIssues(fixture: PrpFixture): ProtocolValidationIssue[] { const existing = uniqueEvents.get(event.sourceEventId); if (existing === undefined) { uniqueEvents.set(event.sourceEventId, event); - } else if (canonicalJson(existing) !== canonicalJson(event)) { - issues.push({ - code: "binding_mismatch", - path: `/events/${index}/sourceEventId`, - message: "duplicate sourceEventId deliveries must be byte-equivalent", - }); + } else { + if (canonicalJson(existing) !== canonicalJson(event)) { + issues.push({ + code: "binding_mismatch", + path: `/events/${index}/sourceEventId`, + message: "duplicate sourceEventId deliveries must be byte-equivalent", + }); + } + // At-least-once source delivery is not a second semantic invocation. + return; + } + const payload = asRecord(event.payload); + const semanticTool = asRecord(payload?.semantic_tool) as PrpSemanticToolEnvelope | null; + if (semanticTool !== null) { + const correlation = asRecord(semanticTool.correlation); + for (const [field, actual, expected] of [ + ["runId", correlation?.runId, event.runId], + ["normalizedSessionId", correlation?.normalizedSessionId, event.normalizedSessionId], + ["turnId", correlation?.turnId, event.turnId], + ["itemId", correlation?.itemId, event.itemId], + ] as const) { + if (actual !== expected) { + issues.push({ + code: "binding_mismatch", + path: `/events/${index}/payload/semantic_tool/correlation/${field}`, + message: `semantic_tool correlation ${field} must match the containing event`, + }); + } + } + const call = semanticCalls.get(semanticTool.callId) ?? {}; + const phase = semanticTool.phase; + if (call[phase] !== undefined) { + issues.push({ + code: "binding_mismatch", + path: `/events/${index}/payload/semantic_tool/callId`, + message: `semantic_tool call ${semanticTool.callId} must contain exactly one ${phase} envelope`, + }); + } else { + call[phase] = { envelope: semanticTool, index }; + semanticCalls.set(semanticTool.callId, call); + } } }); + for (const [callId, call] of semanticCalls) { + if (call.input === undefined || call.result === undefined) { + const present = call.input ?? call.result; + issues.push({ + code: "binding_mismatch", + path: `/events/${present?.index ?? 0}/payload/semantic_tool/callId`, + message: `semantic_tool call ${callId} must contain one input and one result envelope`, + }); + continue; + } + for (const field of ["operationId", "idempotencyKey"] as const) { + if (canonicalJson(call.input.envelope[field]) !== canonicalJson(call.result.envelope[field])) { + issues.push({ + code: "binding_mismatch", + path: `/events/${call.result.index}/payload/semantic_tool/${field}`, + message: `semantic_tool result ${field} must match its input envelope`, + }); + } + } + } + fixture.commands.forEach((command, index) => { if (command.controllerSeq !== index + 1) { issues.push({ diff --git a/packages/paperclip-runner/src/protocol/semantic-tool-receipts.test.ts b/packages/paperclip-runner/src/protocol/semantic-tool-receipts.test.ts new file mode 100644 index 00000000000..7e591b68537 --- /dev/null +++ b/packages/paperclip-runner/src/protocol/semantic-tool-receipts.test.ts @@ -0,0 +1,121 @@ +import { describe, expect, it } from "vitest"; + +import { validatePrpEvent, type PrpEvent } from "./replay-contract.js"; +import { + createPrpBudgetStopReason, + createPrpSemanticToolInputEnvelope, + createPrpSemanticToolResultEnvelope, + semanticAuthorizationBoundaryForCode, +} from "./semantic-tool-receipts.js"; + +const correlation = { + runId: "run_receipt_test", + normalizedSessionId: "session_receipt_test", + turnId: "turn_receipt_test", + itemId: "item_receipt_test", +}; + +describe("PRP provider-neutral semantic receipts", () => { + it("digests raw content and retains only allowlisted references", () => { + const envelope = createPrpSemanticToolInputEnvelope({ + operationId: "get_task_context", + callId: "call_receipt_test", + correlation, + content: { authorization: "Bearer secret-token", apiKey: "do-not-emit" }, + references: [{ kind: "task", id: "issue_receipt_test" }], + }); + + expect(envelope.content).toMatchObject({ + digest: expect.stringMatching(/^sha256:[a-f0-9]{64}$/), + redactionDisposition: "digest_only", + references: [{ kind: "task", id: "issue_receipt_test" }], + }); + expect(JSON.stringify(envelope)).not.toContain("secret-token"); + expect(JSON.stringify(envelope)).not.toContain("do-not-emit"); + }); + + it("gives exact retries the same operation receipt without provider identifiers", () => { + const base = { + operationId: "write_document", + correlation, + idempotencyKey: "write_once", + content: { revisionId: "revision_1" }, + outcome: "succeeded" as const, + code: "ok", + retryable: false, + authorizationBoundary: "revision" as const, + }; + const first = createPrpSemanticToolResultEnvelope({ ...base, callId: "call_first" }); + const retry = createPrpSemanticToolResultEnvelope({ ...base, callId: "call_retry" }); + + expect(retry.operationReceiptId).toBe(first.operationReceiptId); + expect(retry.operationReceiptId).toMatch(/^semantic_receipt:[a-f0-9]{32}$/); + expect(retry).not.toHaveProperty("provider"); + }); + + it("validates semantic input/result events and a terminal stop receipt", () => { + const input = createPrpSemanticToolInputEnvelope({ + operationId: "get_task_context", + callId: "call_receipt_test", + correlation, + content: {}, + }); + const result = createPrpSemanticToolResultEnvelope({ + operationId: "get_task_context", + callId: "call_receipt_test", + correlation, + content: {}, + outcome: "succeeded", + code: "ok", + retryable: false, + authorizationBoundary: "active_task", + }); + + expect(validatePrpEvent(event("mcp_app.tool_input", input)).ok).toBe(true); + expect(validatePrpEvent(event("mcp_app.tool_result", result)).ok).toBe(true); + expect( + createPrpBudgetStopReason({ + receiptId: "stop_receipt_test", + kind: "cost", + code: "run_cost_limit", + retryable: true, + decisionId: "decision_receipt_test", + limitClass: "run_cost", + aggregate: { unit: "usd_micros", observed: 100, limit: 100, window: "run" }, + }), + ).toMatchObject({ + schema: "paperclip.prp.stop_reason.v1", + kind: "cost", + decisionId: "decision_receipt_test", + }); + }); + + it("maps denial and conflict codes onto protocol authorization boundaries", () => { + expect(semanticAuthorizationBoundaryForCode("company_scope_denied")).toBe("company"); + expect(semanticAuthorizationBoundaryForCode("actor_role_denied")).toBe("actor"); + expect(semanticAuthorizationBoundaryForCode("document_revision_conflict")).toBe("revision"); + expect(semanticAuthorizationBoundaryForCode("approval_required")).toBe("governed_action"); + }); +}); + +function event( + eventType: "mcp_app.tool_input" | "mcp_app.tool_result", + semanticTool: ReturnType, +): PrpEvent { + return { + schema: "paperclip.prp.event.v1", + sourceEventId: `${eventType}:receipt_test`, + sourceSeq: eventType === "mcp_app.tool_input" ? 1 : 2, + sourceInstanceId: "runner_receipt_test", + sourceKind: "runner", + runId: correlation.runId, + normalizedSessionId: correlation.normalizedSessionId, + turnId: correlation.turnId, + itemId: correlation.itemId, + eventType, + schemaVersion: 1, + priority: 1, + emittedAt: "2026-08-11T12:00:00.000Z", + payload: { semantic_tool: semanticTool }, + } as PrpEvent; +} diff --git a/packages/paperclip-runner/src/protocol/semantic-tool-receipts.ts b/packages/paperclip-runner/src/protocol/semantic-tool-receipts.ts new file mode 100644 index 00000000000..a8753c81af3 --- /dev/null +++ b/packages/paperclip-runner/src/protocol/semantic-tool-receipts.ts @@ -0,0 +1,239 @@ +import { createHash } from "node:crypto"; + +import type { + PrpEvent, + PrpSemanticToolEnvelope, + PrpStopReason, +} from "./replay-contract.js"; + +export type PrpSemanticAuthorizationBoundary = + | "company" + | "actor" + | "active_task" + | "grant" + | "governed_action" + | "lock" + | "revision"; + +export type PrpSemanticToolOutcome = + | "succeeded" + | "denied" + | "conflict" + | "duplicate" + | "unavailable" + | "failed"; + +export interface PrpSemanticCorrelation { + runId: string; + normalizedSessionId: string; + turnId: string; + itemId: string; + requestId?: string; +} + +export interface PrpSemanticSafeReference { + kind: + | "task" + | "document_revision" + | "interaction" + | "approval" + | "decision" + | "artifact" + | "work_product" + | "wake" + | "monitor" + | "audit" + | "operation"; + id: string; +} + +export interface PrpSemanticImmutableTarget { + kind: "document_revision" | "interaction" | "approval" | "decision"; + id: string; + immutable: true; + revisionId?: string; + decisionId?: string; +} + +interface SemanticEnvelopeBaseInput { + operationId: string; + callId: string; + correlation: PrpSemanticCorrelation; + idempotencyKey?: string | null; + content: unknown; + references?: readonly PrpSemanticSafeReference[]; + redactionDisposition?: "digest_only" | "allowlisted_references" | "redacted"; +} + +export interface CreatePrpSemanticToolResultInput extends SemanticEnvelopeBaseInput { + outcome: PrpSemanticToolOutcome; + code: string; + retryable: boolean; + authorizationBoundary: PrpSemanticAuthorizationBoundary; + operationReceiptId?: string; + auditReceiptId?: string; + currentRevision?: string | number; + duplicateOfReceiptId?: string; + artifactRefs?: readonly PrpSemanticSafeReference[]; + targets?: readonly PrpSemanticImmutableTarget[]; + causalRefs?: readonly PrpSemanticSafeReference[]; +} + +/** + * Creates a safe input envelope: raw content is reduced to a canonical digest, + * while callers may add only typed, non-secret references. + */ +export function createPrpSemanticToolInputEnvelope( + input: SemanticEnvelopeBaseInput, +): PrpSemanticToolEnvelope { + return { + schema: "paperclip.prp.semantic_tool.v1", + schemaVersion: 1, + phase: "input", + operationId: input.operationId, + callId: input.callId, + correlation: { ...input.correlation }, + idempotencyKey: input.idempotencyKey ?? null, + content: safeContent(input), + } as PrpSemanticToolEnvelope; +} + +/** Creates the provider-neutral semantic result receipt carried on PRP. */ +export function createPrpSemanticToolResultEnvelope( + input: CreatePrpSemanticToolResultInput, +): PrpSemanticToolEnvelope { + const operationReceiptId = input.operationReceiptId ?? derivedReceiptId(input); + return { + schema: "paperclip.prp.semantic_tool.v1", + schemaVersion: 1, + phase: "result", + operationId: input.operationId, + callId: input.callId, + correlation: { ...input.correlation }, + idempotencyKey: input.idempotencyKey ?? null, + content: safeContent(input), + outcome: input.outcome, + code: input.code, + retryable: input.retryable, + authorizationBoundary: input.authorizationBoundary, + operationReceiptId, + ...(input.auditReceiptId === undefined ? {} : { auditReceiptId: input.auditReceiptId }), + ...(input.currentRevision === undefined ? {} : { currentRevision: input.currentRevision }), + ...(input.duplicateOfReceiptId === undefined + ? {} + : { duplicateOfReceiptId: input.duplicateOfReceiptId }), + ...(input.artifactRefs === undefined ? {} : { artifactRefs: [...input.artifactRefs] }), + ...(input.targets === undefined ? {} : { targets: [...input.targets] }), + ...(input.causalRefs === undefined ? {} : { causalRefs: [...input.causalRefs] }), + } as PrpSemanticToolEnvelope; +} + +export function createPrpBudgetStopReason(input: { + receiptId: string; + kind: "budget" | "cost"; + code: string; + retryable: boolean; + decisionId: string; + limitClass: "company_monthly" | "actor_monthly" | "project_monthly" | "run_cost" | "provider_quota"; + aggregate: { + unit: "cents" | "usd_micros" | "tokens"; + observed: number; + limit: number; + window: "run" | "monthly_utc" | "provider_window"; + }; + relatedReceiptIds?: readonly string[]; +}): PrpStopReason { + return { + schema: "paperclip.prp.stop_reason.v1", + schemaVersion: 1, + receiptId: input.receiptId, + kind: input.kind, + code: input.code, + retryable: input.retryable, + decisionId: input.decisionId, + limitClass: input.limitClass, + aggregate: { ...input.aggregate }, + ...(input.relatedReceiptIds === undefined + ? {} + : { relatedReceiptIds: [...input.relatedReceiptIds] }), + } as PrpStopReason; +} + +/** Returns only typed result receipts; optional provider payload stays ignored. */ +export function prpSemanticToolResultReceipts( + events: readonly PrpEvent[], +): PrpSemanticToolEnvelope[] { + return events.flatMap((event) => { + if (event.eventType !== "mcp_app.tool_result") return []; + const payload = asRecord(event.payload); + const envelope = asRecord(payload?.semantic_tool); + if ( + envelope?.schema !== "paperclip.prp.semantic_tool.v1" + || envelope.schemaVersion !== 1 + || envelope.phase !== "result" + ) return []; + return [structuredClone(envelope) as PrpSemanticToolEnvelope]; + }); +} + +export function semanticAuthorizationBoundaryForCode( + code: string, +): PrpSemanticAuthorizationBoundary { + if (code.includes("company")) return "company"; + if (code.includes("actor") || code.includes("role")) return "actor"; + if (code.includes("claim") || code.includes("exposed")) return "grant"; + if (code.includes("revision") || code.includes("idempotency_conflict")) return "revision"; + if (code.includes("lock") || code.includes("ownership")) return "lock"; + if (code.includes("approval") || code.includes("interaction") || code.includes("governed")) { + return "governed_action"; + } + return "active_task"; +} + +export function semanticOutcomeForCode(input: { + ok: boolean; + code: string; + disposition?: unknown; +}): PrpSemanticToolOutcome { + if (input.ok) return input.disposition === "duplicate" ? "duplicate" : "succeeded"; + if (input.code.includes("conflict") || input.code.includes("revision")) return "conflict"; + if (input.code.includes("unavailable") || input.code.includes("not_exposed")) return "unavailable"; + return "denied"; +} + +export function digestPrpSemanticContent(value: unknown): string { + return `sha256:${createHash("sha256").update(canonicalJson(value)).digest("hex")}`; +} + +function safeContent(input: SemanticEnvelopeBaseInput) { + return { + digest: digestPrpSemanticContent(input.content), + redactionDisposition: input.redactionDisposition ?? "digest_only", + references: [...(input.references ?? [])], + }; +} + +function derivedReceiptId(input: CreatePrpSemanticToolResultInput): string { + const identity = input.idempotencyKey === undefined || input.idempotencyKey === null + ? `${input.correlation.runId}:${input.operationId}:${input.callId}` + : `${input.correlation.runId}:${input.operationId}:${input.idempotencyKey}`; + return `semantic_receipt:${createHash("sha256").update(identity).digest("hex").slice(0, 32)}`; +} + +function asRecord(value: unknown): Record | null { + return typeof value === "object" && value !== null && !Array.isArray(value) + ? value as Record + : null; +} + +function canonicalJson(value: unknown): string { + if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`; + const record = asRecord(value); + if (record !== null) { + return `{${Object.keys(record) + .sort() + .map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`) + .join(",")}}`; + } + return JSON.stringify(value) ?? "null"; +} diff --git a/packages/paperclip-runner/src/reducer/session-reducer.test.ts b/packages/paperclip-runner/src/reducer/session-reducer.test.ts index 6fe8c56eec7..d03067c7da5 100644 --- a/packages/paperclip-runner/src/reducer/session-reducer.test.ts +++ b/packages/paperclip-runner/src/reducer/session-reducer.test.ts @@ -22,6 +22,12 @@ const fixtureNames = [ "duplicate-event", "source-gap", "unknown-optional-fields", + "semantic-tool-artifact-happy-path", + "semantic-tool-denial-redaction", + "semantic-tool-conflict-duplicate-retry", + "semantic-tool-governance-wake-monitor", + "budget-cost-stop-reason", + "semantic-tool-unknown-optional-envelope", ]; async function loadFixture(name: string): Promise { diff --git a/server/src/__tests__/helpers/paperclip-semantic-conformance.ts b/server/src/__tests__/helpers/paperclip-semantic-conformance.ts index 761be20c948..bc1847c8a2a 100644 --- a/server/src/__tests__/helpers/paperclip-semantic-conformance.ts +++ b/server/src/__tests__/helpers/paperclip-semantic-conformance.ts @@ -95,7 +95,13 @@ export class PaperclipProductionSemanticConformanceAdapter implements SemanticCo input: vector.input, }); const after = world.port.snapshot(); - return normalizeCapabilitySemanticObservation({ result, before, after, taskId: world.taskId }); + return normalizeCapabilitySemanticObservation({ + result, + before, + after, + taskId: world.taskId, + semanticInput: vector.input, + }); } } diff --git a/server/src/__tests__/paperclip-semantic-conformance.test.ts b/server/src/__tests__/paperclip-semantic-conformance.test.ts index 0f161d2404f..7c85878ca89 100644 --- a/server/src/__tests__/paperclip-semantic-conformance.test.ts +++ b/server/src/__tests__/paperclip-semantic-conformance.test.ts @@ -94,5 +94,7 @@ describeEmbedded("Paperclip semantic mock/production conformance", () => { .toMatchObject({ interactions: [{ continuationPolicy: "wake_assignee" }] }); expect(report.rows.find((row) => row.vectorId === "terminal-finish")?.observation.state) .toMatchObject({ task: { status: "done" } }); + expect(report.rows.every((row) => row.observation.receipt?.operationReceiptPresent === true)) + .toBe(true); }, 30_000); });