From 0f5f4617296308ba75680a58af0c1ed89bb9ab7d Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Fri, 10 Jul 2026 08:28:37 -0500 Subject: [PATCH 01/23] Avoid startup crash when Reflection Coach assets are missing (#9351) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The server has built-in agent definitions that are loaded during startup and used to provision optional operational agents such as Reflection Coach > - Reflection Coach stores richer stock instructions, a routine description, and a bundled skill as markdown assets outside the TypeScript module body > - A deployed server can fail before it is healthy if one of those copied markdown assets is absent from `server/dist` > - A recent build fix preserves those assets during normal server builds, but runtime should still degrade gracefully if a packaged asset is missing or unreadable > - This pull request adds resilient loading for built-in Reflection Coach assets and keeps a minimal compiled fallback available > - The benefit is that a missing optional built-in agent file no longer turns into a process-wide startup crash ## Linked Issues or Issue Description Bug fix. No public GitHub issue found for this exact startup crash. - Related public PR: #9339 - What happened: the server could throw `ENOENT` while importing the built-in agent service if `server/dist/built-ins/agents/reflection-coach/AGENTS.md` was missing from a deployed build. - Expected behavior: the server should keep starting, log that the built-in asset was missing, and use safe fallback text for the optional built-in agent resource. - Steps to reproduce: build the server, remove the compiled Reflection Coach `AGENTS.md` asset from `server/dist`, then import/start the server path that loads built-in agent definitions. - Paperclip version/commit: reproduced against a deployed build containing the Reflection Coach built-in agent assets; fixed against current `master` after #9339. - Deployment mode: Node server deployment using compiled `server/dist` output. ## What Changed - Added built-in agent text loading that checks the compiled asset path first, then source/package fallback paths, then a minimal compiled-in fallback string. - Added fallback text for Reflection Coach instructions, routine description, and bundled skill content so startup does not depend on optional markdown assets being present. - Added regression coverage for readable candidate selection and missing-file fallback behavior. ## Verification - `pnpm -w exec vitest run server/src/__tests__/built-in-agents.test.ts` — 1 test file passed, 24 tests passed. - `pnpm --filter @paperclipai/server build` — server TypeScript build completed and copied `src/built-ins` into `dist/built-ins`. - Manual smoke: temporarily moved `server/dist/built-ins/agents/reflection-coach/AGENTS.md`, imported `server/dist/services/built-in-agents.js` through the repo-pinned `tsx` runtime, and confirmed Reflection Coach definitions still loaded with output `reflection-coach:3732`; the asset was restored afterward. ## Risks Low risk. The normal path still uses the full packaged markdown assets. The fallback path is only used when those files are missing or unreadable, and it logs a warning so packaging drift remains visible. ## Model Used OpenAI GPT-5 Codex coding agent, with repository tool access and shell-based verification. Exact context window was not exposed in this runtime. ## 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 --- server/src/__tests__/built-in-agents.test.ts | 55 ++++++++- server/src/services/built-in-agents.ts | 115 +++++++++++++++++-- 2 files changed, 158 insertions(+), 12 deletions(-) diff --git a/server/src/__tests__/built-in-agents.test.ts b/server/src/__tests__/built-in-agents.test.ts index b42ef25822c..3ee9ce13ce5 100644 --- a/server/src/__tests__/built-in-agents.test.ts +++ b/server/src/__tests__/built-in-agents.test.ts @@ -1,5 +1,8 @@ import { randomUUID } from "node:crypto"; -import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest"; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import path from "node:path"; +import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest"; import { eq } from "drizzle-orm"; import { activityLog, @@ -32,6 +35,7 @@ import { builtInAgentService, deriveBuiltInAgentStatus, listBuiltInAgentDefinitions, + readBuiltInTextWithFallback, reconcileBuiltInAgentsOnStartup, validateBuiltInAgentDefinitions, } from "../services/built-in-agents.ts"; @@ -51,6 +55,55 @@ if (!embeddedPostgresSupport.supported) { ); } +describe("built-in agent asset loading", () => { + it("uses the first readable candidate path", () => { + const dir = mkdtempSync(path.join(tmpdir(), "paperclip-built-in-agent-")); + try { + const first = path.join(dir, "missing.md"); + const second = path.join(dir, "asset.md"); + writeFileSync(second, "asset text", "utf8"); + + expect(readBuiltInTextWithFallback(`asset:${randomUUID()}`, [first, second], "fallback text")).toBe("asset text"); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); + + it("falls back instead of throwing when built-in agent files are missing", () => { + const warn = vi.spyOn(console, "warn").mockImplementation(() => {}); + const label = `missing:${randomUUID()}`; + + try { + expect(readBuiltInTextWithFallback(label, [path.join(tmpdir(), label, "AGENTS.md")], "fallback text")).toBe( + "fallback text", + ); + expect(warn).toHaveBeenCalledWith(expect.stringContaining(`Built-in agent asset ${label} was not readable`)); + } finally { + warn.mockRestore(); + } + }); + + it("warns about non-missing read errors before falling back", () => { + const warn = vi.spyOn(console, "warn").mockImplementation(() => {}); + const dir = mkdtempSync(path.join(tmpdir(), "paperclip-built-in-agent-")); + const label = "unreadable:" + randomUUID(); + + try { + const directoryPath = path.join(dir, "asset.md"); + mkdirSync(directoryPath); + + expect(readBuiltInTextWithFallback(label, [directoryPath], "fallback text")).toBe("fallback text"); + expect(warn).toHaveBeenCalledWith(expect.stringContaining("read error on " + directoryPath + ":")); + expect(warn).toHaveBeenCalledWith( + expect.stringContaining("Built-in agent asset " + label + " was not readable"), + ); + } finally { + warn.mockRestore(); + rmSync(dir, { recursive: true, force: true }); + } + }); +}); + describeEmbeddedPostgres("built-in agents", () => { let db!: ReturnType; let tempDb: Awaited> | null = null; diff --git a/server/src/services/built-in-agents.ts b/server/src/services/built-in-agents.ts index e7191f3817a..ae3179457ca 100644 --- a/server/src/services/built-in-agents.ts +++ b/server/src/services/built-in-agents.ts @@ -1,5 +1,6 @@ import { createHash } from "node:crypto"; import { readFileSync } from "node:fs"; +import { createRequire } from "node:module"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { readPaperclipSkillSyncPreference, writePaperclipSkillSyncPreference } from "@paperclipai/adapter-utils/server-utils"; @@ -138,20 +139,112 @@ export interface RequiredBuiltInAgent { const BUILT_IN_AGENT_KEY_PATTERN = /^[a-z][a-z0-9_-]*$/; -const BUILT_INS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../built-ins/agents"); +const moduleDir = path.dirname(fileURLToPath(import.meta.url)); +const require = createRequire(import.meta.url); +const BUILT_INS_DIR = path.resolve(moduleDir, "../built-ins/agents"); +const SOURCE_BUILT_INS_DIR = path.resolve(moduleDir, "../../src/built-ins/agents"); -function readBuiltInText(relativePath: string) { - return readFileSync(path.join(BUILT_INS_DIR, relativePath), "utf8"); +const FALLBACK_REFLECTION_COACH_INSTRUCTIONS = [ + "# Reflection Coach", + "", + "You are Paperclip's built-in Reflection Coach.", + "Review recent agent execution records, identify evidence-backed improvement patterns, and propose the smallest durable instruction, skill, or tool-description change.", + "Do not apply changes in the same run. Present a reviewable diff and wait for the required Paperclip issue-thread approval before any follow-up applies it.", + "", +].join("\n"); + +const FALLBACK_REFLECTION_COACH_ROUTINE = [ + "Review recent agent work for coaching opportunities.", + "", + "Select recent target agents, inspect their work history and current instructions, then propose small, review-gated improvements that would prevent repeated misses.", + "", +].join("\n"); + +const FALLBACK_REFLECTION_COACH_SKILL = [ + "---", + "name: reflection-coach", + "description: Reflect on another agent's recent execution record and propose the smallest review-gated improvement.", + "key: paperclipai/bundled/paperclip-operations/reflection-coach", + "---", + "", + "# Reflection Coach", + "", + "Review another agent's recent execution record, name evidence-backed patterns, and propose the smallest durable improvement as a reviewable diff. Do not hot-swap instructions or skills in the same run.", + "", +].join("\n"); + +const warnedBuiltInTextFallbacks = new Set(); +const warnedBuiltInTextReadErrors = new Set(); + +function resolvePackageRoot(packageName: string) { + try { + return path.dirname(require.resolve(`${packageName}/package.json`)); + } catch { + return null; + } } -const REFLECTION_COACH_INSTRUCTIONS = readBuiltInText("reflection-coach/AGENTS.md"); -const REFLECTION_COACH_ROUTINE = readBuiltInText("reflection-coach/routines/recent-agent-reflection.md"); -const REFLECTION_COACH_SKILL = readFileSync( - path.resolve( - path.dirname(fileURLToPath(import.meta.url)), - "../../../packages/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md", - ), - "utf8", +export function readBuiltInTextWithFallback( + label: string, + candidatePaths: string[], + fallbackText: string, +) { + const attemptedPaths = candidatePaths.filter((candidatePath) => candidatePath.trim().length > 0); + for (const candidatePath of attemptedPaths) { + try { + return readFileSync(candidatePath, "utf8"); + } catch (error) { + const code = (error as NodeJS.ErrnoException).code; + if (code !== "ENOENT") { + const codeLabel = code || String(error); + const warningKey = [label, candidatePath, codeLabel].join(":"); + if (!warnedBuiltInTextReadErrors.has(warningKey)) { + warnedBuiltInTextReadErrors.add(warningKey); + console.warn( + "[paperclip] Built-in agent asset " + label + " read error on " + candidatePath + ": " + codeLabel, + ); + } + } + // Try every known runtime/source path before falling back to compiled text. + } + } + + if (!warnedBuiltInTextFallbacks.has(label)) { + warnedBuiltInTextFallbacks.add(label); + console.warn( + `[paperclip] Built-in agent asset ${label} was not readable; using bundled fallback text. ` + + `Checked: ${attemptedPaths.join(", ")}`, + ); + } + return fallbackText; +} + +function readBuiltInText(relativePath: string, fallbackText: string) { + return readBuiltInTextWithFallback( + relativePath, + [path.join(BUILT_INS_DIR, relativePath), path.join(SOURCE_BUILT_INS_DIR, relativePath)], + fallbackText, + ); +} + +const skillsCatalogRoot = resolvePackageRoot("@paperclipai/skills-catalog"); +const REFLECTION_COACH_INSTRUCTIONS = readBuiltInText("reflection-coach/AGENTS.md", FALLBACK_REFLECTION_COACH_INSTRUCTIONS); +const REFLECTION_COACH_ROUTINE = readBuiltInText( + "reflection-coach/routines/recent-agent-reflection.md", + FALLBACK_REFLECTION_COACH_ROUTINE, +); +const REFLECTION_COACH_SKILL = readBuiltInTextWithFallback( + "reflection-coach/SKILL.md", + [ + path.resolve( + moduleDir, + "../../../packages/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md", + ), + ...(skillsCatalogRoot + ? [path.join(skillsCatalogRoot, "catalog/bundled/paperclip-operations/reflection-coach/SKILL.md")] + : []), + ], + FALLBACK_REFLECTION_COACH_SKILL, ); const DEFINITIONS = validateBuiltInAgentDefinitions([ From 953b315dfb338599bd1b27910cec650423f51acd Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Fri, 10 Jul 2026 08:46:20 -0500 Subject: [PATCH 02/23] Shorten skill frontmatter descriptions (#9353) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Paperclip agents can load repository and catalog skills, and Codex renders skill names and frontmatter descriptions into startup context. > - Long descriptions consume the fixed skill metadata budget before Codex can use the progressively disclosed skill bodies. > - The repo `.agents/skills` descriptions and a few shipped catalog descriptions had grown into operational documentation instead of short trigger metadata. > - This pull request keeps the strongest trigger language in frontmatter while leaving detailed procedures in each skill body. > - The benefit is lower prompt overhead, more reliable skill triggering, and a regression guard that prevents description drift from returning. ## Linked Issues or Issue Description No public GitHub issue found for this maintenance item. ### Pre-submission checklist - [x] I have searched existing open and closed issues and this is not a duplicate. - [x] I am working against `master`. - [x] I have confirmed the issue originates in Paperclip's shipped skill metadata, not in a local agent adapter or provider. ### What happened? Codex startup renders discovered skill names and frontmatter descriptions into a fixed skill metadata budget. Several repository skill descriptions and one shipped catalog description had grown into long-form operational guidance, which can force Codex to truncate descriptions before the model has enough trigger signal to select the right skill. ### Expected behavior Skill frontmatter descriptions should stay short trigger summaries: one capability sentence plus a “use when” clause. Detailed procedures should stay in the skill body and load only after the skill triggers. ### Steps to reproduce 1. Inspect `.agents/skills/*/SKILL.md` and `packages/skills-catalog/catalog/**/SKILL.md` frontmatter descriptions. 2. Measure folded YAML `description` values. 3. Observe descriptions above the intended short-trigger range, including descriptions above 300 characters. 4. Run the new shipped catalog test to verify future descriptions stay capped. ### Paperclip version or commit Reproduced on `master` at `cc81eefb6047d8eaf57faf785f421c03dc97073c`. ### Deployment mode Local dev / source checkout metadata inspection. This is not database-related. ### Installation method Built from source. ### Agent adapter(s) involved Codex, because Codex startup uses the skill metadata prompt budget. The metadata source itself is core repository/catalog content. ### Database mode Not database-related. ### Access context Not applicable; this is static repository metadata. ### Node.js version `v22.22.2` in the verification environment. ### Operating system Linux container environment. ### Relevant logs or output Final measurement after this PR: 29 source `SKILL.md` files, max description length 215 chars, 5,449 total description chars, estimated 1,363 description tokens at 4 chars/token. ### Relevant config None. ### Additional context The shipped catalog manifest was regenerated so the generated package metadata matches the edited catalog `SKILL.md` sources. ### Privacy checklist - [x] I have reviewed all pasted output for PII and redacted where necessary. ## What Changed - Shortened long `.agents/skills/*/SKILL.md` frontmatter descriptions to concise capability plus use-when trigger clauses. - Shortened the over-budget shipped skills catalog descriptions for wireframe, Paperclip capsules, and reflection coach. - Regenerated `packages/skills-catalog/generated/catalog.json` so shipped metadata matches source skill frontmatter. - Added a Vitest regression guard that caps repo skill source descriptions and generated catalog descriptions at 300 characters. ## Verification - `pnpm --filter @paperclipai/skills-catalog build:manifest` - `pnpm --filter @paperclipai/skills-catalog test` — 5 files passed, 19 tests passed - `pnpm --filter @paperclipai/skills-catalog typecheck` - Final measurement: 29 source `SKILL.md` files, max description length 215 chars, 5,449 total description chars, estimated 1,363 description tokens at 4 chars/token. Note: the clean PR worktree was created from `origin/master` and contains only this commit, but it does not have `node_modules`; running `pnpm --filter @paperclipai/skills-catalog test` there failed at tool/package resolution (`vitest`, `tsc`, `@paperclipai/shared`). The dependency-equipped workspace passed the commands above before the commit was cherry-picked onto the clean branch. ## Risks Low risk. This changes skill metadata and tests only. The main risk is over-trimming a useful trigger phrase, mitigated by keeping explicit “use when” clauses and leaving detailed guidance in the skill bodies. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 Codex coding agent via Paperclip/Codex, with shell and file-edit tool use. Exact API model ID and context window were not exposed in the runtime. ## 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 - [ ] All Paperclip CI gates are green - [ ] 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 --- .agents/skills/check-pr/SKILL.md | 8 +-- .agents/skills/company-creator/SKILL.md | 12 +--- .agents/skills/create-agent-adapter/SKILL.md | 8 +-- .../create-issue-interaction-ui/SKILL.md | 12 +--- .../deal-with-security-advisory/SKILL.md | 7 +- .../skills/diagnose-why-work-stopped/SKILL.md | 10 +-- .agents/skills/doc-maintenance/SKILL.md | 8 +-- .../skills/paperclip-create-plugin/SKILL.md | 8 +-- .../SKILL.md | 9 +-- .agents/skills/paperclip-page/SKILL.md | 7 +- .agents/skills/pr-report/SKILL.md | 7 +- .agents/skills/prcheckloop/SKILL.md | 9 +-- .../SKILL.md | 8 +-- .agents/skills/terminal-bench-loop/SKILL.md | 14 +--- .../skills/index-refresh/SKILL.md | 2 +- .../skills/paperclip-distill/SKILL.md | 2 +- .../skills/wiki-ingest/SKILL.md | 2 +- .../plugin-llm-wiki/skills/wiki-lint/SKILL.md | 2 +- .../skills/wiki-query/SKILL.md | 2 +- .../reflection-coach/SKILL.md | 2 +- .../product/paperclip-capsules/SKILL.md | 2 +- .../bundled/product/wireframe/SKILL.md | 2 +- .../skills-catalog/generated/catalog.json | 26 ++++---- .../src/shipped-catalog.test.ts | 65 ++++++++++++++++++- skills/paperclip-board/SKILL.md | 7 +- .../SKILL.md | 10 +-- skills/paperclip/SKILL.md | 10 ++- skills/para-memory-files/SKILL.md | 10 +-- 28 files changed, 140 insertions(+), 131 deletions(-) diff --git a/.agents/skills/check-pr/SKILL.md b/.agents/skills/check-pr/SKILL.md index 88d52c10f0f..b02e2c941fa 100644 --- a/.agents/skills/check-pr/SKILL.md +++ b/.agents/skills/check-pr/SKILL.md @@ -1,11 +1,9 @@ --- name: check-pr description: > - Checks a GitHub, GitLab, or Perforce (p4) pull request (or merge request, or shelved changelist) - for unresolved review comments, failing status checks, and incomplete PR descriptions. Waits for - pending checks to complete, categorizes issues as actionable or informational, and optionally fixes - and resolves them. Use when the user wants to check a PR/MR/CL, address review feedback, or prepare - a change for submission. + Check a GitHub, GitLab, or Perforce PR/MR/CL for review comments, failing + checks, and PR-body gaps. Use when asked to inspect, fix, or prepare a change + for submission. license: MIT compatibility: Requires git and gh (GitHub CLI), glab (GitLab CLI), or p4 (Perforce CLI) installed and authenticated. metadata: diff --git a/.agents/skills/company-creator/SKILL.md b/.agents/skills/company-creator/SKILL.md index b2f4432bcdb..afe4be9b621 100644 --- a/.agents/skills/company-creator/SKILL.md +++ b/.agents/skills/company-creator/SKILL.md @@ -1,15 +1,9 @@ --- name: company-creator description: > - Create agent company packages conforming to the Agent Companies specification - (agentcompanies/v1). Use when a user wants to create a new agent company from - scratch, build a company around an existing git repo or skills collection, or - scaffold a team/department of agents. Triggers on: "create a company", "make me - a company", "build a company from this repo", "set up an agent company", - "create a team of agents", "hire some agents", or when given a repo URL and - asked to turn it into a company. Do NOT use for importing an existing company - package (use the CLI import command instead) or for modifying a company that - is already running in Paperclip. + Create agent company packages that conform to agentcompanies/v1. Use when asked + to create a company, scaffold an agent team, hire agents, or turn a repo/skills + collection into a company package. --- # Company Creator diff --git a/.agents/skills/create-agent-adapter/SKILL.md b/.agents/skills/create-agent-adapter/SKILL.md index a41318580c8..6d11362b099 100644 --- a/.agents/skills/create-agent-adapter/SKILL.md +++ b/.agents/skills/create-agent-adapter/SKILL.md @@ -1,11 +1,9 @@ --- name: create-agent-adapter description: > - Technical guide for creating a new Paperclip agent adapter. Use when building - a new adapter package, adding support for a new AI coding tool (e.g. a new - CLI agent, API-based agent, or custom process), or when modifying the adapter - system. Covers the required interfaces, module structure, registration points, - and conventions derived from the existing claude-local and codex-local adapters. + Create or modify Paperclip agent adapters across server, UI, and CLI surfaces. + Use when adding support for a new CLI agent, API agent, custom process, or + adapter package. --- # Creating a Paperclip Agent Adapter diff --git a/.agents/skills/create-issue-interaction-ui/SKILL.md b/.agents/skills/create-issue-interaction-ui/SKILL.md index 9a3bdde25ca..9c46dacd460 100644 --- a/.agents/skills/create-issue-interaction-ui/SKILL.md +++ b/.agents/skills/create-issue-interaction-ui/SKILL.md @@ -1,15 +1,9 @@ --- name: create-issue-interaction-ui description: > - Developer/maintainer skill for adding a new issue-thread interaction kind to - the Paperclip codebase end-to-end: shared contract, server service/routes, - UI card, fixtures/Storybook, CLI/MCP/plugin SDK helpers, agent guidance, and - tests. Use when a Paperclip contributor is asked to introduce a new - interaction family (something analogous to `request_confirmation`, - `request_checkbox_confirmation`, `ask_user_questions`, or `suggest_tasks`) - or to extend the issue-thread interaction system with a new card type. Do - NOT install this on production Paperclip agents — it is for repo work, not - agent runtime behavior. + Add a new Paperclip issue-thread interaction kind end-to-end. Use when repo + work introduces or extends interaction cards like request_confirmation, + checkbox confirmations, ask_user_questions, or suggest_tasks. --- # Create a new issue-thread interaction UI (developer skill) diff --git a/.agents/skills/deal-with-security-advisory/SKILL.md b/.agents/skills/deal-with-security-advisory/SKILL.md index 0ba122366ec..8ddccd52cc8 100644 --- a/.agents/skills/deal-with-security-advisory/SKILL.md +++ b/.agents/skills/deal-with-security-advisory/SKILL.md @@ -1,10 +1,9 @@ --- name: deal-with-security-advisory description: > - Handle a GitHub Security Advisory response for Paperclip, including - confidential fix development in a temporary private fork, human coordination - on advisory-thread comments, CVE request, synchronized advisory publication, - and immediate security release steps. + Handle confidential GitHub Security Advisory response for Paperclip. Use when + coordinating advisory triage, private-fork fixes, CVE/publication steps, and + immediate security releases. --- # Security Vulnerability Response Instructions diff --git a/.agents/skills/diagnose-why-work-stopped/SKILL.md b/.agents/skills/diagnose-why-work-stopped/SKILL.md index 001738731b4..91caa62fa8b 100644 --- a/.agents/skills/diagnose-why-work-stopped/SKILL.md +++ b/.agents/skills/diagnose-why-work-stopped/SKILL.md @@ -1,13 +1,9 @@ --- name: diagnose-why-work-stopped description: > - How to handle "why did this work stop / why is this looping?" assignments. - Forensics first on the named tree, surface the exact stop-point, frame the - fix as a general product rule that respects three invariants (productive - work continues, only real blockers stop work, no infinite loops), and - deliver a plan — no code changes — gated by board/CTO approval before - child issues are created. Use whenever the issue title or body asks for - forensics on a stalled, looping, or "went too deep" tree. + Diagnose stalled, looping, or over-recovered Paperclip issue trees and propose + a no-code product-rule plan. Use when asked why work stopped, why it looped, or + how to prevent a tree from going too deep. --- # Diagnose Why Work Stopped diff --git a/.agents/skills/doc-maintenance/SKILL.md b/.agents/skills/doc-maintenance/SKILL.md index a597e90ccbc..839786bc826 100644 --- a/.agents/skills/doc-maintenance/SKILL.md +++ b/.agents/skills/doc-maintenance/SKILL.md @@ -1,11 +1,9 @@ --- name: doc-maintenance description: > - Audit top-level documentation (README, SPEC, PRODUCT) against recent git - history to find drift — shipped features missing from docs or features - listed as upcoming that already landed. Proposes minimal edits, creates - a branch, and opens a PR. Use when asked to review docs for accuracy, - after major feature merges, or on a periodic schedule. + Audit README, SPEC, and PRODUCT docs against recent git history for drift and + make minimal PR-ready edits. Use when asked to review docs for accuracy, after + major feature merges, or on a schedule. --- # Doc Maintenance Skill diff --git a/.agents/skills/paperclip-create-plugin/SKILL.md b/.agents/skills/paperclip-create-plugin/SKILL.md index 4dda697d64f..7e660eadd6a 100644 --- a/.agents/skills/paperclip-create-plugin/SKILL.md +++ b/.agents/skills/paperclip-create-plugin/SKILL.md @@ -1,11 +1,9 @@ --- name: paperclip-create-plugin description: > - Create and develop external Paperclip plugins with the CLI-first workflow. - Use when scaffolding a new plugin, working on a local plugin against a running - Paperclip instance, or updating plugin authoring docs. Covers `paperclipai - plugin init`, the local install loop via `paperclipai plugin install `, - worker/UI rebuild and reload semantics, and the required success checklist. + Create and develop external Paperclip plugins with the CLI-first workflow. Use + when scaffolding a plugin, iterating on a local plugin, installing it into + Paperclip, or updating plugin authoring docs. --- # Create and develop a Paperclip plugin diff --git a/.agents/skills/paperclip-dev-workspace-run-verify-fix/SKILL.md b/.agents/skills/paperclip-dev-workspace-run-verify-fix/SKILL.md index 1fae60e3071..9b41eed6a1c 100644 --- a/.agents/skills/paperclip-dev-workspace-run-verify-fix/SKILL.md +++ b/.agents/skills/paperclip-dev-workspace-run-verify-fix/SKILL.md @@ -1,12 +1,9 @@ --- name: paperclip-dev-workspace-run-verify-fix description: > - Run, verify, reseed, and repair a Paperclip isolated dev workspace service. - Use when asked to start or fix a Paperclip project/worktree service and prove - that it is managed by the Paperclip runtime, has the full bootstrapped cloned - database, is healthy, accepts normal dev credentials, exposes populated app - data, and is visible as running from both the control-plane and the served - workspace app. + Run, verify, reseed, and repair Paperclip isolated dev workspace services. Use + when asked to start or fix a managed project/worktree service and prove health, + login readiness, cloned data, and runtime visibility. --- # Paperclip Dev Workspace Run / Verify / Fix diff --git a/.agents/skills/paperclip-page/SKILL.md b/.agents/skills/paperclip-page/SKILL.md index cf2852466d3..e9e74cfe085 100644 --- a/.agents/skills/paperclip-page/SKILL.md +++ b/.agents/skills/paperclip-page/SKILL.md @@ -1,10 +1,9 @@ --- name: paperclip-page description: > - Publish static HTML pages and asset folders to the Paperclip-approved S3 and - CloudFront website host. Use when asked to deploy, publish, host, or share a - persistent Paperclip page, wireframe viewer, prototype, report, or other static - site without using here.now. + Publish static HTML pages and asset folders to the Paperclip S3/CloudFront page + host. Use when asked to deploy, host, or share a persistent page, viewer, + prototype, report, or static site without here.now. --- # Paperclip Page diff --git a/.agents/skills/pr-report/SKILL.md b/.agents/skills/pr-report/SKILL.md index 5064b67c090..3ebe590ee76 100644 --- a/.agents/skills/pr-report/SKILL.md +++ b/.agents/skills/pr-report/SKILL.md @@ -1,10 +1,9 @@ --- name: pr-report description: > - Review a pull request or contribution deeply, explain it tutorial-style for a - maintainer, and produce a polished report artifact such as HTML or Markdown. - Use when asked to analyze a PR, explain a contributor's design decisions, - compare it with similar systems, or prepare a merge recommendation. + Produce a maintainer-grade PR or contribution report as HTML or Markdown. Use + when asked to deeply review a PR, explain a design, compare systems, or prepare + a merge recommendation. --- # PR Report Skill diff --git a/.agents/skills/prcheckloop/SKILL.md b/.agents/skills/prcheckloop/SKILL.md index 70d9e19af66..32dc5d5b442 100644 --- a/.agents/skills/prcheckloop/SKILL.md +++ b/.agents/skills/prcheckloop/SKILL.md @@ -1,12 +1,9 @@ --- name: prcheckloop description: > - Iteratively gets a GitHub pull request's checks green. Detects the PR for the - current branch or uses a provided PR number, waits for every check on the - latest head SHA to appear and finish, investigates failing checks, fixes - actionable code or test issues, pushes, and repeats. Escalates with a precise - blocker when failures are external, flaky, or not safely fixable. Use when a - PR still has unsuccessful checks after review fixes, including after greploop. + Iterate on a GitHub PR until latest-head checks are green or a precise blocker + is named. Use when a PR still has failing or pending checks after review fixes, + including after greploop. --- # PRCheckloop diff --git a/.agents/skills/release-changelog-discord-message/SKILL.md b/.agents/skills/release-changelog-discord-message/SKILL.md index 374f3a089d8..367ee8474d2 100644 --- a/.agents/skills/release-changelog-discord-message/SKILL.md +++ b/.agents/skills/release-changelog-discord-message/SKILL.md @@ -1,11 +1,9 @@ --- name: release-changelog-discord-message description: > - Write the Discord release announcement for a stable Paperclip release. Companion - to `release-changelog` — that skill produces the file at `releases/vYYYY.MDD.P.md`; - this one turns that file into a single copy-pasteable Discord post in dotta's - voice and attaches it as the `discord_announcement` document on the release - issue. + Write the Discord announcement for a stable Paperclip release from the release + changelog. Use when a release issue needs a copy-pasteable dotta-voice Discord + post or refreshed discord_announcement document. --- # Release Discord Announcement Skill diff --git a/.agents/skills/terminal-bench-loop/SKILL.md b/.agents/skills/terminal-bench-loop/SKILL.md index 6a3c8d21159..f106f77450f 100644 --- a/.agents/skills/terminal-bench-loop/SKILL.md +++ b/.agents/skills/terminal-bench-loop/SKILL.md @@ -1,17 +1,9 @@ --- name: terminal-bench-loop description: > - Run a single Terminal-Bench problem through Paperclip in a bounded, - human-in-the-loop improvement cycle until the smoke passes, the board - rejects the next fix, the iteration budget is exhausted, or a real - blocker is named. Each iteration runs a bounded smoke against an - isolated Paperclip App worktree, captures artifacts, diagnoses the - exact stop point with `/diagnose-why-work-stopped`, requests board - confirmation before any product fix, then reruns against the same - worktree. Use whenever an issue asks to "run Terminal-Bench in a - loop", "drive Terminal-Bench until it passes", "loop fix-git through - Paperclip", or otherwise points at a Terminal-Bench task and asks for - bounded iteration with diagnosis. + Run one Terminal-Bench task through a bounded Paperclip smoke/diagnosis/fix + loop. Use when asked to drive Terminal-Bench until it passes, rerun a + Terminal-Bench loop, or iterate with board-gated fixes and diagnosis. --- # Terminal-Bench Loop diff --git a/packages/plugins/plugin-llm-wiki/skills/index-refresh/SKILL.md b/packages/plugins/plugin-llm-wiki/skills/index-refresh/SKILL.md index e0380e67f31..c1e7f32ee52 100644 --- a/packages/plugins/plugin-llm-wiki/skills/index-refresh/SKILL.md +++ b/packages/plugins/plugin-llm-wiki/skills/index-refresh/SKILL.md @@ -1,6 +1,6 @@ --- name: index-refresh -description: Use when an operation issue is an index refresh — typically the hourly index-refresh routine. Rebuild `wiki/index.md` so each entry has a tight, scannable one-line summary and the catalog tracks the actual contents of `wiki/`. Resolve drift between the index and recent log activity, but do not edit page content. +description: Use when an LLM Wiki operation issue requests an index refresh. Rebuild `wiki/index.md` from the actual wiki tree, reconcile missing/deleted entries, and log counts without editing page bodies. --- # Index Refresh diff --git a/packages/plugins/plugin-llm-wiki/skills/paperclip-distill/SKILL.md b/packages/plugins/plugin-llm-wiki/skills/paperclip-distill/SKILL.md index fa7b8d60d50..8bbebfb188f 100644 --- a/packages/plugins/plugin-llm-wiki/skills/paperclip-distill/SKILL.md +++ b/packages/plugins/plugin-llm-wiki/skills/paperclip-distill/SKILL.md @@ -1,6 +1,6 @@ --- name: paperclip-distill -description: Use when an operation issue is a Paperclip cursor-window, distill, or backfill — `operationType: "distill"` or `"backfill"` and the body references a Paperclip source bundle for a project or root issue. Turn raw Paperclip activity into a wiki-insightful project page, decisions log, and history note. This skill exists specifically to replace the stiff, datestamp-heavy templated output that the deterministic distiller produces. +description: Use when an operation issue is a Paperclip cursor-window, distill, or backfill. Turn source-bundled Paperclip activity into wiki-insightful project standups, durable project pages, decisions, and history without asset dereferencing. --- # Paperclip Distill diff --git a/packages/plugins/plugin-llm-wiki/skills/wiki-ingest/SKILL.md b/packages/plugins/plugin-llm-wiki/skills/wiki-ingest/SKILL.md index 3422af806bd..fdcadfe372d 100644 --- a/packages/plugins/plugin-llm-wiki/skills/wiki-ingest/SKILL.md +++ b/packages/plugins/plugin-llm-wiki/skills/wiki-ingest/SKILL.md @@ -1,6 +1,6 @@ --- name: wiki-ingest -description: Use when an operation issue asks you to ingest a captured source from `raw/` into the LLM Wiki, or when the user explicitly says "ingest ". The issue body will name a file under `raw/` (e.g. `raw/karpathy-llm-wiki.md`) and ask for durable wiki pages. Do not invoke this skill for Paperclip activity bundles — those use `paperclip-distill` instead. +description: Use when an operation issue asks to ingest a captured `raw/` source into the LLM Wiki, or the user says "ingest ". Create durable source, entity, concept, synthesis, index, and log pages; use paperclip-distill for Paperclip bundles. --- # Wiki Ingest diff --git a/packages/plugins/plugin-llm-wiki/skills/wiki-lint/SKILL.md b/packages/plugins/plugin-llm-wiki/skills/wiki-lint/SKILL.md index acaa02557f5..345ca995f9c 100644 --- a/packages/plugins/plugin-llm-wiki/skills/wiki-lint/SKILL.md +++ b/packages/plugins/plugin-llm-wiki/skills/wiki-lint/SKILL.md @@ -1,6 +1,6 @@ --- name: wiki-lint -description: Use when an operation issue is a lint or health-check (`operationType: "lint"`) — typically the nightly lint routine or a manual "Run lint" from the UI. Audit the wiki for contradictions, orphans, weak provenance, broken links, and missing concept pages, and return a triage list — do not auto-fix. +description: Use when an LLM Wiki operation issue is a lint or health check. Audit for contradictions, orphans, weak provenance, broken links, missing concept pages, and index/log drift; return triage findings without auto-fixing. --- # Wiki Lint diff --git a/packages/plugins/plugin-llm-wiki/skills/wiki-query/SKILL.md b/packages/plugins/plugin-llm-wiki/skills/wiki-query/SKILL.md index ccb2855a7f2..fe8d9e57bfb 100644 --- a/packages/plugins/plugin-llm-wiki/skills/wiki-query/SKILL.md +++ b/packages/plugins/plugin-llm-wiki/skills/wiki-query/SKILL.md @@ -1,6 +1,6 @@ --- name: wiki-query -description: Use when an operation issue asks you to answer a question from the LLM Wiki — `operationType: "query"` and a question in the issue body. Answer with citations to wiki pages and raw sources, and offer to file durable synthesis back into `wiki/synthesis/` so the work compounds instead of disappearing into a chat thread. +description: Use when an LLM Wiki operation issue asks a question. Answer from wiki pages and raw sources with citations, name gaps plainly, and offer to file durable synthesis when the answer should compound. --- # Wiki Query diff --git a/packages/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md b/packages/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md index c6786939d70..b5167838920 100644 --- a/packages/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md +++ b/packages/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md @@ -1,6 +1,6 @@ --- name: reflection-coach -description: Reflect on another agent's recent execution record, name evidence-backed patterns, and propose the smallest durable change to their AGENTS.md, a reusable skill, or a tool description — as a reviewable, interaction-gated proposal, never a same-run hot-swap. +description: Reflect on another agent's recent execution record and propose the smallest durable instruction, skill, or tool-description change. Use for evidence-backed coaching proposals, never hot-swaps. key: paperclipai/bundled/paperclip-operations/reflection-coach recommendedForRoles: - manager diff --git a/packages/skills-catalog/catalog/bundled/product/paperclip-capsules/SKILL.md b/packages/skills-catalog/catalog/bundled/product/paperclip-capsules/SKILL.md index 059eec505f3..f14a7e62ab4 100644 --- a/packages/skills-catalog/catalog/bundled/product/paperclip-capsules/SKILL.md +++ b/packages/skills-catalog/catalog/bundled/product/paperclip-capsules/SKILL.md @@ -1,6 +1,6 @@ --- name: paperclip-capsules -description: Generate, implement, or review Paperclip capsule visuals. Use when the user asks for Paperclip capsule art, capsule banks, agent capsule visuals, heartbeat status capsules, capsule identicons, capsule graphic-generator output, or validation of Paperclip capsule brand usage. +description: Generate, implement, or review Paperclip capsule visuals. Use for capsule art, agent capsules, heartbeat status capsules, identicons, capsule banks, or brand-usage validation. key: paperclipai/bundled/product/paperclip-capsules recommendedForRoles: - designer diff --git a/packages/skills-catalog/catalog/bundled/product/wireframe/SKILL.md b/packages/skills-catalog/catalog/bundled/product/wireframe/SKILL.md index cc8af1fbb4d..8058c4d48ee 100644 --- a/packages/skills-catalog/catalog/bundled/product/wireframe/SKILL.md +++ b/packages/skills-catalog/catalog/bundled/product/wireframe/SKILL.md @@ -1,6 +1,6 @@ --- name: wireframe -description: Produce low-fidelity black-and-white UI wireframes as standalone SVG files, optionally bundled into a single-page HTML viewer and published via the here-now skill. Use when the user asks to "wireframe X", "sketch a screen for", "draft a layout", "low-fi mockup", "rough mock", "make a page to view the wireframes", "build a viewer for these screens", or to "deploy / publish / host the wireframes". Do NOT use when the user wants production UI code, branded designs, hi-fi mockups, or animated/interactive prototypes — use frontend-design or similar instead. +description: Produce low-fidelity black-and-white UI wireframes as SVGs or viewer pages. Use when asked to wireframe, sketch a screen, draft a layout, make a low-fi mockup, or publish wireframes. key: paperclipai/bundled/product/wireframe recommendedForRoles: - designer diff --git a/packages/skills-catalog/generated/catalog.json b/packages/skills-catalog/generated/catalog.json index aa64ff92291..bb0bdfb0eb3 100644 --- a/packages/skills-catalog/generated/catalog.json +++ b/packages/skills-catalog/generated/catalog.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "packageName": "@paperclipai/skills-catalog", "packageVersion": "0.3.1", - "generatedAt": "2026-07-10T00:27:11.902Z", + "generatedAt": "2026-07-10T13:15:25.878Z", "skills": [ { "id": "paperclipai:bundled:docs:doc-maintenance", @@ -80,7 +80,7 @@ "category": "paperclip-operations", "slug": "reflection-coach", "name": "reflection-coach", - "description": "Reflect on another agent's recent execution record, name evidence-backed patterns, and propose the smallest durable change to their AGENTS.md, a reusable skill, or a tool description — as a reviewable, interaction-gated proposal, never a same-run hot-swap.", + "description": "Reflect on another agent's recent execution record and propose the smallest durable instruction, skill, or tool-description change. Use for evidence-backed coaching proposals, never hot-swaps.", "path": "catalog/bundled/paperclip-operations/reflection-coach", "entrypoint": "SKILL.md", "trustLevel": "markdown_only", @@ -102,11 +102,11 @@ { "path": "SKILL.md", "kind": "skill", - "sizeBytes": 11903, - "sha256": "ca167eac8d1e89cadc8009b61a204368507e7edb7f2da0688fea6dba8223e189" + "sizeBytes": 11837, + "sha256": "86d6e382c32c626213b46c010cc7fc1ec460821a8c777cfa5b8e86fa9d6a86b2" } ], - "contentHash": "sha256:20381a898f05ceb668e305708dd33a03ce36aef0e00b923c01ae20ab785f04d2" + "contentHash": "sha256:1c7a82cd9638a1d845b238032da3ff4ad80c5b6a87dca46082f501fa4583db55" }, { "id": "paperclipai:bundled:paperclip-operations:task-planning", @@ -150,7 +150,7 @@ "category": "product", "slug": "paperclip-capsules", "name": "paperclip-capsules", - "description": "Generate, implement, or review Paperclip capsule visuals. Use when the user asks for Paperclip capsule art, capsule banks, agent capsule visuals, heartbeat status capsules, capsule identicons, capsule graphic-generator output, or validation of Paperclip capsule brand usage.", + "description": "Generate, implement, or review Paperclip capsule visuals. Use for capsule art, agent capsules, heartbeat status capsules, identicons, capsule banks, or brand-usage validation.", "path": "catalog/bundled/product/paperclip-capsules", "entrypoint": "SKILL.md", "trustLevel": "markdown_only", @@ -175,8 +175,8 @@ { "path": "SKILL.md", "kind": "skill", - "sizeBytes": 5930, - "sha256": "eda40e8f29cae07c2ce8ad1cef3406eae243dbbf52069a85cfb56fe7999a25ff" + "sizeBytes": 5831, + "sha256": "dd659ccb46e105336eb00fbe689b1d5531347fc69493c3156390d40ee413c93e" }, { "path": "references/generator-workflows.md", @@ -203,7 +203,7 @@ "sha256": "be1f2eccf96b4d2deefe45b3bc1dd0a3597278472c2ffedadc43c57161e9103d" } ], - "contentHash": "sha256:e8f502f9556103bd575bb664a9d21b1004869990802e639a188a720012116909" + "contentHash": "sha256:a2b26cf6895affeeb70c85567a061094450a59bd3c4fdcf28ee65858599ac12c" }, { "id": "paperclipai:bundled:product:wireframe", @@ -212,7 +212,7 @@ "category": "product", "slug": "wireframe", "name": "wireframe", - "description": "Produce low-fidelity black-and-white UI wireframes as standalone SVG files, optionally bundled into a single-page HTML viewer and published via the here-now skill. Use when the user asks to \"wireframe X\", \"sketch a screen for\", \"draft a layout\", \"low-fi mockup\", \"rough mock\", \"make a page to view the wireframes\", \"build a viewer for these screens\", or to \"deploy / publish / host the wireframes\". Do NOT use when the user wants production UI code, branded designs, hi-fi mockups, or animated/interactive prototypes — use frontend-design or similar instead.", + "description": "Produce low-fidelity black-and-white UI wireframes as SVGs or viewer pages. Use when asked to wireframe, sketch a screen, draft a layout, make a low-fi mockup, or publish wireframes.", "path": "catalog/bundled/product/wireframe", "entrypoint": "SKILL.md", "trustLevel": "assets", @@ -235,8 +235,8 @@ { "path": "SKILL.md", "kind": "skill", - "sizeBytes": 11887, - "sha256": "a910d038d8cdd13615b82f44a2195b781ebccf01c49f9c58babd43b0701fe644" + "sizeBytes": 11509, + "sha256": "6992047cc97b67211cc8c1183718ab9aa26b8afc34c70d54d20558c215daaf48" }, { "path": "assets/site-template.html", @@ -275,7 +275,7 @@ "sha256": "017260d2216859d57e5fa869e0efc6b88c7ed4d8a8a4f5af04fe89a3ef2445bd" } ], - "contentHash": "sha256:0bd9a9fdc656d529e3f97c00cd504dcf72d3a4fecb8b0504ca2fe3e00d63287f" + "contentHash": "sha256:7106d84fc9db2053090f692706e41cfc586e7dd85a44f568e3319c4eefbdde46" }, { "id": "paperclipai:bundled:quality:qa-acceptance", diff --git a/packages/skills-catalog/src/shipped-catalog.test.ts b/packages/skills-catalog/src/shipped-catalog.test.ts index 1a29bbb4739..0dfe0221b44 100644 --- a/packages/skills-catalog/src/shipped-catalog.test.ts +++ b/packages/skills-catalog/src/shipped-catalog.test.ts @@ -1,4 +1,6 @@ -import { readFileSync } from "node:fs"; +import { readFileSync, readdirSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; import { catalogManifest, catalogSkills, resolveCatalogSkillRef } from "./index.js"; @@ -21,7 +23,68 @@ const EXPECTED_OPTIONAL_KEYS = [ "paperclipai/optional/research/last30days", ]; +const MAX_FRONTMATTER_DESCRIPTION_LENGTH = 300; +const REPO_ROOT = path.resolve(fileURLToPath(new URL("../../..", import.meta.url))); +const SKILL_FRONTMATTER_ROOTS = [ + path.join(REPO_ROOT, ".agents"), + path.join(REPO_ROOT, "skills"), + path.join(REPO_ROOT, "packages/adapters"), + path.join(REPO_ROOT, "packages/plugins"), + path.join(REPO_ROOT, "packages/skills-catalog/catalog"), + path.join(REPO_ROOT, "packages/teams-catalog/catalog"), +]; + +function listSkillFiles(dir: string): string[] { + return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => { + const entryPath = path.join(dir, entry.name); + if (entry.isDirectory()) return listSkillFiles(entryPath); + if (entry.isFile() && entry.name === "SKILL.md") return [entryPath]; + return []; + }); +} + +function readFrontmatterDescription(markdown: string): string | null { + const match = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/); + if (!match) return null; + + const lines = match[1]!.split(/\r?\n/); + const descriptionIndex = lines.findIndex((line) => line.startsWith("description:")); + if (descriptionIndex === -1) return null; + + const inlineValue = lines[descriptionIndex]!.slice("description:".length).trim(); + if (/^[>|][+-]?$/.test(inlineValue)) { + const descriptionLines: string[] = []; + for (let index = descriptionIndex + 1; index < lines.length; index += 1) { + const line = lines[index]!; + if (/^[A-Za-z0-9_-]+:/.test(line)) break; + descriptionLines.push(line.trim()); + } + return descriptionLines.join(" ").replace(/\s+/g, " ").trim(); + } + + return inlineValue.replace(/^['"]|['"]$/g, ""); +} + describe("shipped skills catalog", () => { + it("keeps repo and catalog skill descriptions within the prompt budget cap", () => { + const violations: string[] = []; + for (const skillFile of SKILL_FRONTMATTER_ROOTS.flatMap(listSkillFiles)) { + const description = readFrontmatterDescription(readFileSync(skillFile, "utf8")); + if (!description) { + violations.push(`${path.relative(REPO_ROOT, skillFile)} is missing a frontmatter description`); + } else if (description.length > MAX_FRONTMATTER_DESCRIPTION_LENGTH) { + violations.push(`${path.relative(REPO_ROOT, skillFile)} description is ${description.length} chars`); + } + } + for (const skill of catalogSkills) { + if (skill.description.length > MAX_FRONTMATTER_DESCRIPTION_LENGTH) { + violations.push(`${skill.key} generated description is ${skill.description.length} chars`); + } + } + + expect(violations).toEqual([]); + }); + it("ships the expected bundled and optional skill set", () => { const bundledKeys = catalogSkills .filter((skill) => skill.kind === "bundled") diff --git a/skills/paperclip-board/SKILL.md b/skills/paperclip-board/SKILL.md index 55fa03b40cc..318fcb72bce 100644 --- a/skills/paperclip-board/SKILL.md +++ b/skills/paperclip-board/SKILL.md @@ -1,10 +1,9 @@ --- name: paperclip-board description: > - Manage a Paperclip company as a board member via chat. Covers onboarding - (company creation, CEO setup, hiring plans), agent management, approvals, - task monitoring, cost oversight, and work product review. Use this skill - whenever the user wants to interact with their Paperclip control plane. + Manage a Paperclip company as a board member via chat. Use when the user wants + onboarding, company or agent management, approvals, task monitoring, cost + oversight, or work product review in the Paperclip control plane. --- # Paperclip Board Skill diff --git a/skills/paperclip-converting-plans-to-tasks/SKILL.md b/skills/paperclip-converting-plans-to-tasks/SKILL.md index 64d846df395..8e4c4b6d0fd 100644 --- a/skills/paperclip-converting-plans-to-tasks/SKILL.md +++ b/skills/paperclip-converting-plans-to-tasks/SKILL.md @@ -1,13 +1,9 @@ --- name: paperclip-converting-plans-to-tasks description: > - The Paperclip way of converting a plan into executable tasks. Use whenever - you are asked to plan, scope, or break down work inside a Paperclip company. - Industry-agnostic guidance on how to translate a plan into assigned issues - with the right specialty, dependencies, and parallelization so Paperclip's - executor can pick up the work — it does not prescribe a plan format. Pair - with the `paperclip` skill, which covers the mechanics of writing the plan - document and reassigning the issue. + Convert Paperclip plans into executable issue graphs. Use when asked to plan, + scope, or break down Paperclip company work into assigned tasks with specialty + fit, dependencies, blockers, and parallelization. --- # Paperclip — Converting Plans to Tasks diff --git a/skills/paperclip/SKILL.md b/skills/paperclip/SKILL.md index bf4d86634bb..bb7f7463413 100644 --- a/skills/paperclip/SKILL.md +++ b/skills/paperclip/SKILL.md @@ -1,12 +1,10 @@ --- name: paperclip description: > - Interact with the Paperclip control plane API to manage tasks, coordinate with - other agents, and follow company governance. Use when you need to check - assignments, update task status, delegate work, post comments, set up or manage - routines (recurring scheduled tasks), or call any Paperclip API endpoint. Do NOT - use for the actual domain work itself (writing code, research, etc.) — only for - Paperclip coordination. + Interact with the Paperclip control plane API for task coordination and + governance. Use when checking assignments, updating issue status, posting + comments, delegating work, managing routines, or calling Paperclip API + endpoints. --- # Paperclip Skill diff --git a/skills/para-memory-files/SKILL.md b/skills/para-memory-files/SKILL.md index 99da806988c..b90a1aa8cf5 100644 --- a/skills/para-memory-files/SKILL.md +++ b/skills/para-memory-files/SKILL.md @@ -1,13 +1,9 @@ --- name: para-memory-files description: > - File-based memory system using Tiago Forte's PARA method. Use this skill whenever - you need to store, retrieve, update, or organize knowledge across sessions. Covers - three memory layers: (1) Knowledge graph in PARA folders with atomic YAML facts, - (2) Daily notes as raw timeline, (3) Tacit knowledge about user patterns. Also - handles planning files, memory decay, weekly synthesis, and recall via qmd. - Trigger on any memory operation: saving facts, writing daily notes, creating - entities, running weekly synthesis, recalling past context, or managing plans. + Use a file-based PARA memory system to store, retrieve, and organize durable + knowledge across sessions. Trigger on saving facts, daily notes, entity + records, weekly synthesis, recall, tacit user patterns, or plan memory. --- # PARA Memory Files From a02fe8d5756afbf782102e9d7dc8254b95fc7c6b Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Fri, 10 Jul 2026 09:20:13 -0500 Subject: [PATCH 03/23] Update Codex adapter GPT-5.6 defaults (#9352) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Codex local is the adapter subsystem that exposes OpenAI Codex CLI model choices to agents and issue overrides. > - OpenAI has GPT-5.6 Codex-capable models that should appear in Paperclip's built-in Codex model list and refresh behavior. > - Paperclip's server model listing falls back to the adapter metadata and merges OpenAI refresh results with known Codex defaults. > - This pull request updates the Codex default model metadata to include GPT-5.6 options and adds regression coverage for fallback and refresh paths. > - The benefit is that operators can select the new Codex models without relying on manual model IDs, and refresh behavior keeps known GPT-5.6 options visible. ## Linked Issues or Issue Description Refs #9322. Refs #9342. Refs #9346. ### Agent or provider Codex CLI (OpenAI). ### Why this adapter is useful OpenAI's GPT-5.6 Codex-capable models should be available in Paperclip's Codex adapter defaults and model refresh path. ### How the agent is invoked `codex` ## What Changed - Changed the `codex_local` default model metadata from `gpt-5.5` to `gpt-5.6`. - Added `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna` to the built-in Codex adapter model list. - Updated adapter and server model-listing tests to cover GPT-5.6 fallback and refresh behavior. - Aligned Codex Fast mode support and helper text with the new `gpt-5.6` default, while preserving GPT-5.5, GPT-5.4, and manual model ID support. ## Verification - `git diff --check origin/master...HEAD` - `pnpm exec vitest run packages/adapters/codex-local/src/index.test.ts packages/adapters/codex-local/src/server/codex-args.test.ts server/src/__tests__/adapter-models.test.ts server/src/__tests__/adapter-model-refresh-routes.test.ts` - `pnpm check:token-gates` - `pnpm --filter @paperclipai/adapter-codex-local typecheck` - `pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/ui typecheck` ## Risks Medium risk because changing `DEFAULT_CODEX_LOCAL_MODEL` from `gpt-5.5` to `gpt-5.6` changes the adapter's default model selection for new blank configurations. The model-list additions are otherwise low risk and covered by adapter/server metadata tests. This PR intentionally overlaps related PRs #9342 and #9346, so reviewers may prefer to close or fold it into one of those branches. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex coding agent based on GPT-5, with shell, git, GitHub CLI, and repository editing tool use. Exact served model ID and context window were not exposed by the runtime. ## 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 --- packages/adapters/codex-local/src/index.test.ts | 17 +++++++++++++---- packages/adapters/codex-local/src/index.ts | 16 +++++++++------- .../codex-local/src/server/codex-args.test.ts | 2 +- server/src/__tests__/adapter-models.test.ts | 10 +++++++--- ui/src/components/agent-config-primitives.tsx | 2 +- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/packages/adapters/codex-local/src/index.test.ts b/packages/adapters/codex-local/src/index.test.ts index a40331e778b..213edf017e4 100644 --- a/packages/adapters/codex-local/src/index.test.ts +++ b/packages/adapters/codex-local/src/index.test.ts @@ -1,9 +1,18 @@ import { describe, expect, it } from "vitest"; -import { DEFAULT_CODEX_LOCAL_MODEL, models } from "./index.js"; +import { DEFAULT_CODEX_LOCAL_MODEL, isCodexLocalFastModeSupported, models } from "./index.js"; describe("codex local adapter metadata", () => { - it("does not advertise the ChatGPT-unsupported gpt-5.3-codex model as a default option", () => { - expect(DEFAULT_CODEX_LOCAL_MODEL).toBe("gpt-5.5"); - expect(models.map((model) => model.id)).not.toContain("gpt-5.3-codex"); + it("advertises current GPT-5.6 Codex-capable OpenAI models by default", () => { + const modelIds = models.map((model) => model.id); + + expect(DEFAULT_CODEX_LOCAL_MODEL).toBe("gpt-5.6"); + expect(modelIds.slice(0, 4)).toEqual([ + "gpt-5.6", + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", + ]); + expect(isCodexLocalFastModeSupported(DEFAULT_CODEX_LOCAL_MODEL)).toBe(true); + expect(modelIds).not.toContain("gpt-5.3-codex"); }); }); diff --git a/packages/adapters/codex-local/src/index.ts b/packages/adapters/codex-local/src/index.ts index 6af08521c29..c5658d2b057 100644 --- a/packages/adapters/codex-local/src/index.ts +++ b/packages/adapters/codex-local/src/index.ts @@ -5,9 +5,9 @@ export const label = "Codex"; export const SANDBOX_INSTALL_COMMAND = "npm install -g @openai/codex"; -export const DEFAULT_CODEX_LOCAL_MODEL = "gpt-5.5"; +export const DEFAULT_CODEX_LOCAL_MODEL = "gpt-5.6"; export const DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX = true; -export const CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS = ["gpt-5.5", "gpt-5.4"] as const; +export const CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS = ["gpt-5.6", "gpt-5.5", "gpt-5.4"] as const; function normalizeModelId(model: string | null | undefined): string { return typeof model === "string" ? model.trim() : ""; @@ -28,9 +28,8 @@ export function isCodexLocalFastModeSupported(model: string | null | undefined): if (isCodexLocalManualModel(model)) return true; const normalizedModel = typeof model === "string" ? model.trim() : ""; // Empty means we're omitting --model so the Codex CLI picks its own default. - // On subscription auth that's gpt-5.5 (fast-mode capable); manual model IDs - // are also treated as supported. Match that policy: pass the fast-mode - // overrides through and let the CLI reject them if the chosen model can't use them. + // Manual model IDs are also treated as supported: pass the fast-mode overrides + // through and let the CLI reject them if the chosen model can't use them. if (!normalizedModel) return true; return CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS.includes( normalizedModel as (typeof CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS)[number], @@ -39,6 +38,9 @@ export function isCodexLocalFastModeSupported(model: string | null | undefined): export const models = [ { id: DEFAULT_CODEX_LOCAL_MODEL, label: DEFAULT_CODEX_LOCAL_MODEL }, + { id: "gpt-5.6-sol", label: "gpt-5.6-sol" }, + { id: "gpt-5.6-terra", label: "gpt-5.6-terra" }, + { id: "gpt-5.6-luna", label: "gpt-5.6-luna" }, { id: "gpt-5.4", label: "gpt-5.4" }, { id: "gpt-5.4-mini", label: "gpt-5.4-mini" }, { id: "gpt-5.3-codex-spark", label: "gpt-5.3-codex-spark" }, @@ -77,7 +79,7 @@ Core fields: - modelReasoningEffort (string, optional): reasoning effort override (minimal|low|medium|high|xhigh) passed via -c model_reasoning_effort=... - promptTemplate (string, optional): run prompt template - search (boolean, optional): run codex with --search -- fastMode (boolean, optional): enable Codex Fast mode; supported on GPT-5.5, GPT-5.4 and passed through for manual model IDs +- fastMode (boolean, optional): enable Codex Fast mode; supported on GPT-5.6, GPT-5.5, GPT-5.4 and passed through for manual model IDs - dangerouslyBypassApprovalsAndSandbox (boolean, optional): run with bypass flag - command (string, optional): defaults to "codex" - extraArgs (string[], optional): additional CLI args @@ -102,7 +104,7 @@ Notes: - Paperclip injects desired local skills into the effective CODEX_HOME/skills/ directory at execution time so Codex can discover "$paperclip" and related skills without polluting the project working directory. For new and updated agents, Paperclip assigns an isolated managed home at ~/.paperclip/instances//companies//agents//codex-home/skills/; when CODEX_HOME is explicitly overridden in adapter config, that override is used instead. - New and updated codex_local agents persist an empty OPENAI_API_KEY override by default so a host-level OPENAI_API_KEY cannot leak into Codex runs through process inheritance. Explicit CODEX_HOME overrides must not point at the shared company codex-home, $CODEX_HOME, or ~/.codex. - Some model/tool combinations reject certain effort levels (for example minimal with web search enabled). -- Fast mode is supported on GPT-5.5, GPT-5.4 and manual model IDs. When enabled for those models, Paperclip applies \`service_tier="fast"\` and \`features.fast_mode=true\`. +- Fast mode is supported on GPT-5.6, GPT-5.5, GPT-5.4 and manual model IDs. When enabled for those models, Paperclip applies \`service_tier="fast"\` and \`features.fast_mode=true\`. - When Paperclip realizes a workspace/runtime for a run, it injects PAPERCLIP_WORKSPACE_* and PAPERCLIP_RUNTIME_* env vars for agent-side tooling. - Codex ACP is the preferred auto lane when Node >=22.13.0 and the Codex ACP server are available. It reuses shared ACP prompt/runtime guidance, selected skill materialization into CODEX_HOME/skills, model/reasoning/fast-mode session config, and existing quota-window reporting. Auto selection falls back to CLI when ACP prerequisites are unavailable; explicit engine="acp" fails loudly. `; diff --git a/packages/adapters/codex-local/src/server/codex-args.test.ts b/packages/adapters/codex-local/src/server/codex-args.test.ts index 53a86a3455d..e0843ca2e60 100644 --- a/packages/adapters/codex-local/src/server/codex-args.test.ts +++ b/packages/adapters/codex-local/src/server/codex-args.test.ts @@ -98,7 +98,7 @@ describe("buildCodexExecArgs", () => { expect(result.fastModeRequested).toBe(true); expect(result.fastModeApplied).toBe(false); expect(result.fastModeIgnoredReason).toContain( - "currently only supported on gpt-5.5, gpt-5.4 or manually configured model IDs", + "currently only supported on gpt-5.6, gpt-5.5, gpt-5.4 or manually configured model IDs", ); expect(result.args).toEqual([ "exec", diff --git a/server/src/__tests__/adapter-models.test.ts b/server/src/__tests__/adapter-models.test.ts index e82eec5c36e..2db24439dd9 100644 --- a/server/src/__tests__/adapter-models.test.ts +++ b/server/src/__tests__/adapter-models.test.ts @@ -48,7 +48,10 @@ describe("adapter model listing", () => { const models = await listAdapterModels("codex_local"); expect(models).toEqual(codexFallbackModels); - expect(models.some((model) => model.id === "gpt-5.5")).toBe(true); + expect(models.some((model) => model.id === "gpt-5.6")).toBe(true); + expect(models.some((model) => model.id === "gpt-5.6-sol")).toBe(true); + expect(models.some((model) => model.id === "gpt-5.6-terra")).toBe(true); + expect(models.some((model) => model.id === "gpt-5.6-luna")).toBe(true); expect(fetchSpy).not.toHaveBeenCalled(); }); @@ -155,7 +158,7 @@ describe("adapter model listing", () => { .mockResolvedValueOnce({ ok: true, json: async () => ({ - data: [{ id: "gpt-5.5" }], + data: [{ id: "gpt-5.6-terra" }], }), } as Response); @@ -164,7 +167,8 @@ describe("adapter model listing", () => { expect(fetchSpy).toHaveBeenCalledTimes(2); expect(initial.some((model) => model.id === "gpt-5")).toBe(true); - expect(refreshed.some((model) => model.id === "gpt-5.5")).toBe(true); + expect(refreshed.some((model) => model.id === "gpt-5.6-terra")).toBe(true); + expect(refreshed.some((model) => model.id === "gpt-5.6-luna")).toBe(true); }); it("falls back to static codex models when OpenAI model discovery fails", async () => { diff --git a/ui/src/components/agent-config-primitives.tsx b/ui/src/components/agent-config-primitives.tsx index 0ffabc35b91..eea519c93d0 100644 --- a/ui/src/components/agent-config-primitives.tsx +++ b/ui/src/components/agent-config-primitives.tsx @@ -34,7 +34,7 @@ export const help: Record = { dangerouslySkipPermissions: "Run unattended by auto-approving adapter permission prompts when supported.", dangerouslyBypassSandbox: "Run Codex without sandbox restrictions. Required for filesystem/network access.", search: "Enable Codex web search capability during runs.", - fastMode: "Enable Codex Fast mode. This burns credits/tokens much faster and is supported on GPT-5.4 and manual Codex model IDs.", + fastMode: "Enable Codex Fast mode. This burns credits/tokens much faster and is supported on GPT-5.6, GPT-5.5, GPT-5.4, and manual Codex model IDs.", workspaceStrategy: "How Paperclip should realize an execution workspace for this agent. Keep project_primary for normal cwd execution, or use git_worktree for issue-scoped isolated checkouts.", workspaceBaseRef: "Base git ref used when creating a worktree branch. Leave blank to use the resolved workspace ref or HEAD.", workspaceBranchTemplate: "Template for naming derived branches. Supports {{issue.identifier}}, {{issue.title}}, {{agent.name}}, {{project.id}}, {{workspace.repoRef}}, and {{slug}}.", From 991279f52ca7b169b776a3a299d4b829d1f68359 Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Fri, 10 Jul 2026 09:41:24 -0500 Subject: [PATCH 04/23] Fix Skill Studio markdown dirty tracking (#9356) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Skill Studio is the UI surface for editing skill package files, including `SKILL.md`. > - Markdown files are split into frontmatter fields plus a rich markdown body editor. > - The dirty-state guard intentionally ignores markdown editor normalization during initial mount. > - That guard was too narrow: rich markdown body edits could happen before the file was marked as user-interacted, so edits did not reliably enable Save. > - This pull request broadens the user-interaction signals around the markdown body editor and adds a regression test for saving body edits. > - The benefit is that editing `SKILL.md` in Skill Studio now behaves like normal file editing: changes show as unsaved and Save persists the full markdown document. ## Linked Issues or Issue Description No public GitHub issue exists. Inline bug description follows. ### What happened? Editing a Skill Studio markdown body did not reliably mark the file dirty, so the Save action could remain unavailable or fail to persist the body edit. ### Expected behavior User edits in the markdown body editor should mark the file unsaved and allow saving the updated `SKILL.md` content. ### Steps to reproduce 1. Open a Skill Studio markdown file such as `SKILL.md`. 2. Edit the markdown body in the rich editor. 3. Observe whether the unsaved state appears and Save becomes enabled. 4. Save and reload the file. ### Paperclip version or commit Reproduced on `master` before this fix. ### Deployment mode Local dev (`pnpm dev`). ## What Changed - Mark markdown body interaction on capture-phase key, pointer, paste, drop, before-input, and input events around the rich editor. - Preserve the existing guard that prevents MDXEditor mount-time normalization from dirtying a clean file. - Add a Skill Studio regression test that edits the markdown body, observes the Unsaved state, enables Save, and verifies the saved `SKILL.md` includes both frontmatter and the edited body. ## Verification - `pnpm vitest run ui/src/pages/SkillStudio.test.tsx` Manual reviewer path: - Open a Skill Studio markdown file such as `SKILL.md`. - Edit the body text in the rich markdown editor. - Confirm the UI shows an unsaved state and the Save button is enabled. - Save and confirm the updated markdown body persists. ## Risks Low risk. The change only broadens interaction detection before applying existing dirty-state logic, and the guard still prevents initial editor normalization from marking an unopened file dirty. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex CLI using GPT-5, with repository file editing, shell execution, and GitHub CLI tool use. ## 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 --- ui/src/pages/SkillStudio.test.tsx | 78 ++++++++++++++++++++++++++++++- ui/src/pages/SkillStudio.tsx | 12 +++-- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/ui/src/pages/SkillStudio.test.tsx b/ui/src/pages/SkillStudio.test.tsx index 6c132167501..3ed0cb3afd3 100644 --- a/ui/src/pages/SkillStudio.test.tsx +++ b/ui/src/pages/SkillStudio.test.tsx @@ -95,7 +95,29 @@ vi.mock("@/components/SearchableSelect", () => ({ })); vi.mock("@/components/MarkdownEditor", () => ({ - MarkdownEditor: ({ value }: { value: string }) =>