From 08b5d6bd9bce116d5d722e5464faa4fc0627a6b5 Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Sat, 29 Aug 2026 23:05:05 -0500 Subject: [PATCH] Add core runner action contracts (#12358) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Runner tools need stable provider-neutral action contracts > - Core task work must use the same names, policy metadata, schemas, and examples on every provider surface > - A single large 41-action review would hide contract drift > - This pull request adds only the 14 always-present core action definitions > - It does not grant discovery or execution authority > - The benefit is a reviewable immutable contract base for later authorization wiring ## Linked Issues or Issue Description **Subsystem affected** packages/paperclip-runner protocol action contracts **Problem or motivation** The runner has an older compact catalog, but it does not single-source the full policy metadata, documentation, live shape, scenario shape, and examples for each core action. **Proposed solution** Add one immutable definition module per core action. Add an internal core aggregate and validate every input and output example against its declared JSON Schema. Keep all production authorization and execution unavailable. **Alternatives considered** All 41 action definitions could land in one pull request. That would create more than 7,000 changed lines and reduce useful review depth. **Roadmap alignment** This supports the existing experimental Paperclip Runner rollout. It does not enable the adapter or expose any new production tool. ## What Changed - Add 14 core protocol action definitions. - Add immutable policy, schema, documentation, and example data for each action. - Add a deep-freeze helper and a core-only aggregate. - Validate all core examples with JSON Schema. ## Verification - `pnpm --filter @paperclipai/paperclip-runner test:typescript` - `pnpm --filter @paperclipai/paperclip-runner typecheck:typescript` - `pnpm -r typecheck` - `pnpm build` - The branch changes 17 files relative to its declared base. ## Risks Low production risk. These declarations do not contain executable authorization or service bindings. The main risk is schema drift. Tests validate operation identity, placement, immutability, and canonical examples. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, `gpt-5`, with agentic reasoning, tool use, and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either linked an existing public issue or described the issue in-PR - [x] I have not referenced internal or instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --- .../answer-status-question.ts | 234 +++++++++++++ .../src/protocol-actions/block-task.ts | 245 ++++++++++++++ .../protocol-actions/core-contracts.test.ts | 61 ++++ .../src/protocol-actions/core.ts | 33 ++ .../src/protocol-actions/finish-task.ts | 228 +++++++++++++ .../src/protocol-actions/freeze.ts | 9 + .../src/protocol-actions/get-task-context.ts | 149 +++++++++ .../src/protocol-actions/get-task-history.ts | 159 +++++++++ .../inspect-operation-result.ts | 136 ++++++++ .../list-document-revisions.ts | 171 ++++++++++ .../src/protocol-actions/list-documents.ts | 147 ++++++++ .../src/protocol-actions/read-document.ts | 165 +++++++++ .../protocol-actions/register-deliverable.ts | 293 ++++++++++++++++ .../src/protocol-actions/report-progress.ts | 236 +++++++++++++ .../protocol-actions/request-human-input.ts | 314 ++++++++++++++++++ .../src/protocol-actions/request-review.ts | 228 +++++++++++++ .../src/protocol-actions/write-document.ts | 289 ++++++++++++++++ 17 files changed, 3097 insertions(+) create mode 100644 packages/paperclip-runner/src/protocol-actions/answer-status-question.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/block-task.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/core-contracts.test.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/core.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/finish-task.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/freeze.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/get-task-context.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/get-task-history.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/inspect-operation-result.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/list-document-revisions.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/list-documents.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/read-document.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/register-deliverable.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/report-progress.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/request-human-input.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/request-review.ts create mode 100644 packages/paperclip-runner/src/protocol-actions/write-document.ts diff --git a/packages/paperclip-runner/src/protocol-actions/answer-status-question.ts b/packages/paperclip-runner/src/protocol-actions/answer-status-question.ts new file mode 100644 index 0000000000..61a4033b14 --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/answer-status-question.ts @@ -0,0 +1,234 @@ +/** Canonical definition and documentation for `answer_status_question`. */ +export const answerStatusQuestionAction = { + "id": "answer_status_question", + "canonical": { + "operationId": "answer_status_question", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "semantic-operation item event plus active-task state diff, work-assessment, and issue-status-decision events", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Answer status question", + "description": "Append the answer to a status-only wake without changing task disposition.", + "note": null + }, + "examples": { + "call": { + "operationId": "answer_status_question", + "input": { + "idempotencyKey": "example", + "body": "example" + } + }, + "success": { + "ok": true, + "operationId": "answer_status_question", + "result": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": [ + "example" + ], + "scheduledWakeIds": [ + "example" + ] + } + } + }, + "live": { + "order": 6, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "answer_status_question", + "version": 1, + "title": "Answer status question", + "description": "Append the answer to a status-only wake without changing task disposition.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string", + "description": "Caller-stable retry key.", + "minLength": 1, + "maxLength": 240 + }, + "body": { + "type": "string", + "description": "Concise status answer.", + "minLength": 1, + "maxLength": 20000 + } + }, + "required": [ + "idempotencyKey", + "body" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "commandId": { + "type": "string", + "description": "Stable mock command identifier.", + "minLength": 1, + "maxLength": 200 + }, + "disposition": { + "enum": [ + "applied", + "duplicate" + ] + }, + "stateRevision": { + "type": "integer", + "minimum": 0 + }, + "entityRefs": { + "type": "array", + "description": "Mock entities affected by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + }, + "scheduledWakeIds": { + "type": "array", + "description": "Wake identifiers scheduled by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "commandId", + "disposition", + "stateRevision", + "entityRefs", + "scheduledWakeIds" + ], + "additionalProperties": false + } + } + }, + "scenario": { + "order": 6, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "answer_status_question", + "operationResultId": "example-result", + "value": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": ["example"], + "scheduledWakeIds": ["example"] + }, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "answer_status_question", + "version": 1, + "title": "Answer status question", + "description": "Post an answer to a status question without changing task state.", + "inputSchema": { + "type": "object", + "properties": { + "body": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "body" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "redaction": [], + "mockCommandMapping": { + "kind": "semantic_command", + "commandKind": "report_progress" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/block-task.ts b/packages/paperclip-runner/src/protocol-actions/block-task.ts new file mode 100644 index 0000000000..a292e8763c --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/block-task.ts @@ -0,0 +1,245 @@ +/** Canonical definition and documentation for `block_task`. */ +export const blockTaskAction = { + "id": "block_task", + "canonical": { + "operationId": "block_task", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "semantic-operation item event plus active-task state diff, work-assessment, and issue-status-decision events", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Block active task", + "description": "Block the active mock task with a durable reason and optional first-class dependencies.", + "note": null + }, + "examples": { + "call": { + "operationId": "block_task", + "input": { + "idempotencyKey": "example", + "reason": "example" + } + }, + "success": { + "ok": true, + "operationId": "block_task", + "result": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": [ + "example" + ], + "scheduledWakeIds": [ + "example" + ] + } + } + }, + "live": { + "order": 11, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "block_task", + "version": 1, + "title": "Block active task", + "description": "Block the active mock task with a durable reason and optional first-class dependencies.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string", + "description": "Caller-stable retry key.", + "minLength": 1, + "maxLength": 240 + }, + "reason": { + "type": "string", + "description": "Block reason.", + "minLength": 1, + "maxLength": 20000 + }, + "blockedByTaskIds": { + "type": "array", + "description": "Internal mock task ids that block this task.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "idempotencyKey", + "reason" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "commandId": { + "type": "string", + "description": "Stable mock command identifier.", + "minLength": 1, + "maxLength": 200 + }, + "disposition": { + "enum": [ + "applied", + "duplicate" + ] + }, + "stateRevision": { + "type": "integer", + "minimum": 0 + }, + "entityRefs": { + "type": "array", + "description": "Mock entities affected by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + }, + "scheduledWakeIds": { + "type": "array", + "description": "Wake identifiers scheduled by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "commandId", + "disposition", + "stateRevision", + "entityRefs", + "scheduledWakeIds" + ], + "additionalProperties": false + } + } + }, + "scenario": { + "order": 8, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "block_task", + "operationResultId": "example-result", + "value": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": ["example"], + "scheduledWakeIds": ["example"] + }, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "block_task", + "version": 1, + "title": "Block task", + "description": "Block the active task with a reason and optional first-class dependencies.", + "inputSchema": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "minLength": 1 + }, + "blockedByTaskIds": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + } + }, + "required": [ + "reason" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "redaction": [], + "mockCommandMapping": { + "kind": "semantic_command", + "commandKind": "block_task" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/core-contracts.test.ts b/packages/paperclip-runner/src/protocol-actions/core-contracts.test.ts new file mode 100644 index 0000000000..d3bb1eaae7 --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/core-contracts.test.ts @@ -0,0 +1,61 @@ +import Ajv2020 from "ajv/dist/2020.js"; +import { describe, expect, it } from "vitest"; + +import { PAPERCLIP_CORE_PROTOCOL_ACTIONS } from "./core.js"; + +describe("core Paperclip protocol action contracts", () => { + const ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true, strict: false }); + + it.each(PAPERCLIP_CORE_PROTOCOL_ACTIONS.map((action) => [action.id, action] as const))( + "%s has immutable metadata and schema-valid examples", + (operationId, action) => { + expect(action.canonical.operationId).toBe(operationId); + expect(action.canonical.placement).toBe("always_agent_tool"); + expect(action.examples.call.operationId).toBe(operationId); + expect(action.examples.success.operationId).toBe(operationId); + expect(Object.isFrozen(action)).toBe(true); + expect(Object.isFrozen(action.canonical)).toBe(true); + + expect(action.live !== null || action.scenario !== null).toBe(true); + + if (action.live !== null) { + expect( + ajv.validate(action.live.descriptor.inputSchema, action.examples.call.input), + JSON.stringify(ajv.errors), + ).toBe(true); + expect( + ajv.validate(action.live.descriptor.outputSchema, action.examples.success.result), + JSON.stringify(ajv.errors), + ).toBe(true); + } + + if (action.scenario !== null) { + expect(action.scenario.successExample.operationId).toBe(operationId); + const scenarioProperties = action.scenario.descriptor.inputSchema.properties ?? {}; + const callEntries = Object.entries(action.examples.call.input); + const outOfBandKeys = callEntries + .map(([key]) => key) + .filter((key) => !(key in scenarioProperties)); + // Scenario mutation idempotency is carried by the invocation envelope, + // not the operation input. No other example field may be omitted. + expect(outOfBandKeys).toEqual( + "idempotencyKey" in action.examples.call.input ? ["idempotencyKey"] : [], + ); + const scenarioInput = Object.fromEntries( + callEntries.filter(([key]) => key !== "idempotencyKey"), + ); + expect( + ajv.validate(action.scenario.descriptor.inputSchema, scenarioInput), + JSON.stringify(ajv.errors), + ).toBe(true); + expect( + ajv.validate( + action.scenario.descriptor.outputSchema, + action.scenario.successExample, + ), + JSON.stringify(ajv.errors), + ).toBe(true); + } + }, + ); +}); diff --git a/packages/paperclip-runner/src/protocol-actions/core.ts b/packages/paperclip-runner/src/protocol-actions/core.ts new file mode 100644 index 0000000000..ee19581527 --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/core.ts @@ -0,0 +1,33 @@ +import { answerStatusQuestionAction } from "./answer-status-question.js"; +import { blockTaskAction } from "./block-task.js"; +import { finishTaskAction } from "./finish-task.js"; +import { getTaskContextAction } from "./get-task-context.js"; +import { getTaskHistoryAction } from "./get-task-history.js"; +import { inspectOperationResultAction } from "./inspect-operation-result.js"; +import { listDocumentRevisionsAction } from "./list-document-revisions.js"; +import { listDocumentsAction } from "./list-documents.js"; +import { readDocumentAction } from "./read-document.js"; +import { registerDeliverableAction } from "./register-deliverable.js"; +import { reportProgressAction } from "./report-progress.js"; +import { requestHumanInputAction } from "./request-human-input.js"; +import { requestReviewAction } from "./request-review.js"; +import { writeDocumentAction } from "./write-document.js"; +import { deepFreezeProtocolAction } from "./freeze.js"; + +/** Core actions that are always present in an authorized runner projection. */ +export const PAPERCLIP_CORE_PROTOCOL_ACTIONS = deepFreezeProtocolAction([ + answerStatusQuestionAction, + blockTaskAction, + finishTaskAction, + getTaskContextAction, + getTaskHistoryAction, + inspectOperationResultAction, + listDocumentRevisionsAction, + listDocumentsAction, + readDocumentAction, + registerDeliverableAction, + reportProgressAction, + requestHumanInputAction, + requestReviewAction, + writeDocumentAction, +] as const); diff --git a/packages/paperclip-runner/src/protocol-actions/finish-task.ts b/packages/paperclip-runner/src/protocol-actions/finish-task.ts new file mode 100644 index 0000000000..3f9ab66926 --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/finish-task.ts @@ -0,0 +1,228 @@ +/** Canonical definition and documentation for `finish_task`. */ +export const finishTaskAction = { + "id": "finish_task", + "canonical": { + "operationId": "finish_task", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "semantic-operation item event plus active-task state diff, work-assessment, and issue-status-decision events", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Finish active task", + "description": "Finish the active mock task with a durable summary.", + "note": null + }, + "examples": { + "call": { + "operationId": "finish_task", + "input": { + "idempotencyKey": "example", + "summary": "example" + } + }, + "success": { + "ok": true, + "operationId": "finish_task", + "result": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": [ + "example" + ], + "scheduledWakeIds": [ + "example" + ] + } + } + }, + "live": { + "order": 10, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "finish_task", + "version": 1, + "title": "Finish active task", + "description": "Finish the active mock task with a durable summary.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string", + "description": "Caller-stable retry key.", + "minLength": 1, + "maxLength": 240 + }, + "summary": { + "type": "string", + "description": "Completion summary.", + "minLength": 1, + "maxLength": 20000 + } + }, + "required": [ + "idempotencyKey", + "summary" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "commandId": { + "type": "string", + "description": "Stable mock command identifier.", + "minLength": 1, + "maxLength": 200 + }, + "disposition": { + "enum": [ + "applied", + "duplicate" + ] + }, + "stateRevision": { + "type": "integer", + "minimum": 0 + }, + "entityRefs": { + "type": "array", + "description": "Mock entities affected by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + }, + "scheduledWakeIds": { + "type": "array", + "description": "Wake identifiers scheduled by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "commandId", + "disposition", + "stateRevision", + "entityRefs", + "scheduledWakeIds" + ], + "additionalProperties": false + } + } + }, + "scenario": { + "order": 7, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "finish_task", + "operationResultId": "example-result", + "value": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": ["example"], + "scheduledWakeIds": ["example"] + }, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "finish_task", + "version": 1, + "title": "Finish task", + "description": "Finish the active task with a durable completion summary.", + "inputSchema": { + "type": "object", + "properties": { + "summary": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "summary" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "redaction": [], + "mockCommandMapping": { + "kind": "semantic_command", + "commandKind": "finish_task" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/freeze.ts b/packages/paperclip-runner/src/protocol-actions/freeze.ts new file mode 100644 index 0000000000..20765838fa --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/freeze.ts @@ -0,0 +1,9 @@ +export function deepFreezeProtocolAction(value: T): T { + if (value !== null && typeof value === "object" && !Object.isFrozen(value)) { + for (const nested of Object.values(value as Record)) { + deepFreezeProtocolAction(nested); + } + Object.freeze(value); + } + return value; +} diff --git a/packages/paperclip-runner/src/protocol-actions/get-task-context.ts b/packages/paperclip-runner/src/protocol-actions/get-task-context.ts new file mode 100644 index 0000000000..8b6dae57d6 --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/get-task-context.ts @@ -0,0 +1,149 @@ +/** Canonical definition and documentation for `get_task_context`. */ +export const getTaskContextAction = { + "id": "get_task_context", + "canonical": { + "operationId": "get_task_context", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "PaperclipRunnerToolAuthority active issue/run + accepted plan revision", + "prpEvidence": "bound company/assignment query plus exact accepted document revision projection", + "prpBindingStatus": "bound", + "legacyAliases": [ + "mcp:paperclipMe" + ] + }, + "documentation": { + "title": "Get active task context", + "description": "Read the active task and actor, including the exact approved Markdown revision when this issue has an accepted plan.", + "note": null + }, + "examples": { + "call": { + "operationId": "get_task_context", + "input": {} + }, + "success": { + "ok": true, + "operationId": "get_task_context", + "result": {} + } + }, + "live": { + "order": 0, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "get_task_context", + "version": 1, + "title": "Get active task context", + "description": "Read the active task and actor, including the exact approved Markdown revision when this issue has an accepted plan.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "additionalProperties": true + } + } + }, + "scenario": { + "order": 0, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "get_task_context", + "operationResultId": "example-result", + "value": {}, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "get_task_context", + "version": 1, + "title": "Get task context", + "description": "Read the active task, ancestors, wake context, linked results, and budget summary.", + "inputSchema": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "redaction": [], + "mockCommandMapping": { + "kind": "context_read", + "projection": "active_task" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/get-task-history.ts b/packages/paperclip-runner/src/protocol-actions/get-task-history.ts new file mode 100644 index 0000000000..15acbdbabf --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/get-task-history.ts @@ -0,0 +1,159 @@ +/** Canonical definition and documentation for `get_task_history`. */ +export const getTaskHistoryAction = { + "id": "get_task_history", + "canonical": { + "operationId": "get_task_history", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "read projection surfaced via a tool-result item event; no control-plane state diff", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Get active task history", + "description": "Read bounded comments on the active mock task.", + "note": null + }, + "examples": { + "call": { + "operationId": "get_task_history", + "input": {} + }, + "success": { + "ok": true, + "operationId": "get_task_history", + "result": {} + } + }, + "live": { + "order": 1, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "get_task_history", + "version": 1, + "title": "Get active task history", + "description": "Read bounded comments on the active mock task.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 200, + "default": 50 + } + }, + "required": [], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "additionalProperties": true + } + } + }, + "scenario": { + "order": 1, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "get_task_history", + "operationResultId": "example-result", + "value": {}, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "get_task_history", + "version": 1, + "title": "Get task history", + "description": "Read comments and audit-visible history for the active task only.", + "inputSchema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "minimum": 1 + } + }, + "required": [], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "redaction": [], + "mockCommandMapping": { + "kind": "snapshot_read", + "projection": "active_task_history" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/inspect-operation-result.ts b/packages/paperclip-runner/src/protocol-actions/inspect-operation-result.ts new file mode 100644 index 0000000000..fc3c04f915 --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/inspect-operation-result.ts @@ -0,0 +1,136 @@ +/** Canonical definition and documentation for `inspect_operation_result`. */ +export const inspectOperationResultAction = { + "id": "inspect_operation_result", + "canonical": { + "operationId": "inspect_operation_result", + "surfaces": [ + "scenario" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "disabledByDefault": false, + "realBindingStatus": "scenario_mock", + "realServiceBinding": "unbound", + "prpEvidence": "read projection surfaced via a tool-result item event; no control-plane state diff", + "prpBindingStatus": "audit_pending", + "legacyAliases": [], + "note": "Scenario/eval-only re-read of a prior operation result; the live dispatcher returns results inline." + }, + "documentation": { + "title": "Inspect operation result", + "description": "Read a prior semantic operation result from this run.", + "note": "Scenario/eval-only re-read of a prior operation result; the live dispatcher returns results inline." + }, + "examples": { + "call": { + "operationId": "inspect_operation_result", + "input": { + "operationResultId": "example" + } + }, + "success": { + "ok": true, + "operationId": "inspect_operation_result", + "result": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "inspect_operation_result", + "operationResultId": "example", + "value": "example", + "commandResult": "example", + "authorization": "example" + } + } + }, + "live": null, + "scenario": { + "order": 13, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "inspect_operation_result", + "operationResultId": "example", + "value": "example", + "commandResult": "example", + "authorization": "example" + }, + "descriptor": { + "operationId": "inspect_operation_result", + "version": 1, + "title": "Inspect operation result", + "description": "Read a prior semantic operation result from this run.", + "inputSchema": { + "type": "object", + "properties": { + "operationResultId": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "operationResultId" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "redaction": [], + "mockCommandMapping": { + "kind": "operation_result" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/list-document-revisions.ts b/packages/paperclip-runner/src/protocol-actions/list-document-revisions.ts new file mode 100644 index 0000000000..3f9853bcba --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/list-document-revisions.ts @@ -0,0 +1,171 @@ +/** Canonical definition and documentation for `list_document_revisions`. */ +export const listDocumentRevisionsAction = { + "id": "list_document_revisions", + "canonical": { + "operationId": "list_document_revisions", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "read projection surfaced via a tool-result item event; no control-plane state diff", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "List document revisions", + "description": "Read bounded revision history for one active-task document.", + "note": null + }, + "examples": { + "call": { + "operationId": "list_document_revisions", + "input": { + "key": "example" + } + }, + "success": { + "ok": true, + "operationId": "list_document_revisions", + "result": {} + } + }, + "live": { + "order": 4, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "list_document_revisions", + "version": 1, + "title": "List document revisions", + "description": "Read bounded revision history for one active-task document.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Stable issue-document key.", + "minLength": 1, + "maxLength": 120 + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 200, + "default": 50 + } + }, + "required": [ + "key" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "additionalProperties": true + } + } + }, + "scenario": { + "order": 4, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "list_document_revisions", + "operationResultId": "example-result", + "value": {}, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "list_document_revisions", + "version": 1, + "title": "List document revisions", + "description": "Inspect revision history for one active-task document.", + "inputSchema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "key" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "redaction": [], + "mockCommandMapping": { + "kind": "snapshot_read", + "projection": "active_task_document_revisions" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/list-documents.ts b/packages/paperclip-runner/src/protocol-actions/list-documents.ts new file mode 100644 index 0000000000..2dce5dd540 --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/list-documents.ts @@ -0,0 +1,147 @@ +/** Canonical definition and documentation for `list_documents`. */ +export const listDocumentsAction = { + "id": "list_documents", + "canonical": { + "operationId": "list_documents", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "read projection surfaced via a tool-result item event; no control-plane state diff", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "List task documents", + "description": "List revisioned documents on the active mock task.", + "note": null + }, + "examples": { + "call": { + "operationId": "list_documents", + "input": {} + }, + "success": { + "ok": true, + "operationId": "list_documents", + "result": {} + } + }, + "live": { + "order": 2, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "list_documents", + "version": 1, + "title": "List task documents", + "description": "List revisioned documents on the active mock task.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "additionalProperties": true + } + } + }, + "scenario": { + "order": 2, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "list_documents", + "operationResultId": "example-result", + "value": {}, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "list_documents", + "version": 1, + "title": "List task documents", + "description": "List document metadata attached to the active task.", + "inputSchema": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "redaction": [], + "mockCommandMapping": { + "kind": "snapshot_read", + "projection": "active_task_documents" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/read-document.ts b/packages/paperclip-runner/src/protocol-actions/read-document.ts new file mode 100644 index 0000000000..b78f3d1bed --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/read-document.ts @@ -0,0 +1,165 @@ +/** Canonical definition and documentation for `read_document`. */ +export const readDocumentAction = { + "id": "read_document", + "canonical": { + "operationId": "read_document", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "read projection surfaced via a tool-result item event; no control-plane state diff", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Read task document", + "description": "Read the current revision of one active-task document.", + "note": null + }, + "examples": { + "call": { + "operationId": "read_document", + "input": { + "key": "example" + } + }, + "success": { + "ok": true, + "operationId": "read_document", + "result": {} + } + }, + "live": { + "order": 3, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "read_document", + "version": 1, + "title": "Read task document", + "description": "Read the current revision of one active-task document.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Stable issue-document key.", + "minLength": 1, + "maxLength": 120 + } + }, + "required": [ + "key" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "additionalProperties": true + } + } + }, + "scenario": { + "order": 3, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "read_document", + "operationResultId": "example-result", + "value": {}, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "read_document", + "version": 1, + "title": "Read task document", + "description": "Read one document on the active task by stable key.", + "inputSchema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "key" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "read", + "idempotency": "none", + "redaction": [], + "mockCommandMapping": { + "kind": "snapshot_read", + "projection": "active_task_document" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/register-deliverable.ts b/packages/paperclip-runner/src/protocol-actions/register-deliverable.ts new file mode 100644 index 0000000000..040f3477db --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/register-deliverable.ts @@ -0,0 +1,293 @@ +/** Canonical definition and documentation for `register_deliverable`. */ +export const registerDeliverableAction = { + "id": "register_deliverable", + "canonical": { + "operationId": "register_deliverable", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "planning", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "semantic-operation item event plus active-task state diff, work-assessment, and issue-status-decision events", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Register inspectable deliverable", + "description": "Register mock attachment metadata and its artifact work product without credentials or bytes in the tool result.", + "note": null + }, + "examples": { + "call": { + "operationId": "register_deliverable", + "input": { + "idempotencyKey": "example", + "filename": "example", + "contentType": "example", + "byteSize": 1, + "sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "contentRef": "example", + "title": "example" + } + }, + "success": { + "ok": true, + "operationId": "register_deliverable", + "result": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": [ + "example" + ], + "scheduledWakeIds": [ + "example" + ] + } + } + }, + "live": { + "order": 9, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "register_deliverable", + "version": 1, + "title": "Register inspectable deliverable", + "description": "Register mock attachment metadata and its artifact work product without credentials or bytes in the tool result.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string", + "description": "Caller-stable retry key.", + "minLength": 1, + "maxLength": 240 + }, + "filename": { + "type": "string", + "description": "Display filename.", + "minLength": 1, + "maxLength": 500 + }, + "contentType": { + "type": "string", + "description": "Media type.", + "minLength": 1, + "maxLength": 200 + }, + "byteSize": { + "type": "integer", + "minimum": 0, + "maximum": 100000000 + }, + "sha256": { + "type": "string", + "pattern": "^[a-fA-F0-9]{64}$" + }, + "contentRef": { + "type": "string", + "description": "Opaque package-local content reference.", + "minLength": 1, + "maxLength": 2000 + }, + "title": { + "type": "string", + "description": "Work-product title.", + "minLength": 1, + "maxLength": 500 + } + }, + "required": [ + "idempotencyKey", + "filename", + "contentType", + "byteSize", + "sha256", + "contentRef", + "title" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "commandId": { + "type": "string", + "description": "Stable mock command identifier.", + "minLength": 1, + "maxLength": 200 + }, + "disposition": { + "enum": [ + "applied", + "duplicate" + ] + }, + "stateRevision": { + "type": "integer", + "minimum": 0 + }, + "entityRefs": { + "type": "array", + "description": "Mock entities affected by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + }, + "scheduledWakeIds": { + "type": "array", + "description": "Wake identifiers scheduled by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "commandId", + "disposition", + "stateRevision", + "entityRefs", + "scheduledWakeIds" + ], + "additionalProperties": false + } + } + }, + "scenario": { + "order": 12, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "register_deliverable", + "operationResultId": "example-result", + "value": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": ["example"], + "scheduledWakeIds": ["example"] + }, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "register_deliverable", + "version": 1, + "title": "Register deliverable", + "description": "Register an inspectable artifact and its work product on the active task.", + "inputSchema": { + "type": "object", + "properties": { + "filename": { + "type": "string", + "minLength": 1 + }, + "contentType": { + "type": "string", + "minLength": 1 + }, + "byteSize": { + "type": "integer", + "minimum": 0 + }, + "sha256": { + "type": "string", + "minLength": 1 + }, + "contentRef": { + "type": "string", + "minLength": 1 + }, + "title": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "filename", + "contentType", + "byteSize", + "sha256", + "contentRef", + "title" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "planning", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "redaction": [], + "mockCommandMapping": { + "kind": "semantic_command", + "commandKind": "register_deliverable" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/report-progress.ts b/packages/paperclip-runner/src/protocol-actions/report-progress.ts new file mode 100644 index 0000000000..f562c73f6e --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/report-progress.ts @@ -0,0 +1,236 @@ +/** Canonical definition and documentation for `report_progress`. */ +export const reportProgressAction = { + "id": "report_progress", + "canonical": { + "operationId": "report_progress", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "semantic-operation item event plus active-task state diff, work-assessment, and issue-status-decision events", + "prpBindingStatus": "audit_pending", + "legacyAliases": [ + "mcp:paperclipAddComment" + ] + }, + "documentation": { + "title": "Report durable progress", + "description": "Append a durable progress comment to the active mock task.", + "note": null + }, + "examples": { + "call": { + "operationId": "report_progress", + "input": { + "idempotencyKey": "example", + "body": "example" + } + }, + "success": { + "ok": true, + "operationId": "report_progress", + "result": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": [ + "example" + ], + "scheduledWakeIds": [ + "example" + ] + } + } + }, + "live": { + "order": 5, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "report_progress", + "version": 1, + "title": "Report durable progress", + "description": "Append a durable progress comment to the active mock task.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string", + "description": "Caller-stable retry key.", + "minLength": 1, + "maxLength": 240 + }, + "body": { + "type": "string", + "description": "Multiline progress update.", + "minLength": 1, + "maxLength": 20000 + } + }, + "required": [ + "idempotencyKey", + "body" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "commandId": { + "type": "string", + "description": "Stable mock command identifier.", + "minLength": 1, + "maxLength": 200 + }, + "disposition": { + "enum": [ + "applied", + "duplicate" + ] + }, + "stateRevision": { + "type": "integer", + "minimum": 0 + }, + "entityRefs": { + "type": "array", + "description": "Mock entities affected by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + }, + "scheduledWakeIds": { + "type": "array", + "description": "Wake identifiers scheduled by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "commandId", + "disposition", + "stateRevision", + "entityRefs", + "scheduledWakeIds" + ], + "additionalProperties": false + } + } + }, + "scenario": { + "order": 5, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "report_progress", + "operationResultId": "example-result", + "value": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": ["example"], + "scheduledWakeIds": ["example"] + }, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "report_progress", + "version": 1, + "title": "Report progress", + "description": "Append a durable progress update to the active task.", + "inputSchema": { + "type": "object", + "properties": { + "body": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "body" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "ask", + "planning", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "redaction": [], + "mockCommandMapping": { + "kind": "semantic_command", + "commandKind": "report_progress" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/request-human-input.ts b/packages/paperclip-runner/src/protocol-actions/request-human-input.ts new file mode 100644 index 0000000000..34081f7d3e --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/request-human-input.ts @@ -0,0 +1,314 @@ +/** Canonical definition and documentation for `request_human_input`. */ +export const requestHumanInputAction = { + "id": "request_human_input", + "canonical": { + "operationId": "request_human_input", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "planning", + "ask", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "semantic-operation item event plus active-task state diff, work-assessment, and issue-status-decision events", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Request structured human input", + "description": "Create a typed, durable interaction on the active mock task.", + "note": null + }, + "examples": { + "call": { + "operationId": "request_human_input", + "input": { + "idempotencyKey": "example", + "interactionKind": "confirmation", + "title": "example", + "prompt": "example", + "continuationPolicy": "none" + } + }, + "success": { + "ok": true, + "operationId": "request_human_input", + "result": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": [ + "example" + ], + "scheduledWakeIds": [ + "example" + ] + } + } + }, + "live": { + "order": 8, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "request_human_input", + "version": 1, + "title": "Request structured human input", + "description": "Create a typed, durable interaction on the active mock task.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "planning", + "ask", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string", + "description": "Caller-stable retry key.", + "minLength": 1, + "maxLength": 240 + }, + "interactionKind": { + "enum": [ + "confirmation", + "checkbox", + "questions", + "suggest_tasks", + "item_verdicts" + ] + }, + "title": { + "type": "string", + "description": "Interaction card title.", + "minLength": 1, + "maxLength": 300 + }, + "prompt": { + "type": "string", + "description": "Question or decision prompt.", + "minLength": 1, + "maxLength": 10000 + }, + "payload": { + "type": "object", + "description": "Kind-specific interaction data. For interactionKind='questions', use exactly {version:1, questions:[{id,prompt,selectionMode:'single'|'multi',required?,options:[{id,label,description?,freeText?}]}]}; option keys are id/label, not value, and question choice cardinality is selectionMode, not type. For confirmation, payload may be {}. Keep all ids stable across retries.", + "additionalProperties": true + }, + "targetRevisionId": { + "type": [ + "string", + "null" + ], + "description": "Optional bound document revision.", + "maxLength": 20000 + }, + "continuationPolicy": { + "enum": [ + "none", + "wake_assignee", + "wake_assignee_on_accept" + ] + } + }, + "required": [ + "idempotencyKey", + "interactionKind", + "title", + "prompt", + "continuationPolicy" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "commandId": { + "type": "string", + "description": "Stable mock command identifier.", + "minLength": 1, + "maxLength": 200 + }, + "disposition": { + "enum": [ + "applied", + "duplicate" + ] + }, + "stateRevision": { + "type": "integer", + "minimum": 0 + }, + "entityRefs": { + "type": "array", + "description": "Mock entities affected by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + }, + "scheduledWakeIds": { + "type": "array", + "description": "Wake identifiers scheduled by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "commandId", + "disposition", + "stateRevision", + "entityRefs", + "scheduledWakeIds" + ], + "additionalProperties": false + } + } + }, + "scenario": { + "order": 11, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "request_human_input", + "operationResultId": "example-result", + "value": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": ["example"], + "scheduledWakeIds": ["example"] + }, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "request_human_input", + "version": 1, + "title": "Request human input", + "description": "Create a typed confirmation, checkbox, question, task suggestion, or item-verdict request.", + "inputSchema": { + "type": "object", + "properties": { + "interactionKind": { + "type": "string", + "enum": [ + "confirmation", + "checkbox", + "questions", + "suggest_tasks", + "item_verdicts" + ] + }, + "title": { + "type": "string", + "minLength": 1 + }, + "prompt": { + "type": "string", + "minLength": 1 + }, + "payload": { + "description": "Kind-specific interaction data. Questions use {version:1, questions:[{id,prompt,selectionMode:'single'|'multi',required?,options:[{id,label,description?,freeText?}]}]}; do not use type:'single_choice' or option.value." + }, + "targetRevisionId": { + "oneOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "null" + } + ] + }, + "continuationPolicy": { + "type": "string", + "enum": [ + "none", + "wake_assignee", + "wake_assignee_on_accept" + ] + } + }, + "required": [ + "interactionKind", + "title", + "prompt", + "continuationPolicy" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "planning", + "ask", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "redaction": [], + "mockCommandMapping": { + "kind": "semantic_command", + "commandKind": "request_human_input" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/request-review.ts b/packages/paperclip-runner/src/protocol-actions/request-review.ts new file mode 100644 index 0000000000..cb36d25d8d --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/request-review.ts @@ -0,0 +1,228 @@ +/** Canonical definition and documentation for `request_review`. */ +export const requestReviewAction = { + "id": "request_review", + "canonical": { + "operationId": "request_review", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "semantic-operation item event plus active-task state diff, work-assessment, and issue-status-decision events", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Request task review", + "description": "Move the active mock task to review with a durable summary.", + "note": null + }, + "examples": { + "call": { + "operationId": "request_review", + "input": { + "idempotencyKey": "example", + "summary": "example" + } + }, + "success": { + "ok": true, + "operationId": "request_review", + "result": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": [ + "example" + ], + "scheduledWakeIds": [ + "example" + ] + } + } + }, + "live": { + "order": 12, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "request_review", + "version": 1, + "title": "Request task review", + "description": "Move the active mock task to review with a durable summary.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string", + "description": "Caller-stable retry key.", + "minLength": 1, + "maxLength": 240 + }, + "summary": { + "type": "string", + "description": "Review handoff summary.", + "minLength": 1, + "maxLength": 20000 + } + }, + "required": [ + "idempotencyKey", + "summary" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "commandId": { + "type": "string", + "description": "Stable mock command identifier.", + "minLength": 1, + "maxLength": 200 + }, + "disposition": { + "enum": [ + "applied", + "duplicate" + ] + }, + "stateRevision": { + "type": "integer", + "minimum": 0 + }, + "entityRefs": { + "type": "array", + "description": "Mock entities affected by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + }, + "scheduledWakeIds": { + "type": "array", + "description": "Wake identifiers scheduled by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "commandId", + "disposition", + "stateRevision", + "entityRefs", + "scheduledWakeIds" + ], + "additionalProperties": false + } + } + }, + "scenario": { + "order": 9, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "request_review", + "operationResultId": "example-result", + "value": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": ["example"], + "scheduledWakeIds": ["example"] + }, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "request_review", + "version": 1, + "title": "Request task review", + "description": "Move the active task to review with a durable summary.", + "inputSchema": { + "type": "object", + "properties": { + "summary": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "summary" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "redaction": [], + "mockCommandMapping": { + "kind": "semantic_command", + "commandKind": "request_review" + } + } + } +} as const; diff --git a/packages/paperclip-runner/src/protocol-actions/write-document.ts b/packages/paperclip-runner/src/protocol-actions/write-document.ts new file mode 100644 index 0000000000..2b620352a3 --- /dev/null +++ b/packages/paperclip-runner/src/protocol-actions/write-document.ts @@ -0,0 +1,289 @@ +/** Canonical definition and documentation for `write_document`. */ +export const writeDocumentAction = { + "id": "write_document", + "canonical": { + "operationId": "write_document", + "surfaces": [ + "scenario", + "live" + ], + "placement": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "planning", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "disabledByDefault": false, + "realBindingStatus": "live_codex", + "realServiceBinding": "unbound", + "prpEvidence": "semantic-operation item event plus active-task state diff, work-assessment, and issue-status-decision events", + "prpBindingStatus": "audit_pending", + "legacyAliases": [] + }, + "documentation": { + "title": "Write revisioned document", + "description": "Create or update an active-task document with optimistic revision safety.", + "note": null + }, + "examples": { + "call": { + "operationId": "write_document", + "input": { + "idempotencyKey": "example", + "key": "example", + "title": "example", + "body": "example", + "baseRevisionId": "example" + } + }, + "success": { + "ok": true, + "operationId": "write_document", + "result": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": [ + "example" + ], + "scheduledWakeIds": [ + "example" + ] + } + } + }, + "live": { + "order": 7, + "descriptor": { + "schema": "paperclip.semantic-tool.v1", + "operationId": "write_document", + "version": 1, + "title": "Write revisioned document", + "description": "Create or update an active-task document with optimistic revision safety.", + "exposure": "always", + "requiredClaims": [], + "allowedModes": [ + "standard", + "planning", + "skill_test" + ], + "inputSchema": { + "type": "object", + "properties": { + "idempotencyKey": { + "type": "string", + "description": "Caller-stable retry key.", + "minLength": 1, + "maxLength": 240 + }, + "key": { + "type": "string", + "description": "Stable issue-document key.", + "minLength": 1, + "maxLength": 120 + }, + "title": { + "type": "string", + "description": "Document title.", + "minLength": 1, + "maxLength": 300 + }, + "body": { + "type": "string", + "description": "Markdown document body.", + "minLength": 1, + "maxLength": 200000 + }, + "baseRevisionId": { + "type": [ + "string", + "null" + ], + "description": "Current revision id, or null when creating.", + "maxLength": 20000 + }, + "changeSummary": { + "type": [ + "string", + "null" + ], + "description": "Optional revision summary.", + "maxLength": 20000 + } + }, + "required": [ + "idempotencyKey", + "key", + "title", + "body", + "baseRevisionId" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "commandId": { + "type": "string", + "description": "Stable mock command identifier.", + "minLength": 1, + "maxLength": 200 + }, + "disposition": { + "enum": [ + "applied", + "duplicate" + ] + }, + "stateRevision": { + "type": "integer", + "minimum": 0 + }, + "entityRefs": { + "type": "array", + "description": "Mock entities affected by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + }, + "scheduledWakeIds": { + "type": "array", + "description": "Wake identifiers scheduled by the operation.", + "items": { + "type": "string", + "minLength": 1 + }, + "maxItems": 200, + "uniqueItems": true + } + }, + "required": [ + "commandId", + "disposition", + "stateRevision", + "entityRefs", + "scheduledWakeIds" + ], + "additionalProperties": false + } + } + }, + "scenario": { + "order": 10, + "successExample": { + "schema": "paperclip.capability.tool-result.v1", + "ok": true, + "operationId": "write_document", + "operationResultId": "example-result", + "value": { + "commandId": "example", + "disposition": "applied", + "stateRevision": 1, + "entityRefs": ["example"], + "scheduledWakeIds": ["example"] + }, + "commandResult": null, + "authorization": {} + }, + "descriptor": { + "operationId": "write_document", + "version": 1, + "title": "Write task document", + "description": "Create or revision-safely update an active-task document.", + "inputSchema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "minLength": 1 + }, + "title": { + "type": "string", + "minLength": 1 + }, + "body": { + "type": "string" + }, + "baseRevisionId": { + "oneOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "null" + } + ] + }, + "changeSummary": { + "type": "string" + } + }, + "required": [ + "key", + "title", + "body", + "baseRevisionId" + ], + "additionalProperties": false + }, + "outputSchema": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "enum": [ + "paperclip.capability.tool-result.v1" + ] + }, + "ok": { + "type": "boolean" + }, + "operationId": { + "type": "string", + "minLength": 1 + }, + "operationResultId": { + "type": "string", + "minLength": 1 + }, + "value": {}, + "commandResult": {}, + "authorization": {} + }, + "required": [ + "schema", + "ok", + "operationId", + "operationResultId", + "value", + "commandResult", + "authorization" + ], + "additionalProperties": false + }, + "disposition": "always_agent_tool", + "optionalGroup": null, + "requiredClaims": [], + "taskModes": [ + "standard", + "planning", + "skill_test" + ], + "sideEffectClass": "task_write", + "idempotency": "required", + "redaction": [], + "mockCommandMapping": { + "kind": "semantic_command", + "commandKind": "write_document" + } + } + } +} as const;