import { type ResolvedConfig } from "../types.js"; /** The slot every skill must declare, saying where learned rules belong. */ export declare const AMENDMENT_SLOT = "{{amendments}}"; export interface Skill { name: string; description: string; /** Bumped by any amendment; keys the judge ledger. */ version: number; /** Names the reply contract the caller parses, e.g. "judge-findings-v1". */ output: string; /** Composed instruction text, includes resolved, amendment appended. */ text: string; /** Absolute path of the shipped file, for error messages. */ path: string; /** Absolute path of the project amendment, when one is layered in. */ amendmentPath: string | null; } /** Where the shipped skills live: `skills/` beside `src/` or beside `dist/`. */ export declare function shippedSkillDir(name: string): string; /** * Where material every skill includes lives. * * Not a skill: nothing invokes it, it has no frontmatter, and it is * deliberately absent from SKILL_NAMES. It exists so a rule that governs every * reply lookout asks for is written once rather than pasted into fifteen * files, where it would drift the first time one of them was edited alone. */ export declare function sharedSkillDir(): string; /** * The directory holding a project's layer for a skill: the one named for it, or * the one named for whatever it used to be called, when only that exists. * * Read-only on purpose. Moving the directory would be a write, and the callers * here include the page, which is a viewer over what is on disk and must not * rewrite the project to render it. */ export declare function projectSkillDir(resolved: ResolvedConfig, name: string): string; /** Where a project's own amendments to a skill live. */ export declare function projectSkillPath(resolved: ResolvedConfig, name: string): string; /** Where an amendment nothing could grade waits for a person to read it. */ export declare function projectProposalPath(resolved: ResolvedConfig, name: string): string; /** * Write the project's layer for a skill, returning what was there before. * * Beside the paths rather than beside the amendment logic, because reading the * previous layer, adopting a renamed one and writing the new one are all the * same question of where this project's copy of a skill lives. */ export declare function writeLayer(resolved: ResolvedConfig, name: string, body: string, version: number, description: string): Promise; /** Put back whatever `writeLayer` found, when the gate rejects the candidate. */ export declare function restoreLayer(resolved: ResolvedConfig, name: string, before: string | null): Promise; /** * The shipped skill, with the project's amendment layered over it. * * Pass null for `resolved` to read the shipped file alone, which is what a test * or a `lookout skills` listing wants. */ export declare function loadSkill(resolved: ResolvedConfig | null, name: string): Promise; /** * Fill some of a skill's `{{placeholders}}`, leaving the rest for a later * layer. The judge fills its project rules here, before the caller fills the * manifest, so a project's rules land where the skill says they belong rather * than after the evidence. */ export declare function fillPlaceholders(text: string, vars: Record): string; /** * Fill a skill's remaining `{{placeholders}}` and demand that none are left. * * An unfilled placeholder throws rather than reaching the model: a prompt that * says `{{manifest}}` where the screenshots should be would be judged anyway, * and the findings would look real. */ export declare function renderSkill(text: string, vars: Record): string;