/**
 * Teaching surface — the strings and branch logic that teach a connected model
 * how to USE this memory, kept in their own module so tests can import them
 * without booting the stdio server (src/index.ts starts a transport on import).
 *
 * Product frame, first set 2026-08-01 and revised 2026-09-29: the guidance is
 * never gated on the user explicitly asking, but it is also never a push. The
 * Claude connector directory rejects descriptions that "tell Claude how to
 * behave" or "direct Claude to pull behavioral instructions from external
 * sources", and its submission form asks the publisher to confirm that "tool
 * descriptions contain no instructions about model behavior, other tools, or
 * external instruction sources". So this surface says what each tool does and
 * when it applies, and proactivity lives in rules the user adds to their own
 * agent: the setup_memory prompt (src/prompts.ts) renders them for CLAUDE.md,
 * AGENTS.md, Cursor rules or a chat's preferences, and the host plugins carry
 * the same skill. Honesty constraints stay: no over-claiming, and the
 * never-store-secrets safety line is kept on write surfaces.
 */
import type { ReadScope } from "./scope.js";
/**
 * Server-level instructions, passed to the McpServer constructor and landed
 * verbatim in the connected model's system prompt by MCP clients.
 *
 * Constraints (tested in test/teaching-surface.test.ts):
 * - 500–800 chars; some clients (ChatGPT) weight the FIRST ~512 chars, so the
 *   core habit (read before answering, write on learning) is front-loaded.
 * - No brakes ("only when the user explicitly asks") and no pushes
 *   ("proactively", "always", "don't wait to be asked", "as a habit"):
 *   test/descriptions.test.ts bans both on every advertised surface.
 * - Names the setup_memory prompt, the only pointer to guidance, and it points
 *   inside this server, never to a URL (2026-09-29).
 * - Mentions every tool family: read/write/stats/feedback, rooms, vault.
 * - No delete tool on this surface (2026-08-20): deletion was withdrawn to an
 *   administrative REST-only operation, so the instructions point a model at
 *   writing a corrected memory instead of asking to delete one.
 *
 * 2026-09-29 rewrite (793 chars): the ownership and habit framing and "don't
 * wait to be asked" are gone (see the product frame above); the text says what
 * each tool family is for, and ends on the setup_memory prompt. To fit it under
 * the cap, the room-tool sentence ("Rooms: memory_create_room,
 * memory_invite_to_room, memory_join_room") and "deletion is administrative"
 * were dropped: the room rule itself
 * and "write a fresh one" are kept verbatim, and the fact that deletion is not
 * a tool stays stated in memory_read's description and in the README.
 */
export declare const SERVER_INSTRUCTIONS = "Long-term memory kept across sessions and AI tools on this account. memory_read searches earlier preferences, decisions and project context when an answer may depend on them. memory_write saves a durable fact, preference or decision. memory_list_recent is newest-first; memory_stats shows counts and domains; memory_feedback records which recalled memories helped an answer, which reorders later reads; memory_graph shows links. Shared rooms are SEPARATE stores: to read one, pass its address as domain; unscoped reads never cover rooms. To correct a memory, write a fresh one. vault_list names secrets by alias, never values. Never store passwords, API keys, payment data, MFA codes, government IDs, or health records. The setup_memory prompt explains memory rules for CLAUDE.md or AGENTS.md.";
/** The pre-existing zero-result message — kept as the fail-open fallback. */
export declare const NO_MATCH_MESSAGE = "No memories found for this query.";
/** Hint for an UNSCOPED no-match against a non-empty store: widen the query.
 *  (No drop-the-filter clause — none was set; advising to remove a filter that
 *  does not exist nudges the model into confabulating state.) */
