// Sarah-JSON authoring schema for Meeseeks skills. // Frozen at "SkillCore + extensions envelope" (plan v3 ยง 15.3 C1). // This is the canonical authoring shape; the export bundle (SKILL.md + // manifest.json + actions.toon) is derived from it. import { z } from "zod"; export const SKILL_NAME_PATTERN = /^[a-z][a-z0-9-]*$/; export const ACTIONS = ["click", "type", "read", "wait", "verify"] as const; export type Action = (typeof ACTIONS)[number]; export const SkillTarget = z.object({ description: z.string().min(1), bbox: z.tuple([z.number(), z.number(), z.number(), z.number()]).optional(), ax_role: z.string().optional(), ax_name: z.string().optional(), }); export const SkillStep = z.object({ id: z.string().min(1), instruction: z.string().min(1), action: z.enum(ACTIONS), target: SkillTarget, successCheck: z.string().min(1), fallback: z.string().optional(), }); export const SkillMeta = z.object({ domain: z.string().min(1), redacted: z.literal(true), placeholders: z.array(z.string()), }); export const SkillCore = z.object({ schemaVersion: z.literal("0.1"), name: z.string().regex(SKILL_NAME_PATTERN), intent: z.string().min(1), inputs: z.array(z.string()), preconditions: z.array(z.string()), steps: z.array(SkillStep).min(1), meta: SkillMeta, extensions: z.record(z.string(), z.unknown()).default({}), }); export type Skill = z.infer; export type Step = z.infer; export type Target = z.infer; export type Meta = z.infer;