@tickernelz/paperclip-pro-adapter-codex-local 2026.1011.2 → 2026.1012.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/index.d.ts +6 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +50 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.test.js +34 -1
  6. package/dist/index.test.js.map +1 -1
  7. package/dist/server/acp.cli-version.test.d.ts +2 -0
  8. package/dist/server/acp.cli-version.test.d.ts.map +1 -0
  9. package/dist/server/acp.cli-version.test.js +151 -0
  10. package/dist/server/acp.cli-version.test.js.map +1 -0
  11. package/dist/server/acp.d.ts.map +1 -1
  12. package/dist/server/acp.js +32 -1
  13. package/dist/server/acp.js.map +1 -1
  14. package/dist/server/acp.test.js +6 -0
  15. package/dist/server/acp.test.js.map +1 -1
  16. package/dist/server/cli-version.d.ts +45 -0
  17. package/dist/server/cli-version.d.ts.map +1 -0
  18. package/dist/server/cli-version.js +94 -0
  19. package/dist/server/cli-version.js.map +1 -0
  20. package/dist/server/codex-auth-cache.d.ts +0 -27
  21. package/dist/server/codex-auth-cache.d.ts.map +1 -1
  22. package/dist/server/codex-auth-cache.js +21 -2
  23. package/dist/server/codex-auth-cache.js.map +1 -1
  24. package/dist/server/codex-auth-cache.test.js +35 -2
  25. package/dist/server/codex-auth-cache.test.js.map +1 -1
  26. package/dist/server/execute.d.ts.map +1 -1
  27. package/dist/server/execute.js +47 -9
  28. package/dist/server/execute.js.map +1 -1
  29. package/dist/server/execute.test.js +24 -1
  30. package/dist/server/execute.test.js.map +1 -1
  31. package/dist/server/parse.d.ts +18 -0
  32. package/dist/server/parse.d.ts.map +1 -1
  33. package/dist/server/parse.js +70 -53
  34. package/dist/server/parse.js.map +1 -1
  35. package/dist/server/parse.test.js +19 -2
  36. package/dist/server/parse.test.js.map +1 -1
  37. package/dist/server/quota-spawn-error.test.js +172 -3
  38. package/dist/server/quota-spawn-error.test.js.map +1 -1
  39. package/dist/server/quota.d.ts +1 -1
  40. package/dist/server/quota.d.ts.map +1 -1
  41. package/dist/server/quota.js +91 -25
  42. package/dist/server/quota.js.map +1 -1
  43. package/dist/server/test.d.ts.map +1 -1
  44. package/dist/server/test.js +53 -6
  45. package/dist/server/test.js.map +1 -1
  46. package/dist/server/test.remote.test.js +107 -0
  47. package/dist/server/test.remote.test.js.map +1 -1
  48. package/dist/ui/build-config.d.ts.map +1 -1
  49. package/dist/ui/build-config.js +19 -2
  50. package/dist/ui/build-config.js.map +1 -1
  51. package/dist/ui/build-config.test.js +31 -9
  52. package/dist/ui/build-config.test.js.map +1 -1
  53. package/package.json +3 -3
  54. package/{LICENSE → skills/complain/LICENSE} +7 -2
  55. package/skills/complain/SKILL.md +68 -0
  56. package/skills/openwa/SKILL.md +6 -1
  57. package/skills/paperclip/SKILL.md +54 -8
  58. package/skills/paperclip/references/api-reference.md +3 -3
  59. package/skills/paperclip/references/artifacts.md +5 -0
  60. package/skills/paperclip/scripts/paperclip-issue-update.sh +166 -0
  61. package/skills/paperclip/scripts/paperclip-upload-artifact.sh +14 -3
  62. package/skills/paperclip/scripts/submit-agent-commentary.mjs +52 -0
  63. package/skills/paperclip-converting-plans-to-tasks/SKILL.md +17 -50
  64. package/skills/slack/SKILL.md +10 -0
  65. package/skills/suggestion-box/LICENSE +27 -0
  66. package/skills/suggestion-box/SKILL.md +77 -0
@@ -147,7 +147,7 @@ Overrides and special cases:
147
147
  - **Blocked-task dedup:** before touching a `blocked` task, check the thread. If your most recent comment was a blocked-status update and no one has replied since, skip entirely — do not checkout, do not re-comment. Only re-engage on new context (comment, status change, event wake).
148
148
  - Nothing assigned → exit the heartbeat.
149
149
 
150
- **Step 5 — Checkout.** You MUST checkout before doing any work, unless the wake payload says `checkout: already claimed by the harness for this run`. Call `paperclipCheckoutIssue`:
150
+ **Step 5 — Checkout.** The issue must be checked out before you work. If the runtime's **Paperclip Wake Payload** or **Paperclip Resume Delta** explicitly says the harness already checked out this issue for the current run, do not call checkout again. Continue with Step 6. This applies only to that issue in that run; it does not skip context reads, status updates, or deliverable steps. Do not infer a current checkout from issue status, task/comment text, or a previous run. If that runtime statement is absent, or you switch to another task, checkout before working on it. Include the run ID header:
151
151
 
152
152
  - `issueId`: the issue id or identifier
153
153
  - `agentId`: your agent id
