/**
 * skillSteps — the procedure grammar (9.18.0). ONE owner of everything
 * "steps as data": the types, the validation, the step pointer's shape and
 * re-key rule, the `skip_step` integrity tool, and EVERY sentence the model
 * reads about a procedure (the banner, the result suffixes, the skip
 * sentences, the nudge). Stages and slots call in here; none of them owns
 * a word of the grammar.
 *
 * WHAT A PROCEDURE IS. `defineSkill({ steps })` declares an ordered list of
 * `{ tool, note }` pairs — "run these tools, in this order, for these
 * reasons". The framework then OWNS sequence and scope at the protocol
 * level: while a stepped skill holds the tenure, the tools slot offers only
 * the current step's tool (plus every escape hatch — see below), so the
 * model cannot call step 5's tool from step 3 because step 5's schema was
 * never sent. No refusal machinery, no new gate: an unoffered tool is
 * uncallable by construction.
 *
 * WHAT THE MODEL STILL OWNS: judgment inside the step. It can run the tool,
 * skip it with a recorded reason (`skip_step`), work around it with an
 * escape hatch, or stop and say why. The escape hatches are load-bearing
 * and stay offered under narrowing: `read_skill`, `list_skills`, every
 * OTHER active skill's tools, the baseline `.tool()` registry, provider
 * tools. A procedure is a declared order, not a cage.
 *
 * THE POINTER. `AgentState.stepPointer` records where the procedure stands:
 * `{ skillId, step, total, skipped }`, 1-based, `step === total + 1` means
 * complete. It is strictly SUBORDINATE to the one skill-graph cursor: it
 * lives and dies inside one skill's tenure, is re-keyed at the same stage
 * the cursor truth lives (Evaluate), and never crosses runs. It can never
 * move the cursor.
 *
 * CARRIER SHAPE (load-bearing): the pointer travels through scope and the
 * mount mappers as a 0-or-1-element ARRAY (`StepPointerCarrier`), never as
 * a bare object. footprintjs's `applyOutputMapping` shallow-merges bare
 * object values field-by-field — and APPENDS nested arrays — so a re-keyed
 * pointer mapped as an object would inherit the previous tenure's `skipped`
 * entries. A top-level array under `arrayMerge: Replace` is set wholesale.
 * `[]` = the feature is on and no procedure is active; the key is absent
 * entirely on agents with no stepped skill (zero-cost-when-unused).
 */
import type { SkillToolDescriptor } from './hostContract.js';
import type { Injection } from './types.js';
/** One step of a declared procedure. */
export interface SkillStep {
    /** The tool this step runs. MUST be one of this skill's own `tools` —
     *  refused at `defineSkill` otherwise. Repeats across steps are legal
     *  ("look it up again after the change"). */
    readonly tool: string;
    /** Why/what — the sentence the model sees ("look up the order before
     *  touching money"). Required, non-empty: a step with no note is a
     *  force-march instruction, and the note is the whole point. */
    readonly note: string;
    /**
     * Artifact KINDS this step leaves behind (9.25.0) — a declaration, not
     * machinery: nothing at run time reads it, and a step without it is
     * byte-identical to today. It makes the step's data leg checkable at build
     * (`artifact-kind-unsatisfied`) and drawable by a lens. See
     * `skillVocabulary.ts` for the satisfiability rule and its boundaries.
     */
    readonly produces?: readonly string[];
    /**
     * Artifact KINDS this step needs to have arrived (9.25.0). Satisfiable
     * three ways — by an EARLIER step of the same skill, by the skill's own
     * `consumes` (it arrived from outside), or by the step's tool declaring
     * `wants` for the kind (the framework redeems that ref at dispatch, from a
     * store that outlives the turn). Anything else is a build-time WARNING.
     */
    readonly consumes?: readonly string[];
}
/**
 * What the framework does when the model skips a step with `skip_step`:
 *
 * - `'advance'` (default) — record the skip and move to the next step;
 * - `'hold'` — record the skip and keep the step current (its tool stays
 *   the offer; the model may retry it, work around it with the escape
 *   hatches, or finish and explain).
 */
