/** The tier a plugin DECLARES (L17). `mixed` is legal only for plugins whose * reads compose across tiers while their own storage stays conversational — * the assert below holds every entry to that sentence. */ export type PluginTier = 'operational' | 'conversational' | 'mixed'; /** One real table a plugin owns. `tier` exists to be REFUSED when it says * 'operational' (L1) — the field is the assert's evidence, not an option. */ export interface PluginTable { /** logical name — the physical table is dj__ (ddl.ts) */ name: string; tier: 'operational' | 'conversational'; } /** A mechanical postcondition on a migration (L15): checked via * sqlite_master / PRAGMA table_info by the host, compiled in ddl.ts. */ export type VerifyCheck = { kind: 'table-exists'; table: string; } | { kind: 'column-exists'; table: string; column: string; } | { kind: 'index-exists'; index: string; }; /** Raw SQL + marker + verify — the whole migration algebra (L15: the typed * MigrationOp vocabulary is deleted). The host applies sql → verify → marker * in ONE transaction; a failed verify throws and the marker is withheld. */ export interface PluginMigration { /** marker string under dj_markers scope 'plugin:' */ marker: string; sql: string[]; verify: VerifyCheck[]; } /** A placeable surface: `view` is the dj/* name a views: reference resolves * once installed (engineViews), `kind` the widget the placement grammar * places directly ({ widget: comments }). */ export interface PluginWidget { view: string; kind: string; label: string; about: string; } /** An operational plugin's content contribution: a block in format.yaml's own * block grammar, compiled by the SAME loop format blocks ride (definition.ts) * — which is what lands its records in op_record with everything that store * gives every operational thing (L1). */ export interface PluginBlock { /** raw block config — heading/tier/identity/columns/…, verbatim grammar */ config: any; /** whether a format may extend: this block with columns (§2.3). No shipped * plugin sets it in this program; the fixture tests prove the mechanism. */ extendable?: boolean; } export interface PluginDef { /** 'dj/' — the slug carries no '/' */ name: string; about: string; tier: PluginTier; /** conversational-tier real DDL ONLY (L1) */ tables: PluginTable[]; /** operational plugin content → compiled blocks → op_record (L1) */ blocks?: Record; migrations: PluginMigration[]; widgets: PluginWidget[]; } /** The extension-column namespace (§2.3): format-authored extend: columns * compile under `x_`, so a plugin CORE column may never claim it. */ export declare const EXTENSION_PREFIX = "x_"; export declare function assertPluginDef(p: PluginDef): void; /** * THE REACTION VOCABULARY — closed, ordered, engine-shipped (§2.5). * * ORDERED because the order is the UI: the bar renders these left to right, * and a picker that reshuffled between page loads would make "the third one" * unlearnable. CLOSED because an open set is a second vocabulary a format * would end up curating — and 0022's rule is that words a format could have * meant differently belong to the format, while words that mean the same * thing everywhere belong to the engine. An emoji outside this list is * refused BY NAME at the door (`emoji_unknown`, which lists the set), never * stored and never rendered. * * Eight, deliberately: enough for approval, dissent, celebration, affection, * urgency, attention, humour and confusion — the eight things people * actually say without words — and few enough to render as one row on a * phone. */ export declare const REACTION_EMOJI: readonly string[]; /** dj/approvals' verdict vocabulary — closed, ordered, engine-shipped, the * REACTION_EMOJI precedent one tier up. Ordered because the panel renders * the buttons in this sequence; closed because the plugin's own * `approved_when` predicate has to know which word means yes, and a format * that could rename it would be a format that could silently redefine what * "approved" counts as. A format extends the block with `extend:` columns * (severity, a link, whatever it needs); it does not get to edit this list. */ export declare const APPROVAL_VERDICT: readonly string[]; /** the ONE verdict that satisfies — in the compiled (lowercased) spelling * every op-record cell answers to */ export declare const APPROVAL_GRANTED = "approved"; /** `approved_when`'s two readings (§2.5). `all` = every reviewer who was * asked has approved; `any` = at least one has. */ export declare const APPROVAL_MODES: readonly string[]; /** * THE ONE APPROVAL PREDICATE (P25's amendment to L19, its pure half). * * `approved_when` NARROWS `closed_when`: a record is closed when its state is * one of the closed values AND this returns true. Consumers — the engine's * own ApprovalsPanel, and the host's `work.ts` / `remirrorWork` / `wipeReport` * through their SQL-shaped wrapper — must all answer from this function, so a * reviewer who finds a fourth site computing "approved" has found a bug. * * `verdicts` is one entry per approval record for the subject, in any order, * in any spelling (normalised here — totality is the point: an unset Verdict * cell is an approval nobody has cast yet, and it counts as such). * * ZERO REQUESTS IS NOT SATISFIED, in either mode, and that is the ruling. * `approved_when` is a promise that a person signed off; a record nobody was * ever asked to review carries no sign-off, and treating "nobody asked" as * "everybody approved" would make the whole declaration opt-in per record — * a policy that does nothing until someone remembers it is not a policy. The * cost is honest and visible: a record marked done with no approval requested * reads as still-open in the work index, which is a WITNESS, never a gate. */ export declare function approvalsSatisfied(verdicts: readonly string[], mode: string): boolean; /** The closed set (0009/0022): each entry landed WITH its consumers, never * ahead of them (the E36-t7 gate) — dj/work's is the host's org work * endpoint (PR11), dj/activity's the host's activity door (PR14). */ export declare const PLUGINS: ReadonlyMap; /** Names that will NEVER ship, each with the sentence that says why — printed * verbatim (plugin-template finding, the catalogue) and pinned by test, so * the answer cannot drift into a did-you-mean that misdirects. */ export declare const PLUGIN_TOMBSTONES: ReadonlyMap; /** view name → its owning plugin + widget — describeMissingView's second case * (the install hint) reads this so it can never disagree with the registry. */ export declare function pluginWidgetByView(view: string): { plugin: PluginDef; widget: PluginWidget; } | undefined; /** widget kind → its owning plugin — evalWidget's availability check (L21: * the kind is always in the catalogue; whether THIS definition installed the * owner decides what renders). */ export declare function pluginWidgetByKind(kind: string): { plugin: PluginDef; widget: PluginWidget; } | undefined;