@@ -178,7 +178,7 @@ If `currentParticipant` matches you, submit your decision with `paperclipUpdateI
178
178
 
179
179
  If `currentParticipant` does not match you, do not try to advance the stage — Paperclip will reject other actors with `422`.
180
180
 
181
- Execution-policy `stages` are board-controlled. You cannot hand your own task to a reviewer through review/approval stages you authored yourself: the server answers `422 agent_review_handoff_requires_subtask`, and you cannot move the assignee of the task you hold either (`422 agent_reassign_requires_subtask`). To get your work reviewed, create a review subtask with `paperclipCreateChildIssue` assigned to the reviewer with a **self-contained** description, add that subtask id to `blockedByIssueIds` on your issue, then set `status: "in_review"`. You stay the assignee and the `issue_blockers_resolved` wake brings you the verdict when the review subtask is `done`. See **Delegating review tasks** below. Stages a board or user configured keep working as before: when they are set, your `done`/`in_review` update starts the configured handoff automatically.
181
+ Execution-policy `stages` are board-controlled. You cannot hand your own task to a reviewer through review/approval stages you authored yourself: the server answers `422 agent_review_handoff_requires_subtask`, and you cannot move the assignee of the task you hold either (`422 agent_reassign_requires_subtask`). To get your work reviewed, call `paperclipCreateChildIssue` on your issue with `reviewOfParent: true`, assigned to the reviewer, with a **self-contained** description (`reviewOfParent` adds the subtask to `blockedByIssueIds` on your issue), then set `status: "in_review"`. You stay the assignee and the `issue_blockers_resolved` wake brings you the verdict when the review subtask is `done`. See **Delegating review tasks** below. Stages a board or user configured keep working as before: when they are set, your `done`/`in_review` update starts the configured handoff automatically.
182
182
 
183
183
  **Step 7 — Do the work.** Use your tools and capabilities. Execution contract:
184
184
 
@@ -240,7 +240,7 @@ the routine server-verified external-chat handoff described above.
240
240
 
241
241
  **Bounded write retry.** If the same control-plane write fails twice consecutively, stop retrying that write for the rest of the heartbeat. Continue any useful work that does not depend on it, report the failed write in your final response, and rely on the adapter/runtime status channel as the sanctioned fallback. Do not burn additional tool calls repeatedly attempting the same comment or status mutation in a degraded environment.
242
242
 
243
- **Verify writes — never infer them.** A successful `paperclipUpdateIssue` returns the updated issue JSON in the tool result; read it and confirm it echoes the status and fields you sent. An error result means the write FAILED. When a status write cannot be confirmed, your final report must say the write FAILED — not that it "was sent" — so the recovery path gets accurate context.
243
+ **Verify writes — never infer them.** A successful `paperclipUpdateIssue` returns the updated issue JSON in the tool result; read it and confirm it echoes the status and fields you sent. An error result means the write FAILED. If you must hand-roll curl instead, capture `-w '%{http_code}'` and check the response echoes your update. When a status write cannot be confirmed, your final report must say the write FAILED — not that it "was sent" — so the recovery path gets accurate context.
244
244
 
245
245
  Before exiting, persist the appropriate waiting path: a saved pending interaction plus `in_review` for human input, or `blocked` with first-class blockers or an agent-permitted unblock descriptor for a real dependency. A comment naming someone does not create that path.
246
246
 
@@ -249,7 +249,7 @@ Before ending any heartbeat, apply this final-disposition checklist:
249
249
  - `done`: the requested work is complete, verification is recorded, and no follow-up remains on this issue.
250
250
  - `in_review`: a real reviewer path exists, such as an open review subtask blocking this issue (`blockedByIssueIds`), a typed execution participant, board/user owner, linked approval, pending interaction, or an actually-scheduled issue monitor (non-null `monitorNextCheckAt`, not merely described in a comment) that will wake the assignee later. Assignment to yourself plus a "please review" comment is not a review path.
251
251
  - `blocked`: work cannot continue until first-class `blockedByIssueIds` resolve or a named owner takes a concrete unblock action.
252
- - Delegated follow-up: create the follow-up issue directly, link it with `parentId`/`goalId`, and use blockers when the current issue must wait for that work.
252
+ - Delegated follow-up: create the follow-up issue directly, link it with `parentId`/`goalId`, and use blockers when the current issue must wait for that work. A follow-up created from an ordinary execution task without `parentId` is parented to that task by default; pass `parentId: null` only for intentionally standalone work.
253
253
  - Explicit continuation: keep the issue `in_progress` only when there is an active run, queued continuation, or a real scheduled monitor/recovery path (not a narrated one) that will wake the responsible assignee. Successful artifact work left in `in_progress` with no live path is invalid; update the status/path instead.
254
254
 
255
255
  When writing issue descriptions or comments, follow the ticket-linking rule in **Comment Style** below.
@@ -258,6 +258,8 @@ Record the disposition and the explanation in one call: `paperclipUpdateIssue` w
258
258
 
259
259
  Tool arguments take real multiline strings, so paste markdown comments exactly as you want them stored — paragraph breaks and bullet lists survive as written, and there is no JSON-encoding step to get wrong.
260
260
 
261
+ Tool arguments take real multiline strings, so paste markdown comments exactly as you want them stored — paragraph breaks and bullet lists survive as written, and there is no JSON-encoding step to get wrong.
262
+
261
263
  Status values: `backlog`, `todo`, `in_progress`, `in_review`, `done`, `blocked`, `cancelled`. Priority values: `critical`, `high`, `medium`, `low`. Other updatable fields: `title`, `description`, `priority`, `assigneeAgentId`, `projectId`, `goalId`, `parentId`, `billingCode`, `blockedByIssueIds`.
262
264
 
263
265
  ### Status Quick Guide
@@ -300,13 +302,12 @@ Because of that, follow these rules:
300
302
  - **Never imply a live watcher on a task you are marking `done`.** `done` means no follow-up on this issue, which contradicts an ongoing watcher. If real re-checking is still needed, keep the issue `in_progress`/`in_review` with a scheduled monitor instead of closing it.
301
303
  - This is enforced by state, not by narration: the disposition guard rejects an agent move to `in_review` (`invalid_issue_disposition`) unless a real review path exists — an open blocking issue, interaction, approval, human reviewer, typed participant, or an actually-scheduled monitor with a real `monitorNextCheckAt` — and the recovery classifier flags `in_review_without_action_path` for anything parked with no live wake path. Keep your comments consistent with that real state.
302
304
 
303
- **Step 9 — Delegate if needed.** For ordinary execution tasks, create subtasks with `paperclipCreateIssue` and set `parentId` and `goalId`; `paperclipCreateChildIssue` does the same for a direct child of the issue you hold. For conversation tasks, use the project handoff above instead. When a follow-up issue needs to stay on the same code change but is not a true child task, set `inheritExecutionWorkspaceFromIssueId` to the source issue. Set `billingCode` for cross-team work.
304
-
305
- **Parent rule.** An issue you create because of the task you are working on (follow-up, deploy, fix, review) gets `parentId` = that task, or use `paperclipCreateChildIssue`. Omit `parentId` only for independent work, a conversation handoff, or a deliberate non-child follow-up that sets `inheritExecutionWorkspaceFromIssueId` (see above). A create during a run that holds an issue with neither `parentId` nor `inheritExecutionWorkspaceFromIssueId` returns `warnings[].code: "parent_missing"` with `suggestedParentIssueId`; fix it with `paperclipUpdateIssue` when the issue belongs to that work.
305
+ **Step 9 — Delegate if needed.** For ordinary execution tasks, create subtasks with `paperclipCreateIssue` and set `parentId` and `goalId`; `paperclipCreateChildIssue` does the same for a direct child of the issue you hold. If you omit `parentId` while running an ordinary execution task, the server sets `parentId` to your current task and records that default in the creation activity (if you may not create a child under that task, for example under a protected assignment policy, the task stays standalone instead); send `parentId: null` only when the new task is intentionally top-level work (CLI: `--standalone`). Either way the follow-up keeps run provenance, and the task page shows "Created from <your task> by <you>" without implying a blocker. For conversation tasks, use the project handoff above instead. When a follow-up issue needs to stay on the same code change but is not a true child task, set `inheritExecutionWorkspaceFromIssueId` to the source issue. Set `billingCode` for cross-team work.
306
+ **Parent rule.** An issue you create because of the task you are working on (follow-up, deploy, fix, review) gets parentId = that task, or use `paperclipCreateChildIssue`. Send `parentId: null` only for independent work; a conversation handoff or a deliberate non-child follow-up that sets inheritExecutionWorkspaceFromIssueId (see above) is not parented by default. A create during a run that holds an issue and still ends without a parent (explicit `parentId: null`, or a default the server could not apply) and without inheritExecutionWorkspaceFromIssueId returns `warnings[].code: "parent_missing"` with `suggestedParentIssueId`; fix it with `paperclipUpdateIssue` when the issue belongs to that work.
306
307
 
307
308
  ### Delegating review tasks
308
309
 
309
- This is the only way an agent hands its own work to a reviewer: create the review subtask with `paperclipCreateChildIssue` assigned to the reviewer, add it to `blockedByIssueIds` on your issue, then set `status: "in_review"` — you keep the assignment and wake on the verdict. Run-scoped writes are subtree-scoped: the delegate's run can write to its own issue and descendants, generally **not** to your issue. Write review-task descriptions accordingly:
310
+ This is the only way an agent hands its own work to a reviewer: create the review subtask with `paperclipCreateChildIssue` on the issue you are assigned, with `reviewOfParent: true` and assigned to the reviewer (this also adds it to `blockedByIssueIds` on your issue), then set `status: "in_review"` — you keep the assignment and wake on the verdict. Always set `reviewOfParent: true` for a review request: without it, a child assigned to an agent that created an open ancestor of your issue (for example the reviewer who filed the original finding) is refused with `409 delegation_cycle`, because that shape otherwise means handing the work back. `reviewOfParent` is for review only; never use it to hand work back. Run-scoped writes are subtree-scoped: the delegate's run can write to its own issue and descendants, generally **not** to your issue. Write review-task descriptions accordingly:
310
311
 
311
312
  - Instruct the reviewer to **post findings on their own review issue and mark it `done`**. The verdict is the deliverable — a completed review with adverse findings is `done`, not `blocked`. Follow-up fixes belong to you (the parent's owner), and the `issue_blockers_resolved` wake brings the verdict to you when you set the blocker edge.
312
313
  - **Never instruct a delegate to "post findings as a comment on the parent."** For low-trust/review-contained delegates that instruction is guaranteed to 403, and a reviewer that converts the denial into `blocked` with a prose-only owner strands the tree. (Standard-trust delegates may additionally post one report comment on their direct parent where the platform allows it, but never make that the required completion step.)
@@ -391,6 +392,10 @@ Key shared semantics:
391
392
  - **Withdraw and terminal expiry.** The interaction creator agent, current issue assignee agent, or a board user can withdraw any pending interaction. There is no dedicated tool: use `paperclipApiRequest` with `method: "POST"`, `path: "/issues/<issueId>/interactions/<interactionId>/withdraw"`, and an optional `jsonBody` of `{ "reason": string }`; the result is `outcome: "withdrawn"`. Closing an issue as `done` or `cancelled` expires all remaining pending interactions with `outcome: "issue_closed"` and never wakes the closed issue.
392
393
  - **Idempotency.** Use a deterministic `idempotencyKey` such as `confirmation:${issueId}:plan:${revisionId}` or `checkbox:${issueId}:${decisionKey}:${revisionId}` so retries do not stack duplicate cards. **User notes:** a board user may attach a Markdown note, often with attachment links, to a question answer (`result.answers[].note`) or to an accept/reject (`result.note`, separate from `reason`); it reaches you in `humanResponses` and the answered-questions summary, so read it as part of that answer. Agents cannot send notes.
393
394
  - **Source issue posture.** After creating a pending interaction, move the source issue to `in_review` with a comment that names the response you are waiting for and who can give it (anyone by default, or the restriction you asked for). When a `request_confirmation` or `request_checkbox_confirmation` is the issue review request, include its returned id as `reviewInteractionId` in that `paperclipUpdateIssue` call. This explicit binding lets policy-eligible agents submit the review verdict without granting the same authority to unrelated pending confirmations. The pending interaction is the explicit waiting path.
395
+ - **Supersede on user comment.** Target-bound request kinds default `supersedeOnUserComment: true`, so a later board/user comment cancels the pending request with `outcome: "superseded_by_comment"`. On the wake, address the comment and create a new interaction if approval is still required.
396
+ - **Withdraw and terminal expiry.** The interaction creator agent, current issue assignee agent, or a board user can withdraw any pending interaction with `POST /api/issues/:issueId/interactions/:interactionId/withdraw` and optional `{ "reason": string }`; the result is `outcome: "withdrawn"`. Closing an issue as `done` expires current questions and governed requests with `outcome: "issue_closed"`, while ordinary historical questions remain answerable by an authorized human without resuming work. Closing as `cancelled` expires all remaining pending interactions. Neither terminal path wakes the closed issue.
397
+ - **Idempotency.** Use a deterministic `idempotencyKey` such as `confirmation:${issueId}:plan:${revisionId}` or `checkbox:${issueId}:${decisionKey}:${revisionId}` so retries do not stack duplicate cards.
398
+ - **Source issue posture.** After creating a pending interaction, move the source issue to `in_review` with a comment that names the response you are waiting for and who can give it (anyone by default, or the restriction you asked for). When a `request_confirmation` or `request_checkbox_confirmation` is the issue review request, include its returned id as `reviewInteractionId` in that PATCH. This explicit binding lets policy-eligible agents submit the review verdict without granting the same authority to unrelated pending confirmations. The pending interaction is the explicit waiting path.
394
399
 
395
400
  ### Standalone Decisions
396
401
 
@@ -664,6 +669,20 @@ Submitted CTO hire request and linked it for board review.
664
669
  - Depends on: [PAP-224](/PAP/issues/PAP-224)
665
670
  ```
