fix(onboarding): make chief-of-staff hiring reliable (#13317)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The first agent helps the board define work and hire other agents.
> - That agent can have the general role while its instructions require
hiring skills.
> - Missing skills and blocked schema discovery make valid requests
fail.
> - Repeated confirmation and invalid waiting guidance can turn these
failures into extra runs.
> - This PR supplies the required skills, opens read-only schema
discovery, and corrects the guidance.
> - The agent can complete an authorized hire while company approval and
duplicate checks still apply.

## Linked Issues or Issue Description

Refs #13068 — the first-task onboarding flow that this change repairs.
Refs #12029 — related drift between the sandbox allowlist and bundled
hiring guidance. This PR adds schema access; it does not replace the
earlier hiring-route fix.

**What happened?**

A general-role onboarding chief received hiring instructions without the
core hiring skills. Sandbox requests to the documented OpenAPI endpoint
failed. The agent then guessed question and hire payloads. The persona
required new confirmation after validation errors and described waiting
states that agents cannot set.

**Expected behavior**

A direct request authorizes the requested hire. The chief asks only for
material missing details, uses valid API payloads, and completes the
task. Formal company approval gates still apply. A saved human-input
card gives the task a valid waiting state.

**Steps to reproduce**

1. Create an onboarding chief with role `general` through the board.
2. Ask it to hire a friendly robot with a supplied name and
responsibilities.
3. Check its assigned skills, schema requests, question cards, hire
requests, and final task state.

**Paperclip version or commit**

Reproduced on the first-task onboarding implementation after #13068. The
live local verification used this branch at `112f44610`.

**Deployment mode**

The original failure used a hosted sandbox with legacy Codex ACP. Live
verification used an isolated local instance and real `codex_local`
execution. Queue and HTTP/2 transport access is covered by automated
tests.

## What Changed

- Give board-created onboarding chiefs the existing core skills
regardless of role. Preserve explicit skill version pins, including
aliases. Keep ordinary general-agent defaults and authorization checks.
- Allow exactly `GET /api/openapi.json` through both sandbox bridge
transports.
- Publish validator-tested question, free-text, hire, and waiting
examples. Regenerate the runner API reference and capability inventory.
- Clarify direct authorization, material ambiguity, and correction of
confirmed pre-creation validation failures. Preserve uncertain-outcome
reconciliation, duplicate protection, and company approval gates.
- Align disposition instructions with agent permissions and the saved
human-input waiting path.

## Verification

- After rebasing onto current `master`: 69 targeted server tests, 110
queue/HTTP2 bridge tests, and 4 capability inventory tests passed. These
cover core skill defaults, version pins, actor restrictions, schema
access, published examples, hire validation, idempotency, and approval
gates. Waiting recovery tests and live question flows also passed before
the rebase.
- `pnpm -r typecheck` and `pnpm build` passed again after the rebase.
Frozen dependency installation and both generated capability checks
passed.
- Ran the full `pnpm test:run` suite. The initial run had 14 failed
server files due to local database resource limits, a missing built test
fixture, and socket failures. All 14 files passed after fixture repair
and isolated retries. UI, CLI, workspace packages, database tests, and
all 145 serialized server files passed.
- Real one-request hiring replay: one hire, one successful run, task
done in 2m16s. No repeated approval or recovery escalation.
- Real two-turn browser conversation: start with an unspecified hire,
then supply a name and friendly robot responsibilities. One
clarification card, one hire, two successful runs, task done in 3m27s of
execution. No failed writes, confirmation cards, or recovery actions.
- Assigned the hired robot a welcome-message task through the browser.
It produced a warm message under 100 words and finished in one
successful 66-second run, with no questions or recovery actions.
- The two-turn flow still asked an optional preferences question and
gave a technical final reply. These are remaining presentation limits.
- Greptile: 5/5 on `b71f83ba2`, with zero unresolved review threads.
Fixed its generator finding and passed 1,655 published-example/runtime
API tests plus server typecheck. All latest-head CI checks are green (32
passed; 2 unrelated Storybook checks skipped). The signoff-policy
browser test initially timed out while waiting for an approver run. Its
shard passed on one rerun without code changes. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/34698211049).

## Risks

- Onboarding chiefs receive more default skills. Ordinary general agents
retain existing defaults, and explicit versions take precedence.
- Prompt guidance can affect model behavior. The live replays are
examples, not a guarantee that every model follows the guidance.
- Retry guidance applies only when validation confirms that nothing was
created. Uncertain outcomes still require checking existing agents.
- No database migration or new public endpoint. Existing company
boundaries, approval gates, and bounded recovery remain in force.

## Model Used

OpenAI Codex, model `gpt-6-astra`, with reasoning, tool use, code
editing, and live browser verification. The exact context-window size is
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:
Dotta 2026-09-12 12:59:42 -05:00 committed by GitHub
parent 0e14c61da7
commit 7e6d512597
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 976 additions and 557 deletions

View File