export declare const NO_MATCH_HINT = " Try a broader query.";
/**
 * Hint for a DOMAIN-SCOPED no-match: widen the query, or try another domain —
 * and NEVER drop the scope.
 *
 * This doc used to read "here a filter genuinely exists, so suggesting to drop
 * it is honest and actionable", which described a draft that no longer exists:
 * the clause "…or drop the domain filter to search all domains" was deleted, and
 * a test now forbids it. The advice was actively harmful when the domain is a
 * room — an unscoped read does not cover rooms at all, so dropping the filter is
 * the one move guaranteed to lose the content the reader is hunting, and it is
 * the step that cost two agents a day on 2026-08-07.
 */
export declare const NO_MATCH_SCOPED_HINT = " Try a broader query, or a different domain.";
/**
 * The honest line for an account whose OWN domains are empty but whose rooms
 * are not — an invited teammate whose every memory lives in shared rooms.
 *
 * Without this, such a caller was greeted with EMPTY_STORE_WELCOME: "your
 * memory is empty, nothing has been saved yet, which is why this search
 * returned nothing" — three false clauses, immediately contradicted by the
 * scope note appended underneath, in the same payload (review, 2026-08-08).
 * That reader is precisely the person from the incident this release is about.
 *
 * ENDS WITH A COLON, so it is only ever emitted together with the disclosure
 * that follows it. That pairing used to be two independent decisions and they
 * disagreed: this line was chosen from a flag counting ALL rooms while the
 * disclosure was built from the LIVE ones, so an account whose only room was
 * archived received the colon and nothing after it. Both now come out of the
 * same {@link RoomScope} arm, and the arm that has nothing to disclose has no
 * `note` field to forget.
 */
export declare const EMPTY_PERSONAL_STORE_WITH_ROOMS = "Nothing in your own domains \u2014 they hold no memories yet. That is not the whole picture:";
/**
 * The same situation with the room probe UNANSWERED. Says the one true thing —
 * the personal store measured zero and the rest could not be checked — and
 * deliberately does NOT say "nothing has been saved yet", which was reachable
 * here and is a claim about a scope this client failed to reach.
 */
export declare const EMPTY_PERSONAL_STORE_ROOMS_UNCHECKED = "Nothing in your own domains \u2014 they hold no memories yet. Whether that is the whole picture could not be checked:";
/**
 * First-contact greeting: shown ONLY when a read comes back empty, the personal
 * store holds zero memories, AND the room probe answered that there are no rooms
 * — i.e. the very first read of this account's life, established rather than
 * assumed. Seeds the ANSWER, not the store: it says what this store is and
 * how a memory gets into it. It states and does not instruct (2026-09-29):
 * directory reviews treat instructions inside a tool result like instructions
 * in a description.
 */
export declare const EMPTY_STORE_WELCOME: string;
/**
 * Assemble the WHOLE answer for a zero-result read: the head sentence and the
 * disclosure that belongs with it, in one place.
 *
 * They are assembled together on purpose. While the head came from here and the
 * tail was concatenated by the caller, the two could be — and were — derived
 * from different facts: a head promising "that is not the whole picture:" with
 * an empty tail after it, and a first-contact greeting under a tail admitting
 * the room list could not be fetched. Every arm below returns a complete answer,
 * so a head cannot outlive the evidence for it.
 *
 * A NAMED scope never greets and never probes stats: that probe measures the
 * PERSONAL store, so on a scoped read it could claim "the store is empty" about
 * a domain whose memories the query merely missed. Its four arms are the four
 * things we can know about the name.
 *
 * An UNSCOPED scope makes ONE stats call, on this path only:
 * - stats unreachable / no number → the plain no-match message + the disclosure
 * - total_atoms > 0               → no-match + broaden hint + the disclosure
 * - total_atoms === 0             → one head per room state, each with its own
 *   disclosure; only `rooms.state === "none"` may claim the memory is empty,
 *   because only there has the claim been established.
 */
export declare function buildReadEmptyResponse(fetchStats: () => Promise<{
    total_atoms?: number;
}>, scope: ReadScope): Promise<string>;
