/**
 * skillsFromDir — load Skills that were AUTHORED AS FILES.
 *
 * The just-in-time half of skills already ships: `defineSkill` produces an
 * Injection whose `description` is all the model sees until it calls
 * `read_skill(<id>)`, at which point the body enters the context. What did not
 * ship was the other half — a way to keep those bodies where prose belongs, in
 * files, next to the code they describe, reviewable in a diff.
 *
 * This is that loader, and nothing more. It reads a directory of `SKILL.md`
 * files and hands each one to `defineSkill`. The progressive disclosure, the
 * activation tool, the slot routing — all unchanged, all upstream of here.
 *
 *   skills/
 *     billing/SKILL.md
 *     refunds/SKILL.md
 *
 *   ---
 *   name: billing
 *   description: Use for refunds, charges and billing questions.
 *   ---
 *   When handling billing: confirm identity first, then …
 *
 *   const skills = await skillsFromDir('./skills');
 *   const agent = Agent.create({ provider, model }).skills({ list: () => skills }).build();
 *
 * The frontmatter is the disclosure stub (`name` + `description` — what the
 * model reads when deciding), and everything after the closing fence is the
 * body (what it reads after deciding). That is the same file convention Claude
 * Code made familiar, so a skill folder is portable between the two.
 *
 * ── What a SKILL.md can carry (9.36.0: the whole runbook) ────────────────────
 * A runbook you already have on disk is three things — what to do (prose),
 * what to do it WITH (tools), and in what order (steps). This door used to
 * carry the first and drop the other two, so the one thing the library exists
 * to say ("extract the workflow you already have") arrived two-thirds empty.
 * All three now cross:
 *
 *   ---
 *   name: billing
 *   description: Use for refunds, charges and billing questions.
 *   tools: lookup_order, issue_refund
 *   steps:
 *     - lookup_order: look up the order before touching money
 *     - issue_refund: refund only what the lookup found
 *   onSkip: hold
 *   ---
 *   When handling billing: confirm identity first, then …
 *
 *   const skills = await skillsFromDir('./skills', {
 *     tools: [lookupOrder, issueRefund],   // the real Tools, from YOUR code
 *   });
 *
 * The remaining limits, and why each one is a decision rather than an
 * oversight:
 *
 *   - **the file names a tool; it never defines one.** A tool is code with an
 *     `execute`, and a markdown file has none. `tools:` is a list of NAMES,
 *     resolved against the `tools` registry the CALLER passes — so the file
 *     can only ever pick from capabilities you already handed in, and reading a
 *     directory can never introduce one. See "why this is not a code-execution
 *     vector" below.
 *   - **a name the registry does not carry is refused BY NAME at load** —
 *     never a skill that quietly loads without the tool it asked for, because
 *     that skill runs, sounds confident, and cannot do the job.
 *   - **no per-step `produces` / `consumes`** — the artifact vocabularies
 *     (9.25.0) are a build-time contract between skills, not runbook prose;
 *     declare them with `defineSkill` where the rest of the agent is declared.
 *   - **no `autoActivate`** — a directory does not decide the agent's tool
 *     posture. Say it once on the agent with `.toolsFromActiveSkill()`
 *     (9.36.0), which scopes every skill's tools to that skill's activation.
 *     Without it, a loaded skill's tools are on the wire from iteration 1, the
 *     same as any hand-written `defineSkill({ tools })`.
 *   - **no per-file `surfaceMode` or `cache`** — `surfaceMode`
 *     is settable for the WHOLE directory via `opts`, all of them or none; the
 *     others take `defineSkill`'s defaults.
 *   - unknown frontmatter keys are still IGNORED, not rejected, so a file
 *     carrying another tool's metadata still loads here. `name`,
 *     `description`, `tools`, `steps`, `onSkip` and `routes` are the KNOWN
 *     keys — a file that used one of those six for something else is the one
 *     case a release can change, and it changes it loudly.
 *
 * ── The routing, and the door that reads it (9.43.0) ─────────────────────────
 * A runbook says what to do, what to do it with, in what order — and where the
 * work goes NEXT. That last part is the graph, and until now it had to be
 * hand-wired in code even when the files said it plainly. `routes:` closes it:
 *
 *   ---
 *   name: billing
 *   tools: lookup_order, issue_refund
 *   routes:
 *     - escalation: on issue_refund status=denied
 *     - receipts: on issue_refund
 *   ---
 *
 *   const runbook = await runbookFromDir('./skills', { tools: [...] });
 *   const graph = skillGraph({ ...runbook, start: 'billing' });
 *
 * TWO DOORS, one truth: `skillsFromDir` returns skills and REFUSES a file that
 * declares `routes:` (a door that dropped the routing would hand back a graph
 * you believed was declared on disk); {@link runbookFromDir} returns
 * `{ skills, steps }`. Same law as `tools:` — the file PICKS (a route names a
 * skill id this directory declares; an unknown id is refused at load, by name,
 * listing what is available), it never DEFINES. A guard is one of the two DATA
 * conditions a route already has (`on <tool_name>`, `status=<outcome>`), and
 * nothing else: a `when` predicate is CODE, no file can carry code, and that
 * conditional stays in your source. See `skillsFromDirRoutes.ts` for the whole
 * grammar and every refusal.
 *
 * A worked example feeding this into a graph:
 * `examples/features/47-skills-from-dir-graph.ts`.
 *
 * ── Why authorship is decided here, at load time ─────────────────────────────
 * A Skill body is *instructions to a model*. Where it came from is therefore a
 * security property, not a convenience: content fetched at run time from
 * somewhere else is content someone else can change after you reviewed it.
 * This loader accepts a local directory and nothing else — a URL is refused BY
 * NAME rather than fetched — because "these files are mine" is a claim you can
 * only make about a path on your own disk at build time. Each file is read
 * ONCE, here; a later edit does not reach a run already in flight.
 *
 * ── Why carrying tools is not a code-execution vector ───────────────────────
 * Nothing in a SKILL.md is evaluated, imported, required or resolved as a
 * path. `tools:` is a list of strings, and the only thing a string can do here
 * is MATCH — against `tool.schema.name` in a registry the caller constructed in
 * their own source, from their own imports. A hostile file can therefore ask
 * for a tool you already gave the agent (and it would have to guess the name);
 * it can never name a module, widen the agent's capabilities, or cause one byte
 * of new code to run. The set of things this directory can do is a SUBSET of
 * what the calling file already decided to do, which is the same property the
 * local-path rule above buys for bodies.
 *
 * Node-only. `node:fs/promises` and `node:path` are imported lazily inside the
 * call, the same gating `tool-lint/cli.ts` uses: this module is reachable
 * from the `agentfootprint/context` barrel, and a TOP-LEVEL node:fs
 * import detonates a browser bundle at module-eval even when nothing calls it.
 */
