mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-22 00:30:19 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Rust runner now owns validated, scoped ACPX reducer events and safe session suspension > - Durable PRP transport must receive provider-neutral events rather than sidecar-native envelopes > - Semantic calls and questions must retain the exact run, session, turn, item, and provider-request authority used by the durable command stream > - Terminal, result, assistant, process, and diagnostic events also need one reviewed projection boundary > - Permission requests remain impossible under the pinned Codex policy and must fail closed if they reach projection > - This pull request adds only that package-local projection without selecting ACPX in runnerd ## Linked Issues or Issue Description Refs #12422 ## What Changed - Add a validated durable ACPX event projection context bound to one run, normalized session, turn, and item. - Pass already normalized activity events through without reintroducing provider-native envelopes. - Project authorized tool calls into canonical semantic input receipts with exact correlation and content digests. - Project structured questions into provider-neutral `paperclip.runtime_request.v2` events. - Preserve both the public projected request identity and the original provider request identity so responses resolve the exact sidecar request. - Project dynamic semantic operation results as `semantic_tool.result`; only reserved finish/block operations may propose the run result. - Project semantic completion results into `run.result.proposed`. - Project terminal-flushed assistant messages on the final channel and turn terminal states into existing provider-neutral event families. - Project sanitized process metadata and diagnostics into bounded harness diagnostics. - Validate runtime-request origins against their strict durable shape and fall back from empty optional titles to a valid question prompt. - Reject invalid identities, projected-identity collisions, unstable semantic receipt identities, permission requests, and cross-turn projection fail closed. - Add integration coverage across reducer event families, correlation, identity validation, projected question resolution, and pinned-policy denial. - Document the durable projection boundary. - Do not change dependencies, lockfiles, workflows, runnerd selection, server behavior, UI, or migrations. ## Verification - Replay base: `80639f4f69c8938eb74bdc0833df93e0ed91dab3` (`master` after #12422 merged). - Exact replay head: `3cb29581d2bcbc4b47f8069baffd721c6ce4e444`. - Stable patch ID: `92910b56575e67ae83960177d467a565019ba282`. - The exact delta is 22 files, 1,206 additions, and 59 deletions, all in `packages/paperclip-runner`; it contains no lockfile, workflow, server, UI, dependency, or migration change. - `git diff --check` and the Cargo formatting check pass on the replayed delta. - Exact-head GitHub Actions run `33372209037` (attempt 2): **PASSED** with 23/23 jobs passed. - Greptile reviewed exact head `3cb29581d2bcbc4b47f8069baffd721c6ce4e444`: **5/5**, with zero unresolved review threads. - Superagent, contributor trust, Socket, and Snyk security checks: **PASSED**. - No local test result is claimed. GitHub Actions is the authoritative verification environment for this replayed revision. ## Risks - This function accepts reducer output, not raw sidecar frames. Callers must preserve the existing scope-first decode and reduction order. - Semantic input includes the already sanitized provider input while its content receipt uses the same canonical digest. - Structured input preserves the validated provider-neutral question set and sanitized origin. - Noncanonical provider request identities are deterministically projected for PRP while the original identity remains authoritative for the sidecar resolution command. - Existing PRP v1 identifiers remain schema-compatible; the only public ID-schema change widens turn/item limits from 160 to 240 characters. The internal ACPX sidecar wire schema now mirrors the stable IDs its Rust transport already enforced. - The projector verifies event-carried terminal and assistant turn identifiers against the durable context. - No production path invokes this projector in this pull request. Durable command execution remains the next slice. > 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 with GPT-5.6, 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 linked the preceding public PR 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 - [ ] 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
80 lines
3.0 KiB
JSON
80 lines
3.0 KiB
JSON
{
|
|
"$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", "input"],
|
|
"properties": {
|
|
"schema": { "const": "paperclip.runtime_request.v2" },
|
|
"requestKind": { "const": "runtime" },
|
|
"requestId": { "type": "string", "minLength": 1, "maxLength": 160 },
|
|
"type": { "const": "input" },
|
|
"status": { "enum": ["pending", "resolved", "expired", "cancelled"] },
|
|
"prompt": { "type": "string", "minLength": 1, "maxLength": 4000 },
|
|
"input": { "$ref": "https://paperclip.dev/schemas/prp/v1/question-set.schema.json" },
|
|
"origin": {
|
|
"type": "object",
|
|
"required": ["adapter"],
|
|
"properties": {
|
|
"adapter": { "type": "string", "minLength": 1, "maxLength": 160 },
|
|
"provider": { "type": "string", "minLength": 1, "maxLength": 160 },
|
|
"method": { "type": "string", "minLength": 1, "maxLength": 500 }
|
|
},
|
|
"additionalProperties": false
|
|
},
|
|
"turnId": { "type": "string", "minLength": 1, "maxLength": 240 },
|
|
"itemId": { "type": "string", "minLength": 1, "maxLength": 240 }
|
|
},
|
|
"additionalProperties": false
|
|
},
|
|
{
|
|
"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
|
|
}
|
|
]
|
|
}
|