import type { DashboardResult } from '../core/dashboard.js'; import type { CompiledDefinition, FeedbackRecord, Inventory, IR } from '../core/types.js'; import { type PeopleDecl } from './personchip.js'; import type { FormResult, ReportResult } from '../core/surface.js'; export { payloadRowGaps, rowGroupsIn, viewPayload, widgetPayload } from './views/payload.js'; export { BLOCK_LAYOUTS, CARD_ROLES } from './catalog.js'; /** E37 — the columns each block's RECORD VIEWS read (title/subtitle/body/ * properties, and every section's where-column on the section's own blocks), * walked off the evaluated result. The record page composes at open time * from the rows answer (L22), so the rows answer must carry these columns' * rendered cells even where `display.columns` omits them — and ONLY then: * a record-less format returns an empty map and its payload rows keep every * byte (the E32 pins hold that promise). */ export declare function recordColumnsOf(result: { views?: { widgets: any[]; }[]; } | undefined): Map>; export interface PageInput { ir: IR; def: CompiledDefinition; result: DashboardResult; inventory: Inventory | null; meta: { files: number; errors: number; warns: number; date: string; }; /** endpoint accepting declarative form posts; absent → page renders read-only */ writeUrl?: string | null; /** endpoint that scores a text query against stored embeddings. Present only * when the operator named an embedder: the engine never owns a model, so a * host that cannot make a vector simply does not offer semantic search. */ semanticUrl?: string | null; /** endpoint answering NAMED graph queries (dj dashboard /q). Absent — as in * the self-contained artifact — and every search falls back to scanning the * payload, so the page works identically offline, just without FTS ranking. */ queryUrl?: string | null; /** feedback capture layer: endpoint (null = display-only) + ledger records. * statusUrl/deleteUrl are CAPABILITIES the host asserts — review buttons * and Delete render only where the matching endpoint is declared. * + optional upload endpoint for image fields */ feedback?: { url: string | null; records: FeedbackRecord[]; uploadUrl?: string | null; statusUrl?: string | null; deleteUrl?: string | null; }; /** resolved local media: vault-relative path → data URI, or 'toobig' when * the file exceeds vault.media.embed_max_kb */ media?: Record; /** where this host's writes land. The FORMAT says what is editable; the * HOST says what happens when someone edits it, so one definition serves a * laptop that writes files and a service that proposes changes. * direct — applied now, undoable (dj dashboard) * proposal — staged into a change set, landed together (a cloud PR) * capture — recorded as a suggestion in the ledger * Absent = the page cannot write. */ write?: { mode: 'direct' | 'proposal' | 'capture'; proposeUrl?: string; }; /** where the client's row driver reads from (E27 t2). Absent = static: rows * are the baked payload and the page never fetches — file:// keeps working. * `live` names the rows endpoint (GET ?document=…&block=…, payload-shaped * rows) and optionally an events channel (websocket or SSE) delivering * `{path, block}` invalidations. The HOST mints the URLs, like writeUrl — * the engine never invents where rows live. */ rowSource?: { mode: 'static' | 'live'; url?: string; events?: string; }; /** E28 t2 — where CURRENT indicator values come from. `static` means the * baked tiles are the answer, so an offline export asks nothing of the * network. `live` names an endpoint returning the tiles as this payload * carries them. No events channel of its own: the row driver's `{path, * block}` frame already arrives, and each tile names the blocks it read, * so a client refetches exactly the tiles a frame can have changed. */ indicatorSource?: { mode: 'static' | 'live'; url?: string; }; /** E34 — the HOST-supplied people directory (decision 0020), the rowSource * pattern for WHO instead of rows: `inline` bakes the entries, `url` names * a live endpoint (with `entries` as its offline snapshot), and the * declaration travels verbatim as the payload's `people` key. ABSENT means * no directory and the key stays absent — unlike rowSource there is no * spelled-out default, because every person surface fails closed to plain * text and a dashboard that never declared people must not grow a key * (the step-0 byte pins are the enforcement). The engine never invents * where people live; documents store handles, never platform ids. */ people?: PeopleDecl; /** E37 t4 — where the client refreshes the MENTION INDEX from (design §5 * PR9 item 3): the rowSource pattern for mentions. `url` names the host's * /mentions door (GET ?handle=…|?document=…, the {mentions: […]} envelope; * `handle=@me` resolves on the host — 0020, the viewer never rides the * payload). ABSENT means the key stays absent and the baked index is the * whole answer — file:// keeps working with no network. Emission is ALSO * gated on E37 adoption (mentionsAdopted, or a mentions view in the * composed views), so a host may declare this unconditionally without * moving a byte of any format that adopted nothing. */ mentionSource?: { mode: 'live'; url: string; }; /** E41 — where the client re-asks a chart's HISTORY binding: the rowSource * pattern for the event log. `url` names the host's history door, which the * client appends `historyQuery(ask)` to — one engine-owned spelling of the * question, so the door and the page cannot drift. ABSENT means the baked * answer is the whole answer and the page asks nothing of the network * (file:// keeps working). Emission is ALSO gated on adoption (a chart * actually declaring `history:` in the composed views), so a host may * declare this unconditionally without moving a byte of any format that * adopted nothing. */ historySource?: { mode: 'live'; url: string; }; /** E40 t1 — where this knowledge base's OWN pages live: the prefix a * standalone surface builds an in-KB link against (the form surface's * thank-you turns it into `home + recordHash(document, block, id)`). Absent * means the host published none, and every consumer FAILS CLOSED — the * thank-you degrades from a link to the id as text, never to a link that * would reload the intake page. Not a capability and not a write endpoint: * a URL the host knows and the engine cannot invent. */ homeUrl?: string | null; } /** Stylesheet, vault-independent. Cache immutably per engine version. */ export declare const PAGE_CSS: string; /** Client application, vault-independent. Cache immutably per engine version. */ export declare const PAGE_JS: string; /** Third-party runtimes, byte-identical across every vault and every tenant. */ export declare const runtimeSources: { mermaid: () => string; d3: () => string; }; export interface RuntimeNeeds { mermaid: boolean; d3: boolean; } /** Which runtimes this vault actually uses. Pass the payload from * buildAppPayload() to avoid rebuilding it. */ export declare function runtimesNeeded(input: PageInput, payload?: { concepts?: any[]; }): RuntimeNeeds; export interface PayloadOptions { /** Ship a concept INDEX instead of every document body, and let the client * fetch documents as they are opened. The reader looks at one at a time; * on a large vault the bodies are ~90% of the payload. */ split?: boolean; /** URL prefix the client appends an encoded concept path to. Required for * split mode to be able to load anything. */ conceptUrl?: string; /** URL prefix for vault media. Set it and local images are referenced from * the host instead of embedded as data URIs — the host decides where the * bytes actually live, the engine only writes the reference. */ mediaUrl?: string; } /** One document, fully rendered: the response to conceptUrl + path. */ export declare function buildConceptPayload(input: PageInput, path: string, opts?: PayloadOptions): Record | null; /** E37 t2 — the payload's mention index (design §2.6): every MentionIR the * parse collected, flattened across concepts, each entry carrying its * document (`node` — the OwnerSource spelling every attach point uses) and * its content-derived read-state identity (`key`, mentionItemKey — L11/L13: * the SAME key the cloud's mention_seen and mention_live speak, computed by * the one exported function so the baked page, the inbox and the DO can * never disagree about which mention is which). Exported for `dj mentions`, * which prints exactly what a hosted page would carry — one flattener, two * consumers. The MentionIR's own conditional keys (section vs block/row/ * uuid/column) ride through untouched; `?? []` tolerates an IR serialized * before this field existed (cloud fixtures replay stored IR). */ export declare function mentionIndexOf(ir: IR): Record[]; /** E38 t3/t4 (rulings P4/P29) — the payload's RELATIONS slice, conditional on * adoption exactly like people and mentions: a format with no `relations:` * line emits NO key and every payload byte holds. What rides: the VOCABULARY * (name · direction · derived inverse · endpoint sets), and per endpoint * block its tier, its TITLE column (the chip's resolving key, one ladder — * recordTitleKey), which relations it carries (relation → column key), * which it receives, and — P29's declared search space — the DOCUMENTS that * declare the block: the inverse and symmetric sections scan rowsFor(doc, * block) over exactly that list, never the whole corpus. NO URLs: the client * writes through D.writeUrl and reads through sourceDecl(), like every other * surface. */ export declare function relationsPayload(def: CompiledDefinition, ir: IR): Record | null; /** Everything the client renders from — chrome, navigation, dashboard home, * theme and content, as pure data. No HTML shell, no assets. */ export declare function buildAppPayload(input: PageInput, opts?: PayloadOptions): Record; /** * The REPORT surface's app payload (E32 t4) — the same surface-agnostic half * buildAppPayload ships (concepts, display vocabulary, tones, forms, the * write/rowSource declarations), with the report slices where the dashboard * slices would be and `surface: 'report'` naming the kind for the client * dispatch. Assembled HERE because the caller owns key order (R9) — the * slice module returns values, this literal decides where they sit. * * Capture parity comes through the EXISTING gates, not new ones: the caller * runs applyCeiling(input, SURFACE_KINDS.report, findings) first, so by the * time this function reads input, writeUrl is null (or ledger-capture), * write.mode is 'capture', and the row/indicator sources are static — the * lines below are byte-identical to buildAppPayload's, which is the point. * No split mode: a report bakes ONE self-contained artifact (its ceiling is * already capture — design §9.2), so there is nothing to defer. */ export declare function buildReportAppPayload(input: PageInput, report: ReportResult): Record; /** * The FORM surface's app payload (E40 t1) — `surface: 'form'` naming the kind * for the client dispatch, the form slice, and then the SAME surface-agnostic * half every other surface ships, at the exact key positions buildAppPayload * holds them (R9: the caller owns key order, and "the same half" is a claim a * reader can check by reading two literals side by side). * * What an intake page does NOT ship, and why each absence is deliberate: * · views / nav / dash / sections — it renders no views at all; * · refmap / artifacts / mentions — those are reading surfaces' indexes, and * nothing on this page reads them: a stranger filing an issue never opens * the ref map; * · split mode — there is nothing to defer; the concepts index is already * the slim half. * The concepts INDEX still rides, bodies removed (`sections: []`, the heavy * per-document fields dropped), because the surface-agnostic half genuinely * uses it: an options field's `from_concepts:` choices resolved at build time, * a person chip's lookup, a record picker's candidate rows. `conceptUrl` is * deliberately absent — the client's `partial` branch is inert without it, so * the page never tries to fetch a body it has no business showing. */ export declare function buildFormAppPayload(input: PageInput, form: FormResult): Record; /** URLs for separately served assets. Any omitted asset is inlined, so * renderPage() with no urls is the self-contained file:// artifact. */ export interface PageAssetUrls { css?: string; js?: string; mermaid?: string; d3?: string; } export declare function renderPage(input: PageInput, urls?: PageAssetUrls): string; /** The shell around an ALREADY-BUILT payload. A host that caches payloads by * input hash renders the page without recomputing them — the CLI's serve loop * uses the same path, which is why a write no longer costs a full rebuild on * the client. */ export declare function renderShell(input: PageInput, payload: Record, urls?: PageAssetUrls): string;