import type { SerenaReadinessRecord, SerenaReadinessStore } from "./state.js"; /** * Serena readiness nudge (feature 67 P5, decision D5 / AC9). * * A pi user who installs this package gets Serena's tools, but the project * config is `init-workspace`'s to write (AC6: one writer, no drift). So this is * the only thing the package may do about a project that was never provisioned: * **say so, once**, and point at the command that fixes it. * * The contract, in four lines: * - it reads `.serena/project.yml` and reports `missing`, `stale`, `outdated` * (the bundled init-workspace moved on) or `ready`; * - it announces **exactly one** message per recorded state, then latches — * the latch lives in the package's own global state file, so a restart does * not re-nag (the first-run hint's contract); * - it writes nothing to the project and nothing to any configuration; * - every failure is soft: a broken read is `missing`, a failed latch is a * nuisance, and neither ever throws into a command. */ /** The one command that owns Serena provisioning. */ export declare const INIT_WORKSPACE_COMMAND = "/init-workspace"; /** What a `.serena/project.yml` says about itself — only what this check reads. */ export interface SerenaConfig { present: boolean; /** The `language_servers` entries, in file order. Empty when absent or empty. */ languageServers: string[]; } export type SerenaReadiness = { kind: "missing"; } | { kind: "stale"; detail: string; } | { kind: "outdated"; recorded: string; revision: string; } | { kind: "ready"; }; /** * Read the two facts this check needs out of the project config. A tolerant * line scanner, not a YAML parser: the file is written by `init-workspace`, and * the only key read here is the `language_servers` list. Anything it cannot * understand reads as "no servers", which is the fail-closed direction — the * nudge fires rather than a broken config passing silently. */ export declare function inspectSerenaConfig(text: string | null | undefined): SerenaConfig; /** * Decide what this project needs. `recorded` is the latch's last announcement — * a changed shipped revision is itself a trigger, so an upgraded package can * tell the operator that the config predates it. */ export declare function evaluateSerenaReadiness({ config, recorded, revision, }: { config: SerenaConfig; recorded?: SerenaReadinessRecord; revision: string; }): SerenaReadiness; /** The one notification this module may produce, or null when there is nothing to say. */ export declare function serenaReadinessMessage(readiness: SerenaReadiness): string | null; export interface SerenaReadinessGate { /** The message to announce for this project, or null when nothing is due. */ check(projectKey: string): string | null; } /** * The gate the two entry points share (session start and the first command * dispatch). One latch per extension instance, so a single session announces at * most once; the persisted record keeps later sessions quiet. */ export declare function createSerenaReadinessGate({ store, revision, readProject, now, }: { store: SerenaReadinessStore; revision: string; /** Injectable so the suite reads fixtures instead of a real project. */ readProject?: (projectKey: string) => string | null; now?: () => string; }): SerenaReadinessGate; /** The bundled `init-workspace` revision, read from the shipped skill's frontmatter. */ export declare function readInitWorkspaceRevision(skillsDir: string): string;