mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-30 13:20:54 +01:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Users create tasks with a title and a description. > - A required title adds work when the prompt already explains the request. > - An agent can name the task once it reads that request. > - This pull request accepts prompt-only tasks and starts them with a short prompt slice. > - A scoped title tool lets the assigned agent replace that slice early without changing execution state. > - A live browser eval checks the real agent call, saved title, audit entry, and preservation of user titles. ## Linked Issues or Issue Description **Subsystem affected** Cross-cutting: task creation, shared contracts, database, server, runner tools, and board UI. **Problem or motivation** Users must currently write a title before they can submit a detailed task prompt. The agent has enough context to write a useful title itself. **Proposed solution** Make the title optional when a description is present. Save the first 120 characters of the normalized prompt as a provisional title. Ask the assigned agent to call `set_task_title` early. Use an atomic provisional-title guard to preserve titles supplied or edited by users. Keep explicit titles supported. Related: #14543 and #14556 concern empty-title submission. This change intentionally enables that submission when a prompt is present, instead of requiring a title. ## What Changed - Add the `titleNeedsGeneration` field with an idempotent migration. Keep existing titles unchanged. - Add `PUT /api/issues/:id/title` and the native and legacy `set_task_title` tool. Enforce company access, active-run ownership, shared, bounded retry receipts across native/HTTP calls, and transactional audit logging. Refresh external-object links after commit, with the same feature gate and plugin detectors as ordinary title edits. - Add early naming guidance in Standard, Ask, and Plan task context. Preserve the description, status, and assignment. - Allow prompt-only root and child task creation, plus draft restoration in the New Task dialog. Keep user titles supported. - Add an opt-in Product E2E suite for prompt-only Standard and Ask tasks, plus an explicit-title control. It checks actual provider calls within the first five tools, persisted state, audit attribution, and the reloaded UI. - Preserve a closed vocabulary of API key maintenance phrases in declared prose while rejecting opaque credential suffixes. Add one bounded naming retry after wording is rejected, without treating the rejected call as a saved title. - Repair the native cleanup receipt check exposed during full verification: accept matching input digests, retain legacy input checks, and reject conflicting receipts. ## Verification - Live Product E2E on `f43478473800e3a46b85c5ee79677efdb15108e7`: **3/3 passed** with native Codex `gpt-5.4-mini`, first attempts only, automatic retries disabled. Standard and Ask each saved “Rotate expired API key” on their first tool call, with matching persisted state and a single same-run audit entry. The explicit-title control retained its user title with zero title writes. All three verified the reloaded browser UI. - Campaign: `local-2026-09-30T21-30-11-021Z`. Earlier failed campaigns are retained separately; they exposed credential-prose handling and prompted the naming recovery fix. No failed result was regraded or deleted. - Reproduce with `pnpm test:e2e:runner -- --id task-titles.runner-codex-mini.local.prompt-title-standard --id task-titles.runner-codex-mini.local.prompt-title-ask --id task-titles.runner-codex-mini.local.preserve-explicit-title --max-automatic-retries 0` and an authorized provider key. - Full `pnpm -r typecheck` and `pnpm build` passed on the latest commit. The runner build used the configured external eval source tree. - Product E2E unit suite: **61 files, 818 tests passed**; E2E typecheck and UI token gates passed. - Title API/native regressions cover prompt-only and explicit child creation, user edits, ownership/company isolation, external reference refresh, cross-surface retry replay, and the 64-key limit without receipt eviction. All passed. Prompt-context coverage: **44 tests passed**. - Rust credential regressions: **35 tests passed**, including benign maintenance qualifiers and opaque credential rejection in every declared prose field. Catalog/report reconciliation: **28 tests passed**. Native recovery: **560 tests passed**. - Broad local `pnpm test:run`: **14,555 tests passed** in the general server group; two suites failed to initialize embedded PostgreSQL and the existing 40,000-file Git streaming stress test exceeded its 300-second macOS timeout. All three suites then passed in isolation (**5 tests passed**) without code or timeout changes. The original full local command exited nonzero and is not being represented as a clean full run. - Latest-head GitHub checks are green: **53 passed, 4 skipped, zero failed or pending**, including all test shards and the canary packaging dry run. Greptile reviewed the same commit at **5/5**, with zero unresolved review threads. ## Risks - The additive database field must reach the server and UI together. The migration uses `IF NOT EXISTS` and defaults existing tasks to a final title. - Title generation depends on the assigned agent running. Tasks without a run keep their provisional title. - Live qualification covers the native Codex path in Standard and Ask modes. API/legacy and Plan behavior have deterministic coverage. - The credential-prose exception validates the entire suffix against a closed maintenance vocabulary. Unknown suffixes, assignments, quoted values, credential prefixes, and diagnostics retain strict checks. ## Model Used OpenAI Codex, based on GPT-6, with reasoning, tool use, and code execution. The exact deployment ID and context window are not exposed in this session. The live eval uses the native Codex `gpt-5.4-mini` profile. ## 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:8a0dd1013634b17288a63f745782783d086c71f7c50881c9133534e73e372627",
|
|
"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."
|
|
}
|