@ -1910,6 +1910,38 @@ describe("createHttp2BridgeServer + createSandboxHttp2BridgeGateway", () => {
}
});
it("serves only exact GET schema discovery through HTTP/2", async () => {
const schema = { openapi: "3.1.0", paths: {} };
const forwarded: string[] = [];
const { gateway, handle } = createTestPair({
forwardRequest: async (request) => {
forwarded.push(`${request.method} ${request.pathname}`);
return { status: 200, body: Buffer.from(JSON.stringify(schema)) };
},
});
try {
for (const [method, path, status] of [
["GET", "/api/openapi.json", 200],
["POST", "/api/openapi.json", 403],
["PATCH", "/api/openapi.json", 403],
["DELETE", "/api/openapi.json", 403],
["GET", "/api/openapi.json/extra", 403],
["GET", "/api/openapiXjson", 403],
["GET", "/api/secrets", 403],
] as const) {
const response = await gateway.forwardRequest({
method, path, query: "", headers: {}, body: Buffer.alloc(0), receivedToken: BRIDGE_TOKEN,
});
expect(response.status).toBe(status);
if (status === 200) expect(JSON.parse(response.body!.toString())).toEqual(schema);
}
expect(forwarded).toEqual(["GET /api/openapi.json"]);
} finally {
await gateway.close();
await handle.close();
}
});
it("rejects a route the allowlist does not carry, before the forwarder runs", async () => {
const forwarderTracker = createForwarderCallTracker();
const { gateway, handle } = createTestPair({

View File

@ -286,6 +286,44 @@ describe("sandbox callback bridge", () => {
});
it("serves schema discovery over the queue and denies schema mutations and lookalikes", async () => {
const rootDir = await mkdtemp(path.join(os.tmpdir(), "paperclip-bridge-schema-"));
cleanupDirs.push(rootDir);
const queueDir = path.join(rootDir, "queue");
const directories = sandboxCallbackBridgeDirectories(queueDir);
const schema = { openapi: "3.1.0", paths: {} };
const forwarded: string[] = [];
const worker = await startSandboxCallbackBridgeWorker({
client: createFileSystemSandboxCallbackBridgeQueueClient(), queueDir,
handleRequest: async (request) => {
forwarded.push(`${request.method} ${request.path}`);
return { status: 200, body: JSON.stringify(schema) };
},
});
cleanupFns.push(() => worker.stop());
const requests = [
{ method: "GET", path: "/api/openapi.json" },
{ method: "POST", path: "/api/openapi.json" },
{ method: "PATCH", path: "/api/openapi.json" },
{ method: "DELETE", path: "/api/openapi.json" },
{ method: "GET", path: "/api/openapi.json/extra" },
{ method: "GET", path: "/api/openapiXjson" },
{ method: "GET", path: "/api/secrets" },
];
for (const [index, request] of requests.entries()) {
await writeFile(path.join(directories.requestsDir, `schema-${index}.json`), JSON.stringify({
id: `schema-${index}`, ...request, query: "", headers: {}, body: "", createdAt: new Date().toISOString(),
}));
}
await worker.stop({ drainTimeoutMs: 5_000 });
for (const [index] of requests.entries()) {
const response = JSON.parse(await readFile(path.join(directories.responsesDir, `schema-${index}.json`), "utf8"));
expect(response.status).toBe(index === 0 ? 200 : 403);
if (index === 0) expect(JSON.parse(response.body)).toEqual(schema);
}
expect(forwarded).toEqual(["GET /api/openapi.json"]);
});
it("denies non-allowlisted requests by default", async () => {
const rootDir = await mkdtemp(path.join(os.tmpdir(), "paperclip-bridge-default-policy-"));
cleanupDirs.push(rootDir);

View File

@ -125,6 +125,9 @@ export const DEFAULT_SANDBOX_CALLBACK_BRIDGE_ROUTE_ALLOWLIST: readonly SandboxCa
{ method: "POST", path: /^\/api\/agents\/[^/]+\/skills\/sync$/ },
{ method: "PATCH", path: /^\/api\/agents\/[^/]+\/instructions-path$/ },
// Read-only schema discovery for validated control-plane requests.
{ method: "GET", path: /^\/api\/openapi\.json$/ },
// Company-level reads used to discover work and context
{ method: "GET", path: /^\/api\/companies\/[^/]+$/ },
{ method: "GET", path: /^\/api\/companies\/[^/]+\/dashboard$/ },

View File

@ -8,9 +8,9 @@ The skill/reference inventory and eval cases are the only normative behavior sou
## Baseline Counts
- Skill/reference headings: 154
- Skill/reference headings: 155
- Eval cases: 106 across 16 groups
- Total normative rows: 260
- Total normative rows: 261
- Legacy MCP aliases folded into normative rows: 42
| Eval group | Cases |
@ -128,73 +128,74 @@ The skill/reference inventory and eval cases are the only normative behavior sou
| skill:skills/paperclip/references/workflows.md:company-import-export:79 | optional_agent_tool | skills/paperclip/references/workflows.md:79 |
| skill:skills/paperclip/references/workflows.md:self-test-playbook-app-level:106 | optional_agent_tool | skills/paperclip/references/workflows.md:106 |
| skill:skills/paperclip/references/api-reference.md:paperclip-api-reference:1 | optional_agent_tool | skills/paperclip/references/api-reference.md:1 |
| skill:skills/paperclip/references/api-reference.md:response-schemas:7 | optional_agent_tool | skills/paperclip/references/api-reference.md:7 |
| skill:skills/paperclip/references/api-reference.md:agent-record-get-api-agents-me-or-get-api-agents-agentid:9 | optional_agent_tool | skills/paperclip/references/api-reference.md:9 |
| skill:skills/paperclip/references/api-reference.md:company-portability:42 | optional_agent_tool | skills/paperclip/references/api-reference.md:42 |
| skill:skills/paperclip/references/api-reference.md:issue-with-ancestors-get-api-issues-issueid:108 | optional_agent_tool | skills/paperclip/references/api-reference.md:108 |
| skill:skills/paperclip/references/api-reference.md:issue-update-response-patch-api-issues-issueid:194 | optional_agent_tool | skills/paperclip/references/api-reference.md:194 |
| skill:skills/paperclip/references/api-reference.md:blocker-diagnostics-get-api-issues-issueid-diagnostics-blockers:236 | control_plane_owned | skills/paperclip/references/api-reference.md:236 |
| skill:skills/paperclip/references/api-reference.md:wake-diagnostics-get-api-issues-issueid-diagnostics-wakes:275 | control_plane_owned | skills/paperclip/references/api-reference.md:275 |
| skill:skills/paperclip/references/api-reference.md:subtree-diagnostics-get-api-issues-issueid-diagnostics-subtree:319 | optional_agent_tool | skills/paperclip/references/api-reference.md:319 |
| skill:skills/paperclip/references/api-reference.md:execution-policy-fields-on-an-issue:367 | optional_agent_tool | skills/paperclip/references/api-reference.md:367 |
| skill:skills/paperclip/references/api-reference.md:cross-agent-review-gates:419 | always_agent_tool | skills/paperclip/references/api-reference.md:419 |
| skill:skills/paperclip/references/api-reference.md:worked-example-ic-heartbeat:452 | optional_agent_tool | skills/paperclip/references/api-reference.md:452 |
| skill:skills/paperclip/references/api-reference.md:1-identity-skip-if-already-in-context:457 | control_plane_owned | skills/paperclip/references/api-reference.md:457 |
| skill:skills/paperclip/references/api-reference.md:2-check-inbox:461 | control_plane_owned | skills/paperclip/references/api-reference.md:461 |
| skill:skills/paperclip/references/api-reference.md:3-already-have-issue-101-inprogress-highest-priority-continue-it:468 | optional_agent_tool | skills/paperclip/references/api-reference.md:468 |
| skill:skills/paperclip/references/api-reference.md:4-do-the-actual-work-write-code-run-tests:475 | optional_agent_tool | skills/paperclip/references/api-reference.md:475 |
| skill:skills/paperclip/references/api-reference.md:5-work-is-done-update-status-and-comment-in-one-call:477 | always_agent_tool | skills/paperclip/references/api-reference.md:477 |
| skill:skills/paperclip/references/api-reference.md:6-still-have-time-checkout-the-next-task:481 | control_plane_owned | skills/paperclip/references/api-reference.md:481 |
| skill:skills/paperclip/references/api-reference.md:7-made-partial-progress-not-done-yet-comment-and-exit:488 | always_agent_tool | skills/paperclip/references/api-reference.md:488 |
| skill:skills/paperclip/references/api-reference.md:worked-example-report-a-board-user-s-mine-inbox:493 | control_plane_owned | skills/paperclip/references/api-reference.md:493 |
| skill:skills/paperclip/references/api-reference.md:board-user-created-the-requesting-issue:498 | optional_agent_tool | skills/paperclip/references/api-reference.md:498 |
| skill:skills/paperclip/references/api-reference.md:fetch-the-board-user-s-mine-inbox-issues:502 | control_plane_owned | skills/paperclip/references/api-reference.md:502 |
| skill:skills/paperclip/references/api-reference.md:summarize-it-back-to-the-board-in-a-comment-or-document:516 | always_agent_tool | skills/paperclip/references/api-reference.md:516 |
| skill:skills/paperclip/references/api-reference.md:worked-example-archive-a-resolved-inbox-item:521 | control_plane_owned | skills/paperclip/references/api-reference.md:521 |
| skill:skills/paperclip/references/api-reference.md:the-responsible-user-s-id-is-resolved-from-the-authenticated-agent-run:526 | optional_agent_tool | skills/paperclip/references/api-reference.md:526 |
| skill:skills/paperclip/references/api-reference.md:reverse-the-archive-if-it-was-premature-or-no-longer-desired:535 | optional_agent_tool | skills/paperclip/references/api-reference.md:535 |
| skill:skills/paperclip/references/api-reference.md:worked-example-reviewer-approver-heartbeat:545 | always_agent_tool | skills/paperclip/references/api-reference.md:545 |
| skill:skills/paperclip/references/api-reference.md:worked-example-manager-heartbeat:584 | optional_agent_tool | skills/paperclip/references/api-reference.md:584 |
| skill:skills/paperclip/references/api-reference.md:1-identity-skip-if-already-in-context:587 | control_plane_owned | skills/paperclip/references/api-reference.md:587 |
| skill:skills/paperclip/references/api-reference.md:2-check-team-status:591 | optional_agent_tool | skills/paperclip/references/api-reference.md:591 |
| skill:skills/paperclip/references/api-reference.md:3-agent-42-is-blocked-read-comments:598 | control_plane_owned | skills/paperclip/references/api-reference.md:598 |
| skill:skills/paperclip/references/api-reference.md:4-unblock-reassign-and-comment:602 | control_plane_owned | skills/paperclip/references/api-reference.md:602 |
| skill:skills/paperclip/references/api-reference.md:5-check-own-assignments:606 | optional_agent_tool | skills/paperclip/references/api-reference.md:606 |
| skill:skills/paperclip/references/api-reference.md:6-create-subtasks-and-delegate:613 | optional_agent_tool | skills/paperclip/references/api-reference.md:613 |
| 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:619 | control_plane_owned | skills/paperclip/references/api-reference.md:619 |
| skill:skills/paperclip/references/api-reference.md:7-dashboard-for-health-check:624 | optional_agent_tool | skills/paperclip/references/api-reference.md:624 |
| skill:skills/paperclip/references/api-reference.md:comments-and-mentions:630 | always_agent_tool | skills/paperclip/references/api-reference.md:630 |
| skill:skills/paperclip/references/api-reference.md:update:637 | optional_agent_tool | skills/paperclip/references/api-reference.md:637 |
| skill:skills/paperclip/references/api-reference.md:cross-team-work-and-delegation:675 | optional_agent_tool | skills/paperclip/references/api-reference.md:675 |
| skill:skills/paperclip/references/api-reference.md:receiving-cross-team-work:679 | optional_agent_tool | skills/paperclip/references/api-reference.md:679 |
| skill:skills/paperclip/references/api-reference.md:escalation:689 | optional_agent_tool | skills/paperclip/references/api-reference.md:689 |
| skill:skills/paperclip/references/api-reference.md:company-context:699 | optional_agent_tool | skills/paperclip/references/api-reference.md:699 |
| skill:skills/paperclip/references/api-reference.md:company-branding-ceo-board:711 | optional_agent_tool | skills/paperclip/references/api-reference.md:711 |
| skill:skills/paperclip/references/api-reference.md:openclaw-invite-prompt-ceo:731 | optional_agent_tool | skills/paperclip/references/api-reference.md:731 |
| skill:skills/paperclip/references/api-reference.md:setting-agent-instructions-path:750 | optional_agent_tool | skills/paperclip/references/api-reference.md:750 |
| skill:skills/paperclip/references/api-reference.md:project-setup-create-workspace:783 | optional_agent_tool | skills/paperclip/references/api-reference.md:783 |
| skill:skills/paperclip/references/api-reference.md:option-a-one-call-create-with-workspace:807 | optional_agent_tool | skills/paperclip/references/api-reference.md:807 |
| skill:skills/paperclip/references/api-reference.md:option-b-two-calls-project-first-then-workspace:826 | optional_agent_tool | skills/paperclip/references/api-reference.md:826 |
| skill:skills/paperclip/references/api-reference.md:governance-and-approvals:855 | optional_agent_tool | skills/paperclip/references/api-reference.md:855 |
| skill:skills/paperclip/references/api-reference.md:requesting-a-hire-management-only:859 | optional_agent_tool | skills/paperclip/references/api-reference.md:859 |
| skill:skills/paperclip/references/api-reference.md:ceo-strategy-approval:879 | optional_agent_tool | skills/paperclip/references/api-reference.md:879 |
| skill:skills/paperclip/references/api-reference.md:issue-thread-confirmations:888 | always_agent_tool | skills/paperclip/references/api-reference.md:888 |
| skill:skills/paperclip/references/api-reference.md:checkbox-confirmations:946 | always_agent_tool | skills/paperclip/references/api-reference.md:946 |
| skill:skills/paperclip/references/api-reference.md:item-verdict-requests:1061 | optional_agent_tool | skills/paperclip/references/api-reference.md:1061 |
| skill:skills/paperclip/references/api-reference.md:checking-approval-status:1171 | optional_agent_tool | skills/paperclip/references/api-reference.md:1171 |
| skill:skills/paperclip/references/api-reference.md:approval-follow-up-requesting-agent:1177 | always_agent_tool | skills/paperclip/references/api-reference.md:1177 |
| skill:skills/paperclip/references/api-reference.md:issue-lifecycle:1195 | always_agent_tool | skills/paperclip/references/api-reference.md:1195 |
| skill:skills/paperclip/references/api-reference.md:error-handling:1225 | control_plane_owned | skills/paperclip/references/api-reference.md:1225 |
| skill:skills/paperclip/references/api-reference.md:full-api-reference:1239 | optional_agent_tool | skills/paperclip/references/api-reference.md:1239 |
| skill:skills/paperclip/references/api-reference.md:agents:1241 | optional_agent_tool | skills/paperclip/references/api-reference.md:1241 |
| skill:skills/paperclip/references/api-reference.md:issues-tasks:1262 | optional_agent_tool | skills/paperclip/references/api-reference.md:1262 |
| skill:skills/paperclip/references/api-reference.md:companies-projects-goals:1302 | optional_agent_tool | skills/paperclip/references/api-reference.md:1302 |
| skill:skills/paperclip/references/api-reference.md:routines:1326 | optional_agent_tool | skills/paperclip/references/api-reference.md:1326 |
| skill:skills/paperclip/references/api-reference.md:approvals-costs-activity-dashboard:1342 | optional_agent_tool | skills/paperclip/references/api-reference.md:1342 |
| skill:skills/paperclip/references/api-reference.md:secrets:1364 | optional_agent_tool | skills/paperclip/references/api-reference.md:1364 |
| skill:skills/paperclip/references/api-reference.md:agent-secret-proposals:1377 | optional_agent_tool | skills/paperclip/references/api-reference.md:1377 |
| skill:skills/paperclip/references/api-reference.md:agent-secret-access:1477 | optional_agent_tool | skills/paperclip/references/api-reference.md:1477 |
| skill:skills/paperclip/references/api-reference.md:common-mistakes:1517 | optional_agent_tool | skills/paperclip/references/api-reference.md:1517 |
| skill:skills/paperclip/references/api-reference.md:response-schemas:9 | optional_agent_tool | skills/paperclip/references/api-reference.md:9 |
| skill:skills/paperclip/references/api-reference.md:agent-record-get-api-agents-me-or-get-api-agents-agentid:11 | optional_agent_tool | skills/paperclip/references/api-reference.md:11 |
| skill:skills/paperclip/references/api-reference.md:company-portability:44 | optional_agent_tool | skills/paperclip/references/api-reference.md:44 |
| skill:skills/paperclip/references/api-reference.md:issue-with-ancestors-get-api-issues-issueid:110 | optional_agent_tool | skills/paperclip/references/api-reference.md:110 |
| skill:skills/paperclip/references/api-reference.md:issue-update-response-patch-api-issues-issueid:196 | optional_agent_tool | skills/paperclip/references/api-reference.md:196 |
| skill:skills/paperclip/references/api-reference.md:blocker-diagnostics-get-api-issues-issueid-diagnostics-blockers:238 | control_plane_owned | skills/paperclip/references/api-reference.md:238 |
| skill:skills/paperclip/references/api-reference.md:wake-diagnostics-get-api-issues-issueid-diagnostics-wakes:277 | control_plane_owned | skills/paperclip/references/api-reference.md:277 |
| skill:skills/paperclip/references/api-reference.md:subtree-diagnostics-get-api-issues-issueid-diagnostics-subtree:321 | optional_agent_tool | skills/paperclip/references/api-reference.md:321 |
| skill:skills/paperclip/references/api-reference.md:execution-policy-fields-on-an-issue:369 | optional_agent_tool | skills/paperclip/references/api-reference.md:369 |
| skill:skills/paperclip/references/api-reference.md:cross-agent-review-gates:421 | always_agent_tool | skills/paperclip/references/api-reference.md:421 |
| skill:skills/paperclip/references/api-reference.md:worked-example-ic-heartbeat:454 | optional_agent_tool | skills/paperclip/references/api-reference.md:454 |
| skill:skills/paperclip/references/api-reference.md:1-identity-skip-if-already-in-context:459 | control_plane_owned | skills/paperclip/references/api-reference.md:459 |
| skill:skills/paperclip/references/api-reference.md:2-check-inbox:463 | control_plane_owned | skills/paperclip/references/api-reference.md:463 |
| skill:skills/paperclip/references/api-reference.md:3-already-have-issue-101-inprogress-highest-priority-continue-it:470 | optional_agent_tool | skills/paperclip/references/api-reference.md:470 |
| skill:skills/paperclip/references/api-reference.md:4-do-the-actual-work-write-code-run-tests:477 | optional_agent_tool | skills/paperclip/references/api-reference.md:477 |
| skill:skills/paperclip/references/api-reference.md:5-work-is-done-update-status-and-comment-in-one-call:479 | always_agent_tool | skills/paperclip/references/api-reference.md:479 |
| skill:skills/paperclip/references/api-reference.md:6-still-have-time-checkout-the-next-task:483 | control_plane_owned | skills/paperclip/references/api-reference.md:483 |
| skill:skills/paperclip/references/api-reference.md:7-made-partial-progress-not-done-yet-comment-and-exit:490 | always_agent_tool | skills/paperclip/references/api-reference.md:490 |
| skill:skills/paperclip/references/api-reference.md:worked-example-report-a-board-user-s-mine-inbox:495 | control_plane_owned | skills/paperclip/references/api-reference.md:495 |
| skill:skills/paperclip/references/api-reference.md:board-user-created-the-requesting-issue:500 | optional_agent_tool | skills/paperclip/references/api-reference.md:500 |
| skill:skills/paperclip/references/api-reference.md:fetch-the-board-user-s-mine-inbox-issues:504 | control_plane_owned | skills/paperclip/references/api-reference.md:504 |
| skill:skills/paperclip/references/api-reference.md:summarize-it-back-to-the-board-in-a-comment-or-document:518 | always_agent_tool | skills/paperclip/references/api-reference.md:518 |
| skill:skills/paperclip/references/api-reference.md:worked-example-archive-a-resolved-inbox-item:523 | control_plane_owned | skills/paperclip/references/api-reference.md:523 |
| skill:skills/paperclip/references/api-reference.md:the-responsible-user-s-id-is-resolved-from-the-authenticated-agent-run:528 | optional_agent_tool | skills/paperclip/references/api-reference.md:528 |
| skill:skills/paperclip/references/api-reference.md:reverse-the-archive-if-it-was-premature-or-no-longer-desired:537 | optional_agent_tool | skills/paperclip/references/api-reference.md:537 |
| skill:skills/paperclip/references/api-reference.md:worked-example-reviewer-approver-heartbeat:547 | always_agent_tool | skills/paperclip/references/api-reference.md:547 |
| skill:skills/paperclip/references/api-reference.md:worked-example-manager-heartbeat:586 | optional_agent_tool | skills/paperclip/references/api-reference.md:586 |
| skill:skills/paperclip/references/api-reference.md:1-identity-skip-if-already-in-context:589 | control_plane_owned | skills/paperclip/references/api-reference.md:589 |
| skill:skills/paperclip/references/api-reference.md:2-check-team-status:593 | optional_agent_tool | skills/paperclip/references/api-reference.md:593 |
| skill:skills/paperclip/references/api-reference.md:3-agent-42-is-blocked-read-comments:600 | control_plane_owned | skills/paperclip/references/api-reference.md:600 |
| skill:skills/paperclip/references/api-reference.md:4-unblock-reassign-and-comment:604 | control_plane_owned | skills/paperclip/references/api-reference.md:604 |
| skill:skills/paperclip/references/api-reference.md:5-check-own-assignments:608 | optional_agent_tool | skills/paperclip/references/api-reference.md:608 |
| skill:skills/paperclip/references/api-reference.md:6-create-subtasks-and-delegate:615 | optional_agent_tool | skills/paperclip/references/api-reference.md:615 |
| 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:621 | control_plane_owned | skills/paperclip/references/api-reference.md:621 |
| skill:skills/paperclip/references/api-reference.md:7-dashboard-for-health-check:626 | optional_agent_tool | skills/paperclip/references/api-reference.md:626 |
| skill:skills/paperclip/references/api-reference.md:comments-and-mentions:632 | always_agent_tool | skills/paperclip/references/api-reference.md:632 |
| skill:skills/paperclip/references/api-reference.md:update:639 | optional_agent_tool | skills/paperclip/references/api-reference.md:639 |
| skill:skills/paperclip/references/api-reference.md:cross-team-work-and-delegation:677 | optional_agent_tool | skills/paperclip/references/api-reference.md:677 |
| skill:skills/paperclip/references/api-reference.md:receiving-cross-team-work:681 | optional_agent_tool | skills/paperclip/references/api-reference.md:681 |
| skill:skills/paperclip/references/api-reference.md:escalation:691 | optional_agent_tool | skills/paperclip/references/api-reference.md:691 |
| skill:skills/paperclip/references/api-reference.md:company-context:701 | optional_agent_tool | skills/paperclip/references/api-reference.md:701 |
| skill:skills/paperclip/references/api-reference.md:company-branding-ceo-board:713 | optional_agent_tool | skills/paperclip/references/api-reference.md:713 |
| skill:skills/paperclip/references/api-reference.md:openclaw-invite-prompt-ceo:733 | optional_agent_tool | skills/paperclip/references/api-reference.md:733 |
| skill:skills/paperclip/references/api-reference.md:setting-agent-instructions-path:752 | optional_agent_tool | skills/paperclip/references/api-reference.md:752 |
| skill:skills/paperclip/references/api-reference.md:project-setup-create-workspace:785 | optional_agent_tool | skills/paperclip/references/api-reference.md:785 |
| skill:skills/paperclip/references/api-reference.md:option-a-one-call-create-with-workspace:809 | optional_agent_tool | skills/paperclip/references/api-reference.md:809 |
| skill:skills/paperclip/references/api-reference.md:option-b-two-calls-project-first-then-workspace:828 | optional_agent_tool | skills/paperclip/references/api-reference.md:828 |
| skill:skills/paperclip/references/api-reference.md:governance-and-approvals:857 | optional_agent_tool | skills/paperclip/references/api-reference.md:857 |
| skill:skills/paperclip/references/api-reference.md:requesting-a-hire-management-only:861 | optional_agent_tool | skills/paperclip/references/api-reference.md:861 |
| skill:skills/paperclip/references/api-reference.md:ceo-strategy-approval:893 | optional_agent_tool | skills/paperclip/references/api-reference.md:893 |
| skill:skills/paperclip/references/api-reference.md:questions-and-waiting-for-human-input:902 | always_agent_tool | skills/paperclip/references/api-reference.md:902 |
| skill:skills/paperclip/references/api-reference.md:issue-thread-confirmations:984 | always_agent_tool | skills/paperclip/references/api-reference.md:984 |
| skill:skills/paperclip/references/api-reference.md:checkbox-confirmations:1042 | always_agent_tool | skills/paperclip/references/api-reference.md:1042 |
| skill:skills/paperclip/references/api-reference.md:item-verdict-requests:1157 | optional_agent_tool | skills/paperclip/references/api-reference.md:1157 |
| skill:skills/paperclip/references/api-reference.md:checking-approval-status:1267 | optional_agent_tool | skills/paperclip/references/api-reference.md:1267 |
| skill:skills/paperclip/references/api-reference.md:approval-follow-up-requesting-agent:1273 | always_agent_tool | skills/paperclip/references/api-reference.md:1273 |
| skill:skills/paperclip/references/api-reference.md:issue-lifecycle:1291 | always_agent_tool | skills/paperclip/references/api-reference.md:1291 |
| skill:skills/paperclip/references/api-reference.md:error-handling:1321 | control_plane_owned | skills/paperclip/references/api-reference.md:1321 |
| skill:skills/paperclip/references/api-reference.md:full-api-reference:1335 | optional_agent_tool | skills/paperclip/references/api-reference.md:1335 |
| skill:skills/paperclip/references/api-reference.md:agents:1337 | optional_agent_tool | skills/paperclip/references/api-reference.md:1337 |
| skill:skills/paperclip/references/api-reference.md:issues-tasks:1358 | optional_agent_tool | skills/paperclip/references/api-reference.md:1358 |
| skill:skills/paperclip/references/api-reference.md:companies-projects-goals:1398 | optional_agent_tool | skills/paperclip/references/api-reference.md:1398 |
| skill:skills/paperclip/references/api-reference.md:routines:1422 | optional_agent_tool | skills/paperclip/references/api-reference.md:1422 |
| skill:skills/paperclip/references/api-reference.md:approvals-costs-activity-dashboard:1438 | optional_agent_tool | skills/paperclip/references/api-reference.md:1438 |
| skill:skills/paperclip/references/api-reference.md:secrets:1460 | optional_agent_tool | skills/paperclip/references/api-reference.md:1460 |
| skill:skills/paperclip/references/api-reference.md:agent-secret-proposals:1473 | optional_agent_tool | skills/paperclip/references/api-reference.md:1473 |
| skill:skills/paperclip/references/api-reference.md:agent-secret-access:1573 | optional_agent_tool | skills/paperclip/references/api-reference.md:1573 |
| skill:skills/paperclip/references/api-reference.md:common-mistakes:1613 | optional_agent_tool | skills/paperclip/references/api-reference.md:1613 |
## Legacy MCP Alias Index

View File

@ -281,612 +281,621 @@
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:7",
"id": "skill:skills/paperclip/references/api-reference.md:9",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L7:response-schemas",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L9:response-schemas",
"heading": "Response Schemas",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:9",
"id": "skill:skills/paperclip/references/api-reference.md:11",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L9:agent-record-get-api-agents-me-or-get-api-agents-agentid",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L11:agent-record-get-api-agents-me-or-get-api-agents-agentid",
"heading": "Agent Record (`GET /api/agents/me` or `GET /api/agents/:agentId`)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:42",
"id": "skill:skills/paperclip/references/api-reference.md:44",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L42:company-portability",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L44:company-portability",
"heading": "Company Portability",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:108",
"id": "skill:skills/paperclip/references/api-reference.md:110",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L108:issue-with-ancestors-get-api-issues-issueid",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L110:issue-with-ancestors-get-api-issues-issueid",
"heading": "Issue with Ancestors (`GET /api/issues/:issueId`)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:194",
"id": "skill:skills/paperclip/references/api-reference.md:196",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L194:issue-update-response-patch-api-issues-issueid",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L196:issue-update-response-patch-api-issues-issueid",
"heading": "Issue Update Response (`PATCH /api/issues/:issueId`)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:236",
"id": "skill:skills/paperclip/references/api-reference.md:238",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L236:blocker-diagnostics-get-api-issues-issueid-diagnostics-blockers",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L238:blocker-diagnostics-get-api-issues-issueid-diagnostics-blockers",
"heading": "Blocker Diagnostics (`GET /api/issues/:issueId/diagnostics/blockers`)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:275",
"id": "skill:skills/paperclip/references/api-reference.md:277",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L275:wake-diagnostics-get-api-issues-issueid-diagnostics-wakes",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L277:wake-diagnostics-get-api-issues-issueid-diagnostics-wakes",
"heading": "Wake Diagnostics (`GET /api/issues/:issueId/diagnostics/wakes`)",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:319",
"id": "skill:skills/paperclip/references/api-reference.md:321",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L319:subtree-diagnostics-get-api-issues-issueid-diagnostics-subtree",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L321:subtree-diagnostics-get-api-issues-issueid-diagnostics-subtree",
"heading": "Subtree Diagnostics (`GET /api/issues/:issueId/diagnostics/subtree`)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:367",
"id": "skill:skills/paperclip/references/api-reference.md:369",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L367:execution-policy-fields-on-an-issue",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L369:execution-policy-fields-on-an-issue",
"heading": "Execution Policy Fields On An Issue",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:419",
"id": "skill:skills/paperclip/references/api-reference.md:421",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L419:cross-agent-review-gates",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L421:cross-agent-review-gates",
"heading": "Cross-Agent Review Gates",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:452",
"id": "skill:skills/paperclip/references/api-reference.md:454",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L452:worked-example-ic-heartbeat",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L454:worked-example-ic-heartbeat",
"heading": "Worked Example: IC Heartbeat",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:457",
"id": "skill:skills/paperclip/references/api-reference.md:459",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L457:1-identity-skip-if-already-in-context",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L459:1-identity-skip-if-already-in-context",
"heading": "1. Identity (skip if already in context)",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:461",
"id": "skill:skills/paperclip/references/api-reference.md:463",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L461:2-check-inbox",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L463:2-check-inbox",
"heading": "2. Check inbox",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:468",
"id": "skill:skills/paperclip/references/api-reference.md:470",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L468:3-already-have-issue-101-in-progress-highest-priority-continue-it",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L470:3-already-have-issue-101-in-progress-highest-priority-continue-it",
"heading": "3. Already have issue-101 in_progress (highest priority). Continue it.",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:475",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L475:4-do-the-actual-work-write-code-run-tests",
"heading": "4. Do the actual work (write code, run tests)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:477",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L477:5-work-is-done-update-status-and-comment-in-one-call",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L477:4-do-the-actual-work-write-code-run-tests",
"heading": "4. Do the actual work (write code, run tests)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:479",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L479:5-work-is-done-update-status-and-comment-in-one-call",
"heading": "5. Work is done. Update status and comment in one call.",
"primaryDisposition": "always_agent_tool",
"semanticOperation": "report_progress",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:481",
"id": "skill:skills/paperclip/references/api-reference.md:483",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L481:6-still-have-time-checkout-the-next-task",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L483:6-still-have-time-checkout-the-next-task",
"heading": "6. Still have time. Checkout the next task.",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:488",
"id": "skill:skills/paperclip/references/api-reference.md:490",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L488:7-made-partial-progress-not-done-yet-comment-and-exit",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L490:7-made-partial-progress-not-done-yet-comment-and-exit",
"heading": "7. Made partial progress, not done yet. Comment and exit.",
"primaryDisposition": "always_agent_tool",
"semanticOperation": "report_progress",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:493",
"id": "skill:skills/paperclip/references/api-reference.md:495",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L493:worked-example-report-a-board-user-s-mine-inbox",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L495:worked-example-report-a-board-user-s-mine-inbox",
"heading": "Worked Example: Report A Board User's Mine Inbox",
"primaryDisposition": "always_agent_tool",
"semanticOperation": "report_progress",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:498",
"id": "skill:skills/paperclip/references/api-reference.md:500",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L498:board-user-created-the-requesting-issue",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L500:board-user-created-the-requesting-issue",
"heading": "Board user created the requesting issue.",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:502",
"id": "skill:skills/paperclip/references/api-reference.md:504",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L502:fetch-the-board-user-s-mine-inbox-issues",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L504:fetch-the-board-user-s-mine-inbox-issues",
"heading": "Fetch the board user's Mine inbox issues.",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:516",
"id": "skill:skills/paperclip/references/api-reference.md:518",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L516:summarize-it-back-to-the-board-in-a-comment-or-document",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L518:summarize-it-back-to-the-board-in-a-comment-or-document",
"heading": "Summarize it back to the board in a comment or document.",
"primaryDisposition": "always_agent_tool",
"semanticOperation": "write_document",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:521",
"id": "skill:skills/paperclip/references/api-reference.md:523",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L521:worked-example-archive-a-resolved-inbox-item",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L523:worked-example-archive-a-resolved-inbox-item",
"heading": "Worked Example: Archive A Resolved Inbox Item",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:526",
"id": "skill:skills/paperclip/references/api-reference.md:528",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L526:the-responsible-user-s-id-is-resolved-from-the-authenticated-agent-run",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L528:the-responsible-user-s-id-is-resolved-from-the-authenticated-agent-run",
"heading": "The responsible user's id is resolved from the authenticated agent run.",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:535",
"id": "skill:skills/paperclip/references/api-reference.md:537",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L535:reverse-the-archive-if-it-was-premature-or-no-longer-desired",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L537:reverse-the-archive-if-it-was-premature-or-no-longer-desired",
"heading": "Reverse the archive if it was premature or no longer desired.",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:545",
"id": "skill:skills/paperclip/references/api-reference.md:547",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L545:worked-example-reviewer-approver-heartbeat",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L547:worked-example-reviewer-approver-heartbeat",
"heading": "Worked Example: Reviewer / Approver Heartbeat",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:584",
"id": "skill:skills/paperclip/references/api-reference.md:586",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L584:worked-example-manager-heartbeat",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L586:worked-example-manager-heartbeat",
"heading": "Worked Example: Manager Heartbeat",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:587",
"id": "skill:skills/paperclip/references/api-reference.md:589",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L587:1-identity-skip-if-already-in-context",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L589:1-identity-skip-if-already-in-context",
"heading": "1. Identity (skip if already in context)",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:591",
"id": "skill:skills/paperclip/references/api-reference.md:593",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L591:2-check-team-status",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L593:2-check-team-status",
"heading": "2. Check team status",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:598",
"id": "skill:skills/paperclip/references/api-reference.md:600",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L598:3-agent-42-is-blocked-read-comments",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L600:3-agent-42-is-blocked-read-comments",
"heading": "3. Agent-42 is blocked. Read comments.",
"primaryDisposition": "always_agent_tool",
"semanticOperation": "report_progress",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:602",
"id": "skill:skills/paperclip/references/api-reference.md:604",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L602:4-unblock-reassign-and-comment",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L604:4-unblock-reassign-and-comment",
"heading": "4. Unblock: reassign and comment.",
"primaryDisposition": "always_agent_tool",
"semanticOperation": "report_progress",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:606",
"id": "skill:skills/paperclip/references/api-reference.md:608",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L606:5-check-own-assignments",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L608:5-check-own-assignments",
"heading": "5. Check own assignments.",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:613",
"id": "skill:skills/paperclip/references/api-reference.md:615",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L613:6-create-subtasks-and-delegate",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L615:6-create-subtasks-and-delegate",
"heading": "6. Create subtasks and delegate.",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:619",
"id": "skill:skills/paperclip/references/api-reference.md:621",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L619:load-tests-depend-on-caching-layer-being-done-first-paperclip-will-auto-wake-agent-55-when-the-blocker-resolves",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L621:load-tests-depend-on-caching-layer-being-done-first-paperclip-will-auto-wake-agent-55-when-the-blocker-resolves",
"heading": "^ Load tests depend on caching layer being done first. Paperclip will auto-wake agent-55 when the blocker resolves.",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:624",
"id": "skill:skills/paperclip/references/api-reference.md:626",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L624:7-dashboard-for-health-check",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L626:7-dashboard-for-health-check",
"heading": "7. Dashboard for health check.",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:630",
"id": "skill:skills/paperclip/references/api-reference.md:632",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L630:comments-and-mentions",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L632:comments-and-mentions",
"heading": "Comments and @-mentions",
"primaryDisposition": "always_agent_tool",
"semanticOperation": "report_progress",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:637",
"id": "skill:skills/paperclip/references/api-reference.md:639",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L637:update",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L639:update",
"heading": "Update",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:675",
"id": "skill:skills/paperclip/references/api-reference.md:677",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L675:cross-team-work-and-delegation",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L677:cross-team-work-and-delegation",
"heading": "Cross-Team Work and Delegation",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:679",
"id": "skill:skills/paperclip/references/api-reference.md:681",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L679:receiving-cross-team-work",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L681:receiving-cross-team-work",
"heading": "Receiving cross-team work",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:689",
"id": "skill:skills/paperclip/references/api-reference.md:691",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L689:escalation",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L691:escalation",
"heading": "Escalation",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:699",
"id": "skill:skills/paperclip/references/api-reference.md:701",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L699:company-context",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L701:company-context",
"heading": "Company Context",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:711",
"id": "skill:skills/paperclip/references/api-reference.md:713",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L711:company-branding-ceo-board",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L713:company-branding-ceo-board",
"heading": "Company Branding (CEO / Board)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:731",
"id": "skill:skills/paperclip/references/api-reference.md:733",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L731:openclaw-invite-prompt-ceo",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L733:openclaw-invite-prompt-ceo",
"heading": "OpenClaw Invite Prompt (CEO)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:750",
"id": "skill:skills/paperclip/references/api-reference.md:752",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L750:setting-agent-instructions-path",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L752:setting-agent-instructions-path",
"heading": "Setting Agent Instructions Path",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:783",
"id": "skill:skills/paperclip/references/api-reference.md:785",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L783:project-setup-create-workspace",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L785:project-setup-create-workspace",
"heading": "Project Setup (Create + Workspace)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:807",
"id": "skill:skills/paperclip/references/api-reference.md:809",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L807:option-a-one-call-create-with-workspace",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L809:option-a-one-call-create-with-workspace",
"heading": "Option A: One-call create with workspace",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:826",
"id": "skill:skills/paperclip/references/api-reference.md:828",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L826:option-b-two-calls-project-first-then-workspace",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L828:option-b-two-calls-project-first-then-workspace",
"heading": "Option B: Two calls (project first, then workspace)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:855",
"id": "skill:skills/paperclip/references/api-reference.md:857",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L855:governance-and-approvals",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L857:governance-and-approvals",
"heading": "Governance and Approvals",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:859",
"id": "skill:skills/paperclip/references/api-reference.md:861",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L859:requesting-a-hire-management-only",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L861:requesting-a-hire-management-only",
"heading": "Requesting a hire (management only)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:879",
"id": "skill:skills/paperclip/references/api-reference.md:893",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L879:ceo-strategy-approval",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L893:ceo-strategy-approval",
"heading": "CEO strategy approval",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:888",
"id": "skill:skills/paperclip/references/api-reference.md:902",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L888:issue-thread-confirmations",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L902:questions-and-waiting-for-human-input",
"heading": "Questions and waiting for human input",
"primaryDisposition": "always_agent_tool",
"semanticOperation": "request_human_input",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:984",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L984:issue-thread-confirmations",
"heading": "Issue-thread confirmations",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:946",
"id": "skill:skills/paperclip/references/api-reference.md:1042",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L946:checkbox-confirmations",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1042:checkbox-confirmations",
"heading": "Checkbox confirmations",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1061",
"id": "skill:skills/paperclip/references/api-reference.md:1157",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1061:item-verdict-requests",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1157:item-verdict-requests",
"heading": "Item verdict requests",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1171",
"id": "skill:skills/paperclip/references/api-reference.md:1267",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1171:checking-approval-status",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1267:checking-approval-status",
"heading": "Checking approval status",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1177",
"id": "skill:skills/paperclip/references/api-reference.md:1273",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1177:approval-follow-up-requesting-agent",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1273:approval-follow-up-requesting-agent",
"heading": "Approval follow-up (requesting agent)",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1195",
"id": "skill:skills/paperclip/references/api-reference.md:1291",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1195:issue-lifecycle",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1291:issue-lifecycle",
"heading": "Issue Lifecycle",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1225",
"id": "skill:skills/paperclip/references/api-reference.md:1321",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1225:error-handling",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1321:error-handling",
"heading": "Error Handling",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1239",
"id": "skill:skills/paperclip/references/api-reference.md:1335",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1239:full-api-reference",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1335:full-api-reference",
"heading": "Full API Reference",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1241",
"id": "skill:skills/paperclip/references/api-reference.md:1337",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1241:agents",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1337:agents",
"heading": "Agents",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1262",
"id": "skill:skills/paperclip/references/api-reference.md:1358",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1262:issues-tasks",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1358:issues-tasks",
"heading": "Issues (Tasks)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1302",
"id": "skill:skills/paperclip/references/api-reference.md:1398",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1302:companies-projects-goals",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1398:companies-projects-goals",
"heading": "Companies, Projects, Goals",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1326",
"id": "skill:skills/paperclip/references/api-reference.md:1422",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1326:routines",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1422:routines",
"heading": "Routines",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1342",
"id": "skill:skills/paperclip/references/api-reference.md:1438",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1342:approvals-costs-activity-dashboard",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1438:approvals-costs-activity-dashboard",
"heading": "Approvals, Costs, Activity, Dashboard",
"primaryDisposition": "control_plane_owned",
"semanticOperation": "runtime_reconciliation",
"expectedMockState": "runtime_decision_record"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1364",
"id": "skill:skills/paperclip/references/api-reference.md:1460",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1364:secrets",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1460:secrets",
"heading": "Secrets",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1377",
"id": "skill:skills/paperclip/references/api-reference.md:1473",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1377:agent-secret-proposals",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1473:agent-secret-proposals",
"heading": "Agent secret proposals",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1430",
"id": "skill:skills/paperclip/references/api-reference.md:1526",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1430:re-bind-an-existing-secret-under-a-new-path-no-secret-id",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1526:re-bind-an-existing-secret-under-a-new-path-no-secret-id",
"heading": "Re-bind an existing secret under a new path (no secret ID)",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1477",
"id": "skill:skills/paperclip/references/api-reference.md:1573",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1477:agent-secret-access",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1573:agent-secret-access",
"heading": "Agent secret access",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",
"expectedMockState": "operation_result"
},
{
"id": "skill:skills/paperclip/references/api-reference.md:1517",
"id": "skill:skills/paperclip/references/api-reference.md:1613",
"kind": "skill_heading",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1517:common-mistakes",
"sourceAnchor": "skills/paperclip/references/api-reference.md#L1613:common-mistakes",
"heading": "Common Mistakes",
"primaryDisposition": "optional_agent_tool",
"semanticOperation": "scoped_discovery",

View File

@ -2,9 +2,9 @@
Generated by `scripts/generate-capability-contract.mjs`; do not edit generated files.
- Skill/reference headings: 155
- Skill/reference headings: 156
- Legacy MCP tools: 42
- Eval cases: 106 across 16 groups
- Deterministic content SHA-256: `f83b043e95387a56679241e89e330600e198b890e83e1b21012cf2f4b9210a00`
- Deterministic content SHA-256: `8447cdf6ddc5fa7b36e9724b3df1ea695ac084cf3e104273186fbec3ed9bc5fd`
Every row has exactly one primary disposition, a source anchor, a semantic operation, and a mock-state expectation.

View File

@ -42,7 +42,7 @@ function validInventories() {
schemaVersion: 2,
inventoryRole: "normative",
generatedFrom: ["skills/paperclip/SKILL.md"],
rows: Array.from({ length: 154 }, (_, index) => row(`capability-${index}`)),
rows: Array.from({ length: 155 }, (_, index) => row(`capability-${index}`)),
},
evaluations: {
schemaVersion: 2,

View File

@ -247,7 +247,7 @@ export async function buildMcpInventory(repoRoot) {
export function validateInventories(inventories) {
const errors = [];
const expectedCounts = { capabilities: 154, evaluations: 106, legacyMcpAliases: 42 };
const expectedCounts = { capabilities: 155, evaluations: 106, legacyMcpAliases: 42 };
const normativeNames = ["capabilities", "evaluations"];
const normativeRows = new Map();
const globalNormativeIds = new Set();

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,9 @@ export type CapabilityPrimaryDisposition =
| "optional_agent_tool";
export const capabilityInventoryCounts = {
"skillReferenceCapabilities": 154,
"skillReferenceCapabilities": 155,
"evalCases": 106,
"normativeRows": 260,
"normativeRows": 261,
"legacyMcpAliases": 42
} as const;

View File

@ -10,13 +10,20 @@ for (const line of source.split("\n")) {
const table = /^\|\s*(GET|POST|PATCH|PUT|DELETE)\s*\|\s*`([^`]+)`\s*\|\s*(.*?)\s*\|/.exec(line);
if (table) entries[key(table[1], table[2])] = { section, description: table[3] };
}
for (const match of source.matchAll(/^(GET|POST|PATCH|PUT|DELETE) (\/api\/[^\s]+)\n(\{[\s\S]*?\n\})/gm)) {
for (const match of source.matchAll(/^(GET|POST|PATCH|PUT|DELETE) (\/api\/[^\s]+)\n(\{[^\n]*\}|\{\n[\s\S]*?\n\})/gm)) {
try {
const body = JSON.parse(match[3]);
const id = key(match[1], match[2]);
entries[id] ??= { section: "Worked example" };
(entries[id].examples ??= []).push({ body });
entries[id].examples = entries[id].examples.slice(0, 2);
// Runtime consumers look up endpoint templates from OpenAPI. Narrative
// URLs with literal resource IDs must not create unreachable entries.
if (!entries[id]) continue;
// Keep examples for each interaction kind / issue disposition, so new
// question or waiting examples do not displace existing confirmation flows.
const variant = body.kind ?? body.status ?? "";
const examples = entries[id].examples ??= [];
if (examples.filter(({ body: example }) => (example.kind ?? example.status ?? "") === variant).length < 2) {
examples.push({ body });
}
} catch { /* Narrative/pseudocode blocks are not executable examples. */ }
}
const destination = resolve(root, "server/src/services/native-runtime/runner-api-reference.ts");

View File

@ -180,11 +180,11 @@ function createDb(requireBoardApprovalForNewAgents = false) {
let agentRoutes: (typeof import("../routes/agents.js"))["agentRoutes"];
let errorHandler: (typeof import("../middleware/index.js"))["errorHandler"];
async function createApp(db: Record<string, unknown> = createDb()) {
async function createApp(db: Record<string, unknown> = createDb(), actor?: Record<string, unknown>) {
const app = express();
app.use(express.json());
app.use((req, _res, next) => {
(req as any).actor = {
(req as any).actor = actor ?? {
type: "board",
userId: "local-board",
companyIds: ["company-1"],
@ -1228,6 +1228,73 @@ describe.sequential("agent skill routes", () => {
expect(entrySeed?.["AGENTS.md"]).toContain("# Hiring and delegation");
});
it.each([
["agents", "paperclipai/paperclip/paperclip-create-agent"],
["agent-hires", "paperclipai/paperclip/paperclip-create-agent"],
["agents", "paperclip"],
["agent-hires", "paperclip"],
])("gives a general onboarding chief core skills and preserves %s version pins for %s", async (route, skill) => {
mockInstanceSettingsService.getExperimental.mockResolvedValue({ enableBetaSkills: true });
const versionId = "22222222-2222-4222-8222-222222222222";
const res = await request(await createApp(createDb(route === "agent-hires")))
.post(`/api/companies/company-1/${route}`)
.send({
name: "Chiff", role: "general", adapterType: "codex_local",
onboardingFirstAgent: true,
desiredSkills: [{ key: skill, versionId }],
});
expect(res.status, JSON.stringify(res.body)).toBe(201);
const input = mockAgentService.create.mock.calls[0][1];
expect(input.role).toBe("general");
const canonicalKey = skill === "paperclip" ? "paperclipai/paperclip/paperclip" : skill;
const expected = ["paperclip", "paperclip-board", "paperclip-converting-plans-to-tasks", "paperclip-create-agent", "para-memory-files"]
.map((name) => ({ key: `paperclipai/paperclip/${name}`, versionId: `paperclipai/paperclip/${name}` === canonicalKey ? versionId : null }));
expect(input.adapterConfig.paperclipSkillSync.desiredSkills).toEqual(expect.arrayContaining(expected));
expect(input.adapterConfig.paperclipSkillSync.desiredSkills).toHaveLength(5);
});
it.each(["agents", "agent-hires"])("leaves ordinary general agents' defaults unchanged via %s", async (route) => {
const res = await request(await createApp())
.post(`/api/companies/company-1/${route}`)
.send({ name: "Biff", role: "general", adapterType: "codex_local" });
expect(res.status, JSON.stringify(res.body)).toBe(201);
expect(mockAgentService.create.mock.calls[0][1].adapterConfig.paperclipSkillSync).toBeUndefined();
});
it("does not trust an agent-supplied onboarding marker to select chief-of-staff defaults", async () => {
mockAgentService.getById.mockResolvedValue(makeAgent("claude_local"));
const res = await request(await createApp(createDb(), {
type: "agent", agentId: "11111111-1111-4111-8111-111111111111", companyId: "company-1",
}))
.post("/api/companies/company-1/agent-hires")
.send({ name: "Biff", role: "general", adapterType: "claude_local", onboardingFirstAgent: true });
expect(res.status, JSON.stringify(res.body)).toBe(201);
expect(mockAgentService.create.mock.calls[0][1].adapterConfig.paperclipSkillSync).toBeUndefined();
await vi.waitFor(() => expect(mockAgentInstructionsService.materializeManagedBundle).toHaveBeenCalled());
expect(mockAgentInstructionsService.materializeManagedBundle.mock.calls[0][1]["AGENTS.md"])
.not.toContain("chief of staff");
});
it("creates nothing for rejected Biff payloads and exactly one approval-gated hire after correction", async () => {
const app = await createApp(createDb(true));
const hire = { name: "Biff", role: "general", adapterType: "codex_local", capabilities: "Be a friendly, affable robot" };
const retired = await request(app).post("/api/companies/company-1/agent-hires")
.send({ ...hire, adapterConfig: { promptTemplate: "Be friendly" } });
expect(retired.status).toBe(422);
const malformed = await request(app).post("/api/companies/company-1/agent-hires")
.send({ ...hire, instructionsBundle: { files: [{ path: "AGENTS.md", content: "Be friendly" }] } });
expect(malformed.status).toBe(400);
expect(mockAgentService.create).not.toHaveBeenCalled();
expect(mockApprovalService.create).not.toHaveBeenCalled();
const corrected = await request(app).post("/api/companies/company-1/agent-hires")
.send({ ...hire, instructionsBundle: { files: { "AGENTS.md": "Be a friendly, affable robot." } } });
expect(corrected.status, JSON.stringify(corrected.body)).toBe(201);
expect(corrected.body.agent).toMatchObject({ name: "Biff", status: "pending_approval" });
expect(corrected.body.approval).toMatchObject({ type: "hire_agent", status: "pending" });
expect(mockAgentService.create).toHaveBeenCalledTimes(1);
expect(mockApprovalService.create).toHaveBeenCalledTimes(1);
});
it("includes canonical desired skills in hire approvals", async () => {
const db = createDb(true);

View File

@ -0,0 +1,48 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
import { createAgentHireSchema, createIssueThreadInteractionSchema, updateIssueSchema } from "@paperclipai/shared";
import { runnerApiReference } from "../services/native-runtime/runner-api-reference.js";
const reference = readFileSync(new URL("../../../skills/paperclip/references/api-reference.md", import.meta.url), "utf8");
const uuid = "11111111-1111-4111-8111-111111111111";
const examples = [...reference.matchAll(/^(POST|PATCH) (\/api\/[^\s]+)\n(\{[^\n]*\}|\{\n[\s\S]*?\n\})/gm)]
.flatMap((match) => {
try { return [{ method: match[1], path: match[2], body: JSON.parse(match[3]) }]; }
catch { return []; }
});
const substituteIds = (body: unknown) => JSON.parse(JSON.stringify(body).replace(/\{[\w-]+\}/g, uuid));
describe("published hiring and human-input examples", () => {
const questions = examples.filter(({ body }) => body.kind === "ask_user_questions");
const hires = examples.filter(({ path }) => path.endsWith("/agent-hires"));
const waits = examples.filter(({ method, body }) => method === "PATCH" && (body.unblockDescriptor || body.comment === "Waiting for your answer in the saved responsibility question card."));
it("publishes valid structured and free-text questions, managed hires, and waiting states", () => {
expect(questions).toHaveLength(2);
expect(hires.length).toBeGreaterThan(0);
expect(waits).toHaveLength(2);
for (const { body } of questions) expect(createIssueThreadInteractionSchema.safeParse(substituteIds(body))).toMatchObject({ success: true });
for (const { body } of hires) {
expect(createAgentHireSchema.safeParse(substituteIds(body))).toMatchObject({ success: true });
expect(body.instructionsBundle.files["AGENTS.md"]).toEqual(expect.any(String));
}
for (const { body } of waits) expect(updateIssueSchema.safeParse(substituteIds(body))).toMatchObject({ success: true });
});
it("keeps these examples in the generated runner reference without displacing confirmations", () => {
for (const example of [...questions, ...hires, ...waits]) {
const key = `${example.method} ${example.path.replace(/\{[^}]+\}/g, "{}")}`;
expect(runnerApiReference[key]?.examples).toContainEqual({ body: example.body });
}
expect(runnerApiReference["POST /api/issues/{}/interactions"].examples)
.toEqual(expect.arrayContaining([expect.objectContaining({ body: expect.objectContaining({ kind: "request_confirmation" }) })]));
});
it("only enriches documented endpoint templates, not literal narrative URLs", () => {
const documentedOperations = new Set([...reference.matchAll(/^\|\s*(GET|POST|PATCH|PUT|DELETE)\s*\|\s*`([^`]+)`/gm)]
.map((match) => `${match[1]} ${match[2].replace(/:[A-Za-z][A-Za-z0-9_]*|\{[^}]+\}/g, "{}")}`));
expect(Object.keys(runnerApiReference).filter((key) => !documentedOperations.has(key))).toEqual([]);
expect(runnerApiReference["PATCH /api/issues/issue-101"]).toBeUndefined();
expect(runnerApiReference["POST /api/companies/company-1/imports/preview"]).toBeUndefined();
});
});

View File

@ -18,7 +18,7 @@ You are an agent at Paperclip company.
4. Wait for acceptance before creating implementation subtasks.
Never present a plan only in a thread comment or through `ask_user_questions`; comments are supporting context and questions are for gathering input, not plan review.
- `ask_user_questions` and confirmations default `supersedeOnUserComment` to `true`, so a later board/user comment invalidates the pending request. Set it to `false` only when the request should stay open through discussion. If you wake up from a superseding comment, revise the artifact, question set, or proposal and create a fresh interaction if input is still needed.
- If someone needs to unblock you, assign or route the ticket with a comment that names the unblock owner and action.
- For human input, save a pending question/confirmation interaction and set `in_review`; prose alone does not create a waiting path. Use `blockedByIssueIds` for issue dependencies. An agent may set an `unblockDescriptor` only for itself (`owner: { "agentId": "<your-agent-id>" }` plus `action`), not for the board/user or another agent.
- Respect budget, pause/cancel, approval gates, and company boundaries.
Do not let work sit here. You must always update your task with a comment.

View File

@ -1,20 +1,25 @@
# Role
You are {{agentName}}, chief of staff for {{organizationName}}. You report to the person who set up this organization and you are their main point of contact. Understand what they want, propose, and coordinate the work. Do not decide for them.
You are {{agentName}}, chief of staff for {{organizationName}}. You report to the person who set up this organization and you are their main point of contact. Understand what they want, carry out their requests, and propose and coordinate further work.
# Working with the user
- Be conversational. Propose, don't decide.
- Be conversational. Act on clear requests; propose choices that need the user's decision.
- When they ask for something concrete (a brief, a plan, a roadmap, a pitch), produce a real artifact: save it as a document on the relevant task so they can review it.
# Chat hygiene
- Everything you post is read by the user. Keep it terse and written for them.
- Lead with the answer. Never narrate tool calls, API steps, or your own thinking.
- One question card at a time. Don't guess; ask.
- Ask only about material ambiguity that prevents useful work. Accept responsibilities in the user's own words; do not demand an artificial job category. Use `general` when no specialized structural role is needed.
- When input is needed, save one `ask_user_questions` card using the operational API reference, then set the issue to `in_review`. The saved pending interaction provides the waiting path; a question in prose alone does not. Do not try to set a board/user unblock owner as an agent.
# Hiring and delegation
You may hire agents and create tasks, but never without first confirming with the user in a request_confirmation or checkbox card that names exactly what will be created. This applies to every task, not only the first one. A proposed hire is one line: name, role, responsibility.
An explicit user request to hire an agent or create a task authorizes that requested action. Proceed within that scope without asking them to approve it again. For additional hires or tasks you propose, first use a request_confirmation or checkbox card naming what will be created. A proposed hire is one line: name, role, responsibility. Formal company approval gates still apply to every hire, including directly requested hires.
Send each hire exactly once. A hire request that returns HTTP 201 has succeeded; the body is `{"agent": …, "approval": …}`. If the identical hire is sent again during the same run, the server returns the agent it already created (HTTP 200, `idempotent: true`) instead of a duplicate. That covers exact retries only: a changed payload or a later run creates a new agent, and you cannot pause or remove an agent afterwards. So if a result is unclear, list the organization's agents before doing anything else. Never resend a hire.
Read `paperclip-create-agent` before hiring. Supply managed instructions with `instructionsBundle.files` as a record of paths to file contents, not an array; do not use retired `adapterConfig.promptTemplate` fields. Keep timer heartbeats off unless requested or needed for recurring work.
A hire response with HTTP 201 succeeded; its body is `{"agent": …, "approval": …}`. Check whether the agent is pending company approval before reporting it ready. An identical same-run retry returns the existing agent (HTTP 200, `idempotent: true`); changed payloads or later runs can create duplicates. Do not resubmit after success. If the outcome is uncertain (timeout, lost response, or server error), first list the company's agents and reconcile the result before considering any retry.
A confirmed pre-creation validation rejection created no agent. Correct the invalid fields under the original authorization when the requested name, responsibilities, and scope stay the same; do not request another confirmation just to fix the payload. Use the validation error and `GET /api/openapi.json` to fix the shape. This exception is only for confirmed validation failures, not uncertain outcomes or permission/approval denials. Keep the operational skill's bounded write retry limit.

View File

@ -2768,17 +2768,18 @@ export function agentRoutes(
};
}
// The default CEO instructions assume the core paperclip skills (board
// coordination, planning, hiring, memory). Union them into every
// skills-capable CEO hire/create so a fresh CEO never starts with an empty
// desired-skill set that contradicts its own instructions. Optional role
// CEO and board-created onboarding chief-of-staff instructions assume the
// core paperclip skills (board coordination, planning, hiring, memory).
// Union them into these skills-capable hires/creates so their desired skills
// match their instructions. Optional role
// skills remain removable afterwards. Legacy adapters separately guarantee
// the Paperclip operational skill as a runtime invariant.
function defaultRoleSkillSelections(
role: string | null | undefined,
adapterType: string,
boardOnboardingFirstAgent = false,
): AgentDesiredSkillEntry[] | undefined {
if (role !== "ceo") return undefined;
if (role !== "ceo" && !boardOnboardingFirstAgent) return undefined;
const adapter = findActiveServerAdapter(adapterType);
if (!adapter?.listSkills && !adapter?.syncSkills) return undefined;
return PAPERCLIP_CORE_SKILL_KEYS
@ -2792,9 +2793,12 @@ export function agentRoutes(
): AgentDesiredSkillEntry[] | undefined {
if (!defaults) return requested;
if (!requested) return defaults;
const merged = new Map(defaults.map((entry) => [entry.key, entry]));
// An explicit request wins over a default for the same key (version pins).
for (const entry of requested) merged.set(entry.key, entry);
// Resolve explicit selections first: aliases can normalize to a default
// key later, and the skill resolver keeps the first version selection.
const merged = new Map(requested.map((entry) => [entry.key, entry]));
for (const entry of defaults) {
if (!merged.has(entry.key)) merged.set(entry.key, entry);
}
return Array.from(merged.values());
}
@ -4221,7 +4225,11 @@ export function agentRoutes(
requestedAdapterConfig,
withDefaultRoleSkillSelections(
normalizeDesiredSkillSelections(Array.isArray(requestedDesiredSkills) ? requestedDesiredSkills : undefined),
defaultRoleSkillSelections(hireInput.role, hireInput.adapterType),
defaultRoleSkillSelections(
hireInput.role,
hireInput.adapterType,
hireOnboardingFirstAgent === true && req.actor.type === "board",
),
),
"add",
);
@ -4500,7 +4508,11 @@ export function agentRoutes(
requestedAdapterConfig,
withDefaultRoleSkillSelections(
normalizeDesiredSkillSelections(Array.isArray(requestedDesiredSkills) ? requestedDesiredSkills : undefined),
defaultRoleSkillSelections(createInput.role, createInput.adapterType),
defaultRoleSkillSelections(
createInput.role,
createInput.adapterType,
createOnboardingFirstAgent === true && req.actor.type === "board",
),
),
"add",
);

View File

@ -125,6 +125,24 @@ export const runnerApiReference: Record<string, { section: string; description?:
]
}
}
},
{
"body": {
"status": "in_review",
"comment": "Waiting for your answer in the saved responsibility question card."
}
},
{
"body": {
"status": "blocked",
"unblockDescriptor": {
"owner": {
"agentId": "{your-agent-id}"
},
"action": "Restore the failed workspace service, verify health, then resume."
},
"comment": "The workspace service is unavailable; I own restoring it."
}
}
]
},
@ -146,7 +164,14 @@ export const runnerApiReference: Record<string, { section: string; description?:
},
"POST /api/issues/{}/comments": {
"section": "Issues (Tasks)",
"description": "Add comment (@-mentions trigger wakeups)"
"description": "Add comment (@-mentions trigger wakeups)",
"examples": [
{
"body": {
"body": "[@QA Reviewer](agent://qa-agent-id) please review this implementation."
}
}
]
},
"POST /api/issues/{}/inbox-archive": {
"section": "Issues (Tasks)",
@ -164,6 +189,92 @@ export const runnerApiReference: Record<string, { section: string; description?:
"section": "Issues (Tasks)",
"description": "Create issue-thread interaction (`suggest_tasks`, `ask_user_questions`, `request_confirmation`, `request_checkbox_confirmation`, `request_item_verdicts`)",
"examples": [
{
"body": {
"kind": "ask_user_questions",
"idempotencyKey": "questions:{issueId}:responsibility:v1",
"title": "Hire responsibility",
"resolverPolicy": "human_only",
"continuationPolicy": "wake_assignee",
"payload": {
"version": 1,
"questions": [
{
"id": "responsibility",
"prompt": "What should the new agent be responsible for?",
"selectionMode": "single",
"required": true,
"allowOther": true,
"options": [
{
"id": "research",
"label": "Research",
"description": "Find and summarize information."
},
{
"id": "writing",
"label": "Writing",
"description": "Draft and edit content."
}
]
}
]
}
}
},
{
"body": {
"kind": "ask_user_questions",
"idempotencyKey": "questions:{issueId}:responsibility-text:v1",
"title": "Hire responsibility",
"resolverPolicy": "human_only",
"continuationPolicy": "wake_assignee",
"payload": {
"version": 1,
"questions": [
{
"id": "responsibility",
"prompt": "What should the new agent be responsible for?",
"selectionMode": "single",
"required": true,
"options": [
{
"id": "describe",
"label": "I'll describe it",
"freeText": true
}
]
}
]
}
}
},
{
"body": {
"kind": "request_confirmation",
"idempotencyKey": "confirmation:{issueId}:{targetKey}:{targetVersion}",
"title": "Plan approval",
"continuationPolicy": "wake_assignee",
"payload": {
"version": 1,
"prompt": "Accept this plan?",
"acceptLabel": "Accept plan",
"rejectLabel": "Request changes",
"rejectRequiresReason": true,
"rejectReasonLabel": "What needs to change?",
"detailsMarkdown": "Review the latest plan document before accepting.",
"supersedeOnUserComment": true,
"target": {
"type": "issue_document",
"issueId": "{issueId}",
"documentId": "{documentId}",
"key": "plan",
"revisionId": "{latestRevisionId}",
"revisionNumber": 3
}
}
}
},
{
"body": {
"kind": "request_checkbox_confirmation",
@ -253,11 +364,28 @@ export const runnerApiReference: Record<string, { section: string; description?:
},
"POST /api/issues/{}/interactions/{}/accept": {
"section": "Issues (Tasks)",
"description": "Accept suggested tasks or confirmation (body: `selectedClientKeys` for `suggest_tasks`; `selectedOptionIds` for `request_checkbox_confirmation`)"
"description": "Accept suggested tasks or confirmation (body: `selectedClientKeys` for `suggest_tasks`; `selectedOptionIds` for `request_checkbox_confirmation`)",
"examples": [
{
"body": {
"selectedOptionIds": [
"draft-report-march",
"tmp-export-2025"
]
}
}
]
},
"POST /api/issues/{}/interactions/{}/reject": {
"section": "Issues (Tasks)",
"description": "Reject suggested tasks or confirmation"
"description": "Reject suggested tasks or confirmation",
"examples": [
{
"body": {
"reason": "Keep the March draft; only delete tmp/export-2025.csv."
}
}
]
},
"POST /api/issues/{}/interactions/{}/respond": {
"section": "Issues (Tasks)",
@ -370,8 +498,18 @@ export const runnerApiReference: Record<string, { section: string; description?:
},
"POST /api/companies/{}/projects": {
"section": "Companies, Projects, Goals",
"description": "Create project (optional inline `workspace`)",
"description": "Create project (`repositoryIds`/`repositoryUrls` arrays or inline `workspace`; optional `idempotencyKey`)",
"examples": [
{
"body": {
"name": "Web and API",
"repositoryUrls": [
"https://github.com/acme/web",
"https://github.com/acme/api"
],
"idempotencyKey": "web-api-project"
}
},
{
"body": {
"name": "Paperclip Mobile App",
@ -446,7 +584,14 @@ export const runnerApiReference: Record<string, { section: string; description?:
},
"POST /api/companies/{}/openclaw/invite-prompt": {
"section": "Companies, Projects, Goals",
"description": "Generate OpenClaw invite prompt (CEO/board only)"
"description": "Generate OpenClaw invite prompt (CEO/board only)",
"examples": [
{
"body": {
"agentMessage": "optional note for the joining OpenClaw agent"
}
}
]
},
"GET /api/companies/{}/routines": {
"section": "Routines",
@ -498,7 +643,18 @@ export const runnerApiReference: Record<string, { section: string; description?:
},
"POST /api/companies/{}/approvals": {
"section": "Approvals, Costs, Activity, Dashboard",
"description": "Create approval request"
"description": "Create approval request",
"examples": [
{
"body": {
"type": "approve_ceo_strategy",
"requestedByAgentId": "{your-agent-id}",
"payload": {
"plan": "..."
}
}
}
]
},
"POST /api/companies/{}/agent-hires": {
"section": "Approvals, Costs, Activity, Dashboard",
@ -510,7 +666,20 @@ export const runnerApiReference: Record<string, { section: string; description?:
"role": "researcher",
"reportsTo": "{manager-agent-id}",
"capabilities": "Market research, competitor analysis",
"budgetMonthlyCents": 5000
"budgetMonthlyCents": 5000,
"adapterType": "codex_local",
"instructionsBundle": {
"entryFile": "AGENTS.md",
"files": {
"AGENTS.md": "# Marketing Analyst\nResearch markets and competitors. Report findings with sources to your manager. Follow the Paperclip operational skill.\n"
}
},
"runtimeConfig": {
"heartbeat": {
"enabled": false,
"wakeOnDemand": true
}
}
}
}
]
@ -602,88 +771,5 @@ export const runnerApiReference: Record<string, { section: string; description?:
"POST /api/agents/me/secrets/{}/value": {
"section": "Secrets",
"description": "Fetch one granted secret value; request body is empty"
},
"POST /api/companies/company-1/imports/preview": {
"section": "Worked example",
"examples": [
{
"body": {
"source": {
"type": "github",
"url": "https://github.com/acme/agent-company"
},
"include": {
"company": true,
"agents": true,
"projects": true,
"issues": true
},
"target": {
"mode": "existing_company",
"companyId": "company-1"
},
"collisionStrategy": "rename"
}
}
]
},
"POST /api/companies/company-1/imports/apply": {
"section": "Worked example",
"examples": [
{
"body": {
"source": {
"type": "github",
"url": "https://github.com/acme/agent-company"
},
"include": {
"company": true,
"agents": true,
"projects": true,
"issues": false
},
"target": {
"mode": "new_company",
"newCompanyName": "Imported Acme"
},
"collisionStrategy": "rename"
}
}
]
},
"POST /api/companies/company-1/exports/preview": {
"section": "Worked example",
"examples": [
{
"body": {
"include": {
"company": true,
"agents": true,
"projects": true
}
}
}
]
},
"POST /api/companies/company-1/exports": {
"section": "Worked example",
"examples": [
{
"body": {
"include": {
"company": true,
"agents": true,
"projects": true,
"issues": true
},
"selectedFiles": [
"COMPANY.md",
"agents/ceo/AGENTS.md",
"skills/paperclip/SKILL.md",
"tasks/pap-42/TASK.md"
]
}
}
]
}
};

View File

@ -153,7 +153,7 @@ If `currentParticipant` does not match you, do not try to advance the stage —
- 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.
- 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.
- If blocked, move the issue to `blocked` with the unblock owner and exact action needed.
- 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.
- Respect budget, pause/cancel, approval gates, execution policy stages, and company boundaries.
### Generated Artifacts and Work Products
@ -173,7 +173,7 @@ the routine server-verified external-chat handoff described above.
**Verify writes — never infer them.** A successful `PATCH /api/issues/{id}` always returns the updated issue JSON. An empty response body means the write FAILED, even if the command exited 0. Never pipe a disposition write through `head`/`tail` and never rely on `curl -f` inside a pipeline — the pipe swallows curl's exit status, and a lost connection then looks identical to success. Use `scripts/paperclip-issue-update.sh` (it checks the HTTP status, retries connection-level failures, and confirms the echoed `status`); if you must hand-roll curl, capture `-w '%{http_code}'` and check the response echoes your update. When a status write cannot be confirmed, your final report must say the write FAILED — not that it "was sent" — so the recovery path gets accurate context.
If you are blocked at any point, you MUST update the issue to `blocked` before exiting the heartbeat, with a comment that explains the blocker and who needs to act.
Before exiting, persist the appropriate waiting path: a saved pending interaction plus `in_review` for human input, or `blocked` with first-class blockers or an agent-permitted unblock descriptor for a real dependency. A comment naming someone does not create that path.
Before ending any heartbeat, apply this final-disposition checklist:

View File

@ -1,5 +1,7 @@
# Paperclip API Reference
Fetch `GET /api/openapi.json` for the current request schemas. It is available through the queue and HTTP/2 sandbox bridges.
Detailed reference for the Paperclip control plane API. For the core heartbeat procedure and critical rules, see the main `SKILL.md`.
---
@ -865,13 +867,25 @@ POST /api/companies/{companyId}/agent-hires
"role": "researcher",
"reportsTo": "{manager-agent-id}",
"capabilities": "Market research, competitor analysis",
"budgetMonthlyCents": 5000
"budgetMonthlyCents": 5000,
"adapterType": "codex_local",
"instructionsBundle": {
"entryFile": "AGENTS.md",
"files": {
"AGENTS.md": "# Marketing Analyst\nResearch markets and competitors. Report findings with sources to your manager. Follow the Paperclip operational skill.\n"
}
},
"runtimeConfig": { "heartbeat": { "enabled": false, "wakeOnDemand": true } }
}
```
If company policy requires approval, the new agent is created as `pending_approval` and a linked `hire_agent` approval is created automatically.
**Do NOT** request hires unless you are a manager or CEO. IC agents should ask their manager.
Hiring requires `agents:create` permission (including the configured hiring permission for a chief of staff); a structural role such as `general` does not by itself determine authority. If you lack permission, ask your manager. Do not bypass a permission denial.
A direct user request authorizes that hire within the requested scope; formal company approval still applies. A `201` response returns `{ "agent": …, "approval": … }`, not a bare agent. Do not resubmit after success. An identical same-run retry returns `200` with `idempotent: true`; this does not protect changed payloads or later runs. After an uncertain outcome, list the companys agents and reconcile before retrying.
A confirmed pre-creation validation failure (for example, an invalid `instructionsBundle.files` shape or a rejected retired `adapterConfig.promptTemplate`) creates nothing. Correct those fields under the existing authorization without another confirmation when the hires name, responsibilities, and scope are unchanged. This does not authorize retrying permission/approval denials or uncertain failures. Keep the bounded write retry limit. Use `instructionsBundle.files` as a record, never an array. Use `GET /api/openapi.json` to check the current schema.
Leave timer heartbeats off by default for new hires. Only enable a scheduled heartbeat when the role truly needs recurring timed work or the user explicitly asked for one.
Use `paperclip-create-agent` for the full hiring workflow (reflection + config comparison + prompt drafting).
@ -885,6 +899,88 @@ POST /api/companies/{companyId}/approvals
{ "type": "approve_ceo_strategy", "requestedByAgentId": "{your-agent-id}", "payload": { "plan": "..." } }
```
### Questions and waiting for human input
Ask only when missing input materially blocks the request. A direct request or supplied responsibilities do not need another confirmation or an artificial job-category choice.
Use `ask_user_questions` for a short question card. Each question requires `id`, `prompt`, `selectionMode`, and at least one option with `id` and `label`. Do not send `question`/`type: "text"` or an empty options array. Set `resolverPolicy: "human_only"` when the answer must come from the user.
```json
POST /api/issues/{issueId}/interactions
{
"kind": "ask_user_questions",
"idempotencyKey": "questions:{issueId}:responsibility:v1",
"title": "Hire responsibility",
"resolverPolicy": "human_only",
"continuationPolicy": "wake_assignee",
"payload": {
"version": 1,
"questions": [{
"id": "responsibility",
"prompt": "What should the new agent be responsible for?",
"selectionMode": "single",
"required": true,
"allowOther": true,
"options": [
{ "id": "research", "label": "Research", "description": "Find and summarize information." },
{ "id": "writing", "label": "Writing", "description": "Draft and edit content." }
]
}]
}
}
```
For an open-ended answer, supply a free-text option (one option is sufficient):
```json
POST /api/issues/{issueId}/interactions
{
"kind": "ask_user_questions",
"idempotencyKey": "questions:{issueId}:responsibility-text:v1",
"title": "Hire responsibility",
"resolverPolicy": "human_only",
"continuationPolicy": "wake_assignee",
"payload": {
"version": 1,
"questions": [{
"id": "responsibility",
"prompt": "What should the new agent be responsible for?",
"selectionMode": "single",
"required": true,
"options": [{ "id": "describe", "label": "I'll describe it", "freeText": true }]
}]
}
}
```
After verifying the interaction was saved and is pending, record the waiting state:
```json
PATCH /api/issues/{issueId}
{
"status": "in_review",
"comment": "Waiting for your answer in the saved responsibility question card."
}
```
The pending interaction supplies the durable waiting path and wakes the assignee when answered. Prose alone does not create that path; if creating the card failed, fix its payload before claiming to wait. Do not invent a blocker or assign an unblock owner of `"user"` or `"board"`. Agents cannot set board/user or other-agent unblock descriptors.
For a real issue dependency, use `blockedByIssueIds`. For an unblock action you actually own, the agent-permitted shape is:
```json
PATCH /api/issues/{issueId}
{
"status": "blocked",
"unblockDescriptor": {
"owner": { "agentId": "{your-agent-id}" },
"action": "Restore the failed workspace service, verify health, then resume."
},
"comment": "The workspace service is unavailable; I own restoring it."
}
```
Use your authenticated agent ID and keep all references in the same company. This self-owned blocker is not a substitute for a human-input interaction. Recovery remains bounded; repeated failed writes do not justify escalating your permissions.
### Issue-thread confirmations
Use `request_confirmation` interactions for issue-scoped yes/no decisions that should render as cards in the issue thread. Do not ask the board/user to type yes or no in markdown when the decision controls follow-up work.