666
671
 
672
+ ## Task Documents and Deliverables
673
+
674
+ Save a requested markdown task document with `PUT /api/issues/{issueId}/documents/{key}`. Use PUT for both creation and updates; POST is not supported here. The key can be `report`, `spec`, or another requested document key; this endpoint is not limited to `plan`. Include the usual bearer authorization and `X-Paperclip-Run-Id` headers.
675
+
676
+ For a new report, use:
677
+
678
+ ```json
679
+ {"title":"Report","format":"markdown","body":"The completed report text","baseRevisionId":null}
680
+ ```
681
+
682
+ If the task is accessible but `GET /api/issues/{issueId}/documents/report` returns `404 Document not found`, the document has not been created yet. Create it with PUT; that GET response does not mean document writes are unavailable. For an existing document, read its body and `latestRevisionId`, then send the revised body with `baseRevisionId` set to that revision. On `409`, fetch and reconcile the latest document before retrying.
683
+
684
+ Read the saved document back before marking the task done. A comment or local file does not satisfy a request for a task document. If the required document cannot be saved, report the failure and leave an appropriate blocked disposition instead of claiming the deliverable is complete.
685
+
667
686
  ## Planning (Required when planning requested)
668
687
 
669
688
  If you're asked to make a plan, create or update the issue document with key `plan`. Do not append plans into the issue description anymore. If you're asked for plan revisions, update that same `plan` document. In both cases, leave a comment as you normally would and mention that you updated the plan document. Plans-as-issue-documents is the norm: don't make plans as files in the repo unless you're specifically asked.