import type { Injection } from './types.js';
import type { Tool } from '../tools/tools.js';
import { type SurfaceMode } from './factories/defineSkill.js';
import type { SkillGraphStep } from './skillGraph.js';
export interface SkillsFromDirOptions {
    /**
     * Where a loaded skill's body lands once activated. Defaults to
     * `defineSkill`'s own default, `'auto'`. See {@link SurfaceMode}.
     */
    readonly surfaceMode?: SurfaceMode;
    /**
     * The tools a file may NAME (9.36.0) — the resolution registry for every
     * `tools:` declaration in the directory, matched by `tool.schema.name`.
     *
     * This is the half a markdown file cannot supply. The file picks; you decide
     * what there is to pick FROM, in your own source, from your own imports. A
     * declared name that is not in here is refused at load, naming the file, the
     * name, and what this registry does carry.
     *
     * Pass every tool the directory might use; a tool nothing names is simply
     * unused (no skill gets it, and no error). Omit the option entirely on a
     * prose-only directory — a file that declares `tools:` with no registry
     * passed is refused rather than loaded without them.
     */
    readonly tools?: readonly Tool[];
}
/**
 * A whole runbook directory, read as the two things a graph is made of
 * (9.43.0): the skills, and the edges between them.
 *
 * Spreads straight into the graph — the field names are the graph's own, so
 * nothing has to be translated at the call site:
 *
 *   const runbook = await runbookFromDir('./skills', { tools });
 *   const graph = skillGraph({ ...runbook, start: 'triage' });
 */
