diff --git a/.agents/skills/setup-code-maintenance-bot/SKILL.md b/.agents/skills/setup-code-maintenance-bot/SKILL.md new file mode 100644 index 00000000000..ed0fcc1d1ce --- /dev/null +++ b/.agents/skills/setup-code-maintenance-bot/SKILL.md @@ -0,0 +1,121 @@ +--- +name: setup-code-maintenance-bot +description: > + Set up a Paperclip agent and routine that applies a selected code-maintenance + skill to a repository and opens pull requests. Use for nightly maintenance + bots, scheduled code gardening, or webhook-driven maintenance, using an + existing agent or a new hire. +--- + +# Set Up a Code Maintenance Bot + +Turn the user's maintenance intent into a runnable Paperclip routine with a +named agent, accessible repository and skill, bounded work, and inspectable PRs. +The maintenance skill supplies the domain judgment: test auditing, documentation +upkeep, dependency maintenance, refactoring, or another chosen task. + +If asked only to draft instructions or a setup plan, produce that artifact and +stop before provisioning or running anything. Do not perform the maintenance +while setting up the bot. An immediate trial is a separate choice from scheduling. + +## 1. Establish the destination and agent + +Start with the instance and agent choices, using answers already supplied: + +- **Instance:** show a clickable, verified Paperclip web URL and ask which + instance to use. If none is known, ask for its URL; never assume localhost, + the instance used in an earlier task, or the first connected tool. +- **Company:** resolve the company within that instance; ask if ambiguous. +- **Agent:** list accessible, suitable agents with names and links, and offer + **use an existing agent** or **create a new agent**. Do not silently choose. + +Example, after resolving the actual URL: “Use [Paperclip](), +company Acme? Which agent should own this: an existing agent or a new one?” + +For a new agent, resolve its name, harness/adapter, provider and model, AI +connection/account, execution environment, reporting line, and budget. Present +available compatible choices from the selected instance. Distinguish the AI +connection from repository credentials. For an existing agent, inspect these +settings and preserve them unless the requested maintenance needs an authorized +change. Keep maintenance-specific instructions in the routine, not by replacing +an existing agent's role. + +Read [references/paperclip-api.md](references/paperclip-api.md) for authentication, +discovery, connection binding, hiring, and exact provisioning calls. If the API +is unavailable or not working and browser access is available, use the selected +instance's Paperclip UI to perform the same setup. Verify the instance and +company, honor UI approval gates, and inspect the saved agent and routine after +saving. Reconcile any partially completed API setup before creating through the +browser so the fallback does not duplicate resources. Resolve access against +the selected instance before collecting secrets or making writes. + +## 2. Resolve the maintenance contract + +Ask only for missing choices; group related questions rather than presenting a +long questionnaire. Discover actual projects and skills before offering them. + +| Choice | Resolve before activation | +| --- | --- | +| Repository | Project, repository URL, target branch, execution workspace/environment | +| Work | Maintenance goal, exact skill/source, included areas and exclusions | +| Trigger | Timer with local time and IANA timezone; webhook event/source; or manual/API | +| Limits | Per-run time/cost limit, maximum PRs per run, outstanding-PR cap | +| Delivery | PR target and reviewer/owner; draft or ready; required verification | +| Lifecycle | Monitor and revise PRs until checks pass; owner and continuation path for blocked work | + +“Every night” still needs a time and timezone. Propose a concrete time if useful, +but do not infer one silently. A reasonable starting proposal is one coherent PR +per run, a bounded timebox, no automatic merging, and no new work once the agreed +outstanding-PR cap is reached. These are proposals, not fixed product limits. + +Resolve the skill at a source the execution environment can actually read. +A file in this chat's checkout is not proof it exists in a remote worker. +Verify the committed target-branch path and all referenced resources, or install +and assign the company skill. Record the chosen source/version policy. Never +replace an unavailable requested skill with a loosely similar task silently. + +## 3. Prepare the configuration + +Use [references/run-instructions.md](references/run-instructions.md) to write +the complete routine description. It becomes the task given to the worker; +“run maintenance” or a bare skill name is insufficient. + +Inspect existing agents and routines to avoid duplicates. Match by company, +repository, task/skill, and trigger; names alone are not identities. Reuse the +requested agent. If an equivalent routine exists, show it and resolve whether +to reuse or change it rather than creating another nightly job. + +Show a compact summary with the instance link, agent choice, connection/harness, +repository, skill, trigger/timezone, limits, PR behavior, and readiness gaps. +Proceed within the user's existing setup authorization once choices are settled; +ask only for unresolved choices or required product approvals. Draft-only scope +never authorizes creation. Honor server approval gates without bypassing them. + +## 4. Provision, verify, and activate + +Follow the API reference or equivalent browser UI in order: acquire authorized +access, provision/reuse the +agent, make the skill available, create the routine **paused**, add its trigger +**disabled**, and read everything back. Record returned IDs as each step succeeds. +Resume partial setup from those records; an ambiguous response is not a reason +to blindly repeat creation. + +Verify the agent is runnable and can use its selected connection, repository, +skill, and PR credentials in the actual execution environment. A successful +adapter probe alone does not prove Git push/PR permission. Keep the routine +paused if a hire approval, credential, workspace, or skill is unresolved. +Do not change shared project defaults just to make this bot work. + +Enable the trigger and activate the routine only when readiness and scheduling +authorization are established. Use Paperclip's routine trigger as the clock; +do not add a second agent timer or a desktop automation for the same work. +Run a maintenance trial only if requested. Read back the saved schedule and +next run time; distinguish configured scheduling from an observed successful run. + +## 5. Hand off + +Return links to the instance, agent, routine, and project; the selected skill; +the trigger and timezone; active/paused state; limits and PR policy; readiness +evidence and remaining gaps. If trialed, link the run issue and resulting PR or +no-change result. Explain how to pause the routine and which owner handles +follow-up. Never report a draft, pending hire, or paused routine as running. diff --git a/.agents/skills/setup-code-maintenance-bot/agents/openai.yaml b/.agents/skills/setup-code-maintenance-bot/agents/openai.yaml new file mode 100644 index 00000000000..5243bd89424 --- /dev/null +++ b/.agents/skills/setup-code-maintenance-bot/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Set Up Code Maintenance Bot" + short_description: "Set up Paperclip maintenance agents and routines" + default_prompt: "Use $setup-code-maintenance-bot to configure a Paperclip routine that applies my chosen maintenance skill and opens pull requests." diff --git a/.agents/skills/setup-code-maintenance-bot/references/paperclip-api.md b/.agents/skills/setup-code-maintenance-bot/references/paperclip-api.md new file mode 100644 index 00000000000..2c6bc30df2c --- /dev/null +++ b/.agents/skills/setup-code-maintenance-bot/references/paperclip-api.md @@ -0,0 +1,274 @@ +# Paperclip setup API + +Use this reference when executing setup. These are API shapes, not commands to +run while authoring this skill. Read the selected instance's advertised schemas +before mutations; deployments can differ from the source used here. + +## Access and discovery + +Prefer the selected instance's available Paperclip tools. On Runner, discover +operations through its advertised `search_api` / `call_api` tools when present; +they supply authentication and company context. Do not invent tool names or +recover tokens from workspace files when those tools are unavailable. + +If API access is unavailable or calls are not working and browser access is +available, use the authenticated Paperclip web UI on the selected instance. +Perform the same agent, skill, project, routine, and trigger setup through its +visible controls. Inspect existing records first, including resources created +by a partially successful API attempt. Honor the signed-in user's permissions +and approval gates. After saving, reopen the agent/routine and verify its fields, +trigger, and active/paused state. Record IDs and links from the resulting pages. +If the UI cannot configure a required setting, report that specific gap and keep +the setup paused; do not claim the setting was saved or bypass access controls. + +For an authorized HTTP client, use its existing board session or injected +`PAPERCLIP_API_URL` / `PAPERCLIP_API_KEY`. Normalize the base to append `/api` +exactly once. A run bridge address may differ from the user-facing web URL; +show the web URL but use the injected bridge for API requests. Never send the +credential to a different origin while resolving the user's instance choice. +Use the supported sign-in flow if access is missing, not credentials pasted +into chat. Keep secret values out of generated instructions, logs, and files. + +Resolve identity/company through tool context, the authenticated CLI's `whoami`, +or `GET /api/agents/me` for agent callers. The latter is not a board identity +endpoint. Read only the selected company's records: + +| Purpose | Operation | +| --- | --- | +| Candidate agents | `GET /api/companies/{companyId}/agents` | +| Agent configuration (permission required) | `GET /api/agents/{agentId}/configuration` | +| Projects and workspace selection | `GET /api/companies/{companyId}/projects`, `GET /api/projects/{projectId}`, `GET /api/projects/{projectId}/workspaces` | +| Existing routines | `GET /api/companies/{companyId}/routines` | +| Adapter capabilities | `GET /llms/agent-configuration.txt`, then `/llms/agent-configuration/{adapterType}.txt` | +| Available models | `GET /api/companies/{companyId}/adapters/{adapterType}/models` | +| AI connections (board access) | `GET /api/companies/{companyId}/ai-connections` | + +Agent callers can manage only routines assigned to themselves. Creating a new +agent does not confer permission to manage that agent's routine. Use authorized +board/operator access for another agent (including the necessary `tasks:assign` +grant), or hand off through the supported authorized setup path. Do not mint an +agent key or impersonate the assignee to bypass this restriction. A forbidden +connection-list/configuration read is an access gap, not evidence of no accounts. + +## Agent and AI connection + +Read adapter docs before constructing configuration. A harness is the execution +adapter/runtime; a provider/model is its inference choice; an AI connection is +the account used to authenticate/bill it. The runtime also needs an execution +environment and separate Git-host access. Do not copy redacted credentials or +unrelated agents' entire configs. + +For instances supporting managed AI connections, the binding belongs under +`runtimeConfig.aiConnection`, not an invented top-level `connectionId`: + +```json +{ + "mode": "shared", + "provider": "", + "method": "", + "connectionId": "", + "grantId": "" +} +``` + +The alternative `responsible_user` binding uses `provider`, `method`, and +`mode: "responsible_user"` without connection/grant IDs. It resolves the +responsible user's provider default at run time; verify the scheduled routine's +responsible user and access, not just the setup caller's login. Discover compatible +bindings on the deployed instance. Never assume a model/provider combination +works merely because both appear in separate lists. + +Prefer the governance-aware hire endpoint for a new agent: + +```text +POST /api/companies/{companyId}/agent-hires +``` + +Construct the body using discovered values: + +- `name`, `role`, `title`, `reportsTo`, `capabilities`, and a supported `icon`. +- `adapterType`, adapter-specific `adapterConfig`, and `defaultEnvironmentId` + when supported and needed for the selected environment. +- `runtimeConfig.aiConnection` for the resolved managed connection, if used. +- `runtimeConfig.heartbeat: {"enabled": false, "wakeOnDemand": true}` for a new + routine-driven agent when supported. Preserve existing agents' other schedules. +- `instructionsBundle.files["AGENTS.md"]` for managed-instruction adapters: + a focused maintenance role, repository rules, bounded execution, normal + Paperclip task lifecycle, and the user's PR/merge authority. Do not use legacy + prompt-template config when managed instructions are supported. +- `desiredSkills` with installed company skill references when applicable. +- `budgetMonthlyCents` for the user-selected monthly budget, and `sourceIssueId` + only when a real source issue exists. + +Use the installed `paperclip-create-agent` skill for its detailed role-template +and hiring workflow when available. Read the response's `agent` and `approval`. +A pending hire is not runnable; leave activation pending and link the approval. +Do not use direct creation to evade governance. Preserve existing agents' +instructions, permissions, connection, and budgets unless changes are authorized. + +The adapter probe is: + +```text +POST /api/companies/{companyId}/adapters/{adapterType}/test-environment +``` + +Its current body accepts `adapterConfig`, optional `agentId`, `aiConnection`, and +`environmentId`. Supply the actual execution environment: omitting it can test +the Paperclip host instead of the worker. Inspect the probe's diagnostics; an +HTTP success alone is insufficient. Use supported runtime checks to verify +repository/skill readability and Git-host identity/permissions without publishing +a throwaway PR. Report any capability not exercised; leave unresolved access +blocked rather than claiming a successful maintenance run. + +## Make the maintenance skill available + +Choose either verified repository delivery or company installation: + +- **Repository:** verify the full skill directory is committed and reachable on + the selected checkout ref, including references/scripts. Use the worker's + workspace-relative path, never the setup machine's absolute path. Document + whether the worker follows that branch or an explicitly pinned version. +- **Company library:** inspect `GET /api/companies/{companyId}/skills`; reuse the + exact installed skill when suitable. For an external source, use + `POST /api/companies/{companyId}/skills/import` with `{"source":""}`. + For a catalog skill, discover it via `GET /api/skills/catalog`, then use + `POST /api/companies/{companyId}/skills/install-catalog` with its returned + `catalogSkillId`. Local import paths must exist on the importing server. + +Read back the installed skill's `SKILL.md` and required resources. Installation +is separate from assignment. Attach with: + +```text +POST /api/agents/{agentId}/skills/sync +{"mode":"add","desiredSkills":[""]} +``` + +Verify through `GET /api/agents/{agentId}/skills`. Use `add` to preserve other +assignments; do not replace the full set for a single maintenance task. + +## Create a paused routine and disabled trigger + +Serialize the complete run instructions as `description` with real newlines. +Do not interpolate untrusted prose into a shell command. A JSON file or structured +tool argument avoids shell expansion. Replace every placeholder before sending. + +```text +POST /api/companies/{companyId}/routines +``` + +```json +{ + "title": "", + "description": "", + "assigneeAgentId": "", + "projectId": "", + "status": "paused", + "concurrencyPolicy": "skip_if_active", + "catchUpPolicy": "skip_missed", + "activityGatePolicy": "always", + "activityGateScope": "project" +} +``` + +The server derives `responsibleUserId` from the authorized user/parent-issue +context; it is not an arbitrary create-body field. Verify that attribution on +read-back. If an agent caller has no resolvable responsible user, use an +appropriate authorized parent-issue context or operator setup rather than +inventing a user ID. + +`skip_if_active` avoids overlapping run issues; `coalesce_if_active` is another +supported choice if the user wants firings associated with current work. Neither +limits outstanding GitHub PRs: the run instructions must enforce that separately. +Use `always` for literal nightly execution. Paperclip's external-activity gate +tracks Paperclip activity, not Git commits; do not use it as a repository-change +detector. The worker can cheaply check whether new repository work exists. + +The routine schema does not accept arbitrary workspace settings. Inspect the +project's execution policy and verify the worker gets the intended repository +and isolation. Do not assume workspace overrides on one manual run will persist +for future scheduled runs. Prefer an existing suitable project/workspace; if +provisioning one is needed, resolve that scope and use its advertised API. + +```text +POST /api/routines/{routineId}/triggers +``` + +Schedule example, **only if the user selected 02:00 America/Chicago**: + +```json +{"kind":"schedule","enabled":false,"cronExpression":"0 2 * * *","timezone":"America/Chicago"} +``` + +Cron uses five fields. Inspect the server's next run time and daylight-saving +behavior for the chosen timezone; do not promise a fixed 24-hour interval. + +For webhooks, use the supported signing scheme, for example: + +```json +{"kind":"webhook","enabled":false,"signingMode":"hmac_sha256","replayWindowSec":300} +``` + +Use the response's trigger ID, webhook URL, and secret material; do not fabricate +them. Store signing secrets through the supported secret/connection flow without +printing the response's secret fields. Configure the sender only within the +user's authorization. Inspect the deployed signing protocol, event filter, and +replay behavior; a generic Paperclip webhook is not automatically compatible +with every provider's event signature. Keep it disabled if the sender is not ready. + +For manual/API use, the trigger body is `{"kind":"api","enabled":false}`. +API triggers require callers; they do not create a timer. + +## Read back, activate, and report + +Read `GET /api/routines/{routineId}` and verify the complete saved description, +assignee, project, policies, trigger, and absence of unintended extra triggers. +Keep a setup receipt of IDs and completed steps. If a create response is lost, +reconcile existing records before retrying; these create calls should not be +assumed idempotent. A run endpoint's idempotency key does not protect setup calls. + +Once ready and authorized: + +```text +PATCH /api/routine-triggers/{triggerId} +{"enabled":true} + +PATCH /api/routines/{routineId} +{"status":"active"} +``` + +Read back again. If activation fails, leave the routine paused; report the +existing resources and exact next step. Do not delete a reused agent or project +as cleanup for partial setup. + +Only for an authorized immediate trial: + +```text +POST /api/routines/{routineId}/run +{"source":"manual","idempotencyKey":""} +``` + +This starts real work and can dispatch even while the routine is paused; it is +not a dry-run API. Reuse the key only for retries of that trial. Inspect +`GET /api/routines/{routineId}/runs?limit=10` and the returned execution issue: +queued, coalesced, or skipped is not a successful maintenance run. A bounded trial +must either return the promised PR/no-change result or a specific failure. + +To stop future automatic work, `PATCH /api/routines/{routineId}` with +`{"status":"paused"}`. Pausing does not cancel an already dispatched issue/run; +inspect that separately if the user requests a full stop. Archiving is terminal, +so use pause for reversible suspension. + +Prefer returned UI links. Otherwise resolve the company's actual URL prefix and +build links under the verified web base: `/{prefix}/agents/{agent-key-or-id}`, +`/{prefix}/projects/{project-key-or-id}`, `/{prefix}/routines/{routineId}`, and +`/{prefix}/issues/{identifier}`. Never substitute an API bridge URL for a web link. + +## Source anchors + +These shapes were checked against Paperclip source revision +`c65fc9e3c81c41aafe421aa90a00514b84343285`. When available in the target repository, +inspect `packages/shared/src/validators/{agent,routine,project}.ts`, +`packages/shared/src/ai-connections.ts`, `server/src/routes/{agents,routines,ai-connections}.ts`, +and `server/src/services/routines.ts`. The deployed instance's schemas and access +checks remain authoritative. This skill does not require those source files +to be installed alongside it. diff --git a/.agents/skills/setup-code-maintenance-bot/references/run-instructions.md b/.agents/skills/setup-code-maintenance-bot/references/run-instructions.md new file mode 100644 index 00000000000..d382ae12e81 --- /dev/null +++ b/.agents/skills/setup-code-maintenance-bot/references/run-instructions.md @@ -0,0 +1,105 @@ +# Instructions for each maintenance run + +Use this to compose the routine's `description`. Resolve the fields from setup; +do not leave placeholders in the saved task. These instructions invoke the chosen +maintenance skill, **not** `setup-code-maintenance-bot` again. + +## Task template + +```markdown +Maintain , targeting , in project . +Goal: . + +Read and apply . +Skill source/version policy: . +Scope: . Exclusions: . + +Bound this run to