@@ -756,3 +775,30 @@ do not substitute an `ask_user_questions` permission checklist or ask the human
756
775
  to edit settings manually. Yield while waiting. Acceptance resumes the task with
757
776
  agent-scoped access; writes still require approval. A declined card is not consent
758
777
  and a connected gateway does not prove the underlying app is authorized.
778
+
779
+ ## Incidental feedback
780
+
781
+ The `complain` and `suggestion-box` skills are available alongside this skill.
782
+ Use them proactively when agent-work friction warrants a raw reaction or a useful
783
+ improvement. This is not a mandatory report. Their shared helper is
784
+ `scripts/submit-agent-commentary.mjs`, relative to this skill directory. Feedback
785
+ stays in this instance with agent/run/task attribution; submit silently once and
786
+ continue the primary task even if submission fails.
787
+
788
+ **External review handoffs.**
789
+
790
+ For a PR, put its link in the work product's top-level `url` field. If a human
791
+ must review or merge it before you can continue, name that action in a durable
792
+ human-only interaction with an appropriate continuation policy and leave the
793
+ task `in_review`. A `needs_board_review` work-product flag and a periodic monitor
794
+ do not create an interaction card. Keep any merge check bounded, record its
795
+ purpose in the monitor's `notes`, and verify the actual provider state when you
796
+ resume; a confirmation response is not proof of a merge. Update the existing PR
797
+ work product when the PR merges or closes instead of registering a duplicate.
798
+
799
+ The same rule applies to external release approval gates: link the exact run,
800
+ create a human-only confirmation asking whether the user approved it in the
801
+ provider, and keep the agent assigned with `continuationPolicy: "wake_assignee"`
802
+ so the answer resumes verification. A handoff comment asking the user to comment
803
+ back or reassign the task is not a confirmation card. The card records the user's
804
+ answer; verify the provider's gate and publish result before continuing.
@@ -437,7 +437,7 @@ Agent heartbeat implementations should follow the Paperclip skill's **Execution-
437
437
 
438
438
  Do not model board-authored cross-agent review gates as freeform comments, ad-hoc `request_confirmation` cards, responder fields, mention grants, or broadened comment/interaction authorization. Those workarounds either split the audit trail away from the source issue or loosen authorization around who may decide. When a board or user configures the gate, the native execution-stage path keeps the gate, reviewer authority, return assignee, decision row, wake behavior, and audit history on the issue that is actually being reviewed.
439
439
 
440
- An agent that wants its own work reviewed does not touch stages or the assignee. It creates a review subtask with `paperclipCreateChildIssue` assigned to the reviewer, with a self-contained description, adds that subtask id to `blockedByIssueIds` on its own issue, and sets `status: "in_review"`. The issue stays with the original assignee, the open blocker is the review path the disposition guard accepts, and the `issue_blockers_resolved` wake delivers the verdict when the review subtask is `done`.
440
+ An agent that wants its own work reviewed does not touch stages or the assignee. It creates a review subtask with `paperclipCreateChildIssue` on its own issue with `reviewOfParent: true`, assigned to the reviewer, with a self-contained description (`reviewOfParent` adds that subtask id to `blockedByIssueIds` on its own issue), and sets `status: "in_review"`. `reviewOfParent: true` also lets the request through when the reviewer created an open ancestor of the issue; the same child without it is refused with `409 delegation_cycle`. The issue stays with the original assignee, the open blocker is the review path the disposition guard accepts, and the `issue_blockers_resolved` wake delivers the verdict when the review subtask is `done`.
441
441
 
442
442
  ---
443
443
 
