import { Diagnostic } from '@spintax/core';
/**
* Canonical LLM Spintax authoring prompt — spec `docs/spec-llm-authoring-prompt.md`.
*
* ONE prompt, shared by every surface (Telegram bot, n8n node, playground, API), so that a
* template drafted anywhere is drafted the same way. Product content, deliberately NOT part of
* `@spintax/core` — the engine must not grow authoring opinions (spec §2.2).
*
* The engine is a RUNTIME dependency for exactly one thing: plural arity. This package used to keep
* its own copy of the 3-form language table to stay dependency-free, and the copy drifted twice —
* once in content (a locale added to the engine and not here) and once in shape (`slice(0, 2)`
* instead of the engine's normalization, which disagrees on any 3-letter tag). A prompt that
* disagrees with the engine about arity teaches templates the engine then rejects, which is the one
* failure this package exists to prevent. Weightlessness lost to correctness, deliberately.
*/
/** Bump when the prompt text changes in a way that can change model output. */
declare const PROMPT_VERSION = "6";
type VariationLevel = 'conservative' | 'balanced' | 'aggressive';
/**
* Length and tone of ONE block of copy — nothing else.
*
* `landing` is "a headline plus one supporting sentence", not landing-page markup; every channel,
* `generic` included, describes short copy. The prompt never emits markdown or HTML (hard rule 4)
* and no option relaxes that. A host that needs structure — an article of `
` / `
` / `
`,
* a document of sections — calls the prompt once per block and composes the structure itself,
* which removes a whole class of template defects by construction (spec §3, #76). To get a longer
* block, say so in `brief` ("one paragraph of four to five sentences …"): the channel is a
* default, the brief is the instruction.
*/
type Channel = 'email' | 'sms' | 'push' | 'landing' | 'generic';
/**
* The grammatical case of a variable's VALUE.
*
* In an inflected language a variable is not a neutral hole: `%Visitors%` = "посетители" only fits
* a nominative slot. Hosts that serve such languages declare one variable per case — the pattern
* real Russian template sets converge on (`%Visitors%`, `%VisitorsGen%`, `%VisitorsDat%`,
* `%VisitorsLoc%`, `%VisitorsInstr%`). Declaring the case here is what lets the prompt tell the
* model WHICH member of the family a given sentence needs.
*/
type GrammaticalCase = 'nominative' | 'genitive' | 'dative' | 'accusative' | 'instrumental' | 'prepositional';
interface VariableSpec {
name: string;
/** Case of the value. Load-bearing in ru/uk/be; ignorable in English. */
case?: GrammaticalCase;
/** Free-form hint, e.g. "brand name — does not decline". */
note?: string;
}
/** A bare name (case unknown) or a full spec. */
type AllowedVariable = string | VariableSpec;
interface AuthoringPromptOptions {
/** Plain-language description of the copy to write. */
brief: string;
/** BCP-47-ish language tag. Selects the grammar block — it is NOT a translation hint. */
locale?: string;
/** The ONLY variables the model may use. Anything else is a hallucination. */
allowedVariables?: readonly AllowedVariable[];
channel?: Channel;
variationLevel?: VariationLevel;
}
interface BuiltPrompt {
systemPrompt: string;
userPrompt: string;
allowedVariables: readonly string[];
promptVersion: string;
}
interface PromptExamples {
def: string;
set: string;
permutation: string;
optional: string;
conditional: string;
plural: string;
}
/**
* The worked examples the prompt teaches from, for a given locale.
*
* Exported and interpolated into the prompt rather than retyped inside it, so the test suite can
* `validate()` the exact strings the model is shown — under the same locale. A prompt that teaches
* invalid syntax poisons everything downstream of it; that must be a test failure, not a surprise
* in production.
*
* Examples are written IN a language, so they follow the teaching profile, never the arity. The
* conjunction inside a permutation (`lastsep=" и "`) is baked into the example text rather than
* interpolated, so it cannot drift out of agreement with the sentence around it. {@link syntaxBlock}
* derives the same word for its abstract `a|b|c` illustration from the same profile.
*
* `bcs` deliberately teaches from the English set: there are no BCS examples yet, and Croatian
* copy invented to fill the slot would be worse than neutral English. The BCS-specific advice
* lives in {@link grammarBlock}, which does carry BCS words.
*
* The plural example is the one that cannot ride on the example language alone: every example is
* validated UNDER THE TARGET LOCALE, so a 2-form `item|items` fails arity for a 3-form locale
* taught in English. Its forms therefore follow the engine's arity while the carrier sentence
* follows the profile. `sat|sata|sati` is used because all three BCS buckets differ there and the
* shared corpus already pins it — no invented copy.
*/
declare function promptExamples(locale?: string): PromptExamples;
/** Build the canonical authoring prompt: brief → a spintax template. */
declare function buildAuthoringPrompt(opts: AuthoringPromptOptions): BuiltPrompt;
interface AuthoringRulesOptions {
/** Selects the grammar block. The rules are worth far more for an inflected locale. */
locale?: string;
/** Omit to leave the level unstated — a reader choosing for itself needs no instruction. */
variationLevel?: VariationLevel;
}
/**
* The authoring rules as a DOCUMENT TO READ, for a reader that is already a model.
*
* {@link buildAuthoringPrompt} drives a model on someone else's behalf: a host holds a brief, calls
* an LLM with these rules as its system prompt, and feeds the reply straight to the renderer. An
* agent reached over MCP is the other shape entirely — it already has the user, the brief and its
* own conversation, and what it lacks is the craft. It cannot install a system prompt for itself,
* so handing it `buildAuthoringPrompt({ brief: 'x' }).systemPrompt` and discarding the rest would
* be an abuse of the builder, not a use of it.
*
* The difference is not cosmetic, which is the reason this is an export and not a caller-side
* `.systemPrompt`: OUTPUT is deliberately EXCLUDED. It says "return the template and NOTHING else —
* your entire reply is fed straight into the renderer", which is true for a host's LLM call and
* false, even harmful, for an agent that has to talk to a person. Everything else is kept verbatim
* so the two surfaces cannot teach different craft: same ROLE (it defines what a template IS), same
* GOAL, syntax, grammar, variable and hard rules, same self-check.
*/
declare function authoringRules(opts?: AuthoringRulesOptions): string;
interface RepairPromptOptions {
/**
* MUST be the same locale the template was authored under and will be rendered with — the
* plural arity the model is told to produce depends on it, and a mismatch is the very bug the
* repair is supposed to fix.
*/
locale?: string;
/** Restated so a repair cannot smuggle in a variable the host does not have. */
allowedVariables?: readonly AllowedVariable[];
}
/**
* Build a repair prompt from `validate()` output.
*
* Without this the authoring loop dead-ends the first time a model returns something invalid —
* and it will. The precise spans added in core 0.1.3 are what let us point the model at the exact
* offending token instead of saying "something is wrong".
*
* It carries the SAME authoring constraints as the draft prompt (locale, allowed variables): a
* repair that fixes a bracket while inventing a `%variable%` or the wrong plural arity is not a
* repair.
*/
declare function buildRepairPrompt(template: string, diagnostics: readonly Diagnostic[], opts?: RepairPromptOptions): BuiltPrompt;
/**
* Strip what a model wraps its answer in despite being told not to.
*
* The output contract forbids fences and quotes; models emit them anyway. Contract in the prompt,
* tolerant parsing in the host — never trust the contract alone.
*/
declare function cleanModelTemplate(raw: string): string;
export { type AllowedVariable, type AuthoringPromptOptions, type AuthoringRulesOptions, type BuiltPrompt, type Channel, type GrammaticalCase, PROMPT_VERSION, type PromptExamples, type RepairPromptOptions, type VariableSpec, type VariationLevel, authoringRules, buildAuthoringPrompt, buildRepairPrompt, cleanModelTemplate, promptExamples };