/** * The `/api/v1/skills*` surface (skills keystone, design v3 §API) — a FILE MANAGER over the * daemon-owned garden plugin root, with guards on every write/enable and CAS everywhere. * * GET /skills manifest + revision + the current snapshot + the INSTALLED * plugin's identity (wicked-studio#388: whether the root is * behind the plugin on disk) * GET /skills/:name/files the skill's OWN files (nested skills are their own) * GET /skills/:name/files/*path typed capped read (`?side=baseline` for the shipped copy) * PUT /skills/:name/files/*path write one file (guards; CAS) * GET /skills/support/*path root support files: scripts/, schemas/, .claude-plugin/, … * PUT /skills/support/*path * POST /skills add a user skill * POST /skills/:name/{enable,disable,reset,replace} * POST /skills/refresh-baseline three-way per FILE against the live plugin * POST /skills/publish validate → immutable snapshot → flip `current` * POST /skills/analyze dry-run of the publish validation * * Guard results ALWAYS return 2xx `{verdict, findings[], revision}` — studio's `apiFetch` throws * on non-2xx, so a `blocked` verdict is a normal 200 with nothing written; that includes a * containment refusal on a WRITE (the store answers `path-invalid`), a publish refused because one * is already in flight (`publish-in-flight`), and a publish aborted because the skills root changed * under it (`root-changed`) — none of those wrote anything, so each is a normal `blocked` envelope * (codex round 3). 409 (`{error, revision}`) is reserved for EXACTLY ONE thing: a stale * `expectedRevision` (a CAS conflict — the revision the client holds no longer matches). 404 an * unknown skill or file; 400 a body the schemas refuse or a READ path containment refuses (a read * has no verdict envelope); 503 an unseeded root, a `current` link that fails verification, or a * skills root that is not the directory the store bound (a symlink standing in for it, an ancestor * swapped under the daemon — `SkillsRootInvalidError`, codex round 4: every read and mutation is * refused, none redirected); 502 no plugin source to refresh from. A refresh whose destination is * refused (a symlinked `effective/` parent) is a 2xx `blocked` `path-invalid` envelope with nothing * changed, like every other write. Thin by design: validation is zod (strict, unknown keys named); * everything else is the store's. Nothing here (or anywhere in the store) writes outside the * skills root — the user's own CLI directories are never touched (design v3.2 §1). */ import type { FastifyInstance, FastifyRequest } from 'fastify'; import { z } from 'zod'; import type { Actor } from '../core/types.js'; import type { SkillsRuntime } from '../skills/runtime.js'; import type { AuditLog } from './audit.js'; /** A files map is a skill, not a document store. */ export declare const SKILL_FILES_MAX_ENTRIES = 256; export declare const SkillRevisionSchema: z.ZodObject<{ expectedRevision: z.ZodNumber; }, "strict", z.ZodTypeAny, { expectedRevision: number; }, { expectedRevision: number; }>; export declare const PutSkillFileSchema: z.ZodObject<{ content: z.ZodEffects; expectedRevision: z.ZodNumber; }, "strict", z.ZodTypeAny, { content: string; expectedRevision: number; }, { content: string; expectedRevision: number; }>; export declare const AddSkillSchema: z.ZodObject<{ name: z.ZodString; files: z.ZodEffects, Record, Record>, Record, Record>; expectedRevision: z.ZodNumber; }, "strict", z.ZodTypeAny, { name: string; files: Record; expectedRevision: number; }, { name: string; files: Record; expectedRevision: number; }>; export declare const ReplaceSkillSchema: z.ZodObject<{ files: z.ZodEffects, Record, Record>, Record, Record>; expectedRevision: z.ZodNumber; }, "strict", z.ZodTypeAny, { files: Record; expectedRevision: number; }, { files: Record; expectedRevision: number; }>; export interface SkillsRouteDeps { /** Absent = the daemon booted without a skills seam (tests, the manifest collector) → 503. */ runtime?: SkillsRuntime; audit: AuditLog; actorOf: (req: FastifyRequest) => Actor; } export declare function registerSkillsRoutes(app: FastifyInstance, deps: SkillsRouteDeps): void; //# sourceMappingURL=skills.d.ts.map