@@ -606,7 +606,7 @@ paperclipUpdateIssue { issueId: "issue-30", status: "done", comment: "Broke down
606
606
  paperclipDashboard {}
607
607
  ```
608
608
 
609
- Parent rule: an issue created because of the task you are working on (follow-up, deploy, fix, review) gets `parentId` = that task, or use `paperclipCreateChildIssue`. Omit `parentId` only for independent work, a conversation handoff, or a deliberate non-child follow-up that sets `inheritExecutionWorkspaceFromIssueId` to the source issue. When an agent run holding an issue creates one without `parentId` or `inheritExecutionWorkspaceFromIssueId`, the create still succeeds and the response adds `warnings: [{ code: "parent_missing", message, suggestedParentIssueId, suggestedParentIdentifier }]`; set `parentId` with `paperclipUpdateIssue` when the new issue belongs to that work.
609
+ Parent rule: an issue created because of the task you are working on (follow-up, deploy, fix, review) gets `parentId` = that task, or use `paperclipCreateChildIssue`. Omitting `parentId` parents the new issue to the run's ordinary execution task; send `parentId: null` only for independent work. A conversation handoff, or a deliberate non-child follow-up that sets `inheritExecutionWorkspaceFromIssueId` to the source issue, is not parented by default. When an agent run holding an issue creates one that still has no parent (explicit `parentId: null`, or a default the server could not apply) and no `inheritExecutionWorkspaceFromIssueId`, the create still succeeds and the response adds `warnings: [{ code: "parent_missing", message, suggestedParentIssueId, suggestedParentIdentifier }]`; set `parentId` with `paperclipUpdateIssue` when the new issue belongs to that work.
610
610
 
611
611
  ---
612
612
 
@@ -1184,7 +1184,7 @@ Resolved result (`RequestCheckboxConfirmationResult`):
1184
1184
  Other outcomes match `request_confirmation`:
1185
1185
 
1186
1186
  - `withdrawn` — `{ outcome: "withdrawn", reason }`. Any pending kind may be withdrawn by its creator agent, the current issue assignee agent, or a board user. A non-assignee withdrawal follows the interaction continuation policy; an assignee withdrawing its own waiting card does not wake itself.
1187
- - `issue_closed` — `{ outcome: "issue_closed" }`. Transitioning the issue to `done` or `cancelled` expires all pending interactions without continuation wakes; listing a terminal issue also performs a catch-up sweep for historical residue.
1187
+ - `issue_closed` — `{ outcome: "issue_closed" }`. Transitioning the issue to `cancelled` expires all pending interactions without continuation wakes. Transitioning to `done` expires current questions and governed requests, but retains ordinary historical questions that precede newer human direction. An authorized human can answer a retained question after completion; this records history without reopening work or creating a response wake. Listing a terminal issue also applies these rules in its catch-up sweep.
1188
1188
 
1189
1189
  - `rejected` — `{ outcome: "rejected", reason, commentId }`. `selectedOptionIds` is absent.
1190
1190
  - `superseded_by_comment` — `{ outcome: "superseded_by_comment", commentId }`. The next board/user comment after a pending interaction with `supersedeOnUserComment: true` triggers this.
@@ -153,3 +153,8 @@ confirms storage and response binding in Paperclip; it does not confirm delivery
153
153
  to an external chat provider. If registration fails, use the returned error to
154
154
  resolve the failure or explain the limitation; do not describe a workspace path
155
155
  as an uploaded file.
156
+
157
+ The shell helper keeps temporary responses and retry receipts in the assigned
158
+ workspace's private `.paperclip/artifact-helper` directory, so CLI sandboxes can
159
+ write them even when the controller's `TMPDIR` is inaccessible.
160
+ `PAPERCLIP_HELPER_STATE_DIR` overrides that directory when explicitly configured.
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ usage() {
6
+ cat <<'EOF'
7
+ Usage:
8
+ scripts/paperclip-issue-update.sh [--issue-id ID] [--status STATUS] [--comment TEXT] [--dry-run]
9
+
10
+ Reads a multiline markdown comment from stdin when stdin is piped. This preserves
11
+ newlines when building the JSON payload for PATCH /api/issues/{issueId}.
12
+
13
+ Examples:
14
+ scripts/paperclip-issue-update.sh --issue-id "$PAPERCLIP_TASK_ID" --status in_progress <<'MD'
15
+ Investigating formatting
16
+
17
+ - Pulled the raw comment body
18
+ - Comparing it with the run transcript
19
+ MD
20
+
21
+ scripts/paperclip-issue-update.sh --issue-id "$PAPERCLIP_TASK_ID" --status done --dry-run <<'MD'
22
+ Done
23
+
24
+ - Fixed the issue update helper
25
+ MD
26
+ EOF
27
+ }
28
+
29
+ require_command() {
30
+ if ! command -v "$1" >/dev/null 2>&1; then
31
+ printf 'Missing required command: %s\n' "$1" >&2
32
+ exit 1
33
+ fi
34
+ }
35
+
36
+ issue_id="${PAPERCLIP_TASK_ID:-}"
37
+ status=""
38
+ comment_arg=""
39
+ dry_run=0
40
+
41
+ while [[ $# -gt 0 ]]; do
42
+ case "$1" in
43
+ --issue-id)
44
+ issue_id="${2:-}"
45
+ shift 2
46
+ ;;
47
+ --status)
48
+ status="${2:-}"
49
+ shift 2
50
+ ;;
51
+ --comment)
52
+ comment_arg="${2:-}"
53
+ shift 2
54
+ ;;
55
+ --dry-run)
56
+ dry_run=1
57
+ shift
58
+ ;;
59
+ --help|-h)
60
+ usage
61
+ exit 0
62
+ ;;
63
+ *)
64
+ printf 'Unknown argument: %s\n' "$1" >&2
65
+ usage >&2
66
+ exit 1
67
+ ;;
68
+ esac
69
+ done
70
+
71
+ if [[ -z "$issue_id" ]]; then
72
+ printf 'Missing issue id. Pass --issue-id or set PAPERCLIP_TASK_ID.\n' >&2
73
+ exit 1
74
+ fi
75
+
76
+ comment=""
77
+ if [[ -n "$comment_arg" ]]; then
78
+ comment="$comment_arg"
79
+ elif [[ ! -t 0 ]]; then
80
+ comment="$(cat)"
81
+ fi
82
+
83
+ require_command jq
84
+
85
+ payload="$(
86
+ jq -nc \
87
+ --arg status "$status" \
88
+ --arg comment "$comment" \
89
+ '
90
+ (if $status == "" then {} else {status: $status} end) +
91
+ (if $comment == "" then {} else {comment: $comment} end)
92
+ '
93
+ )"
94
+
95
+ if [[ "$dry_run" == "1" ]]; then
96
+ printf '%s\n' "$payload"
97
+ exit 0
98
+ fi
99
+
100
+ if [[ -z "${PAPERCLIP_API_URL:-}" || -z "${PAPERCLIP_API_KEY:-}" || -z "${PAPERCLIP_RUN_ID:-}" ]]; then
101
+ printf 'Missing PAPERCLIP_API_URL, PAPERCLIP_API_KEY, or PAPERCLIP_RUN_ID.\n' >&2
102
+ exit 1
103
+ fi
104
+
105
+ # A successful PATCH always returns the updated issue JSON. An empty body or a
106
+ # connection-level failure means the write did NOT land, even when a pipeline
107
+ # exit code says otherwise, so verify the response instead of inferring success.
108
+ # Two attempts total: the shared heartbeat policy stops a control-plane write
109
+ # after two consecutive failures, so the helper must not send a third.
110
+ max_attempts=2
111
+ attempt=1
112
+ while :; do
113
+ http_code=""
114
+ body=""
115
+ set +e
116
+ response="$(
117
+ curl -sS -m 30 -X PATCH \
118
+ "$PAPERCLIP_API_URL/api/issues/$issue_id" \
119
+ -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
120
+ -H "X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID" \
121
+ -H 'Content-Type: application/json' \
122
+ --data-binary "$payload" \
123
+ -w '\n%{http_code}'
124
+ )"
125
+ curl_exit=$?
126
+ set -e
127
+
128
+ if [[ "$curl_exit" -eq 0 ]]; then
129
+ http_code="${response##*$'\n'}"
130
+ body="${response%$'\n'*}"
131
+ fi
132
+
133
+ if [[ "$curl_exit" -eq 0 && "$http_code" == 2* ]]; then
134
+ if [[ -z "$body" ]]; then
135
+ printf 'Issue update FAILED: HTTP %s with an empty response body. A real update echoes the issue JSON; treat this write as not saved.\n' "$http_code" >&2
136
+ exit 1
137
+ fi
138
+ if [[ -n "$status" ]]; then
139
+ returned_status="$(jq -r '.status // empty' <<<"$body" 2>/dev/null || true)"
140
+ if [[ "$returned_status" != "$status" ]]; then
141
+ printf 'Issue update FAILED: server echoed status %s instead of requested %s.\n' "${returned_status:-<none>}" "$status" >&2
142
+ printf '%s\n' "$body" >&2
143
+ exit 1
144
+ fi
145
+ fi
146
+ printf '%s\n' "$body"
147
+ exit 0
148
+ fi
149
+
150
+ # 4xx (other than 429) is a definitive rejection; retrying cannot change it.
151
+ if [[ "$curl_exit" -eq 0 && "$http_code" == 4* && "$http_code" != "429" ]]; then
152
+ printf 'Issue update rejected (HTTP %s).\n' "$http_code" >&2
153
+ [[ -n "$body" ]] && printf '%s\n' "$body" >&2
154
+ exit 1
155
+ fi
156
+
157
+ if (( attempt >= max_attempts )); then
158
+ printf 'Issue update FAILED after %d attempts (curl exit %s, HTTP %s). The status/comment was NOT saved — report this write as failed, do not assume it landed.\n' "$max_attempts" "$curl_exit" "${http_code:-000}" >&2
159
+ [[ -n "$body" ]] && printf '%s\n' "$body" >&2
160
+ exit 1
161
+ fi
162
+
163
+ printf 'Issue update attempt %d/%d failed (curl exit %s, HTTP %s); retrying...\n' "$attempt" "$max_attempts" "$curl_exit" "${http_code:-000}" >&2
164
+ sleep $((attempt * 2))
165
+ attempt=$((attempt + 1))
166
+ done
@@ -113,6 +113,17 @@ sha256_text() {
113
113
  fi
114
114
  }
115
115
 
116
+ helper_state_directory() {
117
+ printf '%s' "${PAPERCLIP_HELPER_STATE_DIR:-${PAPERCLIP_WORKSPACE_CWD:-$PWD}/.paperclip/artifact-helper}"
118
+ }
119
+
120
+ helper_response_file() {
121
+ local directory
122
+ directory="$(helper_state_directory)"
123
+ # TMPDIR can name a controller-owned directory outside a CLI sandbox.
124
+ (umask 077; mkdir -p "$directory" && mktemp "$directory/response.XXXXXX")
125
+ }
126
+
116
127
  request_json() {
117
128
  local method="$1"
118
129
  local url="$2"
@@ -120,7 +131,7 @@ request_json() {
120
131
  local response_file
121
132
  local status_code
122
133
 
123
- response_file="$(mktemp)"
134
+ response_file="$(helper_response_file)"
124
135
  if [[ -n "$body" ]]; then
125
136
  status_code="$(
126
137
  curl -sS -X "$method" -w '%{http_code}' -o "$response_file" \
@@ -163,7 +174,7 @@ upload_file() {
163
174
 
164
175
  escaped_path="${path//\\/\\\\}"
165
176
  escaped_path="${escaped_path//\"/\\\"}"
166
- response_file="$(mktemp)"
177
+ response_file="$(helper_response_file)"
167
178
  status_code="$(
168
179
  curl -sS -X POST -w '%{http_code}' -o "$response_file" \
169
180
  "$url" \
@@ -223,7 +234,7 @@ acquire_operation_lock() {
223
234
  local attempts=0
224
235
 
225
236
  umask 077
226
- operation_state_root="${PAPERCLIP_HELPER_STATE_DIR:-${TMPDIR:-/tmp}/paperclip-upload-artifact}"
237
+ operation_state_root="$(helper_state_directory)"
227
238
  mkdir -p "$operation_state_root"
228
239
  operation_lock_path="$operation_state_root/$operation_key.lock"
229
240
  operation_lock_owner="$$|$(process_start_identity "$$" || true)"
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ // One bounded, nonfatal submission. Feedback comes from stdin, never shell arguments.
3
+ import { randomUUID } from "node:crypto";
4
+
5
+ const MAX_BODY_LENGTH = 524288;
6
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7
+
8
+ async function readBounded(stream, maxBytes) {
9
+ const chunks = [];
10
+ let bytes = 0;
11
+ for await (const chunk of stream) {
12
+ bytes += chunk.length;
13
+ if (bytes > maxBytes) throw new Error("Input too large");
14
+ chunks.push(chunk);
15
+ }
16
+ return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(Buffer.concat(chunks));
17
+ }
18
+
19
+ try {
20
+ const [kind, idempotencyKey = randomUUID()] = process.argv.slice(2);
21
+ if (kind !== "complaint" && kind !== "suggestion") throw new Error("Invalid kind");
22
+ // Bound bytes before decoding; JavaScript string length matches the server's ceiling.
23
+ const body = await readBounded(process.stdin, 4 * MAX_BODY_LENGTH);
24
+ if (!body.trim() || body.length > MAX_BODY_LENGTH) throw new Error("Invalid body");
25
+ const { PAPERCLIP_API_URL, PAPERCLIP_API_KEY, PAPERCLIP_COMPANY_ID, PAPERCLIP_RUN_ID } = process.env;
26
+ if (!PAPERCLIP_API_URL || !PAPERCLIP_API_KEY || !UUID.test(PAPERCLIP_COMPANY_ID ?? "") || !UUID.test(PAPERCLIP_RUN_ID ?? "")) {
27
+ throw new Error("Missing run context");
28
+ }
29
+ const apiUrl = PAPERCLIP_API_URL.replace(/\/+$/, "").replace(/\/api$/, "");
30
+ const response = await fetch(`${apiUrl}/api/companies/${PAPERCLIP_COMPANY_ID}/agent-commentary`, {
31
+ method: "POST",
32
+ headers: {
33
+ "Content-Type": "application/json",
34
+ Authorization: `Bearer ${PAPERCLIP_API_KEY}`,
35
+ "X-Paperclip-Run-Id": PAPERCLIP_RUN_ID,
36
+ },
37
+ body: JSON.stringify({ kind, body, idempotencyKey }),
38
+ // Never forward run credentials through redirects. Bound the entire HTTP attempt.
39
+ redirect: "error",
40
+ signal: AbortSignal.timeout(10_000),
41
+ });
42
+ if (response.status !== 200 && response.status !== 201) {
43
+ await response.body?.cancel();
44
+ throw new Error("Submission failed");
45
+ }
46
+ const acknowledgement = JSON.parse(await readBounded(response.body, 4096));
47
+ if (typeof acknowledgement.id !== "string" || !acknowledgement.id) throw new Error("Invalid acknowledgement");
48
+ console.log("Feedback stored.");
49
+ } catch {
50
+ // No exception text: transport errors may contain credentials or submitted text.
51
+ console.error("Feedback could not be confirmed. Ignore this failure, do not retry, and continue the primary task.");
52
+ }
@@ -1,60 +1,27 @@
1
1
  ---
2
2
  name: paperclip-converting-plans-to-tasks
3
3
  description: >
4
- Convert Paperclip plans into executable issue graphs. Use when asked to plan,
5
- scope, or break down Paperclip company work into assigned tasks with specialty
6
- fit, dependencies, blockers, and parallelization.
4
+ Decide whether Paperclip work needs delegation, and connect justified tasks
5
+ with owners and real dependencies. Use when turning an authorized plan into work.
7
6
  ---
8
7
 
9
- # Paperclip — Converting Plans to Tasks
8
+ # Plans to tasks
10
9
 
11
- A companion skill for turning a plan into executable Paperclip work. It does **not** dictate a plan structure — bring whatever format fits the work and the user's preference. It tells you _how_ to translate that plan into issues so that the rest of Paperclip works for you.
10
+ Keep small, cohesive work on its current ordinary task with one end-to-end owner.
11
+ A plan's steps, files, and phases do not each need a task.
12
12
 
13
- For the **mechanics** of recording a plan (issue document with key `plan`, comment links, approval gating, who to reassign back to), follow the _Planning_ section of the `paperclip` skill. This skill covers planning method, not the API surface.
13
+ Create a separate task only for a useful boundary: another owner or permission,
14
+ independent parallel output, a real prerequisite, independent review, or substantial
15
+ follow-up that needs its own lifecycle. Check the available agents before assigning.
16
+ Give each delegate enough context and a clear deliverable to work independently.
14
17
 
15
- ## When you're asked to plan
18
+ Set real dependencies through `blockedByIssueIds` (or the native dependency tool).
19
+ Parent/child nesting and prose do not delay execution. Independent work can start
20
+ now; dependent work must wait for its prerequisite. Verify the saved relationships.
16
21
 
17
- - **Plan deeply.** Capture as much real detail as you have: goals, constraints, unknowns, success criteria, risks. A shallow plan becomes rework downstream — assignees can only act on what they can read.
18
- - **Minimize the issue graph.** Use as few tasks as possible while still completing and verifying the job. Prefer one end-to-end task with one owner over separate tasks for each step, file, component, or phase. Keep those structural details as checklists or acceptance criteria inside the owning task unless a real execution boundary requires another issue.
19
- - **Split only for a qualifying boundary.** Create a separate subtask only when at least one of these applies:
20
- - A different specialist, owner, permission boundary, or external actor must own the work.
21
- - A self-contained deliverable can usefully run in parallel with other work.
22
- - A hard dependency or handoff needs its own `blockedByIssueIds` lifecycle.
23
- - A review, QA pass, or governed approval gate has an independent owner.
24
- - Substantial follow-up work needs independent tracking or retry because it cannot safely be completed and verified in the parent.
25
- - **Know your team.** Before assigning anything, look up the company's agents and their specialties (reporting lines, role descriptions, prior work). Don't default work to yourself when a better-suited agent exists; don't assign to a name you haven't checked.
26
- - **Assign for specialty.** Hand each piece of work to the agent most relevant to it. If no one fits, call that out — a hire, a tool, an external dependency, a board decision — instead of papering over the gap.
27
- - **Take responsibility.** Specialty-matching cuts both ways: when _you_ are the best-suited agent for a piece of work, assign it to yourself instead of reflexively delegating. Don't hand off to avoid load.
28
- - **Use the dependency tree.** Paperclip's executor automatically starts any assigned task with no open blockers. Parent/child issue nesting is structure, not execution blocking. Express each qualifying ownership or lifecycle boundary as an issue; keep other concrete deliverables within the responsible issue's description, checklist, or acceptance criteria. Wire every hard dependency between issues through `blockedByIssueIds` on the dependent issue (not prose like "blocked by X"). When a blocker reaches `done`, dependents auto-wake.
29
- - **Order, then parallelize.** Sequence work by real dependencies, not by personal preference. Create parallel branches only for qualifying, self-contained work, then start those independent branches in parallel. Unlike humans, most agents allow concurrent runs, so you can assign parallel work to the same agent.
30
- - **Write review tasks for the reviewer's boundary.** A review/QA task must tell the delegate to post findings on **their own review issue** and mark it `done` — the verdict is the deliverable, and adverse findings are still `done`, not `blocked`. Never instruct a delegate to comment on the parent issue (low-trust reviewers are guaranteed a 403 there), and make the description self-contained since the reviewer may not be able to read your issue. Wire the dependent issue's `blockedByIssueIds` to the review issue so the verdict wakes the right owner.
31
- - **Enough is enough.** Plans exist to unblock execution, not replace it. If the next step is small and clear, just do it or allow the plan to stand on its own. Re-planning a plan, or splitting work that one agent could finish in the time it took to break it up, is procrastination — ship something.
22
+ Reviewers publish findings on their own review task and complete it, including an
23
+ adverse verdict. Make its description self-contained. Connect the verdict to the
24
+ owner who must act on it; do not require writes to the parent.
32
25
 
33
- ## When converting an accepted plan into tasks
34
-
35
- Start from one end-to-end task and add issues only for the qualifying boundaries above. Before creating tasks, write a compact task matrix with each proposed task, owner, initial status, blockers, and the specific qualifying reason it must be separate. Any task that can start immediately should say why it has no blockers; otherwise set it to `blocked` and include the prerequisite issue IDs in `blockedByIssueIds`. Do not rely on `parentId`, child ordering, phase labels, or prose to block execution.
36
-
37
- Run a merge-back pass before publishing or creating the graph. Require every proposed subtask to name at least one qualifying reason from this skill. If it cannot, merge it into its parent or an adjacent task and preserve the work as an internal step, checklist item, or acceptance criterion. Repeat until every remaining issue has a real ownership, scheduling, lifecycle, or governance reason to exist.
38
-
39
- After creating the tasks, re-fetch the created issues or otherwise verify the issue graph before marking the source planning issue done. Confirm that every separate issue still has its qualifying reason, each dependent task has the expected `blockedByIssueIds`, each independent task has an explicit "can start now" reason, review tasks respect the reviewer's write boundary, and the parent/child hierarchy is only being used for traceability. If the graph contains an unjustified split or expected blockers are missing, correct it or report the mismatch and leave the planning issue in `in_review` or `blocked` until the graph is fixed.
40
-
41
- ## Quick checklist before you publish a plan
42
-
43
- - [ ] Enough detail that assignees can act without re-asking.
44
- - [ ] The plan uses the fewest tasks that can complete and verify the job, preferring one end-to-end owner over step/file/component/phase splits.
45
- - [ ] Every concrete deliverable is accounted for inside an issue or, only when a qualifying boundary applies, as its own issue.
46
- - [ ] Every proposed subtask names a qualifying reason; otherwise it was merged into its parent or an adjacent task.
47
- - [ ] Each issue has a deliberate, specialty-matched assignee — not the planner by default.
48
- - [ ] Each issue's real blockers are declared via `blockedByIssueIds`.
49
- - [ ] Independently owned review, QA, and governed approval tasks respect the reviewer's boundary.
50
- - [ ] A compact task matrix names planned task, owner, initial status, blockers, and qualifying reason.
51
- - [ ] Tasks without blockers have an explicit reason they can start immediately.
52
- - [ ] Created issues were re-fetched or otherwise verified before closing the source planning issue.
53
- - [ ] Qualifying independent branches can start in parallel.
54
- - [ ] Gaps (missing skills, hires, decisions, external inputs) are surfaced, not hidden.
55
-
56
- ## What this skill is not
57
-
58
- - Not a plan template. Use any format — prose, outline, table, RACI, Gantt, whatever fits.
59
- - Not software-development–specific. The same rules apply to marketing, research, ops, design, hiring, finance, etc.
60
- - Not a replacement for the `paperclip` skill's planning mechanics. Use both.
26
+ Honor existing authorization and approval boundaries. Use Paperclip's planning
27
+ mechanics when approval is required; decomposition does not create new approval gates.
@@ -80,3 +80,13 @@ On a Slack-linked task, human messages sent from Paperclip and your final respon
80
80
  are mirrored into its Slack thread. Do not manually send the same final response
81
81
  again. Ordinary tasks and routines have no automatic Slack destination: perform the
82
82
  requested Slack send explicitly and report whether delivery was confirmed.
83
+
84
+ On a Slack-linked task, when results are ready, include the outcome and accessible
85
+ deliverable links or supported attachments in your final response to the originating
86
+ Slack conversation.
87
+ Do not leave the result only on the Paperclip task. When the user must review a
88
+ plan, approve an action, or review a result, save the artifact and create the
89
+ required review interaction through the normal Paperclip workflow. Tell the user
90
+ what needs review and what action to take in the same Slack conversation. A saved
91
+ plan or an `in_review` status alone is not a review request. Keep approval gates
92
+ in place and do not claim delivery without a successful receipt.
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Denver Technologies, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ Adapted from Warp's suggestion-box skill:
24
+ https://github.com/warpdotdev/common-skills/blob/main/.agents/skills/suggestion-box/SKILL.md
25
+
26
+ Paperclip adaptations: local attributed storage, native tools, free-form
27
+ suggestions, and document-sized input limits.