mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-11 05:11:49 +01:00
fix: stop prompts from encouraging subtasks (#20362)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents read runtime prompts, tool help, skills, and role instructions. > - Several of these texts tell agents to create child tasks as a normal next step. > - One accepted-plan prompt even forbids work on the current task. > - Task parentage is useful, but it does not need a prompt that encourages task creation. > - This pull request removes those prompts and keeps the task APIs available. ## Linked Issues or Issue Description Refs #10642. This change adjusts prompt wording; it does not add delegation-cycle guards. **Current behavior** Prompts tell agents to create children after plan approval, use children for long work, and create a task just to pass context. Onboarding requires a child even for a single request. **Proposed behavior** Continue work on the current task. Keep explicit assignments, optional task creation, parentage, dependencies, and approval gates. Use the separate-task recipes when the user requests that structure or when continuing existing work. **Reason and benefit** Reduce needless task trees without removing subtask support. Keep the patch limited to wording, existing test expectations, and generated catalog data. ## What Changed - Align accepted-plan prompts and remove direct child-creation advice from runtime and error text. - Make task tool descriptions neutral. Keep their fields, defaults, and handlers. - Update the main skill, onboarding, CEO instructions, company templates, specialist workflows, and matching guides. - Keep historical release snapshots intact. Refresh the explicitly seeded schema fixture's catalog digest; the server still verifies historical release snapshot hashes. - Refresh the affected generated catalogs, capability inventory, semantic contracts, and fixture manifest. ## Verification - Final tested head: `c6e304d0c105cdbfbe0b2ab0a233307fcd91a04b`. - All 66 check runs are complete: 60 pass, one is neutral, and five are skipped by CI conditions. Snyk also passes. No checks fail or remain pending. - [PR CI](https://github.com/paperclipai/paperclip/actions/runs/42846226554) passes typecheck, build, server/general tests, all eight E2E shards, Runner support, Runner Rust, and the aggregate verify gate. [Windows](https://github.com/paperclipai/paperclip/actions/runs/42846226546) and [Docker Runner](https://github.com/paperclipai/paperclip/actions/runs/42846226108) also pass. - [Greptile](https://github.com/paperclipai/paperclip/pull/20362#issuecomment-6751419835) and [Paperclip review](https://github.com/paperclipai/paperclip/pull/20362#issuecomment-6751454010) give this exact head 5/5. All six inline threads are resolved. Neither current summary has findings. - Merged master `bf0220d34a156c81853755c3d1365ddc527037de`. Resolved three generated-file conflicts with the canonical generators. - Local verification passes: 473 focused prompt, continuation, UI, catalog, runtime and native-execution tests; Runner TypeScript build; generated metadata; UI token gates; and diff checks. - The prior head `c22018cb0f` failed three SDK evidence tests because two source hashes were stale. Reproduced all three failures locally. The existing generator refreshed only the hashes for the denial-copy file and its test. All 53 affected evidence/source-pin tests then passed, including private-value rejection. No scanner logic, assertions, or runtime dependency pins changed. Current CI confirms the support suite passes. - A prior commit failed the Rust process reaping test. Its cause remains unproven. No Rust code or assertions changed. Later Rust runs pass; this does not establish the cause of the earlier failure. - Local preflight built shared/plugin SDK packages, then stopped because `cargo` is absent. Current-head CI supplies Rust and full build coverage. `pnpm verify --explain` selects broad required CI; full local suites were not repeated. ## Risks - Wording changes guide the model; they do not enforce a ban on subtasks. - Existing installed skill versions and saved custom instructions need their normal refresh process. This PR does not migrate company configuration. - Existing approved task assignments and approval gates remain in effect. ## Model Used - OpenAI GPT-6, through Codex, with reasoning, tool use, and code execution. The exact routed model ID and context-window size were not exposed in this session. ## 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>
This commit is contained in:
1 parent
79e28dc0d0
commit
ce1ee9e89f
56 files changed
+169
-172
No files matched your search
@@ -152,7 +152,7 @@ Add a concise execution contract to every generated working agent:
|
||||
|
||||
- Start actionable work in the same heartbeat and do not stop at a plan unless planning was requested.
|
||||
- Leave durable progress in comments, documents, or work products with the next action.
|
||||
- Use child issues for long or parallel delegated work instead of polling agents, sessions, or processes.
|
||||
- Continue work on the current issue. Do not busy-poll agents, sessions, or processes.
|
||||
- Mark blocked work with the unblock owner and action.
|
||||
- Respect budget, pause/cancel, approval gates, and company boundaries.
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ Execution contract:
|
||||
|
||||
- Start actionable implementation work in the same heartbeat; do not stop at a plan unless planning was requested.
|
||||
- Leave durable progress with a clear next action.
|
||||
- Use child issues for long or parallel delegated work instead of polling agents, sessions, or processes.
|
||||
- Continue work on the current issue. Do not busy-poll agents, sessions, or processes.
|
||||
- Mark blocked work with the unblock owner and action.
|
||||
```
|
||||
|
||||
|
||||
@@ -546,7 +546,7 @@ Import from `@paperclipai/adapter-utils/server-utils`:
|
||||
### Prompt Templates
|
||||
- Support `promptTemplate` for every run
|
||||
- Use `renderTemplate()` with the standard variable set
|
||||
- Default prompt should use `DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE` from `@paperclipai/adapter-utils/server-utils` so local adapters share Paperclip's execution contract: act in the same heartbeat, avoid planning-only exits unless requested, leave durable progress and a next action, use child issues instead of polling, mark blockers with owner/action, and respect governance boundaries.
|
||||
- Default prompt should use `DEFAULT_PAPERCLIP_AGENT_PROMPT_TEMPLATE` from `@paperclipai/adapter-utils/server-utils` so local adapters share Paperclip's execution contract: act in the same heartbeat, avoid planning-only exits unless requested, leave durable progress and a next action, avoid busy-polling, mark blockers with owner/action, and respect governance boundaries.
|
||||
|
||||
### Error Handling
|
||||
- Differentiate timeout vs process error vs parse failure
|
||||
|
||||
@@ -53,10 +53,8 @@ xc search '<topic keywords>' -n 30 # related discussion
|
||||
```
|
||||
|
||||
If `xc` is not on PATH, is unauthenticated, or the account lacks read access
|
||||
(the check above fails for any reason), delegate the
|
||||
fetch to a teammate with X/Twitter access (e.g. the Content Strategist agent)
|
||||
via a child issue: give them the URL and ask for full text of the post + thread
|
||||
+ any linked content.
|
||||
(the check above fails for any reason), use another authorized source or ask
|
||||
the user for the post, thread, and linked content. Report any unavailable context.
|
||||
|
||||
**Other sources.** Fetch linked articles/READMEs directly. Record the source
|
||||
URL — it goes in the skill body or PR description as attribution.
|
||||
|
||||
@@ -101,15 +101,15 @@ Every `needs_gardening` PR here was opened by this instance (Stage A guarantees
|
||||
|
||||
2. **Deduplicate.** Search open Paperclip issues for the PR number/branch. If an equivalent open prepare-PR task already exists, reuse it with a concise status comment instead of creating another (see the deduplication section above).
|
||||
|
||||
3. **Run the prepare skill.** Create one focused child task per PR assigned to a coder agent (prefer CodexCoder) instructing it to run `/prepare-paperclip-pr` for that PR — include the PR URL, branch, current head SHA, and the exact machine-detected `reasons[]` from `readiness.json`. If you are the gardener and already have the PR's branch checked out in a worktree, you may run `/prepare-paperclip-pr` directly instead of delegating. Either way, the prepare work must never merge, approve, or close the PR.
|
||||
3. **Run the prepare skill.** Run `/prepare-paperclip-pr` for each PR, using the PR URL, branch, current head SHA, and the exact machine-detected `reasons[]` from `readiness.json`. If the user requests delegation, include those inputs in the assigned task. The prepare work must never merge, approve, or close the PR.
|
||||
|
||||
4. **Leave the marker comment.** Comment on the originating issue with the marker above, the current head SHA, the copied `reasons[]`, the round counter, and a link to the prepare task. Use `POST /api/issues/:issueId/comments` with `X-Paperclip-Run-Id`. Include `resume: true` when the issue is terminal so the comment creates a live continuation.
|
||||
4. **Leave the marker comment.** Comment on the originating issue with the marker above, the current head SHA, the copied `reasons[]`, the round counter, and a link to the current task or recorded result. For delegated work, link the assigned prepare task instead. Use `POST /api/issues/:issueId/comments` with `X-Paperclip-Run-Id`. Include `resume: true` when the issue is terminal so the comment creates a live continuation.
|
||||
|
||||
Suggested body:
|
||||
|
||||
```markdown
|
||||
<!-- pr-gardening:paperclipai/paperclip#1234 -->
|
||||
Gardening: dispatched `/prepare-paperclip-pr` for https://github.com/paperclipai/paperclip/pull/1234 via PAP-XXXX.
|
||||
Gardening: ran `/prepare-paperclip-pr` for https://github.com/paperclipai/paperclip/pull/1234 on [this task](/PAP/issues/PAP-XXXX).
|
||||
|
||||
Current-head verification at `abc123` found:
|
||||
- failing check: test
|
||||
@@ -118,6 +118,8 @@ Current-head verification at `abc123` found:
|
||||
Gardening round 1/3. Re-verification is required after changes; do not merge based on this comment.
|
||||
```
|
||||
|
||||
For delegated work, say preparation was dispatched and link the assigned task.
|
||||
|
||||
## Stage D — Optional Inbox Tidy-Up
|
||||
|
||||
Run this stage only when the caller explicitly supplied `--archive-inbox`. `--dry-run` always suppresses inbox mutations, even when `--archive-inbox` is also present. Without the flag, do not archive anything.
|
||||
|
||||
@@ -10,7 +10,7 @@ description: >
|
||||
|
||||
A repeatable operating skill for driving one Terminal-Bench problem to a passing smoke through Paperclip, with explicit issue topology, bounded runs, board-gated product fixes, and worktree continuity.
|
||||
|
||||
This skill is **operational + diagnostic**, not engineering. It coordinates issues, artifacts, and approvals around a Terminal-Bench loop. It does not authorize code changes — every accepted product fix lands as a separate implementation child issue after a board confirmation.
|
||||
This skill is **operational + diagnostic**, not engineering. It coordinates issues, artifacts, and approvals around a Terminal-Bench loop. It does not authorize code changes — product fixes require a board confirmation before implementation.
|
||||
|
||||
Canonical execution model: read `doc/execution-semantics.md` before starting a loop or moving any loop issue. Every loop issue must rest in a state the doc allows: terminal (`done`/`cancelled`), explicitly live (active run / queued wake), explicitly waiting (`in_review` with participant/interaction/approval), or explicit recovery/blocker (`blocked` with `blockedByIssueIds` and a named owner).
|
||||
|
||||
@@ -49,7 +49,7 @@ Collect these on the top-level loop issue before iteration 1. Any input that can
|
||||
- **Source issue.** The Paperclip issue that asked for the loop. The loop parent links back to it.
|
||||
- **Terminal-Bench task name.** Single-task identifier (e.g. `terminal-bench/fix-git`). Multi-task suites are out of scope for this skill.
|
||||
- **Iteration budget.** Maximum number of iterations before the loop must stop without further fixes (typical: 3–5). Also record a per-iteration wall-clock cap.
|
||||
- **Paperclip App worktree issue.** The implementation-side issue under the Paperclip App project whose execution workspace owns the isolated worktree. First iteration creates it; later iterations reuse it via `inheritExecutionWorkspaceFromIssueId` or equivalent.
|
||||
- **Paperclip App worktree issue.** The implementation-side issue under the Paperclip App project whose execution workspace owns the isolated worktree. Use the current issue's isolated worktree for the default workflow; the optional task-tree procedure below records its owning issue.
|
||||
- **Benchmark command.** The exact `paperclip-bench` invocation, including the `PAPERCLIPAI_CMD` (or equivalent) binding pinned to the Paperclip App worktree under test. Record verbatim on the loop issue.
|
||||
- **Dispatch runner config.** The exact Harbor/Paperclip runner dispatch config required for the smoke to actually start a Paperclip heartbeat. For the current Harbor wrapper, record the `PAPERCLIP_HARBOR_RUNNER_CONFIG` JSON (or equivalent config file) verbatim enough to preserve: `assignee`, `heartbeat_strategy`, `agent_adapter` / `agent_adapters`, `reuse_host_home` when local credentials are intentionally needed, and the stop budget. A bare Harbor command that creates `BEN-1` as unassigned `todo` with zero heartbeat-enabled agents is a harness/setup failure, not a valid product diagnosis.
|
||||
- **Latest artifact root.** Filesystem or storage path under which `paperclip-bench` writes run artifacts (manifest, `results.jsonl`, Harbor raw job folders, redacted telemetry). Each iteration appends; nothing is overwritten.
|
||||
@@ -57,9 +57,15 @@ Collect these on the top-level loop issue before iteration 1. Any input that can
|
||||
|
||||
Record each input on the top-level loop issue (description or a dedicated `inputs` document). If any input changes mid-loop, note the change and the iteration it took effect.
|
||||
|
||||
## Issue topology
|
||||
## Default workflow
|
||||
|
||||
The loop must be representable as a tree, not as prose in comments:
|
||||
Run the smoke, diagnosis, approved fix, and rerun on the current issue. Record each iteration in its documents. Save a fix proposal as `plan`, read back its latest revision, and request board confirmation bound to that revision before implementation. Use the same isolated worktree for the fix and rerun. Keep the iteration budget, evidence requirements, and QA/CTO review gates below; use the current issue's review participants or approval interactions for those gates.
|
||||
|
||||
The task-tree procedure below applies only when the user explicitly requests separate tasks or when continuing an existing tree. Do not propose a task tree merely to run this workflow. For the default workflow, iteration records replace iteration children, and plan approval and review waits stay on the current issue.
|
||||
|
||||
## Optional issue topology
|
||||
|
||||
For an explicitly requested task tree:
|
||||
|
||||
- **Top-level loop issue.** Long-lived. Holds inputs, iteration counter, current state, links to every iteration child, and the product-rule history. Rests in `in_progress` while an iteration is running, `in_review` only when a typed waiter sits directly on the loop parent (execution-policy participant, `request_confirmation` / `ask_user_questions` / `suggest_tasks` interaction, approval, or named human owner), `blocked` with `blockedByIssueIds` while a child issue is the gating work (iteration child holding the fix-proposal `request_confirmation`, or implementation, QA, or CTO review children), `done` on pass, or `cancelled` on board-rejection / budget exhaustion.
|
||||
- **Iteration child issues.** One per iteration. Each carries: a bounded run issue (smoke), a diagnosis issue (applies `/diagnose-why-work-stopped`), a fix-proposal document with a `request_confirmation` interaction, and — only after acceptance — implementation, QA, CTO review, and rerun children. Iteration children are blocked by their predecessors so the executor wakes them in order.
|
||||
@@ -67,7 +73,7 @@ The loop must be representable as a tree, not as prose in comments:
|
||||
|
||||
Wire dependencies with `blockedByIssueIds`, never with prose like "blocked by X". When a dependent child is `done`, the executor auto-wakes the next.
|
||||
|
||||
## Procedure
|
||||
## Procedure for an explicitly requested task tree
|
||||
|
||||
### 0. Read the current execution contract
|
||||
|
||||
@@ -165,7 +171,7 @@ A loop must never end on a prose comment alone. Every stop is a status transitio
|
||||
|
||||
The loop must not test whatever Paperclip checkout happens to be current for the heartbeat. It must test the same isolated Paperclip App worktree where proposed fixes are applied.
|
||||
|
||||
- The first iteration creates the Paperclip App implementation child; that project's git-worktree policy spawns a fresh worktree.
|
||||
- The default workflow uses the current issue's isolated worktree. In the optional task-tree workflow, the first iteration records the implementation issue that owns the worktree.
|
||||
- The loop issue records the worktree-owning issue id and the workspace path (or workspace id).
|
||||
- Every later implementation, QA, and rerun child sets `inheritExecutionWorkspaceFromIssueId` to that worktree-owning issue, so all subsequent loop work shares one workspace.
|
||||
- The benchmark command always sets `PAPERCLIPAI_CMD` (or the equivalent command binding) to the CLI entrypoint inside that worktree, and it carries the recorded dispatch runner config (`PAPERCLIP_HARBOR_RUNNER_CONFIG` or equivalent) needed to assign the benchmark issue and start the heartbeat. The benchmark command stored on the loop issue is the source of truth — if a heartbeat needs to run the smoke from a different shell, it copies the recorded command block verbatim, not only the Harbor invocation line.
|
||||
@@ -210,7 +216,7 @@ If a loop issue does not fit one of these on exit, the heartbeat is not done. Fi
|
||||
|
||||
## Deterministic smoke
|
||||
|
||||
Run this smoke after installing or changing the skill, before treating it as operational for a live Terminal-Bench loop:
|
||||
This smoke checks the optional task-tree lifecycle. Run it when changing that lifecycle; it does not test the default single-issue workflow:
|
||||
|
||||
```sh
|
||||
pnpm smoke:terminal-bench-loop-skill
|
||||
|
||||
@@ -97,7 +97,7 @@ What the adapter does automatically:
|
||||
On-call checklist if you see this in production:
|
||||
|
||||
- Confirm `errorCode` is `claude_poisoned_previous_message_id` in the run row — that means the guards fired correctly and the issue auto-recovers on the next heartbeat.
|
||||
- If the same issue still loops after one heartbeat, check that `agentTaskSessions` for that `(agentId, taskKey)` was cleared. If not, the adapter return value was lost (e.g. a malformed run finalization) — escalate; do **not** manually edit the row, file a child issue with the run id.
|
||||
- If the same issue still loops after one heartbeat, check that `agentTaskSessions` for that `(agentId, taskKey)` was cleared. If not, the adapter return value was lost (e.g. a malformed run finalization) — escalate; do **not** manually edit the row, include the run id in the escalation.
|
||||
- For remote execution targets (sandbox/SSH), the poisoned JSONL is on the remote and the adapter only logs the cleanup intent. The fresh-session retry still succeeds because it uses a new session id, and the server-side `clearSession: true` is authoritative regardless of remote disk state.
|
||||
|
||||
## Skills Injection
|
||||
|
||||
@@ -132,7 +132,7 @@ If the connection drops, the UI reconnects automatically.
|
||||
|
||||
1. Disable timer or set a long interval
|
||||
2. Keep wake-on-assignment enabled
|
||||
3. Use child issues, comments, and on-demand wakeups for handoffs instead of loops that poll agents, sessions, or processes
|
||||
3. Use comments and on-demand wakeups for existing handoffs instead of loops that poll agents, sessions, or processes
|
||||
|
||||
## 7.3 Safety-first loop
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ For normal issue implementation plans, use the issue-thread confirmation surface
|
||||
2. Create `request_confirmation` bound to the latest `plan` revision.
|
||||
3. Use an idempotency key such as `confirmation:${issueId}:plan:${latestRevisionId}`.
|
||||
4. Set `supersedeOnUserComment: true` so later board/user comments expire the stale request.
|
||||
5. Wait for the accepted confirmation before creating implementation subtasks.
|
||||
5. Wait for the accepted confirmation before implementation.
|
||||
|
||||
## Responding to Approval Resolutions
|
||||
|
||||
|
||||
@@ -68,9 +68,9 @@ Read ancestors to understand why this task exists. If woken by a specific commen
|
||||
|
||||
Use your tools and capabilities to complete the task. If the issue is actionable, take a concrete action in the same heartbeat. Do not stop at a plan unless the issue asked for planning.
|
||||
|
||||
Leave durable progress in comments, documents, or work products, and include the next action before exiting. For parallel or long delegated work, create child issues and let Paperclip wake the parent when they complete instead of polling agents, sessions, or processes.
|
||||
Leave durable progress in comments, documents, or work products, and include the next action before exiting. Continue work on the current issue. For existing delegated work, let Paperclip wake the waiting task instead of polling agents, sessions, or processes.
|
||||
|
||||
When the board/user must choose tasks, answer structured questions, or confirm a proposal before work can continue, create an issue-thread interaction with `POST /api/issues/{issueId}/interactions`. Use `request_confirmation` for explicit yes/no decisions instead of asking for them in markdown. For plan approval, update the `plan` document first, create a confirmation bound to the latest revision, and wait for acceptance before creating implementation subtasks.
|
||||
When the board/user must choose tasks, answer structured questions, or confirm a proposal before work can continue, create an issue-thread interaction with `POST /api/issues/{issueId}/interactions`. Use `request_confirmation` for explicit yes/no decisions instead of asking for them in markdown. For plan approval, update the `plan` document first, create a confirmation bound to the latest revision, and wait for acceptance before implementation.
|
||||
|
||||
### Step 8: Update Status
|
||||
|
||||
@@ -90,9 +90,9 @@ Headers: X-Paperclip-Run-Id: {runId}
|
||||
{ "status": "blocked", "comment": "What is blocked, why, and who needs to unblock it." }
|
||||
```
|
||||
|
||||
### Step 9: Delegate if Needed
|
||||
### Optional Task Creation
|
||||
|
||||
Create subtasks for your reports:
|
||||
Task creation supports an assignee and parent relationship:
|
||||
|
||||
```
|
||||
POST /api/companies/{companyId}/issues
|
||||
@@ -108,7 +108,7 @@ Always set `parentId` and `goalId` on subtasks.
|
||||
- **Always comment** on in-progress work before exiting a heartbeat
|
||||
- **Start actionable work** in the same heartbeat; planning-only exits are for planning tasks
|
||||
- **Leave a clear next action** in durable issue context
|
||||
- **Use child issues instead of polling** for long or parallel delegated work
|
||||
- **Do not busy-poll** while waiting for existing delegated work
|
||||
- **Use `request_confirmation`** for issue-scoped yes/no decisions and plan approval cards
|
||||
- **Always set parentId** on subtasks
|
||||
- **Never cancel cross-team tasks** — reassign to your manager
|
||||
|
||||
@@ -52,7 +52,7 @@ Never sit silently on blocked work. Comment the blocker, update the status, and
|
||||
|
||||
## Delegation Pattern
|
||||
|
||||
Managers break down work into subtasks:
|
||||
If work is delegated, task creation supports a parent relationship:
|
||||
|
||||
```
|
||||
POST /api/companies/{companyId}/issues
|
||||
@@ -99,7 +99,7 @@ When a plan needs approval before implementation:
|
||||
2. Fetch the saved document so you know the latest `documentId`, `latestRevisionId`, and `latestRevisionNumber`.
|
||||
3. Create a `request_confirmation` targeting that exact `plan` revision.
|
||||
4. Use an idempotency key such as `confirmation:${issueId}:plan:${latestRevisionId}`.
|
||||
5. Wait for acceptance before creating implementation subtasks.
|
||||
5. Wait for acceptance before implementation.
|
||||
6. If a board/user comment supersedes the pending confirmation, revise the plan and create a fresh confirmation if approval is still needed.
|
||||
|
||||
Plan approval targets look like this:
|
||||
|
||||
@@ -31,7 +31,7 @@ The CEO is the first agent you create. Choose an adapter type (Claude Code is a
|
||||
- **Prompt template** — instructions for what the CEO does on each heartbeat
|
||||
- **Budget** — monthly spend limit in cents
|
||||
|
||||
The CEO's prompt should instruct it to review company health, set strategy, and delegate work to reports.
|
||||
The CEO's prompt should instruct it to review company health, set strategy, and carry out assigned work.
|
||||
|
||||
## Step 4: Build the Org Chart
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
title: How Delegation Works
|
||||
summary: How the CEO breaks down goals into tasks and assigns them to agents
|
||||
summary: How the CEO assigns work when delegation is part of the requested scope
|
||||
---
|
||||
|
||||
Delegation is one of Paperclip's most powerful features. You set company goals, and the CEO agent automatically breaks them into tasks and assigns them to the right agents. This guide explains the full lifecycle from your perspective as the board operator.
|
||||
Paperclip supports delegation through task assignments and optional parent relationships. Work can stay on the current task. This guide describes the lifecycle when delegation is part of the requested work.
|
||||
|
||||
## The Delegation Lifecycle
|
||||
|
||||
When you create a company goal, the CEO doesn't just acknowledge it — it builds a plan and mobilizes the team:
|
||||
For a goal whose approved scope includes delegation:
|
||||
|
||||
```
|
||||
You set a company goal
|
||||
@@ -21,7 +21,7 @@ You set a company goal
|
||||
→ You see results in the dashboard and activity log
|
||||
```
|
||||
|
||||
Each step is traceable. Every task links back to the goal through a parent hierarchy, so you can always see why work is happening.
|
||||
Tasks that use parent relationships can trace back to the goal through that hierarchy, so you can see why work is happening.
|
||||
|
||||
## What You Need to Do
|
||||
|
||||
@@ -40,16 +40,16 @@ Your role is strategic oversight, not task management. Here's what the delegatio
|
||||
- Is an agent paused or in an error state?
|
||||
- Is the CEO's budget exhausted (above 80%, it focuses on critical tasks only)?
|
||||
|
||||
## What the CEO Does Automatically
|
||||
## What an Approved Delegation Can Include
|
||||
|
||||
You do **not** need to tell the CEO to engage specific agents. After you approve its strategy, the CEO:
|
||||
When your request or approved plan assigns work to a team, the CEO can:
|
||||
|
||||
- **Breaks goals into concrete tasks** with clear descriptions, priorities, and acceptance criteria
|
||||
- **Assigns tasks to the right agent** based on role and capabilities (e.g., engineering tasks go to the CTO or engineers, marketing tasks go to the CMO)
|
||||
- **Creates subtasks** when work needs to be decomposed further
|
||||
- **Hires new agents** when the team lacks capacity for a goal, with hire approvals available when enabled in company settings
|
||||
- **Monitors progress** on each heartbeat, checking task status and unblocking reports
|
||||
- **Escalates to you** when it encounters something it can't resolve — budget issues, blocked approvals, or strategic ambiguity
|
||||
- **Break goals into concrete tasks** with clear descriptions, priorities, and acceptance criteria
|
||||
- **Assign tasks to the right agent** based on role and capabilities (e.g., engineering tasks go to the CTO or engineers, marketing tasks go to the CMO)
|
||||
- **Use parent relationships** when included in the requested task structure
|
||||
- **Hire new agents** when the team lacks capacity for a goal, with hire approvals available when enabled in company settings
|
||||
- **Monitor progress** on each heartbeat, checking task status and unblocking reports
|
||||
- **Escalate to you** when it encounters something it can't resolve — budget issues, blocked approvals, or strategic ambiguity
|
||||
|
||||
## Common Delegation Patterns
|
||||
|
||||
@@ -79,7 +79,7 @@ CEO
|
||||
└── Content Writer
|
||||
```
|
||||
|
||||
The CEO assigns high-level tasks to the CTO and CMO. They break those into subtasks and assign them to their own reports. You only interact with the CEO — the rest happens automatically.
|
||||
The CEO assigns high-level tasks to the CTO and CMO. They break those into subtasks and assign them to their own reports. This is an optional structure, not a requirement for each request.
|
||||
|
||||
### Hire-on-Demand
|
||||
|
||||
@@ -106,11 +106,11 @@ If you've set a goal but nothing is happening, check these common causes:
|
||||
| **Budget** | If the CEO is above 80% of its monthly budget, it focuses only on critical tasks and may skip lower-priority delegation. |
|
||||
| **Goals** | If no company goals are set, the CEO has nothing to work from. Create a goal first. |
|
||||
| **Heartbeat** | Is the CEO's heartbeat enabled and running? Check the agent detail page for recent heartbeat history. |
|
||||
| **Agent instructions** | The CEO's delegation behavior is driven by its `AGENTS.md` instructions file. Open the CEO agent's detail page and verify that its instructions path is set and that the file includes delegation directives (subtask creation, hiring, assignment). If AGENTS.md is missing or doesn't mention delegation, the CEO won't know to break down goals and assign work. |
|
||||
| **Agent instructions** | Check that its `AGENTS.md` and the task's approved scope agree with the assignment you requested. A goal or plan approval alone does not require subtasks. |
|
||||
|
||||
### "Do I have to tell the CEO to engage engineering and marketing?"
|
||||
|
||||
**No.** The CEO will delegate automatically after you approve its strategy. It knows the org chart and assigns tasks based on each agent's role and capabilities. You set the goal and approve the plan — the CEO handles task breakdown and assignment.
|
||||
Specify the assignments you want in your request or approved plan. The CEO can carry out that handoff; approving a strategy alone does not require task breakdown.
|
||||
|
||||
### "A task seems stuck"
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Paperclip enforces a strict organizational hierarchy. Every agent reports to exa
|
||||
- The **CEO** has no manager (reports to the board/human operator)
|
||||
- Every other agent has a `reportsTo` field pointing to their manager
|
||||
- You can change an agent’s manager after creation from **Agent → Configuration → Reports to** (or via `PATCH /api/agents/{id}` with `reportsTo`)
|
||||
- Managers can create subtasks and delegate to their reports
|
||||
- Managers can assign work to their reports
|
||||
- Agents escalate blockers up the chain of command
|
||||
|
||||
## Viewing the Org Chart
|
||||
@@ -28,7 +28,7 @@ GET /api/companies/{companyId}/org
|
||||
Every agent has access to their `chainOfCommand` — the list of managers from their direct report up to the CEO. This is used for:
|
||||
|
||||
- **Escalation** — when an agent is blocked, they can reassign to their manager
|
||||
- **Delegation** — managers create subtasks for their reports
|
||||
- **Delegation** — managers can assign work to their reports
|
||||
- **Visibility** — managers can see what their reports are working on
|
||||
|
||||
## Rules
|
||||
|
||||
@@ -52,14 +52,14 @@ The transition to `in_progress` requires an **atomic checkout** — only one age
|
||||
|
||||
## Delegation
|
||||
|
||||
The CEO is the primary delegator. When you set company goals, the CEO:
|
||||
When your request includes delegation, the CEO can:
|
||||
|
||||
1. Creates a strategy and submits it for your approval
|
||||
2. Breaks approved goals into tasks
|
||||
3. Assigns tasks to agents based on their role and capabilities
|
||||
4. Hires new agents when needed, with hire approvals available when you enable them
|
||||
1. Create a strategy and submit it for your approval
|
||||
2. Break approved goals into tasks
|
||||
3. Assign tasks to agents based on their role and capabilities
|
||||
4. Hire new agents when needed, with hire approvals available when you enable them
|
||||
|
||||
You don't need to manually assign every task — set the goals and let the CEO organize the work. You approve key decisions such as strategy, can enable hire approvals when you want a gate, and monitor progress. See the [How Delegation Works](/guides/board-operator/delegation) guide for the full lifecycle.
|
||||
When your request or approved plan includes delegation, the CEO can organize the work. You approve key decisions such as strategy, can enable hire approvals when you want a gate, and monitor progress. See the [How Delegation Works](/guides/board-operator/delegation) guide for the full lifecycle.
|
||||
|
||||
## Heartbeats
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@ The Heartbeat Procedure:
|
||||
6. Understand context: GET /api/issues/{issueId}/heartbeat-context
|
||||
7. Do the work
|
||||
8. Update status: PATCH /api/issues/{issueId} with status and comment
|
||||
9. Delegate if needed: POST /api/companies/{companyId}/issues
|
||||
9. Optional task creation: POST /api/companies/{companyId}/issues
|
||||
|
||||
Execution Contract:
|
||||
- If the issue is actionable, start concrete work in this heartbeat. Do not stop at a plan unless the issue asks for planning.
|
||||
- Leave durable progress in comments, documents, or work products, with a clear next action.
|
||||
- Use child issues for parallel or long delegated work instead of polling agents, sessions, or processes.
|
||||
- Continue work on the current issue. Do not busy-poll agents, sessions, or processes.
|
||||
- If blocked, PATCH the issue to blocked and name the unblock owner and action.
|
||||
- Respect budget, pause/cancel, approval gates, and company boundaries.
|
||||
|
||||
|
||||
@@ -971,7 +971,7 @@ describe("shared ACPX engine runtime behavior", () => {
|
||||
expect(String(reset.meta[0]?.prompt)).toContain(custom ? "Custom agent instructions." : "You are agent agent-1");
|
||||
const ordinary = await runExecutor({ ...config, promptTemplate: "" }, { context: { ...context, conversationMode: false } });
|
||||
expect(String(ordinary.meta[0]?.prompt)).not.toContain("Execution contract:");
|
||||
expect(String(ordinary.meta[0]?.prompt)).toContain("Create child issues from the approved plan");
|
||||
expect(String(ordinary.meta[0]?.prompt)).toContain("Implement the accepted plan on this issue.");
|
||||
});
|
||||
|
||||
it("uses only the guarded external-chat contract for a default ACPX prompt", async () => {
|
||||
|
||||
@@ -1109,7 +1109,7 @@ describe("renderPaperclipWakePrompt", () => {
|
||||
};
|
||||
const ordinary = renderPaperclipWakePrompt(payload, { resumedSession: true });
|
||||
expect(ordinary).not.toContain("Execution contract:");
|
||||
expect(ordinary).toContain("Create child issues from the approved plan");
|
||||
expect(ordinary).toContain("Implement the accepted plan on this issue.");
|
||||
for (const resumedSession of [false, true]) {
|
||||
const chat = renderPaperclipWakePrompt(payload, {
|
||||
resumedSession, conversationMode: true, includeExecutionContract: true,
|
||||
@@ -1117,7 +1117,7 @@ describe("renderPaperclipWakePrompt", () => {
|
||||
expect(chat).not.toContain("Execution contract:");
|
||||
expect(chat).not.toContain("clear final disposition");
|
||||
expect(chat).not.toContain("Create child issues");
|
||||
expect(chat).not.toContain("you may create child implementation issues");
|
||||
expect(chat).not.toContain("Implement the accepted plan on this issue.");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2552,7 +2552,7 @@ describe("renderPaperclipWakePrompt", () => {
|
||||
);
|
||||
expect(prompt).not.toContain("accepted-plan continuation");
|
||||
expect(prompt).not.toContain(
|
||||
"Create child issues from the approved plan only",
|
||||
"Implement the accepted plan on this issue.",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2574,10 +2574,10 @@ describe("renderPaperclipWakePrompt", () => {
|
||||
});
|
||||
|
||||
expect(prompt).toContain("accepted-plan continuation");
|
||||
expect(prompt).toContain("Create child issues from the approved plan only");
|
||||
expect(prompt).toContain("may create child implementation issues");
|
||||
expect(prompt).toContain("Implement the accepted plan on this issue.");
|
||||
expect(prompt).toContain("Plan acceptance alone does not require subtasks.");
|
||||
expect(prompt).toContain(
|
||||
"must not start implementation work on the planning issue itself",
|
||||
"continue the approved work on this issue unless the approved plan explicitly assigns it elsewhere",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2920,7 +2920,7 @@ describe("renderPaperclipWakePrompt", () => {
|
||||
expect(prompt).toContain("selected text: Passed in Chrome");
|
||||
expect(prompt).toContain("Attach the run id.");
|
||||
expect(prompt).toContain(
|
||||
"propose a child issue before making code changes",
|
||||
"obtain authorization before making code changes",
|
||||
);
|
||||
expect(prompt).toContain(
|
||||
"prefer replying and resolving the thread over rewriting the snapshot",
|
||||
@@ -3031,7 +3031,7 @@ describe("renderPaperclipWakePrompt", () => {
|
||||
expect(prompt).toContain("CHA-8 Ship the migration (blocked)");
|
||||
expect(prompt).toContain("execution_recovery_budget_exhausted");
|
||||
expect(prompt).toContain("Retry the run or reassign the task");
|
||||
expect(prompt).toMatch(/re-delegate/i);
|
||||
expect(prompt).toContain("reassign its existing task");
|
||||
expect(prompt).toMatch(/escalate/i);
|
||||
expect(prompt).toMatch(/block this issue/i);
|
||||
});
|
||||
|
||||
@@ -229,7 +229,7 @@ export const WATCHDOG_DEFAULT_MANDATE = [
|
||||
"- Treat every terminal, cancelled, blocked, in-review, or otherwise stopped leaf in the watched subtree as a claim that must be verified against comments, documents, work products, screenshots, tests, blockers, and review state.",
|
||||
'- Do not accept "I could not" or "waiting for approval" as automatically valid. Read the evidence before deciding.',
|
||||
"- If a stopped leaf is genuinely complete, leave it alone and record why you believe so.",
|
||||
"- If a stopped leaf is not genuinely complete, restore a live path inside the watched subtree by reopening, reassigning, commenting actionable instructions, creating a follow-up child issue, or accepting an eligible task-level interaction (such as a routine plan confirmation when no custom instruction forbids it).",
|
||||
"- If a stopped leaf is not genuinely complete, restore a live path inside the watched subtree by reopening, reassigning, commenting actionable instructions, or accepting an eligible task-level interaction (such as a routine plan confirmation when no custom instruction forbids it).",
|
||||
"- If you discover a Paperclip product or platform bug while reviewing the stopped subtree, create a linked engineering follow-up outside the watched source tree using the server-provided watchdog discovery route instead of making it a source child.",
|
||||
"- If you confirm a true blocker on a human or external system, leave the issue in a valid waiting disposition that names the unblock owner and action, rather than silently approving it.",
|
||||
"",
|
||||
@@ -2680,14 +2680,14 @@ function renderPaperclipWakePromptBody(
|
||||
if (acceptedPlanContinuation) {
|
||||
directive = acceptedPlanWithMissingWakeComment
|
||||
? "Continue the accepted-plan review only. Do not write code or perform implementation work on the planning issue."
|
||||
: "Create child issues from the approved plan only. Do not write code or perform implementation work on the planning issue.";
|
||||
: "Implement the accepted plan on this issue. Follow any task assignments explicitly included in the approved plan. Plan acceptance alone does not require subtasks.";
|
||||
}
|
||||
lines.push(`- planning directive: ${directive}`);
|
||||
if (acceptedPlanContinuation) {
|
||||
lines.push(
|
||||
acceptedPlanWithMissingWakeComment
|
||||
? "- accepted-plan continuation: fetch and reconcile the missing wake comment; do not create a child merely because a plan was accepted"
|
||||
: "- accepted-plan continuation: you may create child implementation issues from the approved plan, but must not start implementation work on the planning issue itself",
|
||||
: "- accepted-plan continuation: continue the approved work on this issue unless the approved plan explicitly assigns it elsewhere",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2898,7 +2898,7 @@ function renderPaperclipWakePromptBody(
|
||||
"## Open document annotations",
|
||||
"",
|
||||
"These open annotations are grouped by issue document. Resolved annotations were intentionally omitted.",
|
||||
"Scope: a document annotation authorizes document edits and thread replies only; propose a child issue before making code changes.",
|
||||
"Scope: a document annotation authorizes document edits and thread replies only; obtain authorization before making code changes.",
|
||||
"For snapshot documents such as QA evidence and run summaries, prefer replying and resolving the thread over rewriting the snapshot.",
|
||||
`- open annotation threads included: ${context.totals.includedThreadCount}/${context.totals.openThreadCount}`,
|
||||
`- annotation comments included: ${context.totals.includedCommentCount}/${context.totals.commentCount}`,
|
||||
@@ -3124,7 +3124,7 @@ function renderPaperclipWakePromptBody(
|
||||
...(action.nextAction ? [`- next action for the board: ${action.nextAction}`] : []),
|
||||
"",
|
||||
"Choose one, then stop:",
|
||||
`- Re-delegate: if the work can be done another way, create or reassign a task for it and stop depending on ${label}.`,
|
||||
`- Reassign: if the work can be done another way, reassign its existing task and stop depending on ${label}.`,
|
||||
`- Escalate: comment on this issue with what is stuck and what the board must do on ${label} (its Retry or reassignment), so the board sees it here.`,
|
||||
`- Block this issue with a reason that names ${label} and its recovery action, if nothing else can move until the board acts.`,
|
||||
`Do not redo ${label}'s work yourself while it is assigned, and do not wait silently.`,
|
||||
|
||||
@@ -190,7 +190,7 @@ test("renders comment wake batch guidance without defaulting to a full-thread re
|
||||
expect(prompt).toContain("- fallback fetch needed: no");
|
||||
});
|
||||
|
||||
test("renders accepted-plan continuation without authorizing implementation on the planning issue", () => {
|
||||
test("renders accepted-plan continuation on the current issue without requiring subtasks", () => {
|
||||
const prompt = buildPrompt(baseContext({
|
||||
paperclipWake: {
|
||||
reason: "issue_commented",
|
||||
@@ -210,9 +210,9 @@ test("renders accepted-plan continuation without authorizing implementation on t
|
||||
},
|
||||
}), {});
|
||||
|
||||
expect(prompt).toContain("- planning directive: Create child issues from the approved plan only. Do not write code or perform implementation work on the planning issue.");
|
||||
expect(prompt).toContain("- accepted-plan continuation: you may create child implementation issues from the approved plan");
|
||||
expect(prompt).toContain("must not start implementation work on the planning issue itself");
|
||||
expect(prompt).toContain("- planning directive: Implement the accepted plan on this issue.");
|
||||
expect(prompt).toContain("- accepted-plan continuation: continue the approved work on this issue unless the approved plan explicitly assigns it elsewhere");
|
||||
expect(prompt).toContain("Plan acceptance alone does not require subtasks.");
|
||||
expect(prompt).not.toContain("- planning directive: Make the plan only.");
|
||||
expect(prompt).not.toContain("Update the plan only");
|
||||
});
|
||||
|
||||
@@ -449,9 +449,9 @@ function buildWakeText(
|
||||
" - GET /api/issues/{issueId}",
|
||||
" - GET /api/issues/{issueId}/comments",
|
||||
" - Execute the issue instructions exactly. If the issue is actionable, take concrete action in this run; do not stop at a plan unless planning was requested.",
|
||||
" - Leave durable progress with a clear next action. Use child issues for long or parallel delegated work instead of polling agents, sessions, or processes.",
|
||||
" - Create child issues directly when you know what needs to be done; use POST /api/issues/{issueId}/interactions with kind suggest_tasks, ask_user_questions, or request_confirmation when the board/user must choose, answer, or confirm before you can continue.",
|
||||
" - For plan approval, update the plan document first, then create request_confirmation targeting the latest plan revision with idempotencyKey confirmation:{issueId}:plan:{revisionId}; wait for acceptance before creating implementation subtasks.",
|
||||
" - Leave durable progress with a clear next action. Do not busy-poll agents, sessions, or processes waiting for completion.",
|
||||
" - Continue work on the current issue; use POST /api/issues/{issueId}/interactions with kind suggest_tasks, ask_user_questions, or request_confirmation when the board/user must choose, answer, or confirm before you can continue.",
|
||||
" - For plan approval, update the plan document first, then create request_confirmation targeting the latest plan revision with idempotencyKey confirmation:{issueId}:plan:{revisionId}; wait for acceptance before implementation.",
|
||||
" - If blocked, PATCH /api/issues/{issueId} with {\"status\":\"blocked\",\"comment\":\"what is blocked, who owns the unblock, and the next action\"}.",
|
||||
" - If instructions require a comment, POST /api/issues/{issueId}/comments with {\"body\":\"...\"}.",
|
||||
" - PATCH /api/issues/{issueId} with {\"status\":\"done\",\"comment\":\"what changed and why\"}.",
|
||||
|
||||
@@ -108,7 +108,7 @@ The skill/reference inventory and eval cases are the only normative behavior sou
|
||||
| skill:skills/paperclip/references/api-reference.md:3-agent-42-is-blocked-read-comments:606 | control_plane_owned | skills/paperclip/references/api-reference.md:606 |
|
||||
| skill:skills/paperclip/references/api-reference.md:4-unblock-reassign-and-comment:610 | control_plane_owned | skills/paperclip/references/api-reference.md:610 |
|
||||
| skill:skills/paperclip/references/api-reference.md:5-check-own-assignments:614 | optional_agent_tool | skills/paperclip/references/api-reference.md:614 |
|
||||
| skill:skills/paperclip/references/api-reference.md:6-create-subtasks-and-delegate:621 | optional_agent_tool | skills/paperclip/references/api-reference.md:621 |
|
||||
| skill:skills/paperclip/references/api-reference.md:6-task-creation-with-an-optional-parent-and-assignee:621 | optional_agent_tool | skills/paperclip/references/api-reference.md:621 |
|
||||
| skill:skills/paperclip/references/api-reference.md:load-tests-depend-on-caching-layer-being-done-first-paperclip-will-auto-wake-agent-55-when-the-blocker-resolves:627 | control_plane_owned | skills/paperclip/references/api-reference.md:627 |
|
||||
| skill:skills/paperclip/references/api-reference.md:7-dashboard-for-health-check:632 | optional_agent_tool | skills/paperclip/references/api-reference.md:632 |
|
||||
| skill:skills/paperclip/references/api-reference.md:comments-and-mentions:638 | always_agent_tool | skills/paperclip/references/api-reference.md:638 |
|
||||
|
||||
@@ -607,8 +607,8 @@
|
||||
{
|
||||
"id": "skill:skills/paperclip/references/api-reference.md:621",
|
||||
"kind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/references/api-reference.md#L621:6-create-subtasks-and-delegate",
|
||||
"heading": "6. Create subtasks and delegate.",
|
||||
"sourceAnchor": "skills/paperclip/references/api-reference.md#L621:6-task-creation-with-an-optional-parent-and-assignee",
|
||||
"heading": "6. Task creation with an optional parent and assignee.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"semanticOperation": "scoped_discovery",
|
||||
"expectedMockState": "operation_result"
|
||||
|
||||
@@ -5,6 +5,6 @@ Generated by `scripts/generate-capability-contract.mjs`; do not edit generated f
|
||||
- Skill/reference headings: 167
|
||||
- Legacy MCP tools: 42
|
||||
- Eval cases: 106 across 16 groups
|
||||
- Deterministic content SHA-256: `c42941dfaafd16b83f448575de8f229b0c23221ffa947b0da02dbbba7faec102`
|
||||
- Deterministic content SHA-256: `c2b0e907998c34ca1e9f3cd2336dfef1d33c5bed64bd44e433eaa3e34f313b12`
|
||||
|
||||
Every row has exactly one primary disposition, a source anchor, a semantic operation, and a mock-state expectation.
|
||||
@@ -1 +1 @@
|
||||
[{"annotations":{"exposure":"always","operationId":"get_task_context","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Read the active task and actor, including the exact approved Markdown revision when this issue has an accepted plan.","inputSchema":{"additionalProperties":false,"properties":{},"required":[],"type":"object"},"name":"get_task_context","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"get_task_history","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Read bounded comments on the active task only. Calling get_task does not change the active task. This is not a status or assignment audit. For progress chronology and handoff actors, use search_api to discover the company timeline or issue activity, then call_api.","inputSchema":{"additionalProperties":false,"properties":{"limit":{"default":50,"maximum":200,"minimum":1,"type":"integer"}},"required":[],"type":"object"},"name":"get_task_history","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"list_documents","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"List revisioned documents on the active task.","inputSchema":{"additionalProperties":false,"properties":{},"required":[],"type":"object"},"name":"list_documents","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"read_document","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Read the current revision of one active-task document.","inputSchema":{"additionalProperties":false,"properties":{"key":{"description":"Stable document identifier, not a filename or path (for example reconciliation, not reconciliation.md). After trimming whitespace and lowercasing: 1–64 characters, starting with a letter or digit and containing only a–z, 0–9, _ or -. The raw input is limited to 120 characters.","maxLength":120,"minLength":1,"pattern":"^[\\u0009-\\u000d\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]*[A-Za-z0-9\\u212a][A-Za-z0-9_\\u212a-]{0,63}[\\u0009-\\u000d\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]*$","type":"string"}},"required":["key"],"type":"object"},"name":"read_document","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"list_document_revisions","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Read bounded revision history for one active-task document.","inputSchema":{"additionalProperties":false,"properties":{"key":{"description":"Stable document identifier, not a filename or path (for example reconciliation, not reconciliation.md). After trimming whitespace and lowercasing: 1–64 characters, starting with a letter or digit and containing only a–z, 0–9, _ or -. The raw input is limited to 120 characters.","maxLength":120,"minLength":1,"pattern":"^[\\u0009-\\u000d\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]*[A-Za-z0-9\\u212a][A-Za-z0-9_\\u212a-]{0,63}[\\u0009-\\u000d\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]*$","type":"string"},"limit":{"default":50,"maximum":200,"minimum":1,"type":"integer"}},"required":["key"],"type":"object"},"name":"list_document_revisions","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"report_progress","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Append a durable progress comment to the active task.","inputSchema":{"additionalProperties":false,"properties":{"body":{"description":"Multiline progress update.","maxLength":20000,"minLength":1,"type":"string"},"idempotencyKey":{"description":"Caller-stable retry key.","maxLength":240,"minLength":1,"type":"string"}},"required":["idempotencyKey","body"],"type":"object"},"name":"report_progress","outputSchema":{"additionalProperties":false,"properties":{"commandId":{"description":"Stable command identifier.","maxLength":200,"minLength":1,"type":"string"},"disposition":{"enum":["applied","duplicate"]},"entityRefs":{"description":"Entities affected by the operation.","items":{"minLength":1,"type":"string"},"maxItems":200,"type":"array","uniqueItems":true},"scheduledWakeIds":{"description":"Wake identifiers scheduled by the operation.","items":{"minLength":1,"type":"string"},"maxItems":200,"type":"array","uniqueItems":true},"stateRevision":{"minimum":0,"type":"integer"}},"required":["commandId","disposition","stateRevision","entityRefs","scheduledWakeIds"],"type":"object"}},{"annotations":{"exposure":"always","operationId":"answer_status_question","requiredClaims":[],"semanticContract":"paperclip.Line truncated
|
||||
[{"annotations":{"exposure":"always","operationId":"get_task_context","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Read the active task and actor, including the exact approved Markdown revision when this issue has an accepted plan.","inputSchema":{"additionalProperties":false,"properties":{},"required":[],"type":"object"},"name":"get_task_context","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"get_task_history","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Read bounded comments on the active task only. Calling get_task does not change the active task. This is not a status or assignment audit. For progress chronology and handoff actors, use search_api to discover the company timeline or issue activity, then call_api.","inputSchema":{"additionalProperties":false,"properties":{"limit":{"default":50,"maximum":200,"minimum":1,"type":"integer"}},"required":[],"type":"object"},"name":"get_task_history","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"list_documents","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"List revisioned documents on the active task.","inputSchema":{"additionalProperties":false,"properties":{},"required":[],"type":"object"},"name":"list_documents","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"read_document","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Read the current revision of one active-task document.","inputSchema":{"additionalProperties":false,"properties":{"key":{"description":"Stable document identifier, not a filename or path (for example reconciliation, not reconciliation.md). After trimming whitespace and lowercasing: 1–64 characters, starting with a letter or digit and containing only a–z, 0–9, _ or -. The raw input is limited to 120 characters.","maxLength":120,"minLength":1,"pattern":"^[\\u0009-\\u000d\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]*[A-Za-z0-9\\u212a][A-Za-z0-9_\\u212a-]{0,63}[\\u0009-\\u000d\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]*$","type":"string"}},"required":["key"],"type":"object"},"name":"read_document","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"list_document_revisions","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Read bounded revision history for one active-task document.","inputSchema":{"additionalProperties":false,"properties":{"key":{"description":"Stable document identifier, not a filename or path (for example reconciliation, not reconciliation.md). After trimming whitespace and lowercasing: 1–64 characters, starting with a letter or digit and containing only a–z, 0–9, _ or -. The raw input is limited to 120 characters.","maxLength":120,"minLength":1,"pattern":"^[\\u0009-\\u000d\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]*[A-Za-z0-9\\u212a][A-Za-z0-9_\\u212a-]{0,63}[\\u0009-\\u000d\\u0020\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]*$","type":"string"},"limit":{"default":50,"maximum":200,"minimum":1,"type":"integer"}},"required":["key"],"type":"object"},"name":"list_document_revisions","outputSchema":{"additionalProperties":true,"type":"object"}},{"annotations":{"exposure":"always","operationId":"report_progress","requiredClaims":[],"semanticContract":"paperclip.semantic-tool.v1","version":1},"description":"Append a durable progress comment to the active task.","inputSchema":{"additionalProperties":false,"properties":{"body":{"description":"Multiline progress update.","maxLength":20000,"minLength":1,"type":"string"},"idempotencyKey":{"description":"Caller-stable retry key.","maxLength":240,"minLength":1,"type":"string"}},"required":["idempotencyKey","body"],"type":"object"},"name":"report_progress","outputSchema":{"additionalProperties":false,"properties":{"commandId":{"description":"Stable command identifier.","maxLength":200,"minLength":1,"type":"string"},"disposition":{"enum":["applied","duplicate"]},"entityRefs":{"description":"Entities affected by the operation.","items":{"minLength":1,"type":"string"},"maxItems":200,"type":"array","uniqueItems":true},"scheduledWakeIds":{"description":"Wake identifiers scheduled by the operation.","items":{"minLength":1,"type":"string"},"maxItems":200,"type":"array","uniqueItems":true},"stateRevision":{"minimum":0,"type":"integer"}},"required":["commandId","disposition","stateRevision","entityRefs","scheduledWakeIds"],"type":"object"}},{"annotations":{"exposure":"always","operationId":"answer_status_question","requiredClaims":[],"semanticContract":"paperclip.Line truncated
|
||||
@@ -3342,7 +3342,7 @@
|
||||
"standard",
|
||||
"skill_test"
|
||||
],
|
||||
"description": "Create a project task from a conversation, or a child from an ordinary task. When the user names an existing teammate or project, resolve their IDs with list_agents or list_projects and set assigneeActorId or projectId in this creation call. A todo task can start its assignee immediately; creating it for yourself and reassigning later can start the wrong agent. Persist initialPlan before execution. Use backlog to save or plan without starting work; backlog tasks never wake an agent. Omitted status means todo, subject to blockers. Include required inputs and constraints in self-contained child instructions.",
|
||||
"description": "Create a task. When the user names an existing teammate or project, resolve their IDs with list_agents or list_projects and set assigneeActorId or projectId in this creation call. A todo task can start its assignee immediately; creating it for yourself and reassigning later can start the wrong agent. Persist initialPlan before execution. Use backlog to save or plan without starting work; backlog tasks never wake an agent. Omitted status means todo, subject to blockers. Include required inputs and constraints in self-contained task instructions.",
|
||||
"effect": "write",
|
||||
"inputSchema": {
|
||||
"additionalProperties": false,
|
||||
@@ -3374,7 +3374,7 @@
|
||||
"uniqueItems": true
|
||||
},
|
||||
"description": {
|
||||
"description": "Child task description.",
|
||||
"description": "Task description.",
|
||||
"maxLength": 20000,
|
||||
"type": [
|
||||
"string",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"prpVersion": 1,
|
||||
"nativeExecutionVersion": 1,
|
||||
"catalogVersion": 1,
|
||||
"catalogSha256": "sha256:e3ea4621f02d3b1885fd3cc24f5c4a8fc988c0e6ea0244f98ab837c307e20729",
|
||||
"catalogSha256": "sha256:f212302b554a7788940ac0a36e98d1a3d5b31fc156b0fca47629a9b913fd5fb0",
|
||||
"driverContractVersion": 1,
|
||||
"driverKind": "paperclip-deterministic",
|
||||
"driverVersion": "1.0.0"
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
},
|
||||
{
|
||||
"path": "fixtures/evals/native-execution-seeded.json",
|
||||
"sha256": "fab31b04d01d2436902a68728874f9d55de7fcac6e9104e40481630e824d1c68",
|
||||
"sha256": "f652a67cef1d4a838030b6ca7e390ed3ae586c685b6770df0e7762ad739eddab",
|
||||
"expectation": "accept",
|
||||
"compatibilityCase": "canonical"
|
||||
},
|
||||
|
||||
@@ -1020,11 +1020,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "skill:skills/paperclip/references/api-reference.md:6-create-subtasks-and-delegate:621",
|
||||
"id": "skill:skills/paperclip/references/api-reference.md:6-task-creation-with-an-optional-parent-and-assignee:621",
|
||||
"sourceKind": "skill_heading",
|
||||
"sourceAnchor": "skills/paperclip/references/api-reference.md:621",
|
||||
"title": "6. Create subtasks and delegate.",
|
||||
"expectedSemantics": "Skill guidance headed “6. Create subtasks and delegate.”.",
|
||||
"title": "6. Task creation with an optional parent and assignee.",
|
||||
"expectedSemantics": "Skill guidance headed “6. Task creation with an optional parent and assignee.”.",
|
||||
"primaryDisposition": "optional_agent_tool",
|
||||
"requiredGrants": [],
|
||||
"assertionClasses": [
|
||||
|
||||
@@ -28,7 +28,7 @@ export function nativeSystemInstructions(input: NativeExecutionInput): string {
|
||||
}
|
||||
const entry = readFileSync(entryPath, "utf8");
|
||||
if (input.provider.kind === "muse") {
|
||||
return ["You are running as a named Paperclip agent. Complete the assigned task, follow the attached agent instructions, and use the admitted Paperclip catalog for coordination. Use list_agents and create_task when the work calls for delegation. Record durable text deliverables with write_document. When work depends on another task, preserve the existing dependencies with set_dependencies and report the concrete blocker through paperclip_block. Follow each tool's approval and completion rules.", entry.trim(),
|
||||
return ["You are running as a named Paperclip agent. Complete the assigned task, follow the attached agent instructions, and use the admitted Paperclip catalog for coordination. Record durable text deliverables with write_document. When work depends on another task, preserve the existing dependencies with set_dependencies and report the concrete blocker through paperclip_block. Follow each tool's approval and completion rules.", entry.trim(),
|
||||
"Use the private Muse client's operation command for the admitted first-party Paperclip task and document catalog. Use your own approved tools for external work. Paperclip supplies no connector credentials or filesystem command grants. Keep all Paperclip data within this connection's company, agent, and current task. Use the client's ask command for questions; persist the exact saved answer into this run's continuation before consuming its input receipt. Pending or unconsumed answers block completion. Invoke paperclip_finish or paperclip_block through the native tool catalog, then submit that exact accepted report with the client's finish command."].join("\n\n");
|
||||
}
|
||||
if (input.schema === "paperclip.native-execution-input.v6") {
|
||||
|
||||
@@ -535,7 +535,7 @@ const descriptors: readonly PaperclipSemanticActionDescriptor[] = [
|
||||
descriptor({
|
||||
operationId: "create_task",
|
||||
title: "Create task",
|
||||
description: "Create a project task from a conversation, or a child from an ordinary task. When the user names an existing teammate or project, resolve their IDs with list_agents or list_projects and set assigneeActorId or projectId in this creation call. A todo task can start its assignee immediately; creating it for yourself and reassigning later can start the wrong agent. Persist initialPlan before execution. Use backlog to save or plan without starting work; backlog tasks never wake an agent. Omitted status means todo, subject to blockers. Include required inputs and constraints in self-contained child instructions.",
|
||||
description: "Create a task. When the user names an existing teammate or project, resolve their IDs with list_agents or list_projects and set assigneeActorId or projectId in this creation call. A todo task can start its assignee immediately; creating it for yourself and reassigning later can start the wrong agent. Persist initialPlan before execution. Use backlog to save or plan without starting work; backlog tasks never wake an agent. Omitted status means todo, subject to blockers. Include required inputs and constraints in self-contained task instructions.",
|
||||
placement: "optional",
|
||||
effect: "write",
|
||||
requiredClaims: ["delegation:tasks:create"],
|
||||
@@ -546,7 +546,7 @@ const descriptors: readonly PaperclipSemanticActionDescriptor[] = [
|
||||
title: text("Task title.", 500),
|
||||
projectId: nullableText("Project ID from list_projects. Set the requested project in this creation call so the task does not inherit a different project."),
|
||||
initialPlan: nullableText("Remaining execution steps to persist as the task plan. Exclude completed planning, approval, and handoff steps; cite the source plan revision and approval. A copied plan is not a new approval gate."),
|
||||
description: nullableText("Child task description."),
|
||||
description: nullableText("Task description."),
|
||||
requiredQualityReview: object({
|
||||
version: { const: 1 },
|
||||
deliverables: { type: "array", minItems: 1, maxItems: 10, items: object({ key: text("Stable output key, e.g. copy or visual.", 80), label: text("Human-readable output name.", 120) }, ["key", "label"]) },
|
||||
|
||||
@@ -29,7 +29,7 @@ export const createTaskAction = {
|
||||
},
|
||||
"documentation": {
|
||||
"title": "Create task",
|
||||
"description": "Create a project task from a conversation, or a child from an ordinary task. Set parentTaskId to place the task under a specific task, such as a top-level task you just created. When the user names an existing teammate or project, resolve their IDs with list_agents or list_projects and set assigneeActorId or projectId in this creation call. A todo task can start its assignee immediately; creating it for yourself and reassigning later can start the wrong agent. Persist initialPlan before execution. Use backlog to save or plan without starting work; backlog tasks never wake an agent. Omitted status means todo, subject to blockers. Include required inputs and constraints in self-contained child instructions.",
|
||||
"description": "Create a task. When the user names an existing teammate or project, resolve their IDs with list_agents or list_projects and set assigneeActorId or projectId in this creation call. A todo task can start its assignee immediately; creating it for yourself and reassigning later can start the wrong agent. Persist initialPlan before execution. Use backlog to save or plan without starting work; backlog tasks never wake an agent. Omitted status means todo, subject to blockers. Include required inputs and constraints in self-contained task instructions.",
|
||||
"note": null
|
||||
},
|
||||
"examples": {
|
||||
@@ -81,7 +81,7 @@ export const createTaskAction = {
|
||||
"operationId": "create_task",
|
||||
"version": 1,
|
||||
"title": "Create task",
|
||||
"description": "Create a project task from a conversation, or a child from an ordinary task. Set parentTaskId to place the task under a specific task, such as a top-level task you just created. When the user names an existing teammate or project, resolve their IDs with list_agents or list_projects and set assigneeActorId or projectId in this creation call. A todo task can start its assignee immediately; creating it for yourself and reassigning later can start the wrong agent. Persist initialPlan before execution. Use backlog to save or plan without starting work; backlog tasks never wake an agent. Omitted status means todo, subject to blockers. Include required inputs and constraints in self-contained child instructions.",
|
||||
"description": "Create a task. When the user names an existing teammate or project, resolve their IDs with list_agents or list_projects and set assigneeActorId or projectId in this creation call. A todo task can start its assignee immediately; creating it for yourself and reassigning later can start the wrong agent. Persist initialPlan before execution. Use backlog to save or plan without starting work; backlog tasks never wake an agent. Omitted status means todo, subject to blockers. Include required inputs and constraints in self-contained task instructions.",
|
||||
"exposure": "optional",
|
||||
"requiredClaims": [
|
||||
"delegation:tasks:create"
|
||||
@@ -101,7 +101,7 @@ export const createTaskAction = {
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Child task title.",
|
||||
"description": "Task title.",
|
||||
"minLength": 1,
|
||||
"maxLength": 500
|
||||
},
|
||||
@@ -110,7 +110,7 @@ export const createTaskAction = {
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "Self-contained child instructions with actual required inputs, exact payloads or accessible authorized source references, constraints, and requested outputs. The child does not inherit the parent conversation. Do not use unresolved references such as provided above, or copy credentials or secrets.",
|
||||
"description": "Self-contained task instructions with actual required inputs, exact payloads or accessible authorized source references, constraints, and requested outputs. The new task does not inherit this conversation. Do not use unresolved references such as provided above, or copy credentials or secrets.",
|
||||
"maxLength": 20000
|
||||
},
|
||||
"assigneeUserId": { "type": ["string", "null"], "description": "Company person ID from list_people. Mutually exclusive with assigneeActorId." },
|
||||
@@ -156,7 +156,7 @@ export const createTaskAction = {
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "Optional parent task ID. Omit it to create a child of the current task, or a top-level task from a conversation. To split work into a parent and subtasks, create the parent first, then pass its ID here for each subtask. Agents nest one level: a child of a child is placed beside it, and the result reports the parent actually used. A conversation is never a parent.",
|
||||
"description": "Optional parent task ID. Omit it to create a child of the current task, or a top-level task from a conversation. Agents nest one level: a child of a child is placed beside it, and the result reports the parent actually used. A conversation is never a parent.",
|
||||
"minLength": 1,
|
||||
"maxLength": 200
|
||||
},
|
||||
@@ -285,7 +285,7 @@ export const createTaskAction = {
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Self-contained child instructions with actual required inputs, exact payloads or accessible authorized source references, constraints, and requested outputs. The child does not inherit the parent conversation. Do not use unresolved references such as provided above, or copy credentials or secrets."
|
||||
"description": "Self-contained task instructions with actual required inputs, exact payloads or accessible authorized source references, constraints, and requested outputs. The new task does not inherit this conversation. Do not use unresolved references such as provided above, or copy credentials or secrets."
|
||||
},
|
||||
"assigneeUserId": { "type": ["string", "null"], "description": "Company person ID from list_people. Mutually exclusive with assigneeActorId." },
|
||||
"assigneeActorId": {
|
||||
|
||||
@@ -51,7 +51,7 @@ const NAMESPACE: Readonly<Record<CapabilitySemanticOperationId, string>> = Objec
|
||||
export const CAPABILITY_DISCOVERY_NAMESPACES = Object.freeze([
|
||||
{ name: "api_fallback", description: "API escape hatch for work unsupported by available dedicated tools." },
|
||||
{ name: "discovery", description: "Find company tasks and agents." },
|
||||
{ name: "delegation", description: "Create bounded child work and task dependencies." },
|
||||
{ name: "delegation", description: "Task assignment, parentage, and dependencies." },
|
||||
{ name: "governance", description: "Read, request, discuss, and decide approvals." },
|
||||
{ name: "workspace", description: "Inspect task files, prepare repositories, select workspaces, and control workspace services." },
|
||||
{ name: "continuation", description: "Schedule a bounded continuation wake." },
|
||||
|
||||
@@ -54,10 +54,9 @@ describe("describeIssueWriteDenial", () => {
|
||||
expect(copy.whoCanAct).toContain("CodexCoder");
|
||||
});
|
||||
|
||||
it("points a visibility denial at the sanctioned child-issue path", () => {
|
||||
it("points a visibility denial at the missing permission", () => {
|
||||
const copy = describeIssueWriteDenial("issue_write_not_visible");
|
||||
// The incident detour was discovering exactly this workaround.
|
||||
expect(copy.sanctionedPath).toContain("child issue");
|
||||
expect(copy.sanctionedPath).toContain("Ask the board to widen visibility");
|
||||
});
|
||||
|
||||
it("frames the per-run cap as a rate backstop, not a permission decision", () => {
|
||||
|
||||
@@ -117,15 +117,6 @@ function actorLabel(name: string | null | undefined): string {
|
||||
return trimmed && trimmed.length > 0 ? trimmed : "this agent";
|
||||
}
|
||||
|
||||
/**
|
||||
* The escape hatch an earlier incident had to discover by trial and error. Naming it in
|
||||
* every boundary denial is the point of plan §6 — an agent that reads the error
|
||||
* should not need a detour to find the supported path.
|
||||
*/
|
||||
const CHILD_ISSUE_PATH =
|
||||
"create a child issue with the request in its description (issue creation is a " +
|
||||
"separate, open write path) and let its assignee act";
|
||||
|
||||
export function describeIssueWriteDenial(
|
||||
code: IssueWriteDenialCode,
|
||||
context: IssueWriteDenialContext = {},
|
||||
@@ -150,7 +141,7 @@ export function describeIssueWriteDenial(
|
||||
whoCanAct:
|
||||
`${assignee}, and any agent or board member the task is visible to.`,
|
||||
sanctionedPath:
|
||||
`Ask the board to widen visibility for ${actor}, or ${CHILD_ISSUE_PATH}.`,
|
||||
`Ask the board to widen visibility for ${actor}.`,
|
||||
};
|
||||
|
||||
case "issue_write_actor_class_excluded":
|
||||
|
||||
+3
-4
@@ -190,10 +190,9 @@ its commit before writing code. For each accepted connection:
|
||||
connect, catalog discovery, an allowed read, an ask-first write, a
|
||||
denied/quarantined action, revoke, and audit. Include negative company,
|
||||
actor, resource, and changed-schema cases where applicable.
|
||||
6. Use a first-class QA child issue only when real credentials, vendor consent,
|
||||
or browser evidence cannot be completed safely by the implementing agent.
|
||||
Link it as a blocker and give QA exact, secret-safe steps and expected
|
||||
evidence.
|
||||
6. If real credentials, vendor consent, or browser evidence are unavailable,
|
||||
report the missing input and required evidence on the current task. Preserve
|
||||
any required QA review and permission controls.
|
||||
7. Run the standard PR-preparation workflow for this connector PR. Do not hand
|
||||
it back for merge until focused verification passes, all required checks are
|
||||
green, Greptile is 5/5, and every actionable comment is resolved.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"schemaVersion": 1,
|
||||
"packageName": "@paperclipai/skills-catalog",
|
||||
"packageVersion": "0.3.1",
|
||||
"generatedAt": "2026-10-06T01:21:47.421Z",
|
||||
"generatedAt": "2026-11-09T20:56:52.178Z",
|
||||
"skills": [
|
||||
{
|
||||
"id": "paperclipai:bundled:docs:doc-maintenance",
|
||||
@@ -1149,8 +1149,8 @@
|
||||
{
|
||||
"path": "SKILL.md",
|
||||
"kind": "skill",
|
||||
"sizeBytes": 12409,
|
||||
"sha256": "5278d288a0cbfe10fdda4ef3d99cf61e6ed068f4b6c1282406b0e001c9f45253"
|
||||
"sizeBytes": 12373,
|
||||
"sha256": "e508528adc29b78ea47374df461f05f5ea2c97628427a6fe26edbd3d5a8eef54"
|
||||
},
|
||||
{
|
||||
"path": "examples/notion-mcp-research-gate.md",
|
||||
@@ -1159,7 +1159,7 @@
|
||||
"sha256": "944b13ac67c06c65643eb236e856f1479106749861535648d29334f84cf1b50b"
|
||||
}
|
||||
],
|
||||
"contentHash": "sha256:84f2a28d7d004393719684f2b435e5ee01ddc58591e0dfeb73d72c7605db7f49"
|
||||
"contentHash": "sha256:59be0a3aed017c368f22ef4855bd41be0787e7e410189d2d7d1f478f24916c1a"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -37,7 +37,7 @@ A minimal design team built around a single Principal Product Designer. Install
|
||||
|
||||
- `wireframe` (bundled) — structured low-fidelity wireframing for new flows.
|
||||
- `design-critique` (optional skill catalog) — structured visual/UX critique format. Installs from the skill catalog as a prerequisite at team install time.
|
||||
- `task-planning` — breaks larger design asks into reviewable child issues.
|
||||
- `task-planning` — defines scope and review steps for larger design asks.
|
||||
|
||||
## Migration notes
|
||||
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ An optional drop-in engineering pod for companies that want a working software-d
|
||||
|
||||
- `github-pr-workflow` keeps logical commits, branch hygiene, and merge discipline consistent across the pod.
|
||||
- `qa-acceptance` gives QA a structured pass/fail format coders can act on.
|
||||
- `task-planning` lets the CTO turn larger asks into well-scoped child issues.
|
||||
- `task-planning` lets the CTO plan larger asks with clear scope.
|
||||
- `doc-maintenance` keeps docs aligned with shipped changes — install if the company has any user-facing docs surface.
|
||||
|
||||
## Migration notes
|
||||
|
||||
+1
-1
@@ -5,4 +5,4 @@ description: Rolling backlog for product engineering implementation, review, and
|
||||
owner: cto
|
||||
---
|
||||
|
||||
The pod's home project. Inbound product priorities become engineering child issues here. Use the CTO for triage and review, the Senior Coder for implementation, and QA for verification.
|
||||
The pod's home project. This project holds engineering work for product priorities. Use the CTO for triage and review, the Senior Coder for implementation, and QA for verification.
|
||||
+1
-1
@@ -16,7 +16,7 @@ Use the current task and authenticated caller context supplied by Paperclip. Cal
|
||||
|
||||
## Work and delegation
|
||||
|
||||
Start actionable work in the same heartbeat; stop at a plan only when planning was requested. Preserve the task's existing assignment and context. If another company agent should help, create a scoped child issue with a clear deliverable and report its result to the caller through the parent task. Do not invent a team, change the parent assignee, or repeatedly poll agents or sessions.
|
||||
Start actionable work in the same heartbeat; stop at a plan only when planning was requested. Preserve the task's existing assignment and context. Continue work on the current task. If the user requests another agent, include a clear deliverable in that assignment and report its result to the caller. Do not invent a team, change the parent assignee, or repeatedly poll agents or sessions.
|
||||
|
||||
Persist progress, decisions, and the next action in task comments, documents, or work products. For long work, publish a brief safe progress summary and continue. Keep the runtime turn open until commands finish using the adapter's supported wait or monitor tools. Background processes can be terminated when the turn ends: do not finish with a promise to check later while the only remaining work lives in a background process. If work must continue after your turn, arrange a durable Paperclip continuation before returning. Mark blocked work with the owner and action needed to unblock it. Respect company boundaries, budgets, pause/cancel instructions, and approval gates. Spoken consent does not replace a governed approval in Paperclip.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"schemaVersion": 1,
|
||||
"packageName": "@paperclipai/teams-catalog",
|
||||
"packageVersion": "0.1.0",
|
||||
"generatedAt": "2026-10-08T10:35:56.448Z",
|
||||
"generatedAt": "2026-11-09T20:56:53.242Z",
|
||||
"teams": [
|
||||
{
|
||||
"id": "paperclipai:bundled:company-defaults:core-exec-team",
|
||||
@@ -212,8 +212,8 @@
|
||||
{
|
||||
"path": "TEAM.md",
|
||||
"kind": "team",
|
||||
"sizeBytes": 2025,
|
||||
"sha256": "f950f4f77a26afa458ca0696994b51353a6bcfac81471fdc00c05f63950fcac5"
|
||||
"sizeBytes": 2024,
|
||||
"sha256": "358e1039e2ced32e8b40ecdb91e8be922451eac1283a81546030fdae1f0ac22c"
|
||||
},
|
||||
{
|
||||
"path": "agents/ux-designer/AGENTS.md",
|
||||
@@ -236,7 +236,7 @@
|
||||
],
|
||||
"trustLevel": "markdown_only",
|
||||
"compatibility": "compatible",
|
||||
"contentHash": "sha256:67b041c3adc20583f844fd2415e1c67859a8342b59e46ec32b038b70b7af0108"
|
||||
"contentHash": "sha256:ce0c76ace4fe19fca6a1b3b59e63ea6717366e90d1c437f3a7215d5c1da1bcf1"
|
||||
},
|
||||
{
|
||||
"id": "paperclipai:bundled:software-development:product-engineering",
|
||||
@@ -331,8 +331,8 @@
|
||||
{
|
||||
"path": "TEAM.md",
|
||||
"kind": "team",
|
||||
"sizeBytes": 2583,
|
||||
"sha256": "7204eeef78a48714dd3f82b82e171a4039adc6325e91a6bdf51a442105ee33b0"
|
||||
"sizeBytes": 2570,
|
||||
"sha256": "36da9b22db9087340a5cf30c5bdf5072ea68bf14fd4d2a2ddd0486b4725f78fe"
|
||||
},
|
||||
{
|
||||
"path": ".paperclip.yaml",
|
||||
@@ -361,8 +361,8 @@
|
||||
{
|
||||
"path": "projects/product-engineering/PROJECT.md",
|
||||
"kind": "project",
|
||||
"sizeBytes": 358,
|
||||
"sha256": "225d01c5b5b77f5d4dafedc083899c9368c9b079db1d3b7b67cfebd4677fc527"
|
||||
"sizeBytes": 353,
|
||||
"sha256": "2570ca611c78da876759458167706981777fa7b4e4efd8d0db57c7412976f376"
|
||||
},
|
||||
{
|
||||
"path": "projects/product-engineering/tasks/weekly-engineering-sync/TASK.md",
|
||||
@@ -373,7 +373,7 @@
|
||||
],
|
||||
"trustLevel": "assets",
|
||||
"compatibility": "compatible",
|
||||
"contentHash": "sha256:b9076b17a551b704a97df2e0204cefb83edfda4d36e909889071bb02d251e5ea"
|
||||
"contentHash": "sha256:78aeac52e7052b74dd8a3770a0f3c8f3c19bf6e5201cf87e56428ad51d59af66"
|
||||
},
|
||||
{
|
||||
"id": "paperclipai:optional:communications:speko-company-phone-agent",
|
||||
@@ -427,8 +427,8 @@
|
||||
{
|
||||
"path": "agents/speko-company-phone-agent/AGENTS.md",
|
||||
"kind": "agent",
|
||||
"sizeBytes": 3199,
|
||||
"sha256": "922d60cfae8a469876390b3434a513f0b3eff09c8263b51c3f222d388417ac1d"
|
||||
"sizeBytes": 3202,
|
||||
"sha256": "76953ef1ab541a219d9835bd0a3461845e92a1861e90675a167734854f2647f2"
|
||||
},
|
||||
{
|
||||
"path": "LICENSE",
|
||||
@@ -445,7 +445,7 @@
|
||||
],
|
||||
"trustLevel": "assets",
|
||||
"compatibility": "compatible",
|
||||
"contentHash": "sha256:e723a036948dcb292382fbcb116c68500c2247b004d0a8d8ef818b6725f91215"
|
||||
"contentHash": "sha256:4a38efe38a407db87a6872880aa9c575f39b34dbb8c0c65dbac0d28aec69116c"
|
||||
},
|
||||
{
|
||||
"id": "paperclipai:optional:content:content-machine",
|
||||
|
||||
@@ -863,7 +863,7 @@ describeEmbeddedPostgres("accepted plan workspace refresh", () => {
|
||||
otherActiveClaimIdentifier: "PAP-9302",
|
||||
}));
|
||||
expect(adapterInput.context.paperclipTaskMarkdown).toContain("Make the plan only.");
|
||||
expect(adapterInput.context.paperclipTaskMarkdown).not.toContain("Create child issues from the approved plan only");
|
||||
expect(adapterInput.context.paperclipTaskMarkdown).not.toContain("Implement the accepted plan on this issue.");
|
||||
}, 20_000);
|
||||
|
||||
it("guards cross-issue accepted-plan retries even when the waking issue is standard work mode", async () => {
|
||||
@@ -1025,7 +1025,7 @@ describeEmbeddedPostgres("accepted plan workspace refresh", () => {
|
||||
otherActiveClaimIdentifier: "PAP-9402",
|
||||
}));
|
||||
expect(adapterInput.context.paperclipTaskMarkdown).toContain("Issue: \"PAP-9401\"");
|
||||
expect(adapterInput.context.paperclipTaskMarkdown).not.toContain("Create child issues from the approved plan only");
|
||||
expect(adapterInput.context.paperclipTaskMarkdown).not.toContain("Implement the accepted plan on this issue.");
|
||||
}, 20_000);
|
||||
|
||||
it("preserves accepted-plan instructions but replaces a pre-identity session when the wake issue owns the in-flight claim", async () => {
|
||||
@@ -1163,7 +1163,7 @@ describeEmbeddedPostgres("accepted plan workspace refresh", () => {
|
||||
expect(adapterInput.runtime.sessionId).toBeNull();
|
||||
expect(adapterInput.context.acceptedPlanWakeRouting).toBeUndefined();
|
||||
expect(adapterInput.context.paperclipTaskMarkdown).toContain(
|
||||
"Implement the accepted plan on this issue when the work is small and cohesive.",
|
||||
"Implement the accepted plan on this issue.",
|
||||
);
|
||||
}, 20_000);
|
||||
});
|
||||
@@ -519,7 +519,7 @@ describe("buildPaperclipTaskMarkdown", () => {
|
||||
});
|
||||
|
||||
expect(acceptedConfirmation).toContain(
|
||||
"Implement the accepted plan on this issue when the work is small and cohesive.",
|
||||
"Implement the accepted plan on this issue.",
|
||||
);
|
||||
expect(acceptedConfirmation).not.toContain("Make the plan only.");
|
||||
});
|
||||
@@ -538,7 +538,7 @@ describe("buildPaperclipTaskMarkdown", () => {
|
||||
|
||||
expect(acceptedConfirmation).toContain("Accepted plan directive:");
|
||||
expect(acceptedConfirmation).toContain(
|
||||
"Implement the accepted plan on this issue when the work is small and cohesive.",
|
||||
"Implement the accepted plan on this issue.",
|
||||
);
|
||||
expect(acceptedConfirmation).not.toContain("- Work mode: \"planning\"");
|
||||
});
|
||||
@@ -646,7 +646,7 @@ describe("buildPaperclipTaskMarkdown", () => {
|
||||
});
|
||||
|
||||
expect(commentWake).toContain("Update the plan only. Do not write code or perform implementation work.");
|
||||
expect(commentWake).not.toContain("Create child issues from the approved plan only");
|
||||
expect(commentWake).not.toContain("Implement the accepted plan on this issue.");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1062,7 +1062,7 @@ describe("issue comment reopen routes", () => {
|
||||
// Plan §6: name the boundary, who can act, and the sanctioned path.
|
||||
expect(res.body.error).toContain("Issue visibility");
|
||||
expect(res.body.error).toContain("Who can act:");
|
||||
expect(res.body.details.sanctionedPath).toContain("child issue");
|
||||
expect(res.body.details.sanctionedPath).toContain("Ask the board to widen visibility");
|
||||
expect(mockAccessService.decide).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ action: "issue:comment" }),
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ async function nativeProposalRecipe(kind: "confirmation" | "checkbox", planRevis
|
||||
const recipes = [...skill.matchAll(/^ {0,3}```json\n([\s\S]*?)^ {0,3}```/gm)].map(match => JSON.parse(match[1]!) as Record<string, unknown>);
|
||||
const matches = recipes.filter(recipe => recipe.interactionKind === kind);
|
||||
expect(matches, `one executable native ${kind} recipe must ship with the first-task skill`).toHaveLength(1);
|
||||
return JSON.parse(JSON.stringify(matches[0]).replaceAll("<child-title>", "Approved child")
|
||||
return JSON.parse(JSON.stringify(matches[0]).replaceAll("<task-title>", "Approved work")
|
||||
.replaceAll("<plan-revision-id>", planRevisionId)) as Record<string, unknown>;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,6 @@ Server-enforced target keys:
|
||||
|
||||
- Start concrete work in the same heartbeat when the issue is actionable; do not stop at a plan unless planning was requested.
|
||||
- Leave durable progress in comments, issue documents, or draft files, with a clear next action owner.
|
||||
- Use child issues for long or parallel delegated work instead of polling.
|
||||
- Continue work on the current issue; do not busy-poll.
|
||||
- If blocked, mark the issue blocked and name the unblock owner and exact action needed.
|
||||
- Respect budget, pause/cancel, approval gates, execution policy stages, and company boundaries.
|
||||
@@ -47,9 +47,9 @@ Status quick guide:
|
||||
|
||||
## 6. Delegation
|
||||
|
||||
- Create subtasks with `POST /api/companies/{companyId}/issues`. Always set `parentId` and `goalId`. Each subtask gets its own workspace from the project base, never the parent's checkout or unmerged changes.
|
||||
- When you know the needed work and owner, create those subtasks directly. When the board/user must choose from a proposed task tree, answer structured questions, or confirm a proposal before you can proceed, create an issue-thread interaction on the current issue with `POST /api/issues/{issueId}/interactions` using `kind: "suggest_tasks"`, `kind: "ask_user_questions"`, or `kind: "request_confirmation"` and `continuationPolicy: "wake_assignee"` when the answer should wake you.
|
||||
- For plan approval, update the `plan` document first, create `request_confirmation` targeting the latest `plan` revision, use an idempotency key like `confirmation:{issueId}:plan:{revisionId}`, set the source issue to `in_review`, and do not create implementation subtasks until the board/user accepts it.
|
||||
- Optional task creation uses `POST /api/companies/{companyId}/issues`, with `parentId` and `goalId` available. Each subtask gets its own workspace from the project base, never the parent's checkout or unmerged changes.
|
||||
- Continue work on the current issue. When the board/user must choose from a proposed task tree, answer structured questions, or confirm a proposal before you can proceed, create an issue-thread interaction on the current issue with `POST /api/issues/{issueId}/interactions` using `kind: "suggest_tasks"`, `kind: "ask_user_questions"`, or `kind: "request_confirmation"` and `continuationPolicy: "wake_assignee"` when the answer should wake you.
|
||||
- For plan approval, update the `plan` document first, create `request_confirmation` targeting the latest `plan` revision, use an idempotency key like `confirmation:{issueId}:plan:{revisionId}`, set the source issue to `in_review`, and do not start implementation until the board/user accepts it.
|
||||
- `ask_user_questions` and confirmations default `supersedeOnUserComment` to `false`, so a later board/user comment keeps the pending card open while discussion continues. Set it to `true` when a new comment should replace the pending request. If you are woken by a superseding comment, revise the question set or proposal and create a fresh interaction if input is still needed.
|
||||
- Use `paperclip-create-agent` skill when hiring new agents.
|
||||
- Assign work to the right agent for the job.
|
||||
|
||||
@@ -16,7 +16,7 @@ You are the CEO.
|
||||
- Create organizational clarity. If priorities are unclear, it's on you; repeat strategy until it sticks.
|
||||
- Pull for bad news and reward candor. If problems stop surfacing, you've lost your information edge.
|
||||
- Stay close to the customer. Dashboards help, but regular firsthand conversations keep you honest.
|
||||
- Be replaceable in operations and irreplaceable in judgment. Delegate execution; keep your time for strategy, capital allocation, key hires, and existential risk.
|
||||
- Be replaceable in operations and irreplaceable in judgment. Balance execution with strategy, capital allocation, key hires, and existential risk.
|
||||
|
||||
## Voice and Tone
|
||||
|
||||
|
||||
@@ -33,19 +33,19 @@ Work in this order.
|
||||
|
||||
- Determine the requested outcome before choosing an approval boundary. The interview path and requests to build, improve, or deliver something are execution requests: the plan is an intermediate artifact. Treat a request as plan-only only when the user explicitly limits the deliverable to planning. Asking to review a plan before work begins does not make it plan-only. Preserve any separate hiring or execution approvals the user explicitly requests and any applicable company policies.
|
||||
|
||||
- If the user asks to continue onboarding in your chat with them instead, ask your questions there. Your first question in the chat replaces this task's pending question cards, and Paperclip closes this task with a link to the chat. From then on the chat replaces this task for the rest of this workflow: save the plan and post proposal cards in the chat, create accepted child tasks from the chat, and report their results there. Skip the steps below that keep this task `in_review`, save documents on it, or make it wait for a child. Do not reopen this task or ask the user what should happen to it.
|
||||
- If the user asks to continue onboarding in your chat with them instead, ask your questions there. Your first question in the chat replaces this task's pending question cards, and Paperclip closes this task with a link to the chat. From then on the chat replaces this task for the rest of this workflow: save the plan and post proposal cards in the chat, create accepted execution tasks from the chat, and report their results there. Skip the steps below that keep this task `in_review`, save documents on it, or make it wait for a child. Do not reopen this task or ask the user what should happen to it.
|
||||
|
||||
2. Propose, then wait for acceptance.
|
||||
|
||||
- Choose the proposal form from the user’s request first: an explicit plan request or the interview path always requires a saved plan, even when the task description says `confirmation`.
|
||||
- For the interview path or an explicit plan request, save a `plan` document on this onboarding task describing the goal, scope, steps, proposed team, and what done means. Post one `request_checkbox_confirmation` targeting the saved plan revision. A card or thread message alone is not a saved plan. This applies to explicit plan requests regardless of the single-task proposal mode. Proposing a team alone does not authorize hiring it; the recorded acceptance authorizes only the team and work actually included in the accepted scope, subject to normal hiring and budget policies.
|
||||
- For an execution request, make the saved plan and approval card say "Approve this plan and start the described work." Describe the tasks and any proposed hires the user is approving. Do not add a separate implementation-approval requirement unless the user or an applicable policy requires it. For an explicitly plan-only request, make the card say "Approve this plan only; do not start implementation."
|
||||
- If they want one thing done, propose exactly one child task with a clear outcome and scope. Ask them to accept it before creating the child. Do not produce the requested finished work inside the proposal, even when it is quick to do.
|
||||
- For a single-task proposal, follow the `Single-task proposal mode` saved in the task description: `confirmation` means one `request_confirmation` card describing the child task, without a plan document; `plan` means save a short `plan` document describing that same child task and post one `request_checkbox_confirmation` targeting its saved revision.
|
||||
- If they want one thing done, propose completing it on this task with a clear outcome and scope. Ask them to accept the scope before execution. Do not produce the requested finished work inside the proposal, even when it is quick to do.
|
||||
- For a single-task proposal, follow the `Single-task proposal mode` saved in the task description: `confirmation` means one `request_confirmation` card describing the work, without a plan document; `plan` means save a short `plan` document describing that same work and post one `request_checkbox_confirmation` targeting its saved revision.
|
||||
- With native tools, create those proposal cards using `request_human_input`: `interactionKind: "confirmation"` creates `request_confirmation`; `interactionKind: "checkbox"` creates `request_checkbox_confirmation`. Use `continuationPolicy: "wake_assignee"` so acceptance and rejection both return the decision to you; only a saved acceptance authorizes the approved work. Use `interactionKind: "questions"` only to collect scope or clarification answers. An Approve/Revise choice question is still a question, so answering it does not record proposal acceptance or authorize child creation. Present the proposal through the matching confirmation kind instead.
|
||||
- Keep this task `in_review` while waiting. You may clarify, research for planning, and save or revise a plan/proposal before acceptance. Do not hire, create execution tasks, perform the deliverable, save finished output, or claim completion yet.
|
||||
|
||||
For a native single-task confirmation, call `request_human_input` with arguments like these. Replace `<child-title>` with the proposed title and describe its actual scope in the prompt. Use a new idempotency key for each changed or revised proposal. Reuse a key only for the exact same proposal when reconciling an interrupted call; the example key below is for the first proposal.
|
||||
For a native single-task confirmation, call `request_human_input` with arguments like these. Replace `<task-title>` with the proposed title and describe its actual scope in the prompt. Use a new idempotency key for each changed or revised proposal. Reuse a key only for the exact same proposal when reconciling an interrupted call; the example key below is for the first proposal.
|
||||
|
||||
The tool's root fields are `idempotencyKey`, `interactionKind`, `title`, `prompt`, `continuationPolicy`, and `payload`, with optional `targetRevisionId` and `resolverPolicy` as advertised. Put `version` and `supersedeOnUserComment` inside `payload`; neither is a root argument. If validation rejects a proposal, correct its argument placement and keep the confirmation or checkbox approval kind. Switching it to a question form cannot authorize the proposed work. Wait for a successful saved card receipt before claiming you requested approval.
|
||||
|
||||
@@ -55,8 +55,8 @@ Work in this order.
|
||||
{
|
||||
"idempotencyKey": "first-task-proposal-confirmation",
|
||||
"interactionKind": "confirmation",
|
||||
"title": "Approve child task",
|
||||
"prompt": "Approve creating exactly one child task named \"<child-title>\" for the scope described above?",
|
||||
"title": "Approve work",
|
||||
"prompt": "Approve completing \"<task-title>\" on this task for the scope described above?",
|
||||
"continuationPolicy": "wake_assignee",
|
||||
"payload": {
|
||||
"version": 1,
|
||||
@@ -68,7 +68,7 @@ Work in this order.
|
||||
}
|
||||
```
|
||||
|
||||
For a native single-task proposal in plan mode, save the plan first, then call `request_human_input` with a checkbox card bound to its actual revision. Replace `<child-title>` and `<plan-revision-id>`; make the options describe the scope the user is approving. For an explicitly plan-only request, change the prompt and option to approve the plan alone without implementation or hiring.
|
||||
For a native single-task proposal in plan mode, save the plan first, then call `request_human_input` with a checkbox card bound to its actual revision. Replace `<task-title>` and `<plan-revision-id>`; make the options describe the scope the user is approving. For an explicitly plan-only request, change the prompt and option to approve the plan alone without implementation or hiring.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -80,7 +80,7 @@ Work in this order.
|
||||
"payload": {
|
||||
"version": 1,
|
||||
"supersedeOnUserComment": false,
|
||||
"options": [{ "id": "scope", "label": "Approve the plan and start <child-title>" }],
|
||||
"options": [{ "id": "scope", "label": "Approve the plan and start <task-title>" }],
|
||||
"defaultSelectedOptionIds": ["scope"],
|
||||
"minSelected": 1,
|
||||
"maxSelected": 1,
|
||||
@@ -100,10 +100,13 @@ Work in this order.
|
||||
4. Carry out the accepted scope.
|
||||
|
||||
- For a plan-only request, retain the accepted plan on this task. Do not start its implementation or hire the proposed team without authorization to do that work.
|
||||
- For an accepted interview execution plan, create or resume the minimum execution tasks needed for the approved outcome. Link them to this onboarding task and assign each to yourself or an approved agent, ready to run. Use normal hiring controls for any approved hires. Check for existing tasks from this proposal first so later wakes and retries continue the same work.
|
||||
- For an accepted interview execution plan, carry out the approved work on this task unless the accepted plan explicitly assigns work elsewhere. Use normal hiring controls for any approved hires. Check for existing tasks from this proposal first so later wakes and retries continue the same work.
|
||||
- A recorded acceptance of an execution proposal authorizes starting its selected work. Start that work without asking the user to approve the same scope again. Honor an accepted proposal that explicitly reserved a later approval; never expand its authorization retroactively. Missing credentials or connections block only the steps that require them; continue independent approved work.
|
||||
- For an accepted single task, check for an existing child from this proposal before creating anything. Create exactly one child linked to this onboarding task and assign it to yourself. On later wakes, continue that same child instead of creating another.
|
||||
- For an accepted single task, complete the work here. Save the output document and publish any requested file on this task before marking it done. If the accepted proposal already specified a separate task, honor that assignment and reuse any task already created for it.
|
||||
- A saved, approved plan alone does not complete an execution request. Follow the execution and result-delivery steps below for the approved tasks, and report the actual output before completing onboarding. An explicitly plan-only request is complete when its accepted plan is retained.
|
||||
|
||||
The following handoff steps apply only when the accepted proposal explicitly includes a separate task. They do not require a new task for work you can complete here.
|
||||
|
||||
- If the accepted child work requires a file deliverable, include the approved scope, document requirements, and requested filenames in a self-contained child description. Delegate the work to the child's own Paperclip execution, even when the child is assigned to yourself. That execution must save the document and publish the requested file on the child before marking it done. Do not create or register that file from the onboarding run, or mark the child done before its execution delivers the file. Native `register_deliverable` is bound to its current task.
|
||||
- Copy required input payloads verbatim, including encoded bytes, nonces, constraints, and requested filenames, from the accepted request and its accepted corrections into the child description. The child has its own execution context and does not inherit this conversation. Do not leave references such as "provided above" or "same as the parent" in place of actual inputs. When an input is not inline, include its actual retrievable source reference as an identifier link such as `[BRA-2](/BRA/issues/BRA-2#document-plan)`, not a raw UUID, and ensure the child is authorized to read it. Keep credentials and secrets out of handoff text.
|
||||
- Parent-child linkage is not a dependency. Do not put this onboarding task in the child's `blockedByTaskIds`: the child must execute before this task can finish. Create the child ready to run, then make this onboarding task wait for the child.
|
||||
|
||||
@@ -257,7 +257,7 @@ export function buildPaperclipTaskMarkdown(input: {
|
||||
}
|
||||
if (acceptedPlanContinuation) {
|
||||
directive =
|
||||
"Implement the accepted plan on this issue when the work is small and cohesive. Use the paperclip-converting-plans-to-tasks skill to decide whether decomposition is justified. Create the minimum child issue graph only for qualifying ownership, parallelism, dependency, review, or lifecycle boundaries. Do not create a child merely because a plan was accepted.";
|
||||
"Implement the accepted plan on this issue. Follow any task assignments explicitly included in the approved plan. Plan acceptance alone does not require subtasks.";
|
||||
}
|
||||
lines.push(
|
||||
`- Work mode: ${quoteTaskScalar("planning")}`,
|
||||
@@ -276,7 +276,7 @@ export function buildPaperclipTaskMarkdown(input: {
|
||||
lines.push(
|
||||
"",
|
||||
"Accepted plan directive:",
|
||||
"Implement the accepted plan on this issue when the work is small and cohesive. Use the paperclip-converting-plans-to-tasks skill to decide whether decomposition is justified. Create the minimum child issue graph only for qualifying ownership, parallelism, dependency, review, or lifecycle boundaries. Do not create a child merely because a plan was accepted.",
|
||||
"Implement the accepted plan on this issue. Follow any task assignments explicitly included in the approved plan. Plan acceptance alone does not require subtasks.",
|
||||
);
|
||||
}
|
||||
if (rejectedPlan) {
|
||||
|
||||
@@ -153,10 +153,10 @@ describe("first-task proposal mode policy", () => {
|
||||
const skill = await readFile(new URL("../onboarding-assets/first-task/skills/first-task/SKILL.md", import.meta.url), "utf8");
|
||||
expect(skill).toContain("For a plan-only request, retain the accepted plan on this task");
|
||||
expect(skill).toContain("Do not start its implementation or hire the proposed team without authorization");
|
||||
expect(skill).toContain("Create exactly one child linked to this onboarding task");
|
||||
expect(skill).toContain("For an accepted single task, complete the work here.");
|
||||
expect(skill).toContain("For document-only child work, you may execute it directly");
|
||||
expect(skill).toContain("Save the finished output as a document on the child task and mark that child done");
|
||||
expect(skill).toContain("On later wakes, continue that same child instead of creating another");
|
||||
expect(skill).toContain("reuse any task already created for it");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ If `currentParticipant` does not match you, do not try to advance the stage —
|
||||
- Ask for information only when it prevents the next useful action. Optional reproduction details, an example of a past failure, or a preferred test case do not block general inspection and verification. Continue the independent work; explain what remains unverified if the specific example is still unavailable. Keep real access restrictions and approval gates authoritative.
|
||||
- Leave durable progress in comments, issue documents, or work products, then update the issue state/path to a clear final disposition before you exit.
|
||||
- Treat comments, documents, screenshots, work products, and `Remaining` bullets as evidence. They are not valid liveness paths by themselves.
|
||||
- Use child issues for parallel or long delegated work; do not busy-poll agents, sessions, child issues, or processes waiting for completion.
|
||||
- Continue work on the current issue. Do not busy-poll agents, sessions, child issues, or processes waiting for completion.
|
||||
- If your heartbeat creates a pending board/user interaction or approval before more work can proceed, leave the source issue in an explicit waiting posture before you exit. Prefer `in_review` for review, approval, `request_confirmation`, `ask_user_questions`, and `suggest_tasks` waits. Use `blocked` with `blockedByIssueIds` when another issue is the blocker.
|
||||
- For a real blocker, use `blockedByIssueIds` or an `unblockDescriptor` with your own `owner: { "agentId": "<your-agent-id>" }` and an exact `action`. Agents cannot set board/user or other-agent unblock owners. Human-input waits use a saved pending interaction and `in_review`; prose alone is not a waiting path. See [Questions and waiting for human input](references/api-reference.md#questions-and-waiting-for-human-input) for valid payloads.
|
||||
- Human authority or missing permission does not imply a manager handoff. Keep ownership, identify the missing capability, and use the human-input payload below when a person must decide. Verify actual capability and permission before suggesting delegation.
|
||||
@@ -227,7 +227,7 @@ Before ending any heartbeat, apply this final-disposition checklist:
|
||||
- `done`: the requested work is complete, verification is recorded, and no follow-up remains on this issue.
|
||||
- `in_review`: a real reviewer path exists, such as 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.
|
||||
- `blocked`: work cannot continue until first-class `blockedByIssueIds` resolve or a named owner takes a concrete unblock action.
|
||||
- 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.
|
||||
- If work is delegated, 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.
|
||||
- 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.
|
||||
|
||||
When writing issue descriptions or comments, follow the ticket-linking rule in **Comment Style** below.
|
||||
@@ -280,7 +280,7 @@ response. Moving a task that has its own children under another task is skipped
|
||||
the same way. Use `blockedByIssueIds` (or `blockParentUntilDone`) when your task
|
||||
must wait for the new work; nesting is not a wait. Board users are not limited.
|
||||
|
||||
**Step 9 — Delegate if needed.** For ordinary execution tasks, create subtasks with `POST /api/companies/{companyId}/issues` and set `parentId` and `goalId`. 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. Every subtask gets its own workspace from the project base, never your checkout, branch or unmerged changes; to hand a subtask code, push or merge it first. Set `billingCode` for cross-team work.
|
||||
**Step 9 — Optional task creation.** `POST /api/companies/{companyId}/issues` supports `parentId` and `goalId`. 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. Every subtask gets its own workspace from the project base, never your checkout, branch or unmerged changes; to hand a subtask code, push or merge it first. Set `billingCode` for cross-team work.
|
||||
|
||||
### Delegating review tasks
|
||||
|
||||
@@ -291,7 +291,7 @@ Run-scoped writes are subtree-scoped: the delegate's run can write to its own is
|
||||
- Make the review issue's description **self-contained** — the delegate may not be able to read your issue or its documents. Put the full instructions, acceptance criteria, and material to review (or repo-relative pointers) in the description.
|
||||
- Block your issue on the review issue (`blockedByIssueIds`) so you wake when the verdict lands.
|
||||
|
||||
**Courier pattern (lateral coordination):** to nudge or hand context to an agent whose issues you cannot write to, create a new issue assigned to that agent carrying complete, self-contained instructions. Issue-CREATE is company-scoped and always available; commenting into another agent's boundary is not.
|
||||
**Lateral coordination:** use an authorized comment on the existing task to pass context. If access is denied, report the missing permission on your current task.
|
||||
|
||||
## Managing A User's Inbox
|
||||
|
||||
@@ -616,7 +616,7 @@ Exact response fields are documented in `skills/paperclip/references/api-referen
|
||||
- **Honor "send it back to me" requests from board users.** If a board/user asks for review handoff (e.g. "let me review it", "assign it back to me"), reassign to them with `assigneeAgentId: null` and `assigneeUserId: "<requesting-user-id>"`, typically setting status to `in_review` instead of `done`. Resolve the user id from the triggering comment's `authorUserId` when available, else the issue's `createdByUserId` if it matches the requester context.
|
||||
- **Start actionable work before planning-only closure.** Do concrete work in the same heartbeat unless the task asks for a plan or review only.
|
||||
- **Leave a next action.** Every progress comment should make clear what is complete, what remains, and who owns the next step.
|
||||
- **Prefer child issues over polling.** Create bounded child issues for long or parallel delegated work and rely on Paperclip wake events or comments for completion.
|
||||
- **Do not busy-poll.** For existing delegated work, rely on Paperclip wake events or comments for completion.
|
||||
- **Subtasks get their own workspace.** A child issue keeps its parent's project and workspace strategy, but the server always realizes a separate workspace for it from the project base. It never shares the parent's checkout, branch or unsaved files, and `inheritExecutionWorkspaceFromIssueId` does not change that. Share code between tasks through pushed branches or merged changes.
|
||||
- **Never cancel cross-team tasks.** If you question the task, follow the requester-directed decision flow in [Receiving cross-team work](references/api-reference.md#receiving-cross-team-work). Keep the task assigned to yourself; do not automatically hand it to a manager.
|
||||
- **Use first-class blockers** (`blockedByIssueIds`) rather than free-text "blocked by X" comments.
|
||||
|
||||
@@ -618,7 +618,7 @@ GET /api/companies/company-1/issues?assigneeAgentId=mgr-1&status=todo,in_progres
|
||||
POST /api/issues/issue-30/checkout
|
||||
{ "agentId": "mgr-1", "expectedStatuses": ["todo", "backlog", "blocked", "in_review"] }
|
||||
|
||||
# 6. Create subtasks and delegate.
|
||||
# 6. Task creation with an optional parent and assignee.
|
||||
POST /api/companies/company-1/issues
|
||||
{ "title": "Implement caching layer", "assigneeAgentId": "agent-42", "parentId": "issue-30", "status": "todo", "priority": "high", "goalId": "goal-1" }
|
||||
|
||||
@@ -1084,7 +1084,7 @@ Rules:
|
||||
- Use idempotency keys that include the target and version, for example `confirmation:${issueId}:plan:${latestRevisionId}`.
|
||||
- Set `supersedeOnUserComment: true` when a later board/user comment should expire the pending request. On that wake, revise the artifact/proposal and create a fresh confirmation if approval is still needed.
|
||||
- A pending interaction is an explicit waiting path. Before ending the heartbeat, update the source issue into a visible waiting posture, normally `in_review`, and leave a comment that names the response needed and the effective audience.
|
||||
- For plan approval, update the `plan` issue document first, create the confirmation against the latest plan revision, set the source issue to `in_review`, and wait for acceptance before creating implementation subtasks.
|
||||
- For plan approval, update the `plan` issue document first, create the confirmation against the latest plan revision, set the source issue to `in_review`, and wait for acceptance before implementation.
|
||||
|
||||
### Conversational confirmation answers
|
||||
|
||||
@@ -1674,7 +1674,7 @@ Every successful or failed value fetch writes both `secret_access_events` and `a
|
||||
| Retry a `409` checkout | The task belongs to someone else | Pick a different task |
|
||||
| Look for unassigned work | You're overstepping; managers assign work | If you have no assignments, exit |
|
||||
| Exit without commenting on in-progress work | Your manager can't see progress; work appears stalled | Leave a comment explaining where you are |
|
||||
| Create tasks without `parentId` | Breaks the task hierarchy; work becomes untraceable | Link every subtask to its parent |
|
||||
| Omit a required parent relationship | The task appears outside its intended hierarchy | Set `parentId` when a parent relationship is intended |
|
||||
| Cancel cross-team tasks | Only the assigning team's manager can cancel | Request a decision through a saved interaction |
|
||||
| Ignore budget warnings | You'll be auto-paused at 100% mid-work | Check spend at start; prioritize above 80% |
|
||||
| Expect an @-mention to dispatch work | Mentions are context only | Assign a task or request an explicit review |
|
||||
|
||||
@@ -275,8 +275,8 @@
|
||||
"packages/shared/src/issue-references.test.ts": "d4af275ae8c615ccdc587dfbfd675cea8626e530",
|
||||
"packages/shared/src/issue-references.ts": "bfdd2126fb12797f2c8177113285b2c3233aecef",
|
||||
"packages/shared/src/issue-thread-interactions.test.ts": "6f516055744fcedd2e0c06ce82c6a1a019120762",
|
||||
"packages/shared/src/issue-write-denial.test.ts": "2cf4d4977fda5f2894f7349594dd4a63abcd6962",
|
||||
"packages/shared/src/issue-write-denial.ts": "8e551dabfa1cbab9126d2431680429e90250fd2f",
|
||||
"packages/shared/src/issue-write-denial.test.ts": "e21b93aa79e6635c019ac338eff954ec618a98ed",
|
||||
"packages/shared/src/issue-write-denial.ts": "7844fa576492d53e064fc6326c9d94af827ce157",
|
||||
"packages/shared/src/markdown-work-products.test.ts": "7293d14ad45ec2b11b5deaab4ce070c36f7c9010",
|
||||
"packages/shared/src/markdown-work-products.ts": "16a88cfb717f325c247a516e78b47d53871b52ed",
|
||||
"packages/shared/src/mcp-config-help-prompt.ts": "fa58effb7cd995198909315d9ba2a93dedde0552",
|
||||
|
||||
@@ -27,8 +27,7 @@ describe("IssueWriteDenialNotice", () => {
|
||||
expect(html).toContain("Issue visibility");
|
||||
expect(html).toContain("TASK-482");
|
||||
expect(html).toContain("Fable");
|
||||
// The workaround the incident had to discover is now stated outright.
|
||||
expect(html).toContain("child issue");
|
||||
expect(html).toContain("Ask the board to widen visibility for Fable.");
|
||||
});
|
||||
|
||||
it("tones a run lock as transient rather than a permission wall", () => {
|
||||
|
||||
Reference in new issue
Block a user