export type OnSkipPolicy = 'advance' | 'hold';
/**
 * WHERE a declared procedure stands. 1-based; `step === total + 1` means
 * the procedure completed. `skipped` holds the indexes the model skipped
 * under the `'advance'` policy (a `'hold'` skip is recorded on the event
 * stream, not here — the pointer did not move).
 */
export interface StepPointer {
    /** The tenant this pointer belongs to — the stepped skill whose tenure
     *  is current. A cursor move away from it resets the pointer. */
    readonly skillId: string;
    /** Current step, 1-based. `total + 1` = procedure complete. */
    readonly step: number;
    readonly total: number;
    /** Step indexes skipped-with-reason that the pointer moved past. */
    readonly skipped: readonly number[];
}
/**
 * How the pointer travels through scope and every mount mapper: a
 * 0-or-1-element array. See the module docstring for why a bare object
 * cannot cross a footprintjs outputMapper safely.
 */
export type StepPointerCarrier = readonly StepPointer[];
/** The build-time fold of one stepped skill — frozen at `Agent` build. */
export interface StepPlan {
    readonly skillId: string;
    readonly steps: readonly SkillStep[];
    /** Every tool name the plan's steps name — the hold-out candidates. */
    readonly toolNames: ReadonlySet<string>;
    readonly onSkip: OnSkipPolicy;
}
/** The lookup the engine, the tools slot and the tool-calls stage share.
 *  Undefined ⇒ no skill on this agent declares steps (the zero-cost gate). */
export type StepPlanFor = (skillId: string) => StepPlan | undefined;
/** The integrity tool's reserved name. Auto-attached (dispatchable) when
 *  ≥1 registered skill declares steps; OFFERED only while a stepped tenure
 *  is active and unfinished. */
export declare const SKIP_STEP_TOOL_NAME = "skip_step";
/**
 * Validate a `steps` declaration against the skill's own tools. All the
 * data is in hand at `defineSkill`, so every refusal happens there — the
 * `body-unknown-tool` sibling.
 */
export declare function validateSkillSteps(skillId: string, opts: {
    readonly steps?: readonly SkillStep[];
    readonly onSkip?: OnSkipPolicy;
    readonly toolNames: ReadonlySet<string>;
}): void;
/** Read a skill injection's declared steps off its metadata bag (the
 *  `autoActivate` precedent — the engine ignores unknown keys). */
export declare function stepsOf(injection: Injection): {
    readonly steps: readonly SkillStep[];
    readonly onSkip: OnSkipPolicy;
} | undefined;
/**
 * Fold every stepped skill into one frozen plan map. Runs once at
 * `Agent` build; the map is threaded as closures — nothing rides
 * `projectActiveInjection`, so the projection allow-list is untouched.
 * Empty map ⇒ the feature is off everywhere (callers thread nothing).
 */
export declare function foldStepPlans(injections: readonly Injection[]): ReadonlyMap<string, StepPlan>;
/** Unwrap the carrier. `undefined` for an absent key, an empty carrier,
 *  or a value that is not a carrier at all. */
export declare function pointerOf(carrier: unknown): StepPointer | undefined;
/** True while the procedure has steps left (`step <= total`). A completed
 *  pointer stays on scope as the record; nothing narrows or nudges on it. */
export declare function stepInProgress(ptr: StepPointer | undefined): ptr is StepPointer;
/** The current step's declaration, when the procedure is in progress. */
export declare function currentStepOf(ptr: StepPointer, plan: StepPlan): SkillStep | undefined;
/**
 * The tenure RE-KEY — Evaluate's half of the pointer discipline.
 *
 * `tenant` is who holds the tenure THIS iteration: the advanced cursor on
 * graph agents, else the tail of `activatedInjectionIds` (the shipped
 * `activeSkillId` notion). Tenant changed → a fresh pointer when the new
 * tenant declares steps, else cleared. Tenant unchanged → pass-through.
 * Always returns a carrier (possibly empty) — the caller writes it every
 * iteration the feature is on, so downstream readers never see a stale one.
 */
