mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-06 14:02:36 +01:00
## Thinking Path
> - Paperclip helps people manage AI agents that do work.
> - Native agents use tools to read and write task documents.
> - A document key is a stable identifier. The service trims it and
converts it to lowercase before it checks the key.
> - The tool schemas accepted filenames and long keys that the service
rejects.
> - This pull request makes ordinary document tool schemas match the
existing service contract.
> - Agents can now see the key rules before they call the tools.
## Linked Issues or Issue Description
**What happened?**
The schemas for `read_document`, `write_document`, and
`list_document_revisions` accepted `reconciliation.md` and keys longer
than 64 characters after normalization. The task document service
rejects these values. The descriptions did not explain that the key is
an identifier rather than a filename.
**Expected behavior**
The model catalog and the live and scenario tool definitions must
describe the existing document key rules. Values accepted after trimming
and conversion to lowercase must remain compatible. Historical
case-document keys use a separate contract.
**Steps to reproduce**
Validate `{ "key": "reconciliation.md" }` against the previous
`read_document` schema. It passes. Call the document service with that
key. It rejects the key before it reads the database. The added
regression repeats this comparison for all three tools.
## What Changed
- Apply the same document-key pattern to `read_task_document` and
`write_task_document` at the API bridge. Keep their existing raw-input
limit of 100 characters; ordinary tools keep 120. Export the shared
schema through the existing Runner package and server vendor boundary.
Route permissions, normalization and document locks stay with their
current owners.
- Add one shared schema for ordinary task-document keys. Keep the
existing 120-character raw input cap and the 64-character normalized
identifier limit.
- Preserve uppercase input, ECMAScript trim whitespace, and the Kelvin
sign, which converts to ASCII `k`.
- Apply the schema to the model catalog and the three live and scenario
definitions. Regenerate the catalogs, seeded fixture identity, and
fixture manifest.
- Test schema parity against the real task document service. Keep
historical case keys and the backend validator unchanged.
## Verification
- Current-head required CI is green at
`e67d3f1f49393660f0c70b3d1d136e6f86af821d`: 56 successful checks, four
intentional skips, and two neutral checks. [CI attempt
2](https://github.com/paperclipai/paperclip/actions/runs/41715924252)
passed after one targeted rerun of five jobs interrupted by the same
runner shutdown; the original interruption is retained. Fresh Greptile
and Paperclip reviews are both 5/5 with no unresolved review threads.
Hosted recovery remains unverified until automatic deployment and
replay.
- Normal master refresh to `e67d3f1f49393660f0c70b3d1d136e6f86af821d`
includes the already merged external-object startup fixture correction.
The previous required canary failed downloading
`mdast-util-gfm-table@2.0.1` with npm E404; later registry metadata and
tarball HEAD both returned 200. A separate general shard failed the
ten-thousand-future-objects startup assertion. Both original failures
remain recorded; neither was bypassed or retried. At the refreshed
baseline, 122 document/bridge cases and the exact large-object startup
case pass locally. Six document cases skip by platform. Fresh required
CI and reviews must pass on this head.
- The current-head Paperclip review found the same mismatch in the
task-scoped bridge. Before the correction, the real advertised schemas
failed 22 parity cases while 87 controls passed. After the correction
and a normal master refresh, the document-key and bridge suites pass 122
cases, with six platform-specific skips. The tests compare advertised
JSON Schema, runtime Zod validation, and the actual normalized document
service. They retain the bridge raw 100/101 boundary and historical
case-key controls.
- Runner TypeScript build, all server typecheck layers, and the actual
production Runner and server build pass. The final server build stamp
binds commit `80c880709c5f5630799fb8a48d54ff11ebc16610`. Full
current-head CI and fresh review are required after the correction. The
earlier CI run was externally cancelled and rerun; its cancellation
remains recorded.
- The regression failed in 33 of 64 cases before the fix. The remaining
cases passed as controls.
- The fixed regression passes all 67 cases, including every ECMAScript
trim character.
- The four focused Runner contract suites pass: 116 tests. They cover
all three tool surfaces and existing case behavior.
- Generated catalogs and manifest checks pass. Module-boundary and diff
checks pass.
- All server production typecheck layers pass. The test layer passes
after correcting the new test’s Ajv import. The full production server
and Runner build passes at a3e6191590.
- Full repository checks run in required CI. No hosted replay or
provider behavior claim is made.
## Risks
- The tool schema now rejects unsupported keys before the service does.
Older callers that used invalid filenames must use a stable key such as
`reconciliation`.
- The compatibility pattern must track the service normalization rules.
The regression checks the real service and includes Unicode
compatibility controls.
- No database, authorization, document revision, idempotency, or
case-document rules change.
## Model Used
OpenAI `gpt-6.1-sol`, Extra High reasoning. The model used code
execution, repository tools, and test output. The host does not expose
the context window size.
## 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 (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [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
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
263 lines
8.1 KiB
JSON
263 lines
8.1 KiB
JSON
{
|
|
"schema": "paperclip-runner/native-execution/v1",
|
|
"provenance": "seeded",
|
|
"identity": {
|
|
"runId": "run_evals_seeded",
|
|
"caseId": "case_semantic_denial",
|
|
"configId": "config_deterministic_v1",
|
|
"attemptId": "attempt_semantic_denial_0001"
|
|
},
|
|
"input": {
|
|
"caseSha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
"configSha256": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
"deterministicSeed": "paperclip-evals-v1-seed"
|
|
},
|
|
"runner": {
|
|
"package": {
|
|
"name": "@paperclipai/paperclip-runner",
|
|
"version": "0.0.0"
|
|
},
|
|
"binary": {
|
|
"name": "paperclip-runnerd",
|
|
"sha256": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
|
},
|
|
"prpVersion": 1,
|
|
"nativeExecutionVersion": 1,
|
|
"catalogVersion": 1,
|
|
"catalogSha256": "sha256:ea55aec60ac7737359115227cc0a5e9000bf0098d1e3f92d4281661cac290868",
|
|
"driverContractVersion": 1,
|
|
"driverKind": "paperclip-deterministic",
|
|
"driverVersion": "1.0.0"
|
|
},
|
|
"events": [
|
|
{
|
|
"schema": "paperclip.prp.event.v1",
|
|
"sourceEventId": "evals_seeded_01",
|
|
"sourceSeq": 1,
|
|
"sourceInstanceId": "runner_evals_seeded",
|
|
"sourceKind": "runner",
|
|
"runId": "run_evals_seeded",
|
|
"normalizedSessionId": "session_evals_seeded",
|
|
"turnId": "turn_evals_seeded",
|
|
"itemId": "item_evals_seeded",
|
|
"eventType": "mcp_app.tool_input",
|
|
"schemaVersion": 1,
|
|
"priority": 1,
|
|
"emittedAt": "2026-08-11T12:00:00.000Z",
|
|
"payload": {
|
|
"semantic_tool": {
|
|
"schema": "paperclip.prp.semantic_tool.v1",
|
|
"schemaVersion": 1,
|
|
"phase": "input",
|
|
"operationId": "decide_approval",
|
|
"callId": "call_evals_seeded",
|
|
"correlation": {
|
|
"runId": "run_evals_seeded",
|
|
"normalizedSessionId": "session_evals_seeded",
|
|
"turnId": "turn_evals_seeded",
|
|
"itemId": "item_evals_seeded"
|
|
},
|
|
"idempotencyKey": "decide_evals_seeded",
|
|
"content": {
|
|
"digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
|
"redactionDisposition": "redacted",
|
|
"references": []
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"schema": "paperclip.prp.event.v1",
|
|
"sourceEventId": "evals_seeded_02",
|
|
"sourceSeq": 2,
|
|
"sourceInstanceId": "runner_evals_seeded",
|
|
"sourceKind": "runner",
|
|
"runId": "run_evals_seeded",
|
|
"normalizedSessionId": "session_evals_seeded",
|
|
"turnId": "turn_evals_seeded",
|
|
"itemId": "item_evals_seeded",
|
|
"eventType": "mcp_app.tool_result",
|
|
"schemaVersion": 1,
|
|
"priority": 1,
|
|
"emittedAt": "2026-08-11T12:00:00.010Z",
|
|
"payload": {
|
|
"semantic_tool": {
|
|
"schema": "paperclip.prp.semantic_tool.v1",
|
|
"schemaVersion": 1,
|
|
"phase": "result",
|
|
"operationId": "decide_approval",
|
|
"callId": "call_evals_seeded",
|
|
"correlation": {
|
|
"runId": "run_evals_seeded",
|
|
"normalizedSessionId": "session_evals_seeded",
|
|
"turnId": "turn_evals_seeded",
|
|
"itemId": "item_evals_seeded"
|
|
},
|
|
"idempotencyKey": "decide_evals_seeded",
|
|
"content": {
|
|
"digest": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
"redactionDisposition": "redacted",
|
|
"references": []
|
|
},
|
|
"outcome": "denied",
|
|
"code": "required_claim_missing",
|
|
"retryable": false,
|
|
"authorizationBoundary": "grant",
|
|
"operationReceiptId": "receipt_evals_seeded",
|
|
"auditReceiptId": "audit_evals_seeded"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"schema": "paperclip.prp.event.v1",
|
|
"sourceEventId": "evals_seeded_03",
|
|
"sourceSeq": 3,
|
|
"sourceInstanceId": "runner_evals_seeded",
|
|
"sourceKind": "runner",
|
|
"runId": "run_evals_seeded",
|
|
"normalizedSessionId": "session_evals_seeded",
|
|
"turnId": "turn_evals_seeded",
|
|
"eventType": "run.result.proposed",
|
|
"schemaVersion": 1,
|
|
"priority": 0,
|
|
"emittedAt": "2026-08-11T12:00:00.020Z",
|
|
"payload": {
|
|
"schema": "paperclip.run_result.v1",
|
|
"reportedWorkDisposition": "needs_review",
|
|
"summary": "The governed tool effect was rejected and preserved as a denial.",
|
|
"completionClaim": {
|
|
"contractRevision": "evals-native-execution-v1",
|
|
"objectiveSatisfied": false,
|
|
"criteria": [],
|
|
"remainingWork": [
|
|
{
|
|
"description": "An authorized approver must decide.",
|
|
"blocksCompletion": true
|
|
}
|
|
]
|
|
},
|
|
"evidence": [
|
|
{
|
|
"receiptId": "receipt_evals_seeded"
|
|
}
|
|
],
|
|
"verification": [
|
|
{
|
|
"commandOrCheck": "rejected tool effect stays denied",
|
|
"status": "passed"
|
|
}
|
|
],
|
|
"attentionRequests": [],
|
|
"artifacts": []
|
|
}
|
|
},
|
|
{
|
|
"schema": "paperclip.prp.event.v1",
|
|
"sourceEventId": "evals_seeded_04",
|
|
"sourceSeq": 4,
|
|
"sourceInstanceId": "runner_evals_seeded",
|
|
"sourceKind": "runner",
|
|
"runId": "run_evals_seeded",
|
|
"normalizedSessionId": "session_evals_seeded",
|
|
"turnId": "turn_evals_seeded",
|
|
"eventType": "run.terminal",
|
|
"schemaVersion": 1,
|
|
"priority": 0,
|
|
"emittedAt": "2026-08-11T12:00:00.030Z",
|
|
"payload": {
|
|
"schema": "paperclip.prp.terminal.v1",
|
|
"turnTerminalState": "completed",
|
|
"runTerminalState": "succeeded",
|
|
"reportedWorkDisposition": "needs_review",
|
|
"workAssessmentId": "assessment_evals_seeded",
|
|
"statusDecisionId": "decision_evals_seeded"
|
|
}
|
|
}
|
|
],
|
|
"semanticTools": {
|
|
"definitions": [
|
|
{
|
|
"operationId": "decide_approval",
|
|
"schemaVersion": 1,
|
|
"availability": "denied"
|
|
}
|
|
],
|
|
"calls": [
|
|
{
|
|
"callId": "call_evals_seeded",
|
|
"operationId": "decide_approval",
|
|
"eventId": "evals_seeded_01"
|
|
}
|
|
],
|
|
"results": [
|
|
{
|
|
"callId": "call_evals_seeded",
|
|
"operationId": "decide_approval",
|
|
"eventId": "evals_seeded_02",
|
|
"outcome": "denied"
|
|
}
|
|
],
|
|
"denials": [
|
|
{
|
|
"callId": "call_evals_seeded",
|
|
"code": "required_claim_missing",
|
|
"authorizationBoundary": "grant",
|
|
"retryable": false
|
|
}
|
|
]
|
|
},
|
|
"terminal": {
|
|
"schema": "paperclip.prp.terminal.v1",
|
|
"turnTerminalState": "completed",
|
|
"runTerminalState": "succeeded",
|
|
"reportedWorkDisposition": "needs_review",
|
|
"workAssessmentId": "assessment_evals_seeded",
|
|
"statusDecisionId": "decision_evals_seeded"
|
|
},
|
|
"observations": {
|
|
"checks": [
|
|
{
|
|
"id": "tool-effect-denied",
|
|
"passed": true,
|
|
"receiptId": "receipt_evals_seeded"
|
|
}
|
|
]
|
|
},
|
|
"usage": {
|
|
"inputTokens": 12,
|
|
"outputTokens": 8,
|
|
"totalTokens": 20,
|
|
"requestCount": 1,
|
|
"durationMs": 30,
|
|
"cost": {
|
|
"currency": "USD",
|
|
"amountMicros": 0
|
|
}
|
|
},
|
|
"transcript": {
|
|
"uri": "artifact://native/attempt_semantic_denial_0001/transcript.jsonl",
|
|
"sha256": "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
"byteSize": 2048,
|
|
"mediaType": "application/x-ndjson",
|
|
"complete": true,
|
|
"eventCount": 4,
|
|
"omissionReason": null
|
|
},
|
|
"artifactRoot": {
|
|
"uri": "artifact://native/attempt_semantic_denial_0001/",
|
|
"sha256": "sha256:1212121212121212121212121212121212121212121212121212121212121212",
|
|
"byteSize": 4096,
|
|
"mediaType": "application/vnd.paperclip.runner-artifact-root+json"
|
|
},
|
|
"artifacts": [
|
|
{
|
|
"uri": "artifact://native/attempt_semantic_denial_0001/denial-receipt.json",
|
|
"sha256": "sha256:1313131313131313131313131313131313131313131313131313131313131313",
|
|
"byteSize": 512,
|
|
"mediaType": "application/json"
|
|
}
|
|
],
|
|
"failure": null,
|
|
"x_fixturePurpose": "Proves seeded provenance, denied effects, and additive field preservation."
|
|
}
|