export interface DirRunbook {
    /** Every `SKILL.md` under the directory, as Skill Injections — byte-identical
     *  to what `skillsFromDir` returns for the same directory. */
    readonly skills: readonly Injection[];
    /**
     * The declared edges, ready for `skillGraph({ steps })`. In skill-name order,
     * then file order, so a graph built from a directory is stable.
     *
     * NAME NOTE, because two different things are spelled `steps` in this
     * library: a file's own `steps:` key is that SKILL's tool sequence (which
     * rides on the skill, unchanged); these `steps` are the GRAPH's edges, read
     * from each file's `routes:` key. They never meet.
     */
    readonly steps: readonly SkillGraphStep[];
}
/**
 * Load every `SKILL.md` under `dir` as a Skill Injection.
 *
 * Two layouts are accepted, and they can be mixed:
 *   - `dir/<anything>/SKILL.md` — one folder per skill (the portable layout,
 *     and the one to prefer: the folder can hold the skill's other assets).
 *   - `dir/SKILL.md` — the directory IS one skill.
 *
 * The returned array is sorted by skill name, so a chart built from it is
 * stable regardless of the order the filesystem happened to hand back.
 *
 * @param dir - A local filesystem path. A URL (or any `scheme://` string, or a
 *   UNC network path) is refused by name — see the module header for why.
 * @param opts - Applied uniformly to every loaded skill.
 *
 * @throws when `dir` is not a local path, does not exist, is not a directory,
 *   or contains no `SKILL.md` at all; when a file's frontmatter is malformed
 *   (the message names the file); when two files claim the same skill name
 *   (the message names both); or when a file names a tool the `tools` registry
 *   does not carry, or sequences a tool the file itself did not declare.
 */
export declare function skillsFromDir(dir: string, opts?: SkillsFromDirOptions): Promise<readonly Injection[]>;
/**
 * Load a directory as a whole RUNBOOK (9.43.0) — the skills AND the edges
 * between them.
 *
 * `skillsFromDir` reads what one skill is; this reads what the skills are TO
 * EACH OTHER, from each file's `routes:` key, and hands back both halves ready
 * for `skillGraph({ ...runbook, start })`. Everything else is identical: same
 * layouts, same frontmatter, same tool registry, same refusals.
 *
 * The routing a file may carry is deliberately small, and the boundary is a
 * security property rather than a limitation — see `skillsFromDirRoutes.ts`:
 * a route NAMES a skill this directory declares (an unknown id is refused at
 * load, by name, listing what is available — never a half-graph), and a guard
 * is one of the two DATA conditions a route already has (`on <tool>`,
 * `status=<outcome>`). A `when` predicate is code, so no file can express one;
 * that conditional stays in your source, where `skillGraph({ steps })` takes it.
 *
 * @param dir - A local filesystem path. Same rule as `skillsFromDir`.
 * @param opts - Applied uniformly to every loaded skill.
 *
 * @throws everything `skillsFromDir` throws, plus: a route to an id no
 *   `SKILL.md` in the directory declares (the message lists what is
 *   available), a guard the grammar cannot express (the message quotes the
 *   whole grammar), a guard naming a tool the file itself does not declare,
 *   and a file routing to the same skill twice.
 */
export declare function runbookFromDir(dir: string, opts?: SkillsFromDirOptions): Promise<DirRunbook>;