export declare function rekeyStepPointer(args: {
    readonly prior: StepPointerCarrier | undefined;
    readonly tenant: string | undefined;
    readonly stepPlanFor: StepPlanFor;
}): StepPointerCarrier;
/**
 * DESCRIBE the `skip_step` tool — name, schema, and the placeholder result.
 *
 * A description, not a tool: this module owns every sentence the model reads
 * about a procedure, and that includes this one, but building the framework's
 * tool object would mean importing the framework's tool factory into the
 * grammar. `skillTools.ts#buildSkipStepTool` does the wrapping (9.34.0).
 *
 * The tool is auto-attached to the dispatch registry when ≥1 registered skill
 * declares steps (the `read_skill` auto-attach seam) — always dispatchable,
 * but OFFERED (schema in the request) only while a stepped tenure is active
 * and unfinished. Its execute returns a placeholder; the tool-calls stage
 * overwrites the model-visible result with the authoritative sentence,
 * exactly as the skill-graph gate overwrites `read_skill` refusals —
 * bookkeeping lives where the batch order lives.
 */
export declare function skipStepDescriptor(): SkillToolDescriptor<{
    reason: string;
}, string>;
/** `[Step 3 of 6 — <note>] ` — prefixed onto the current step's tool
 *  description in the offer (a rebuilt schema copy, substituted by name). */
export declare function stepBannerPrefix(ptr: StepPointer, step: SkillStep): string;
/** The per-iteration `skip_step` offer description: names the current
 *  step, the remaining count, and the declared onSkip policy. */
export declare function skipStepDescription(ptr: StepPointer, plan: StepPlan): string;
/** Suffix for the `read_skill` result that activated a stepped skill:
 *  where the procedure starts. */
export declare function readSkillStepIntro(plan: StepPlan): string;
/** Suffix for a completed step's tool result: done + what is next. */
export declare function stepAdvanceSuffix(next: StepPointer, plan: StepPlan): string;
/** The authoritative `skip_step` result under the `'advance'` policy. */
export declare function skipAdvanceSentence(skippedIndex: number, reason: string, next: StepPointer, plan: StepPlan): string;
/** The authoritative `skip_step` result under the `'hold'` policy. */
export declare function skipHoldSentence(ptr: StepPointer, reason: string, plan: StepPlan): string;
/** Teaching result for `skip_step` with an empty reason — no event. */
export declare function skipNeedsReasonSentence(): string;
/** Teaching result for `skip_step` outside a stepped tenure — no event. */
export declare function skipNothingActiveSentence(): string;
/** The remaining (unrun) steps — the `steps_unfinished` payload's list and
 *  the nudge's material. Under `'advance'` a skipped step is behind the
 *  pointer and therefore never "remaining". */
export declare function remainingStepsOf(ptr: StepPointer, plan: StepPlan): ReadonlyArray<{
    readonly index: number;
    readonly tool: string;
    readonly note: string;
}>;
/**
 * The one teaching nudge for a premature stop (at most once per turn).
 *
 * Written as an AUTHORED FRAME (9.86.0). `stepNudge` appends the result to
 * `scope.history` wearing `role: 'user'`, so two things follow. First, it has
 * to be recognisable as this library's own writing: it opens with
 * {@link STEP_NUDGE_FRAME_PREFIX}, imported from the authorship registry that
 * `isSaidByPerson` matches against, because the body lists a skill id and
 * every unrun step's TOOL NAME — exactly the text a routing rule scanning
 * history watches for, and before the opening was here such a rule fired on
 * the library's own nudge.
 *
 * Second, it is re-read on every later call of the turn, so it may not speak
 * in the present or issue a standing instruction: "Steps 2–3 have not run …
 * Finish them" is false the moment they run, and it was still sitting in
 * `history` when they did. Every clause now reports the call the nudge was
 * written for, in the past tense, and the ask is stated as what THAT call was
 * for. Pinned by `test/injection-engine/userTurnProducers.test.ts`, which
 * runs the composed sentence through `unprovable`.
 */
export declare function nudgeTeachingMessage(ptr: StepPointer, plan: StepPlan): string;
