import { C as CoercibleField, U as Uuid, T as TableDuplicateProgress, R as RecordsResult, a as TableDuplicated, b as CaptureFileRef, c as CaptureOutcome, F as FieldTypeWord, N as NewFieldDeclaration, M as MergeFieldSource, d as MergeFieldSemanticType, e as MergeFieldModifier, O as OverridePolicy, D as Delivery, f as Timestamp, g as Freshness, h as RecordsDataSource, i as RecordDocument, j as RecordsClient, K as KernelTargets, k as ReadRow, E as EntityBackLinkItem, l as EntityBackLinks, m as RecordsError, n as NewEntityFieldDeclaration, o as EntityRecordRead, p as FieldPatch, W as WriteConflict, S as StoreFilter, q as RecordPageSort, r as TableArchiveProgress, s as EntityFieldRights, t as Field, u as EntityTableFacts, P as PermissionLevel, v as RecordRead, w as ReverseColumn, x as ReverseLinks, y as RowAction, A as AggregateRow, z as Table, B as RecordsConfig, G as EntityReferenceKind, H as EntityRefWithWords, I as EntityRef, J as FieldDrift } from '../provider-GiXq538p.cjs'; export { L as ABSENCE_REASONS, Q as ACTOR_VOCABULARY, V as ADDRESS_PARTS, X as AGENT_WRITER_WORDS, Y as ARCHIVE_LANES, Z as ARCHIVE_LANE_LABEL, _ as ARCHIVE_LANE_MEANS, $ as AUTOMATION_APP_TRIGGERS, a0 as AbsenceReason, a1 as ActionRefusal, a2 as ActionRunResult, a3 as Actor, a4 as AddressPart, a5 as AddressValue, a6 as AdminTable, a7 as AggregateBucket, a8 as AggregateCompare, a9 as AggregateCompareKind, aa as AggregateCompareWindows, ab as AggregateDelta, ac as AggregateFilter, ad as AggregateGroupValue, ae as AggregateMeasure, af as AggregateOperation, ag as AggregateWindow, ah as AnonTokenBinding, ai as ArchiveLane, aj as ArchivedChecklistTemplate, ak as ArchivedDoorRow, al as ArchivedForm, am as ArchivedRow, an as AutomationAction, ao as AutomationAppTrigger, ap as AutomationAppTriggerTerms, aq as AutomationComparison, ar as AutomationDeclared, as as AutomationFilter, at as AutomationFlipped, au as AutomationItem, av as AutomationLastRun, aw as AutomationList, ax as AutomationRevision, ay as AutomationRevisions, az as AutomationRun, aA as AutomationRunStatus, aB as AutomationRuns, aC as AutomationSpec, aD as AutomationStep, aE as AutomationTested, aF as AutomationToken, aG as AutomationTrigger, aH as AutomationValue, aI as AutomationValues, aJ as AutomationWeekday, aK as AutomationWhen, aL as BARCODE_SYMBOLOGIES, aM as BUILT_KIND_WORD, aN as BUTTON_DOES, aO as BookingAvailability, aP as BookingDeclared, aQ as BookingSummary, aR as BookingWindow, aS as ButtonDoes, aT as ButtonPressed, aU as ButtonSettings, aV as CHOICE_NUDGES, aW as COMPUTE_ON, aX as CONTEXT_POLICIES, aY as CaptureField, aZ as CaptureQuestion, a_ as CaptureSheetFace, a$ as CaptureSheetSummary, b0 as ChecklistDeclared, b1 as ChecklistRequirement, b2 as ChecklistRequirementKind, b3 as ChecklistRoleSpec, b4 as ChecklistRunStarted, b5 as ChecklistRunStep, b6 as ChecklistRunSummary, b7 as ChecklistSpec, b8 as ChecklistStepCompleted, b9 as ChecklistStepSpec, ba as ChecklistTemplateShape, bb as ChecklistTemplateSummary, bc as ChecklistTrigger, bd as ChecklistTriggerKind, be as ChoiceCellBack, bf as ChoiceLike, bg as ChoiceNudge, bh as ChoiceOption, bi as ChoiceOptions, bj as ChoiceRehome, bk as ChoiceUsage, bl as ChoicesRehomed, bm as CoerceOptions, bn as Coerced, bo as CoercedAnswers, bp as CommentThreadRead, bq as CommentWritten, br as ComputeOn, bs as ContextPolicy, bt as ConversationScope, bu as ConversationScopeContext, bv as CustomFieldTableType, bw as DECLARABLE_FIELD_KINDS, bx as DEFAULT_ARCHIVE_LANE, by as DEFAULT_PORTAL_ARCHIVE_FILTER, bz as DELIVERIES, bA as DRILL_CHART_TOKENS, bB as DRILL_DESCRIPTION_MAX, bC as DRILL_DOORS, bD as DRILL_SCHEMA, bE as DashboardBlock, bF as DashboardBlockKind, bG as DashboardBlockResult, bH as DashboardRunResult, bI as DashboardSummary, bJ as DashboardTarget, bK as DashboardTargetBase, bL as DashboardTargetOp, bM as DashboardTargetResult, bN as DashboardTotals, bO as DataHomeTable, bP as DeclarableFieldKind, bQ as DecorationColor, bR as DecorationPath, bS as DecorationRule, bT as DecorationRuleOp, bU as DecorationTarget, bV as DigestPreview, bW as DocRenderRow, bX as DocSignatureCheck, bY as DocSignatureRow, bZ as DocTemplateRow, b_ as DocToken, b$ as DocUnresolvedToken, c0 as DrillAdHocOp, c1 as DrillAnswer, c2 as DrillAnswerRow, c3 as DrillChartToken, c4 as DrillDeclaration, c5 as DrillDefinition, c6 as DrillDimension, c7 as DrillFinding, c8 as DrillGrain, c9 as DrillHaving, ca as DrillLane, cb as DrillLevel, cc as DrillMeasure, cd as DrillMeasureOp, ce as DrillMeasureWhereValue, cf as DrillPath, cg as DrillQuestion, ch as DrillRecords, ci as DrillRowsPage, cj as DrillSource, ck as DrillView, cl as ENTITY_TOKENS, cm as EnrichAlternate, cn as EnrichCell, co as EnrichDeclared, cp as EnrichDueRow, cq as EnrichRun, cr as EnrichSource, cs as Enrichment, ct as EnrichmentSummary, cu as EntityFieldValue, cv as EntityFieldsAcross, cw as EntityRecordMatch, cx as EntityRecordsFound, cy as EntityRowWritten, cz as EntityToken, cA as ExternalPrincipalCard, cB as FIELD_KINDS, cC as FIELD_SENSITIVITIES, cD as FIELD_SOURCES, cE as FORMULA_NODE_RESULTS, cF as FRESHNESS, cG as FieldBehavior, cH as FieldDriftAspect, cI as FieldDuplicated, cJ as FieldHistoryEntry, cK as FieldKind, cL as FieldOptionEdit, cM as FieldProposal, cN as FieldRetypePreview, cO as FieldRetyped, cP as FieldRule, cQ as FieldSensitivity, cR as FieldSource, cS as FilterWords, cT as ForbiddenEnvelopeWord, cU as FormArchiveAnswer, cV as FormLookOptions, cW as FormResults, cX as FormRoute, cY as FormSummary, cZ as FormulaHistoryEntry, c_ as FormulaParse, c$ as FormulaPreview, d0 as GridLayout, d1 as GridLayoutMode, d2 as GridRowHeight, d3 as HiddenFieldNotice, d4 as HistoryActor, d5 as HistoryActorKind, d6 as HistoryChange, d7 as HistoryRetention, d8 as Home, d9 as ImportBatchResult, da as ImportColumnPlan, db as ImportColumnsDeclared, dc as ImportFinished, dd as ImportOpened, de as ImportOutcome, df as ImportPlan, dg as ImportPolicy, dh as ImportProposal, di as ImportReport, dj as ImportRun, dk as InboundAddress, dl as InboundDeclared, dm as InboxCounts, dn as InboxStateChange, dp as InterfaceRead, dq as InterfaceRows, dr as InterfaceRowsField, ds as IoExportPage, dt as KERNEL_TABLES, du as KernelTableName, dv as KeysetRow, dw as MERGE_FIELD_MODIFIERS, dx as MERGE_FIELD_SEMANTIC_TYPES, dy as MERGE_FIELD_SOURCES, dz as MigrationEntry, dA as MigrationUndone, dB as MyLevel, dC as MySubscription, dD as NEWER_FIELD_KINDS, dE as NOT_A_MEMBER_WORDS, dF as NewerFieldKind, dG as ON_DELETE, dH as OVERRIDE_POLICIES, dI as OnDelete, dJ as OpLedger, dK as OutsideShareAnswer, dL as PARITY_FIELD_TYPES, dM as PER_VALUE_ACCESS_WORDS, dN as PIPELINE_RULE_KINDS, dO as PORTAL_ACCENTS, dP as PORTAL_ARCHIVE_FILTERS, dQ as ParentExtracted, dR as ParityFieldType, dS as ParityFieldTypeDescriptor, dT as PerValueAccessWord, dU as PersonStamp, dV as PgError, dW as PickListDocument, dX as PickListIndexDocument, dY as PickListIndexEntry, dZ as PickListItem, d_ as PickListItemInput, d$ as Pipeline, e0 as PipelineColumn, e1 as PipelineDeclared, e2 as PipelineGate, e3 as PipelineGatePreview, e4 as PipelineMissingField, e5 as PipelineMoveMany, e6 as PipelineMoveManyItem, e7 as PipelineMoveManyResult, e8 as PipelineMoveResult, e9 as PipelineMoveVerdict, ea as PipelineRule, eb as PipelineRuleKind, ec as PipelineSpec, ed as PipelineStage, ee as PipelineVerdict, ef as PortalAccent, eg as PortalArchiveAnswer, eh as PortalArchiveFilter, ei as PortalCard, ej as PortalConfig, ek as PortalConfigInput, el as PortalFooterLink, em as PortalFormAnswer, en as PortalFormInput, eo as PortalFormRef, ep as PortalFormSpec, eq as PortalInvitation, er as PortalPreviewRow, es as PortalPrincipal, et as PortalRevocation, eu as PortalStage, ev as PortalStyle, ew as PortalStyleInput, ex as PortalSummary, ey as PortalTableExposure, ez as PortalTableRef, eA as PredictedRefusal, eB as ProvenancePointer, eC as PublicPicture, eD as PublishBinding, eE as PublishBindingKind, eF as QuietHours, eG as RELATION_BINDINGS, eH as RELATION_CARDINALITIES, eI as RELATION_FLAVORS, eJ as RETIRED_ACTOR_WORDS, eK as REVERSE_LINKS_PAGE_MAX, eL as REVERSE_LINKS_RECORDS_PER_CALL, eM as ROW_LABEL_FORMULA_MAX_LENGTH, eN as ROW_WEB_NOT_READY, eO as RULE_NODE_KINDS, eP as RULE_USES, eQ as ReadValue, eR as RecordChange, eS as RecordChangeAction, eT as RecordChangeResult, eU as RecordComment, eV as RecordEvent, eW as RecordFilter, eX as RecordFollowSet, eY as RecordFollowers, eZ as RecordGraphWritten, e_ as RecordHeader, e$ as RecordHistoryEntry, f0 as RecordKeysetPage, f1 as RecordMoved, f2 as RecordPage, f3 as RecordRevision, f4 as RecordRowControls, f5 as RecordScopeComment, f6 as RecordScopeContext, f7 as RecordScopeField, f8 as RecordScopeHistoryEntry, f9 as RecordScopeRelation, fa as RecordScopeWithheld, fb as RecordSplit, fc as RecordsActor, fd as RecordsChangeSink, fe as RecordsErrorCode, ff as RecordsErrorSink, fg as RecordsFilter, fh as RecordsMerged, fi as RecordsProvider, fj as RecordsProviderProps, fk as RecordsRealtimePort, fl as RecordsResolverPort, fm as RecordsResponse, fn as RecordsTableQuery, fo as RegisteredTable, fp as Relation, fq as RelationBinding, fr as RelationCardinality, fs as RelationCarries, ft as RelationCoordinate, fu as RelationDisplay, fv as RelationFlavor, fw as RelationIcons, fx as RelationNameIndex, fy as RelationNameMatch, fz as RelationNamesAnswer, fA as RelationProperties, fB as RelationTarget, fC as RelationWordsManyArgs, fD as ResolvedPublishBinding, fE as ResolvedPublishBindingKind, fF as RestorePreview, fG as RestoreResult, fH as RetiredActorWord, fI as RetypeBehaviour, fJ as RetypePreview, fK as ReverseLink, fL as ReverseLinksFieldsArgs, fM as ReverseLinksManyArgs, fN as RowActionStep, fO as RowAgentPort, fP as RowAgentTarget, fQ as RowDefaultsApplied, fR as RowTemplateRow, fS as Rule, fT as RuleAnswer, fU as RuleExpression, fV as RuleNodeKind, fW as RuleUse, fX as SHOWN_TO_LABEL, fY as SHOWN_TO_VALUES, fZ as SHOWN_TO_WHO_MAY_CHANGE, f_ as STAGE_RULE_ENFORCEMENT, f$ as STAGE_RULE_ON_FAIL, g0 as STATUS_GROUPS, g1 as STATUS_GROUP_WORDS, g2 as STORAGE_MODES, g3 as STORE_DOORS, g4 as STORE_KNOBS, g5 as STORE_PERMISSION_LEVELS, g6 as STORE_REFUSAL_CODES, g7 as SYSTEM_WRITER_WORDS, g8 as SavedViewColorBy, g9 as SavedViewDefinition, ga as SavedViewLayout, gb as SavedViewRow, gc as SavedViewSpecIn, gd as ShownTo, ge as SourceArchived, gf as StagePending, gg as StagePendingOnBoard, gh as StageRuleEnforcement, gi as StageRuleOnFail, gj as StageRuleWarning, gk as StaleWriteDetail, gl as StatusGroup, gm as StorageMode, gn as StoreDoorName, go as StoreRefusalCode, gp as StoredRecord, gq as StuckRow, gr as Subscription, gs as SubscriptionBlock, gt as SubscriptionCadence, gu as SubscriptionSpec, gv as SyncAutoRefresh, gw as TABLE_DISPLAYS, gx as TABLE_KIND_PREFIX, gy as TABLE_ORIGINS, gz as TABLE_TYPES, gA as TableCapacity, gB as TableCopyInProgress, gC as TableCopySpec, gD as TableDecorations, gE as TableDisplay, gF as TableHome, gG as TableHomeDestination, gH as TableKindFacts, gI as TableLevel, gJ as TableLevelApproval, gK as TableLevelFacts, gL as TableLevelSet, gM as TableListEntry, gN as TableMoved, gO as TableOrigin, gP as TablePlacement, gQ as TablePlacementFact, gR as TableProposal, gS as TableReaderRule, gT as TableRenderSchema, gU as TableRestoreProgress, gV as TableRowCount, gW as TableRowDefaults, gX as TableRowDefaultsPatch, gY as TableRowLabel, gZ as TableSchemaMode, g_ as TableSyncAnswer, g$ as TableSyncResult, h0 as TableSyncSettings, h1 as TableSyncSource, h2 as TableSyncSourceDocument, h3 as TableSyncSpec, h4 as TableType, h5 as TableWebhook, h6 as TableWebhookDeclared, h7 as TypedChoiceDecision, h8 as VALUE_ALTERNATE_KEYS, h9 as VALUE_ENVELOPE_KEYS, ha as ValueAlternate, hb as ValueAlternateKey, hc as ValueEnvelope, hd as ValueEnvelopeKey, he as ValueSource, hf as ViewLayout, hg as ViewOrderSet, hh as WorkApprovalDecision, hi as WorkApprovalFiled, hj as WorkApprovalState, hk as WorkApprover, hl as WorkAssignment, hm as WorkAssignmentField, hn as WorkChange, ho as WorkDecideMany, hp as WorkDecideManyItem, hq as WorkDecideManyResult, hr as WorkDecideVerdict, hs as WorkDueState, ht as WorkGraph, hu as WorkInboxItem, hv as WorkInboxKind, hw as WorkInboxView, hx as WorkInstantiation, hy as WorkListFlavour, hz as WorkListItem, hA as WorkOrigin, hB as WorkRecordState, hC as WorkSlotHold, hD as WorkState, hE as WorkTemplateNode, hF as WorkTemplateRelation, hG as WorkTurn, hH as actionRefusals, hI as addressFromText, hJ as addressMapUrl, hK as addressValueText, hL as allowsOtherValues, hM as archivedByLine, hN as archivedWhen, hO as asChoiceNudge, hP as asPermissionLevel, hQ as atLeast, hR as automationWebhookUrl, hS as bookingPath, hT as buttonNeeds, hU as buttonOf, hV as buttonUrlPlaceholders, hW as callersTimeZone, hX as cellMatchesWords, hY as choiceSlug, hZ as choiceValuesOf, h_ as choicesOf, h$ as clearsRowLabel, i0 as coerceTypedAnswer, i1 as coerceTypedAnswers, i2 as coercionLabel, i3 as createOpLedger, i4 as decideTypedChoice, i5 as declareDrillDefinition, i6 as defaultOpLedger, i7 as drillAnswerOf, i8 as drillFindingKnob, i9 as durationText, ia as emptyArchiveLine, ib as emptyPortalArchiveLine, ic as entityReferenceKinds, id as entityReferenceKindsOf, ie as entityReferenceSearch, ig as entityReferenceWords, ih as entityRefsOf, ii as entityRefsToWrite, ij as err, ik as exportPageXlsx, il as fieldKindFor, im as fieldKindOf, io as filterWordsOf, ip as forgetAllOps, iq as hasQuietHours, ir as highestLevel, is as holdsARetiredChoice, it as isAddressValue, iu as isArchiveLane, iv as isAutomationAppTrigger, iw as isButtonField, ix as isEntityReferenceConfig, iy as isFoundation, iz as isLockedStub, iA as isOwnOp, iB as isPersonStamp, iC as isPortalAccent, iD as isPortalArchiveFilter, iE as isRecordsErr, iF as isReverseField, iG as isRuleFilter, iH as isShownTo, iI as isTableKind, iJ as isTheChosen, iK as keptGroups, iL as keptOutOfSight, iM as keptTableHref, iN as levelHasShownTo, iO as liftWithheld, iP as looksLikeAnId, iQ as mayDrag, iR as measureKey, iS as mintOpId, iT as moveConsequence, iU as moveInOrder, iV as newerKindExportWords, iW as newerKindOf, iX as newerKindWords, iY as offeredAsContext, iZ as ok, i_ as optionKey, i$ as optionLabel, j0 as parseFieldDrift, j1 as parseTableCopiesInProgress, j2 as parseTableDuplicateProgress, j3 as parseTableDuplicated, j4 as parseTableHome, j5 as parseTableMoved, j6 as personStampText, j7 as portalArchiveConsequence, j8 as portalConfirmLine, j9 as portalPath, ja as portalTitleTypedBack, jb as previewRetype, jc as previewRuleChange, jd as publicFormPath, je as ratingMaxOf, jf as readTypedDuration, jg as recordChangeTrigger, jh as recordSourceKey, ji as recordSourceTable, jj as recordsUseSentence, jk as rehomeSentence, jl as relationNameIndexOf, jm as relationNameKey, jn as relationNamesIn, jo as rememberedOpCount, jp as removedChoicesInUse, jq as richTextPlain, jr as ruleThatRefuses, js as rulesWithTopStar, jt as safeLinkHref, ju as sameDocument, jv as scopeChip, jw as sheetSyncSpec, jx as sourceArchivedOf, jy as splitListCell, jz as splitLockedRows, jA as stableFilterKey, jB as statusGroupOf, jC as tableIdOf, jD as tableJsonSchema, jE as tableKindMapping, jF as tableKindSlug, jG as tableRenderSchema, jH as unwrapRecords, jI as useOptionalRecordsClient, jJ as useRecordsActor, jK as useRecordsClient, jL as valueConverts, jM as withCallersClock, jN as withRowCounts, jO as withTablePlacement } from '../provider-GiXq538p.cjs'; import * as react from 'react'; import { ReactNode } from 'react'; /** Anything that names the record types it applies to: a Field, or one of its Rules. */ interface NamesRecordTypes { applies_to_types?: readonly string[] | null | undefined; } /** Asked of `client.fields` / `useFields`: every column of the table, whichever record types it applies to. */ declare const EVERY_RECORD_TYPE = "*"; /** * The record type of one record: the value of its table's type field (a choice's key), or undefined when the * table has no type field or the record has no type yet. A list value reads as its first choice. */ declare function recordTypeOf(table: { type_field?: string | null | undefined; } | null | undefined, document: Record | null | undefined): string | undefined; /** A column every record has (it names no record types). */ declare function fieldAppliesToEveryType(field: NamesRecordTypes): boolean; /** * Whether a column applies to a record of this type. A column that names no types applies to every record; one * that names types applies only to a record whose type is one of them, compared as words (the store also * matches a choice's id, so a column declared by option id may read as applying here only after the store says * so — a screen asks the store when it matters). */ declare function fieldAppliesToType(field: NamesRecordTypes, recordType: string | null | undefined): boolean; /** The record types a column names, as they were written. Empty for a column every record has. */ declare function typesOfField(field: NamesRecordTypes): string[]; type Json = Record; /** * THE NUMBER FORMAT A ROLLUP OR LOOKUP INHERITS from the column it reads (BUTTON-STAMPS; the store's * custom._picked_look twin): the column's own chosen number look whole, else money keeps its currency, a percent * stays a percent and a number keeps its unit as a suffix. `undefined` when the column has no number format worth * carrying. */ declare function pickedLookOf(field: Json): { id: string; options?: Json; } | undefined; /** * THE NUMBER FORMAT A FORMULA COLUMN SHOWS when the template declares none: a label that says percent is a * percent; otherwise a formula that does arithmetic with money columns (and never divides by one: a ratio is not * money) shows money in that currency — "Net to client" = offer − fee − costs − liens reads "$18,247", not * "18,247" (ADVERSARIAL-3 D8). `fields` are the table's columns as the store keeps them (their `display_format` * already inherited). `undefined` when nothing is worth carrying — a formula answering words stays words. */ declare function formulaLookOf(formula: string, field: Json, fields: readonly Json[]): { id: string; options?: Json; } | undefined; /** Does this stored field read as a rollup or a lookup (a column that reads another table's column)? */ declare function isDerivedField(f: Json): boolean; /** * THE NUMBER FORMAT A ROLLUP OR LOOKUP SHOWS when it declares none (ROLLUP-FORMAT): that of the column it reads * ("Material cost per unit (USD)" = sum of the BOM lines' "Line cost" reads "$56", a lookup of a money column reads * "$"). sum / min / max / avg keep the source's look; count and the other measures stay plain numbers. `farFieldsOf` * answers the candidate far tables' columns (their own looks already worked out) for the field's `via` link; the * first candidate that holds the picked column and has a look worth carrying wins. `undefined` otherwise. */ declare function derivedLookOf(field: Json, farFieldsOf: (via: string) => ReadonlyArray): { id: string; options?: Json; } | undefined; /** * THE DISPLAY FALLBACK: every formula column with no declared `display_format` gets the inferred one, so an older * install or a hand-made formula reads "$18,247" / "42%" like a new one. A declared format is never touched; a * formula with nothing worth carrying stays as it is. Returns the same array when nothing changed. */ declare function withFormulaLooks(fields: readonly F[]): F[]; /** * THE DISPLAY FALLBACK FOR ROLLUPS AND LOOKUPS: every rollup / lookup with no declared `display_format` gets the * look of the column it reads (`derivedLookOf`). A formula that reads such a column is worked out again after, so * chains (lookup -> formula -> rollup) settle. Never touches a declared format. */ declare function withDerivedLooks(fields: readonly F[], farFieldsOf: (via: string) => ReadonlyArray): F[]; type WithFormat = CoercibleField & { display_format?: unknown; key?: string; }; /** Whether a Field is a record number. */ declare function isAutonumberField(field: CoercibleField | null | undefined): boolean; /** A record number's prefix ("TASK-"), or "" when it has none or the Field is not a record number. */ declare function autonumberPrefixOf(field: WithFormat | null | undefined): string; /** A record number as a person reads it: its prefix and the number ("TASK-42"); null when there is none. */ declare function autonumberWords(field: WithFormat, value: unknown): string | null; /** * A prefix as it stands before its number (walk 2026-10-08 D4): "TASK" reads "TASK-2", as the * Prefix box's own placeholder promises; a prefix that already ends in a separator ("TASK-", * "INV #", "PO/") is kept as typed. The same rule as the grid's `autonumber` format * (@ai-matrx/design-system field-formats), so a card, a copy and a cell never disagree. */ declare function autonumberJoin(prefix: string): string; /** * A SEARCH FOR A RECORD NUMBER BY ITS WORDS. "TASK-42", "task-42" or "TASK 42" names record 42 of the record * number whose prefix is "TASK-": the store keeps 42, so the words are turned into that column's number. * Null when the words name no record number of these Fields. */ declare function autonumberSearchOf(fields: readonly F[], words: string): { field: F; number: number; } | null; /** * A read's filter with "this record number is N" added (AND). The flat shape takes the column's key; a rule * expression is wrapped in an `and` with `{op: eq, args: [{field: id}, {const: N}]}`. */ declare function filterWithAutonumber(filter: Record | null | undefined, field: { id: string; key: string; }, n: number): Record; type WallParts = { year: number; month: number; day: number; hour: number; minute: number; second: number; }; /** The wall clock `at` shows in the person's zone (the device's when none is saved). */ declare function wallPartsInZone(at: Date): WallParts; /** The instant at which the person's wall clock reads these fields (the device's clock when no zone is saved). */ declare function instantFromWallInZone(year: number, month: number, day: number, hour?: number, minute?: number, second?: number): Date; type TypedDate = { ok: true; day: string; /** ISO instant, only when a time of day was read or asked for. */ instant: string | null; } | { ok: false; why: string; }; /** The order a locale writes a numeric date in: "mdy", "dmy" or "ymd". */ declare function localeDateOrder(locale?: string): "mdy" | "dmy" | "ymd"; /** Sheets' and Excel's two-digit-year window: 00–29 → 2000–2029, 30–99 → 1930–1999. */ declare function twoDigitYear(yy: number): number; type TypedTime = { ok: true; /** 24-hour `HH:MM`, or `HH:MM:SS` when seconds were typed. */ value: string; } | { ok: false; why: string; }; /** Read one typed time of day. Never throws; never guesses. */ declare function readTypedTime(raw: string): TypedTime; /** * Read one typed date. `withTime` is true for a date-and-time column. Never throws; never guesses. */ declare function readTypedDate(raw: string, opts?: { withTime?: boolean; locale?: string; }): TypedDate; /** * THE TEXT AN EDITOR OPENS WITH for a stored day or instant — the inverse of `readTypedDate`, so * a cell opened by Enter or a double-click shows words this reader reads back to the SAME value * (grids review 3, 2026-09-30: those paths used to open the browser's own date picker, which lost * the time and saved "now"). The day is numeric in the locale's own order with a four-digit year; * a time of day follows as `2:30 PM` (a 12-hour locale) or `14:30` (a 24-hour one). An unreadable * stored value opens as the stored characters, untouched. */ declare function typedDateText(value: unknown, opts?: { withTime?: boolean; locale?: string; }): string; /** A time of day in the words `readTypedTime` reads back: `2:30 PM` or `14:30`, by the locale's clock. */ declare function typedTimeText(hours: number, minutes: number, locale?: string): string; /** How well one text matches what was typed: 4 exact, 3 starts with, 2 a word starts with, 1 contains, 0 not at all. */ type TypedMatchScore = 0 | 1 | 2 | 3 | 4; /** * How well `text` matches what was typed. An empty search matches everything at the lowest rank * that still shows (1), so an empty box lists every item in its own order. */ declare function typedMatchScore(text: string, typed: string): TypedMatchScore; /** * The items that match what was typed, best first; ties keep the given order. `textsOf` answers the * words an item is found by — its NAME first, then anything that tells two apart (a second line). * The name ranks at its full strength; a second line only ever finds an item (it ranks as * "contains"), so `Sun` puts Sunny Okafor before the Patricia Marsh who lives on Sunset Blvd. */ declare function rankTypedMatches(items: readonly T[], typed: string, textsOf: (item: T) => string | readonly string[]): T[]; type TypedNumber = { ok: true; value: number; } | { ok: false; why: string; }; declare function readTypedNumber(raw: string): TypedNumber; declare const RELATIVE_DAY_KINDS: readonly ["today", "tomorrow", "yesterday", "this_week", "next_week", "last_week", "this_month", "next_month", "last_month", "before_today", "next_days", "past_days"]; type RelativeDayKind = (typeof RELATIVE_DAY_KINDS)[number]; /** The zone the host reads this person's day in (their saved zone, or the browser's while it follows). `null` clears. */ declare function setReadersTimeZone(zone: string | null | undefined): void; /** The zone a relative day is worked out in: the host's mirrored zone, else this browser's, else UTC. */ declare function readersTimeZone(): string; interface RelativeWindowOptions { zone?: string; now?: Date; /** First day of the week, Sunday 0 ... Saturday 6. Monday (1) by default, the organization knob's default. */ weekStart?: number; /** A moment column (created_at, a datetime): the window is the reader's local midnights as instants. */ instants?: boolean; } /** * One relative window as exact bounds, half-open [from, to), or `null` when `window` is not a relative * window this knows (it is then left for the store to judge). A date-only column gets calendar days. */ declare function relativeWindowBounds(window: unknown, opts?: RelativeWindowOptions): { from?: string; to?: string; } | null; /** What the filter needs to know about a column to cut its window: the key and whether it holds moments. */ interface RelativeFieldLookup { byKey(key: string): { instants: boolean; } | null; byId(id: string): { instants: boolean; } | null; } /** A lookup over the table's Fields (a moment column is `created_at` / `updated_at` or `config.kind === "datetime"`). */ declare function lookupFromFields(fields: ReadonlyArray<{ id: string; key: string; config?: Record | null; }>): RelativeFieldLookup; /** Does this filter hold a relative window anywhere? (Cheap test so a filter without one never loads Fields.) */ declare function holdsRelativeDays(filter: unknown): boolean; /** * The filter with every relative window worked out for THIS reader, now. Flat filters (`{ due_on: { relative } }`) and * Rule `within` nodes, at any depth. A window it cannot place (an unknown column, an unknown kind) is left as it was. * Never mutates its input. */ declare function resolveRelativeDays(filter: unknown, lookup: RelativeFieldLookup, opts?: Omit): unknown; /** `"sunday"` .. `"saturday"` as `Date.getUTCDay()` counts; anything else is Monday, the knob's default. */ declare function weekStartIndexOf(word: string | null | undefined): number; interface BaseTable { id: Uuid; name: string; } interface BasePort { /** `RecordsClient.tableDuplicate`: one table, with its own passes looped until done. */ tableDuplicate(args: { tableId: Uuid; withRecords?: boolean; name?: string | null; organizationId?: Uuid | null; onProgress?: (progress: TableDuplicateProgress) => void; }): Promise>; /** `custom.base_copy_finish`: {old table id: its copy's id} → how many link columns and cells now point inside the copy. */ finish(args: { organizationId: Uuid; pairs: Record; }): Promise>; /** * `custom.copy_table_extras`: {source table id: its copy's id} → the automations (switched OFF) and pages every copy now carries, * with the copy's own column and view ids. THE ONE home of that step — the base-move job in aidream calls the same function. */ copyTableExtras(args: { organizationId: Uuid; pairs: Record; }): Promise>; /** `RecordsClient.tableArchive` / its restore: put a copy away, or bring it back to be copied from. */ archive?(tableId: Uuid): Promise>; unarchive?(tableId: Uuid): Promise>; /** The door that makes a table's Home today (`declareTable`): a new record "" in the person kernel. A NEW base is a new Home. */ createHome?(name: string): Promise>; /** The one door that moves a table between Homes: `custom.record_reparent` (`RecordsClient.recordReparent`). Pages and automations ride on their table. */ moveInto?(tableId: Uuid, homeId: Uuid): Promise>; } interface BaseCopyProgress { /** 1-based position of the table being copied, and how many there are. */ at: number; of: number; tableName: string; pass: TableDuplicateProgress | null; } interface BaseCopied { /** The NEW Home every copied table now lives in (a copy is its own base); null when the port cannot make Homes. */ homeId: Uuid | null; /** Source table id → its copy. */ pairs: Record; tables: Array<{ from: BaseTable; copy: BaseTable; records: number; }>; relinkedColumns: number; relinkedCells: number; /** Automations copied (every one OFF) and pages copied, with every table id inside them pointing at the copies. */ automations: number; pages: number; /** One sentence per automation or page that could not be copied. */ extrasRefused: string[]; /** What a copy never carries, from the per-table door's own words, once per table. */ notCopied: string[]; } type BaseCopyResult = { ok: true; data: BaseCopied; } /** * The table it stopped at; the copies made before it are named so they can be opened or archived. * `strayCopyId`: the store made a copy of `stoppedAt` before the refusal (a pass failed, or its * answer could not be read), so a table exists that `made` does not name — null when none did. */ | { ok: false; error: unknown; stoppedAt: BaseTable; made: BaseCopied["tables"]; strayCopyId: Uuid | null; }; /** The copy a `tableDuplicate` refusal says the store had already made (`detail.copyId`), or null. */ declare function copyIdOfRefusal(error: unknown): Uuid | null; /** "Harbor Studio (copy)", the same word the table dialog offers. */ declare function baseCopyName(name: string): string; /** "Harbor Studio (restored 10/15/2026)". */ declare function restoredBaseName(name: string, on: string): string; /** Duplicate every table of a base. `names` (by source table id) overrides the "" a copy is given. */ declare function duplicateBase(port: BasePort, args: { organizationId: Uuid; tables: readonly BaseTable[]; withRecords: boolean; /** The copy's name for each table; default the source's own name (the copies live together in the new base). */ nameFor?: (table: BaseTable) => string; onProgress?: (p: BaseCopyProgress) => void; /** Put the copies in a NEW Home with this name (a base is a Home); absent keeps each copy where the per-table door put it. */ homeName?: string; }): Promise; interface BaseSnapshotRecord { label: string; origin: "manual" | "schedule"; /** Source table → the put-away copy that holds its columns, views and records as they were. */ tables: Array<{ table_id: Uuid; snapshot_table_id: Uuid; name: string; records: number; }>; } /** Take a snapshot: copy every table WITH records, then put each copy away so no list shows it. */ declare function snapshotBase(port: BasePort, args: { organizationId: Uuid; tables: readonly BaseTable[]; label: string; origin?: "manual" | "schedule"; onProgress?: (p: BaseCopyProgress) => void; }): Promise<{ ok: true; snapshot: BaseSnapshotRecord; } /** `leftInLists`: copies that could NOT be put away (each still in the lists) — empty when the failure left nothing behind. */ | { ok: false; error: unknown; stoppedAt: BaseTable; leftInLists: Uuid[]; }>; /** Restore a snapshot as a NEW base: each put-away copy is brought back, copied under its own name, and put away again. */ declare function restoreSnapshot(port: BasePort, args: { organizationId: Uuid; snapshot: BaseSnapshotRecord; baseName?: string; restoredOn?: string; onProgress?: (p: BaseCopyProgress) => void; }): Promise; /** One file waiting to go up, with its bytes until they have. */ interface QueuedCaptureFile { field: string; name: string; mime_type: string; size_bytes: number; duration_ms?: number | null | undefined; /** The bytes. Dropped once `uploaded` is set, so the queue does not hold them twice. */ blob?: Blob | null | undefined; /** Set once the platform's byte store has them. */ uploaded?: { file_id?: string | null | undefined; url?: string | null | undefined; } | null | undefined; } /** `waiting` → `sending` → `landed`, or `refused` when the door has decided. */ type QueuedCaptureState = "waiting" | "sending" | "landed" | "refused"; interface QueuedCapture { /** Minted on the phone when the capture was taken. The row's key AND the door's. */ client_key: string; organization_id: string; sheet_id: string; sheet_title?: string | undefined; answers: Record; files: QueuedCaptureFile[]; device: string | null; /** The moment the PHONE took it — never the moment the signal came back. */ captured_at: string; location: Record | null; state: QueuedCaptureState; attempts: number; /** The door's own words, or the network's. Always something a person can act on. */ last_error: string | null; record_id: string | null; replayed: boolean; queued_at: string; landed_at: string | null; } interface CaptureQueueCounts { waiting: number; sending: number; refused: number; landed: number; } /** What one pass of `sync` did, item by item. Never a single boolean. */ interface CaptureSyncReport { attempted: number; landed: number; replayed: number; refused: number; deferred: number; outcomes: Array<{ client_key: string; state: QueuedCaptureState; record_id: string | null; replay: boolean; says: string | null; }>; /** Set when the pass stopped early because the network went away again. */ stopped_because?: string; } /** The two calls the queue makes on the outside world. Injected, so this file is headless. */ interface CaptureQueuePorts { /** Put the bytes in the platform's ONE byte store and answer with the reference. */ uploadFile(file: QueuedCaptureFile, item: QueuedCapture): Promise<{ file_id?: string | null; url?: string | null; }>; /** `client.captureSubmit`. */ submit(args: { sheet_id: string; client_key: string; answers: Record; files: CaptureFileRef[]; device?: string | null; captured_at?: string | null; location?: Record | null; }): Promise<{ ok: boolean; data?: CaptureOutcome | null; error?: { message?: string; code?: string; } | null; }>; } /** The smallest store the queue needs. IndexedDB in a browser, a Map in a test. */ interface CaptureQueueStore { all(): Promise; put(item: QueuedCapture): Promise; remove(clientKey: string): Promise; meta(key: string): Promise; setMeta(key: string, value: string): Promise; } /** * THE TWO REFUSALS WORTH REPEATING, and they are the package's own list, not a guess. * `results.ts` says it in as many words: `stale_read` (40001) and `timed_out` (57014) are * "the only two refusals in this list worth repeating"; `store_limit` (53400) is the third * — the store ran out of something and the same call works in a quieter moment. * * EVERYTHING ELSE THE DOOR NAMES IS A DECISION. This was the other way round until a real * browser ran it (2026-09-20): the check listed SQLSTATEs, and `RecordsClient` hands back * its own WORD — `invalid_argument`, `door` — with the sqlstate beside it. So a capture the * store had refused by name was filed as a hiccup and queued again forever, which is the * exact silent hole this file's decision 4 exists to prevent. The unit suite passed because * it fed the check SQLSTATEs: it was testing the assumption, not the client. */ declare const REFUSALS_WORTH_REPEATING: ReadonlySet; /** * Did the door DECIDE, or did the attempt merely fail? A failure with no code at all is a * network failure and waits; a refusal the store named is a decision and stays. */ declare function isDecided(error: { code?: string | null; sqlstate?: string | null; } | null | undefined): boolean; /** * A key that is unique on a phone that has been offline for a day and has never spoken to * a server. `crypto.randomUUID` where it exists; otherwise random bytes, and only then the * clock — because two captures in the same millisecond on two phones is exactly the case * that must not collide. */ declare function mintClientKey(): string; /** The IndexedDB store. Returns null where there is no IndexedDB at all. */ declare function indexedDbStore(name?: string): CaptureQueueStore | null; /** The in-memory store — for a test, and for a browser with storage switched off. */ declare function memoryStore(): CaptureQueueStore; interface CaptureQueueOptions { ports: CaptureQueuePorts; store?: CaptureQueueStore | null; /** Watch `online` and drain when the signal comes back. Default true in a browser. */ autoSync?: boolean; /** Told when anything changes, so a badge can say how many are waiting. */ onChange?: (counts: CaptureQueueCounts, items: QueuedCapture[]) => void; now?: () => Date; } interface CaptureQueue { /** Write one capture to disk. Returns its client key; the network is not asked here. */ enqueue(input: { organization_id: string; sheet_id: string; sheet_title?: string; answers: Record; files?: Array>; device?: string | null; captured_at?: string | null; location?: Record | null; client_key?: string; }): Promise; list(): Promise; counts(): Promise; /** Send everything waiting, oldest first, one at a time. Safe to call at any moment. */ sync(): Promise; /** Try one refused item again — after the person has fixed what the door named. */ retry(clientKey: string, patch?: { answers?: Record; }): Promise; /** Throw one away. The only thing that ever removes a capture nobody sent. */ discard(clientKey: string): Promise; /** Forget what has already landed. Never touches anything still waiting. */ clearLanded(): Promise; lastSyncedAt(): Promise; isOnline(): boolean; dispose(): void; } declare function openCaptureQueue(opts: CaptureQueueOptions): CaptureQueue; /** One Field a person asked for, in the words a person uses (FLD-1 / FLD-11). */ interface NewFieldSpec { key: string; label: string; /** * The word for what this column holds — any word `custom._field_document_for` * resolves for `type` (a parity type, a behavior, a plain synonym, or a kind * such as `signature`, `relation`, `entity_reference`, `autonumber`). It is * sent to the door as `type`, unmapped; a word that means nothing is refused * by name, with the list. */ type: FieldTypeWord; sort?: number; required?: boolean; multi?: boolean; config?: Record; /** A choice list's choices, as words. The store keeps them as a Table (FLD-5). */ options?: string[]; /** A column that points at another Table of this organization (FLD-11 / REL-8). */ relationTarget?: Uuid; /** A currency column's symbol; a date column's day-or-day-and-time. */ unit?: string; kind?: "date" | "datetime"; /** * An `entity_reference` column's kinds: the platform entity tokens it may point * at (`ai_model`, `note`, `web_site` …; `custom.entity_reference_kinds()` lists * them). The store refuses an entity reference that names none. */ allowedTypes?: string[]; /** * No two live records may hold the same value here (a `unique` Rule, FLD-3 / B1). A column * `recordUpsert` finds a record by must carry it. */ unique?: boolean; /** * An EXISTING choice list's Table — the column uses those very option records instead of making a * new list (a drafts table copying its source table's column keeps the same choices). Sent as * `config.options_table_id`. */ optionsTableId?: Uuid; /** * Anything else `custom.field_declare` accepts, passed through verbatim and applied LAST (a stored * Field document copied key for key, `format`, `sensitivity`, `via` / `pick` / `agg` / `of`, …). * The store judges every key; a word it does not take is refused by name. */ declaration?: Partial & Record; } /** One door's answer, under its exact arguments. Plain JSON: it crosses from server to browser. */ interface RecordsSeedAnswer { door: string; args: Record; data: unknown; } /** What a server asked for a page, as the person, and when. */ interface RecordsSeed { /** Epoch ms when the server asked. */ at: number; answers: RecordsSeedAnswer[]; } /** * DYN-14 / DYN-15. An ordered list of merge fields ENDING IN A LITERAL, or the * decision to block the turn, or a named absence. No unresolved value is ever * rendered blank or left as a literal placeholder. */ type MissingBehavior = { kind: "fallback"; chain: Array<{ merge_field_key: string; } | { literal: unknown; }>; } | { kind: "block_turn"; } | { kind: "named_absence"; say: string; }; /** DYN-16. Applied AFTER resolution, on the merge field and never on the Field. */ interface MergeFieldTransform { /** e.g. `currency`, `upper`, `date`; the organization's own list. */ name: string; options?: Record; } /** DYN-1. A Record of the kernel Table `Merge Field`. */ interface MergeField { id: Uuid; organization_id: Uuid; key: string; label: string; /** DYN-3. Exactly one of eight. Relationships and rules are NOT sources. */ source: MergeFieldSource; /** DYN-4. What it resolves INTO. The consumer never learns which. */ semantic_type: MergeFieldSemanticType; /** §A. Any number. Never fused into the source. */ modifiers: MergeFieldModifier[]; /** * DYN-12. Exactly one, and it drives the input surface. It OUTRANKS the * precedence ladder: `server_fixed` is not offered as an input at all, and a * value sent for one anyway is discarded and recorded — never merged. */ override_policy: OverridePolicy; /** * DYN-13. Whether an override is POSSIBLE and WHO MAY perform it are two * settings. This is the second one: an access level or an organization role. */ override_requires: string | null; /** DYN-16. */ format: MergeFieldTransform | null; /** DYN-17. `inline`, `on_demand`, or `auto` by budget. A value in no tier is a defect. */ delivery?: Delivery; /** DYN-14. Declared, always. */ missing?: MissingBehavior; /** * What the source needs: for `record`, the starting record and the chain; for * `tool`, the connection token and the freshness ceiling (DYN-20); for * `literal`, the literal. */ source_config: Record; created_by: Uuid | null; updated_by: Uuid | null; created_at: Timestamp; updated_at: Timestamp; version: number; metadata: Record; visibility: string; } /** DYN-8. The triple the RUN gets. Every audit question is answerable from it. */ interface ResolutionTriple { record_id: Uuid | null; field_id: Uuid | null; value_version: number | null; } /** DYN-22. The one provenance row per merge field per turn. */ interface MergeFieldProvenance { merge_field_id: Uuid; declared_source: MergeFieldSource; /** Which source actually answered — the fallback chain makes these differ. */ actual_source: MergeFieldSource | null; record_id: Uuid | null; field_id: Uuid | null; value_version: number | null; rule_id: Uuid | null; rule_version: number | null; /** DYN-11. Who overrode it, and every LOSER of the ladder, not only the winner. */ override_by: Uuid | null; losers?: Array<{ source: MergeFieldSource; value: unknown; why_lost: string; }>; /** DYN-11/DYN-12. A value a client sent for a field it may not supply, discarded and recorded. */ discarded_attempt?: { value: unknown; because: string; } | null; resolved_at: Timestamp; freshness: Freshness; outcome: string; } /** * What a consumer gets back. `pending` is a first-class answer, not a blank: * until the server's resolver exists, a merge field says so and says WHY * (AGT-N-7 — anything that could not be delivered is named, never omitted). */ type MergeFieldResolution = { state: "resolved"; /** The rendered string the prompt gets. */ rendered: string; value: unknown; triple: ResolutionTriple; provenance: MergeFieldProvenance; } | { state: "absent"; /** DYN-14's named absence — what the screen says instead of a blank. */ say: string; reason: string; provenance: MergeFieldProvenance | null; } | { state: "pending"; /** WHY it is pending, in the words a person can act on. Never empty. */ reason: string; }; /** What kind of object the id is, as `custom.where_id_opens` names it — carried as the door's own word. */ type ObjectKind = string; type ObjectOrganizationAnswer = /** The store named the object's organization, and the person may open the object. */ { state: "found"; organizationId: string; kind: ObjectKind; /** The screen the store says opens it (`/data/?record=…`), or null for a part with none. */ path: string | null; /** False when it is in the trash — the person may still open it, to bring it back. */ live: boolean; /** The id it answers as — a merged record's survivor. */ resolvedId: string; /** A table only: how many rows THIS person sees, capped at `rows_visible_cap` (200) — a loading frame's height. Absent when not asked/known. */ rowsVisible?: number; /** * A table only: the layout it opens in and, when that view groups by a Field (a board), the cards each group * holds (largest first; counted over at most `cap` rows, a several-choice card in each of its groups). */ opening?: OpeningViewShape; } /** Not given to this person — or not there at all. The store does not say which, on purpose. */ | { state: "not-given"; } /** We could not ask. NOT an answer about the person's access. */ | { state: "unavailable"; why: string; }; /** Which organization owns an object — the port `createRecords({ organizationOf })` accepts. */ interface RecordOrganizationPort { organizationOf(id: string): Promise; } /** What the store says of the layout a table opens in — enough to size a board's or a gallery's loading frame. */ interface OpeningViewShape { layout?: string; groupField?: string; /** Cards per group, largest first. */ groups?: number[]; cap: number; } /** Reads `opening_view` of the door's answer; anything malformed is no shape at all. */ declare function readOpeningViewShape(raw: unknown): OpeningViewShape | undefined; declare const WHERE_ID_OPENS_DOOR = "where_id_opens"; /** Ask the store which organization `id` lives in — the one call an object page makes before any other door. */ declare function resolveObjectOrganization(dataSource: Pick, id: string): Promise; /** Read one `custom.where_id_opens` answer — asked here, or asked by a server render as the same person. */ declare function readObjectOrganizationAnswer(answered: { data: unknown; error: { code?: string | null; message?: string | null; } | null; }, id: string): ObjectOrganizationAnswer; /** The default port: one `custom.where_id_opens` call per ask, nothing kept. */ declare function whereIdOpensPort(dataSource: Pick): RecordOrganizationPort; interface ChooseAlternateArgs { record_id: Uuid; field_key: string; /** Position in the field's `alternates` list as the record holds it. */ alternate_index: number; /** When given, the alternate holding this rank is chosen instead — the list a screen drew may be ordered differently. */ rank?: number; } /** The patch that makes alternate `alternate_index` of `field_key` the value. Pure; exported for tests. */ declare function alternatePatch(document: RecordDocument, field_key: string, alternate_index: number, rank?: number): { ok: true; patch: Record; } | { ok: false; message: string; }; declare function chooseAlternate(client: Pick, { record_id, field_key, alternate_index, rank }: ChooseAlternateArgs): Promise>; /** One period a value was true between. `from`/`to` are `YYYY-MM-DD`; `null` is open-ended. */ interface ValuePeriod { from: string | null; to: string | null; value: unknown; } interface SetValuePeriodsArgs { record_id: Uuid; field_key: string; /** The whole list, in any order. An empty list clears the field's dates. */ periods: ValuePeriod[]; /** `YYYY-MM-DD` — the day whose period becomes the plain value. Defaults to today (UTC). */ today?: string; } /** The periods a document holds for one field, oldest first. Pure. */ declare function valuePeriodsOf(document: RecordDocument | null | undefined, field_key: string): ValuePeriod[]; /** The period true on `day` (`YYYY-MM-DD`), or null. Half-open: true from `from`, no longer true on `to`. */ declare function periodInForce(periods: ValuePeriod[], day: string): ValuePeriod | null; /** Why a list of periods cannot be stored, in a person's words — or null when it can. Pure. */ declare function valuePeriodsProblem(periods: ValuePeriod[]): string | null; /** The patch that stores `periods` on `field_key`, keeping every other field's envelope. Pure; exported for tests. */ declare function valuePeriodsPatch(document: RecordDocument, field_key: string, periods: ValuePeriod[], today: string): { ok: true; patch: Record; } | { ok: false; message: string; }; /** * STORE WHEN A VALUE WAS TRUE. Reads the record's own document (`recordAsOf`, recorded now) after its * version, writes the whole `_values` block back with this field's periods replaced, against that version. * Refused when any field is hidden from the reader (the block could not be copied whole). */ declare function setValuePeriods(client: Pick, { record_id, field_key, periods, today }: SetValuePeriodsArgs): Promise>; type AiPresetKey = "summarize" | "keywords" | "categorize" | "translate" | "extract" | "sentiment" | "describe_image"; /** What the person must still say after choosing a preset. */ type AiPresetAsk = "language" | "what"; /** Spaces' autofill kinds (`features/spaces/data/sources.ts`); `custom` carries the instruction. */ type AiAutofillKind = "summary" | "keywords" | "translation" | "custom"; interface AiFieldPreset { key: AiPresetKey; label: string; autofillKind: AiAutofillKind; /** The one thing still to ask: a language (Translate) or what to pull out (Extract). */ ask?: AiPresetAsk; /** The column kind the preset needs: Categorize fills a choice column, Describe image reads an attachment column. */ needs?: "choice" | "attachment"; /** * The platform job (mandate key) that fills a column made from this preset when it is not the plain text one. Describe image * is filled by a model that can SEE: the server shows it the row's picture attachments (the attachment columns named in the * column's `inputs`). Every preset without a `mandate` runs as `table.column_fill`. */ mandate?: string; } declare const AI_FIELD_PRESETS: readonly AiFieldPreset[]; declare function aiFieldPreset(key: string): AiFieldPreset | undefined; interface AiPresetContext { /** The language for Translate ("Spanish"); what to pull out for Extract ("the invoice number"). */ answer?: string | undefined; /** The names of the columns the preset reads, when the person narrowed it (e.g. the attachment column). */ reads?: readonly string[] | undefined; } /** * The instruction a preset writes. It is a plain sentence a person can read and edit; it names no model and no table. A preset that * still needs an answer (language, what to extract) and was given none returns `null`, so a screen never saves half a sentence. */ declare function presetInstruction(key: AiPresetKey, ctx?: AiPresetContext): string | null; /** * The columns a preset's model must read, as the `inputs` of the column's enrichment. Describe image reads the table's attachment * columns (without them the model is shown nothing and answers "nothing found"); every other preset reads none by name, so the * answer is `undefined` and the declaration stays as it was. */ declare function presetInputs(key: AiPresetKey | undefined, attachmentColumnKeys: readonly string[]): string[] | undefined; /** * Which presets a column may offer: Categorize only for a choice column (the server passes the column's own choices to the * mandate), Describe image only when the table has an attachment column to read. Everything else fits any column. */ declare function presetsFor(args: { targetIsChoice: boolean; hasAttachmentColumn: boolean; }): readonly AiFieldPreset[]; /** Whether a column of this sensitivity is within the ceiling; an unknown word (either side) is never read by default. */ declare function withinSensitivityCeiling(sensitivity: string | null | undefined, ceiling: string): boolean; /** The slice of a Field the default-inputs question reads. */ type EnrichInputField = CoercibleField & { key: string; archived_at?: string | null; source?: string | null; sensitivity?: string | null; context_policy?: string | null; }; /** * THE DEFAULT `inputs` of a new AI column: the record's OTHER readable fields, by key. A column saved with no inputs hands the * model nothing to read (every row comes back "nothing to find"), so both homes of AI columns - the table page's "Let AI fill" and * Spaces' "AI autofill" - start from this list. Left out: the column itself, other AI columns (no loops), retired columns, * pictures/links/people/rolled-up values (a text model cannot read them), and anything the store would refuse an enrichment * to read (sensitivity above the organization's ceiling - `recordsLimits().enrichmentSensitivityCeiling`, the knob * custom/enrichment_sensitivity_ceiling - or a column that says no agent may see it). `on_request` columns are fetched only when * asked, so they are not read by default either. */ declare function defaultEnrichInputs(fields: readonly EnrichInputField[], targetKey: string, ceiling?: string, kernel?: KernelTargets): string[]; interface Async { data: T | null; loading: boolean; /** The store's own refusal. Never null-and-empty at the same time. */ error: RecordsError | null; reload: () => void; /** * Replace what is held WITHOUT a round trip — for a caller that has just read fresher rows * through the SAME door and would otherwise throw them away and read the page again. * It is never a way to put un-doored data on a screen: everything handed in here came back * from a door that applied the ladder. */ setData: (update: (current: T | null) => T | null) => void; } /** * THE SERVER'S ANSWER TO A SCREEN'S OWN QUESTION, IN THE FIRST PASS (lane SSR-ROWS). * * For a screen that holds a read in its OWN state (filled by an effect) rather than in a records * hook: under a live page seed (``), `run` is run against the seed — suspending * on the server and while hydrating, never touching the network — and its answer is returned so the * screen can START from it (`useState(() => seeded ?? …)`) and skip its first effect read. Without a * seed, or when `run` asks a door the seed does not hold, it answers `undefined` and the screen reads * exactly as before. Never cached beyond the seed: a later mount asks for itself. */ declare function useSeededAnswer(key: string | null, run: (client: RecordsClient) => Promise<{ ok: true; data: T; } | { ok: false; error: RecordsError; }>): T | undefined; /** * `useSeededAnswer`, with when the server asked (epoch ms). A screen that starts from the answer keeps * that moment: while the answer is that young, a records client REBUILT underneath it (the active * organization resolving, a token refresh) is not a new question — the screen's question did not change — * so it reads nothing (lane SEED-ENTITY, charts asking again 4-7 s in). */ declare function useSeededAnswerAt(key: string | null, run: (client: RecordsClient) => Promise<{ ok: true; data: T; } | { ok: false; error: RecordsError; }>): { data: T; at: number; } | undefined; /** * A TILE'S NUMBER FROM THE SERVER'S SEED (lane SEED-ENTITY): the rows of `custom.record_aggregate` * for `spec` over `tableId`, when the page seed holds that exact question (`askTileSeed`, records-ui * `/first-page`); else `undefined` and the tile reads for itself. Asks through `client.recordAggregate`, * so the arguments are exactly the ones the tile's own read sends. */ declare function useSeededAggregate(tableId: Uuid | null, spec: Omit[0], "table_id">): AggregateRow[] | undefined; /** One Table's declaration. */ declare function useTable(tableId: Uuid | null): Async
; /** Every Table this person can see in this organization. */ declare function useTables(): Async; /** * WHAT THIS PERSON MAY DO TO THESE THINGS — one call for a whole page. * * A screen asks this BEFORE it draws a control, which is the whole difference * between a product that offers what you may use and one that offers everything * and apologises afterwards. The ids are joined into the dependency key so a * page that re-renders with the same rows does not re-ask. * * `null` for a subject is an ANSWER ("you hold nothing on this"), and `loading` * is a third state that is neither — a caller that treated loading as "no" * would blink every control off on every reload. */ declare function useMyLevels(ids: Uuid[]): Async>; /** The same question about one thing. */ declare function useMyLevel(id: Uuid | null): Async; declare function tableShapeChanged(tableId: Uuid): void; /** * FLD-10. The Fields that APPLY — the store decides, from the record type, and * the client asks rather than filtering a list it has. * * Re-reads whenever this table's shape changes anywhere in the app — see * `tableShapeChanged`. */ declare function useFields(tableId: Uuid | null, recordType?: string): Async; /** * VIEWS-AND-FIELDS BL (REL-9). The REVERSE COLUMNS of a Table — one per relation column elsewhere * that links here (`client.reverseColumns`). Virtual: never in `useFields`. Re-read when any * table's shape changes in this app, because a new link column on ANOTHER table makes one here. */ declare function useReverseColumns(tableId: Uuid | null): Async; /** * A page of records' links through each of `columns`, `limit` a record (1–50): `{ [column key]: * { [record id]: { total, links } } }`. One `reverseLinksMany` per column, shared between every * screen asking the same question, and re-read after any write this page makes — a link is made * from the OTHER table's side, so no row here changes when it is. */ declare function useReverseLinks(tableId: Uuid | null, columns: readonly ReverseColumn[], recordIds: readonly Uuid[], limit?: number, offset?: number): Async>>; interface UseRecordsOptions { pageSize?: number; page?: number; /** * THE STORE'S ONE FILTER SHAPE. Left out, this is the whole page. Supplied, * the store narrows in its own query and the hook re-reads when the question * changes — it is never filtered in the browser, which could only ever filter * the rows it had already been handed and would silently drop the rest. * * This is what makes a dashboard number walkable: the same object that * counted it opens it. */ filter?: StoreFilter; } interface UseRecordsState extends Async<{ rows: ReadRow[]; total: number | null; locked?: number; }> { /** * Whether this list is actually live. FALSE with a reason is an answer a * screen can print; a list that silently stopped updating is not. */ live: boolean; liveReason: string; } /** A page of records, realtime-aware when the host bound the port. */ declare function useRecords(tableId: Uuid | null, options?: UseRecordsOptions): UseRecordsState; interface UseRecordPageOptions { /** Rows per page. */ pageSize?: number; /** Zero-based page. */ page?: number; /** The store's one filter shape (flat or a Rule expression), compiled in the store's own query. */ filter?: StoreFilter; /** Text searched by the store over every column this reader may see (and choice words). */ search?: string | null; /** The order; empty = the store's own (or the view's hand order when `viewId` is named). */ sort?: readonly RecordPageSort[]; /** A hand-ordered view: the page follows the positions the view keeps. */ viewId?: Uuid | null; } /** A store-read page: its rows, the matching total, and the sort keys the store skipped. */ interface RecordPageData { rows: ReadRow[]; total: number | null; /** Rows listed only as a header because this person cannot open them (never in `rows`, never in `total`). */ locked?: number; /** Sort keys naming a column this reader cannot see — skipped by the store, never a dead page. */ sortIgnored: string[]; /** Columns of a saved view's filter skipped because this reader cannot see them (WITHHELD-HONEST-2). */ filterIgnored?: string[]; } interface UseRecordPageState extends Async { live: boolean; liveReason: string; } /** * DOOR-SPEED. ONE PAGE THE STORE SORTED, SEARCHED, FILTERED AND COUNTED (`client.listPage` → * `custom.read_records_page`), realtime-aware exactly like `useRecords`: a notice re-reads only the * ids it names and patches them into this page. What a grid pages with — a row on page six of a * thousand is found by the store's search, a sort orders the whole table, and `total` is the * matching set this reader may see. `tableId: null` reads nothing. */ declare function useRecordPage(tableId: Uuid | null, options?: UseRecordPageOptions): UseRecordPageState; /** * HOW MANY WRITES THIS PAGE HAS MADE, counted once per burst (250 ms). For a screen that holds an * answer in its own state rather than in a records hook — a chart's aggregate, a tile — and must * ask again after any add, edit, archive or duplicate made on this page: put it in the read's * dependencies. A write names a record, not its table, so every write counts; a burst asks once. */ declare function useRecordWrites(): number; /** One record, its values and (optionally) which Rule version computed each. */ /** * HOW MANY TIMES THIS PAGE HAS WRITTEN THIS RECORD (lane RECORDS-UI-FIX, 2026-09-23). * A screen that shows a record puts this in its read's dependencies and re-reads when a * write through any client on the page lands on it — the record panel's history read * "3 versions" after its fourth write because nothing told it. See `core/recordChanges`. */ declare function useRecordChangeRevision(recordId: Uuid | null | undefined): number; interface UseRecordOptions { /** * The Table the record lives in. Named, the record is LIVE: a change another tab, person or * agent makes to it arrives on the table's realtime notice and is re-read into the one entry * every view of this record reads — including a view that is asleep. Left out, the record * hears only the writes made on this page. */ tableId?: Uuid | null; } declare function useRecord(recordId: Uuid | null, withComputed?: boolean, options?: UseRecordOptions): Async; interface UseRecordMutation { write: (args: { table_id: Uuid; data: Record; }) => Promise; update: (args: { record_id: Uuid; patch: Record; expectedVersion?: number; }) => Promise; remove: (args: { record_id: Uuid; }) => Promise; restore: (args: { record_id: Uuid; }) => Promise; saving: boolean; error: RecordsError | null; /** * THE CONFLICT, as something a screen can SHOW rather than a toast it flashes: * the version you wrote against, the version that won, and every field you * touched as it stands now. Nothing was overwritten and nothing was lost — * which is exactly what the store's own hint says, and it is carried here. */ conflict: WriteConflict | null; clearConflict: () => void; } /** Writes, with optimistic concurrency surfaced instead of swallowed. */ declare function useRecordMutation(): UseRecordMutation; /** * GETTING RID OF A WHOLE TABLE — the loop, once, for every screen (VERIFIER-11 F3). * * `useRecordMutation().remove` is right for a record and WRONG for a Table: * `custom.record_delete` aimed at a Table recurses through everything it * contains inside one transaction, so on 1,430 records — a size the product's * own import reaches in half a minute — it died twelve seconds in on `57014`, * "canceling statement due to statement timeout", and the screen told the * person nothing had changed and to "try a smaller page". There is no page. * * So archiving a table is a JOB: this hook makes the passes, holds the numbers * the store answers each one with, and stops on `done`. * * WHAT MAKES IT RESUMABLE is that nothing here is the state of the run — the * store reads what remains off the records themselves every call. A refused * pass, a `stop()`, a closed tab or a reload all leave `interrupted` true and a * `carryOn()` that continues from exactly where the last pass stopped. Which is * also why a screen driving this may never say "nothing was changed" after a * failure: `progress.archived_total` is what actually landed, and it is the * number the person is owed. */ interface UseTableArchive { /** The numbers from the last pass or preview. Null until something has been asked. */ progress: TableArchiveProgress | null; /** A loop is in flight. */ running: boolean; /** Passes made since the last `start()`. */ passes: number; /** * The pass size in use. It STARTS at `chunk` and HALVES whenever the store * runs out of time, so a screen can say the run slowed down rather than * letting it look stuck. Never below ten: at that point the store is not slow, * it is refusing, and a loop that kept shrinking would hide it. */ chunkInUse: number; /** * The loop backed the pass size off because the store ran out of time. An * automatic intervention ANNOUNCES ITSELF: a run that quietly went four times * slower would read as a stuck screen. */ slowedDown: boolean; /** The refusal that stopped the loop. The work already done still stands. */ error: RecordsError | null; /** * The loop ended with records still live — because a pass was refused or * because `stop()` was called. It is the screen's cue to offer carrying on * rather than to claim a finished or a failed run. */ interrupted: boolean; /** Ask what would happen and change NOTHING, so a person sees the number first. */ preview: () => Promise; /** Run passes until done, refused, or stopped. */ start: () => Promise; /** Same loop, said in the word a screen uses after an interruption. */ carryOn: () => Promise; /** Cut cleanly after the pass in flight. Never mid-pass: a pass is one transaction. */ stop: () => void; } declare function useTableArchive(tableId: Uuid, options?: { chunk?: number; includeTable?: boolean; }): UseTableArchive; interface UseFieldMutation { /** Add a column. One call; the store decides what the parity type is made of. */ declare: (args: { table_id: Uuid; spec: NewFieldDeclaration; }) => Promise; /** One field's own settings. What it HOLDS is a conversion and is refused by name. */ update: (args: { field_id: Uuid; patch: FieldPatch; }) => Promise; /** Take a column off a table. */ retire: (args: { field_id: Uuid; }) => Promise; /** Bring a removed column back, with its values. */ restore: (args: { field_id: Uuid; }) => Promise; saving: boolean; error: RecordsError | null; clearError: () => void; } /** * THE SHAPE OF A TABLE, changed through the store's own doors. * * Deliberately separate from `useRecordMutation`. A Field IS a record, but * adding one is not writing a record: it changes what every record of the table * means, it is an administrator's right rather than an editor's, and it is the * one write `custom.record_write` was never able to make — it cannot tell the * Table about the field, and the field guard refuses any definition the Table * has not declared. A screen that reached for the record writer here is the * screen that spent 19 September refusing every column a person tried to add. */ /** * A STANDARD BUSINESS TABLE'S CUSTOM FIELDS, by its registry token. * * `useFields(tableId)` is about one of YOUR OWN tables. This is the other half: * the fields an organization added to a CRM contact, a deal, a note - any of the * 643 tables the registry types Entity or Detail - and there is no per-entity * code here or in any screen that uses it. `{ includeRetired: true }` adds the * fields taken away (each with `archived_at`), live first — the archived view. */ declare function useEntityFields(token: string | null, opts?: { includeRetired?: boolean; }): Async; /** * REC-53 in one answer: a standard row's real columns AND its organization's * custom values AND the definitions that describe them. A row the person may * not open comes back as the store's own refusal, because the door reads it AS * them through the table's own row-level security. */ declare function useEntityRecord(token: string | null, recordId: Uuid | null): Async; interface UseEntityBackLinks { /** The custom rows linking here, first page then every loaded page, in the store's order. */ items: EntityBackLinkItem[]; /** The platform record the rows link to (label as the store names it). Null until the first page lands. */ target: EntityBackLinks["target"] | null; /** Still reading the first page. */ loading: boolean; /** The first page's refusal, in the store's own words (door absent included). Never swallowed. */ error: RecordsError | null; /** More pages exist. */ hasMore: boolean; loadingMore: boolean; /** The next page's refusal; the pages already loaded stay. */ moreError: RecordsError | null; /** Ask the next page. */ loadMore: () => Promise; /** Ask the first page again (and forget the later pages). */ reload: () => void; } /** * AP-4: THE CUSTOM ROWS THAT LINK TO ONE PLATFORM RECORD (`custom.entity_back_links`). A CRM contact * or an HR employee page shows the organization's own custom rows that point at it ("Onboarding * checklist" linked to an employee). Keyed by the ROW's organization, never the active one; * `organizationId: null` asks nothing. The first page rides the shared cache like its siblings; * later pages ride `next_cursor` and are held by the hook. */ declare function useEntityBackLinks(token: string | null, recordId: Uuid | null, options: { organizationId: Uuid | null; limit?: number; }): UseEntityBackLinks; /** What the registry says about a token - and whether it can hold a value at all. */ declare function useEntityTable(token: string | null): Async; /** * G2: A TABLE'S ROW ACTIONS, read once per table per tab (the remount law, 2026-10-03). Every * grid, page button and action picker of the table shares one entry: a board tile that sleeps * and wakes, a Remove + Undo or a second view reads nothing. `reload()` is the re-read (an * action declared in the settings rail). `null` asks nothing. */ declare function useRowActions(tableId: Uuid | null): Async<{ actions: RowAction[]; stale: unknown[]; } | null>; /** SCR-12: the answer a screen needs to make "Add field" absent-or-honest. */ declare function useEntityFieldRights(token: string | null): Async; interface UseEntityFieldMutation { /** Add a column to a standard table. Refused for anybody but an organization admin. */ declare: (args: { token: string; spec: NewEntityFieldDeclaration; }) => Promise; update: (args: { field_id: Uuid; patch: Record; }) => Promise; retire: (args: { field_id: Uuid; }) => Promise; /** Set custom values on one standard row. A key left out is left alone. */ write: (args: { token: string; record_id: Uuid; patch: Record; }) => Promise; saving: boolean; error: RecordsError | null; clearError: () => void; } /** * Changing a standard table's custom fields, and filling them in. Deliberately * ONE hook for both, because the store keeps them the same way: the definition * is a record in the field kernel and the value is in the row's own * `custom_fields` column, and a screen that had two mutation hooks would have * two places to get the refusal wording from. */ declare function useEntityFieldMutation(): UseEntityFieldMutation; declare function useFieldMutation(): UseFieldMutation; /** * DYN-14 / AGT-N-7. A merge field's value — and while the resolver's server half * does not exist, `pending` WITH THE REASON. Never a blank, never a leftover * `{{brace}}`, never an empty string that a prompt would carry into a model. */ declare function useMergeField(key: string | null, state?: Record): MergeFieldResolution | null; /** The hold the hooks below this point pin their answers to. */ declare function RecordsHoldScope({ holdKey, children }: { holdKey: string | null; children: ReactNode; }): react.FunctionComponentElement>; /** * Own a hold for as long as this component is mounted. Mount it where the view's LIFE is * decided, never inside the part that sleeps (a sleeping subtree's effects are torn down). */ declare function useRecordsHold(holdKey: string | null): void; /** Past this, a seeded answer is drawn and then re-asked in the background. */ declare const SEED_FRESH_MS = 30000; type SeedOutcome = { seeded: true; data: T; stale: boolean; } | { seeded: false; }; interface SeedStore { /** True until the provider's first commit: only the first pass is drawn from the seed. */ live: boolean; /** The outcome of one question against the seed — the same promise for every render of it. */ run(slot: string, run: (client: RecordsClient) => Promise<{ ok: true; data: T; } | { ok: false; error: RecordsError; }>, config: RecordsConfig): Promise>; /** * The same, for a reader that holds no records client (the entity engine): `run` is handed a data * source that answers from the seed only. A miss anywhere in the run is "not seeded". */ runSource(slot: string, run: (source: RecordsDataSource) => Promise<{ ok: true; data: T; } | { ok: false; error: unknown; }>): Promise>; /** Epoch ms the server asked. */ at: number; } interface RecordsSeedProviderProps { /** What the server asked for this page as the person (`recordingDataSource(...).seed()`), or null. */ seed: RecordsSeed | null | undefined; children: ReactNode; } /** Mount above a server-rendered records screen. A null seed is no seed: every hook asks for itself. */ declare function RecordsSeedProvider({ seed, children }: RecordsSeedProviderProps): react.FunctionComponentElement>; /** * A READER WITHOUT A RECORDS CLIENT, AGAINST THE PAGE SEED (lane SEED-ENTITY): under a live * ``, `run` is asked of a data source that answers from the seed only — * suspending on the server and while hydrating, never touching the network. Its answer (and when the * server asked) is returned for the reader to start from; a miss, or no seed, answers `undefined` and * the reader asks for itself. Always suspends while the seed is live (React matches awaited promises * by order), so call it unconditionally. */ declare function useSeededSource(key: string | null, run: (source: RecordsDataSource) => Promise<{ ok: true; data: T; } | { ok: false; error: unknown; }>): { data: T; at: number; } | undefined; /** How long an entry outlives its last reader, so a remount or an Undo costs nothing. */ declare const RECORDS_CACHE_GRACE_MS = 30000; /** Door reads the cache has made, and live halves it has started and stopped, since load. */ declare function recordsCacheCounters(): Readonly<{ reads: number; liveStarts: number; liveStops: number; }>; interface EntityReferenceRead { data: T | null; loading: boolean; /** The store's own refusal, verbatim. */ error: RecordsError | null; } /** The kinds of platform thing a record may point at, for the kind picker. */ declare function useEntityReferenceKinds(): EntityReferenceRead; /** The words of each reference, read for THIS person (withheld where they may not open it). */ declare function useEntityReferenceWords(refs: readonly EntityRef[]): EntityReferenceRead; /** * THE PICKER'S LIST: things of these kinds whose words hold `search`, that this person may point a * record at (`custom.entity_reference_search`). `enabled: false` reads nothing (a closed picker). */ declare function useEntityReferenceSearch(tokens: readonly string[], search: string, enabled?: boolean): EntityReferenceRead; /** Where a declared field's value goes in the graduated table. */ declare const TO_CUSTOM_FIELDS: "custom_fields"; /** A relation's values become `platform.associations` rows (R5), never a column. */ declare const TO_ASSOCIATION: "association"; interface TypedTableGraduation { /** Where the feature's rows now live: `.
` (registered in `platform.entity_types`). */ readonly token: string; /** Every declared field key → its column, `custom_fields`, or (relations only) `association`. */ readonly map: Readonly>; } /** The columns the mover writes itself; a field may never map onto one of them. */ declare const GRADUATION_BASE_COLUMNS: readonly ["id", "organization_id", "created_by", "updated_by", "created_at", "updated_at", "deleted_at", "version", "metadata", "visibility", "shown_to", "category_id"]; /** The minimum a validation needs to know about a field: its store word. */ interface GraduationField { readonly word: string; } /** * Every sentence that says why this `graduatedTo` cannot be used — empty when it can. Pure. * `fields` is the definition's fields by key. */ declare function graduationProblems(fields: Readonly>, graduation: TypedTableGraduation): string[]; /** One store row (`custom.record`, data_class 'record') as the mover reads it. */ interface StoreRowSnapshot { id: Uuid; organization_id: Uuid; /** The organization's copy of the typed table this row lives in. */ store_table_id: Uuid; created_by: Uuid | null; updated_by: Uuid | null; created_at: string; updated_at: string; deleted_at: string | null; version: number; visibility: string | null; shown_to: string | null; custom_fields: Record | null; data: Record; } /** One relation value to become an association edge. */ interface GraduatedRelation { field: string; targetIds: Uuid[]; } interface GraduatedRow { /** Every column of the entity-table row, by column name (`custom_fields` and `metadata` included). */ row: Record; /** Relation values found in the document, to become associations. */ relations: GraduatedRelation[]; } /** * ONE STORE ROW → ONE ENTITY-TABLE ROW. Keeps id, organization, author, timestamps, version, * archived state (`deleted_at`), visibility and `shown_to` exactly. A declared field goes where * the map says; every undeclared key goes to `custom_fields` (merged over what the row already * held there); a store bookkeeping key (leading `_`) and the row's origin go to `metadata`. */ declare function graduatedRow(fields: Readonly>, graduation: TypedTableGraduation, snapshot: StoreRowSnapshot): GraduatedRow; /** * Whose rows a person sees by default. * - `organization`: every member of the row's organization. * - `person`: the author's rows. HIDDEN FROM LISTS, NOT LOCKED — the store has no Private level * for its Tables yet, so an organization admin (and any reader of the record by id) can still * open the row. Never put anything that must be private in a `person` table. * - `global`: one copy in the platform organization, written only by server code. */ type TypedTableScope = "person" | "organization" | "global"; /** * One declared column. `T` is the value a row holds; `Req` whether it must be given; `RO` whether * the store computes it (absent from inserts); `Uniq` whether no two records may share it. */ interface AppField { /** The store's word for the column (`text`, `select`, `datetime` …), sent unmapped. */ readonly word: string; readonly label: string | undefined; readonly required: Req; readonly readOnly: RO; readonly unique: Uniq; /** Everything else the column door takes (options, unit, kind, allowed types, declaration). */ readonly extra: Readonly>; /** A relation's other table — ensured first, its id sent as `relationTarget`. */ readonly target: AnyTypedTableDef | undefined; /** Type only; never set. */ readonly __value?: T; } interface FieldOptions { label?: string; required?: boolean; unique?: boolean; /** Anything else `custom.field_declare` accepts, applied last (format, sensitivity …). */ declaration?: NewFieldSpec["declaration"]; } type Req = O extends { required: true; } ? true : false; type Uniq = O extends { unique: true; } ? true : false; /** A computed column takes only a label. */ type ComputedOptions = Pick; /** * The field builders. Each emits exactly what `ensureTable`'s `NewFieldSpec` takes; the key is the * property name in `fields`, kept exactly (a `__` included). */ declare const f: { text: (opts?: O) => AppField, false, Uniq>; longText: (opts?: O) => AppField, false, Uniq>; email: (opts?: O) => AppField, false, Uniq>; phone: (opts?: O) => AppField, false, Uniq>; url: (opts?: O) => AppField, false, Uniq>; number: (opts?: O) => AppField, false, Uniq>; integer: (opts?: O) => AppField, false, Uniq>; decimal: (opts?: O) => AppField, false, Uniq>; currency: (unit: string, opts?: O) => AppField, false, Uniq>; percent: (opts?: O) => AppField, false, Uniq>; checkbox: (opts?: O) => AppField, false, Uniq>; /** A day, as `YYYY-MM-DD`. */ date: (opts?: O) => AppField, false, Uniq>; /** A moment, as an ISO instant. */ datetime: (opts?: O) => AppField, false, Uniq>; /** One of the choices. The row holds the choice word itself. */ select: (choices: C, opts?: O) => AppField, false, Uniq>; /** Any of the choices. */ multiSelect: (choices: C, opts?: O) => AppField, false, Uniq>; /** A record of another typed table, in the same organization. */ relation: (target: D, opts?: O) => AppField, false, Uniq>; /** A person of the organization. */ member: (opts?: O) => AppField, false, Uniq>; /** A file. */ attachment: (opts?: O) => AppField, false, Uniq>; /** A platform thing (`note`, `agent` …) of one of `kinds`: `{ token, id }`, the store's own shape. */ entityReference: (kinds: readonly string[], opts?: O) => AppField<{ token: string; id: Uuid; }, Req, false, Uniq>; /** Computed by the store from `formulaText` (`{Visit fee} - {Deposit taken}`); read-only. */ formula: (formulaText: string, opts?: O) => AppField, true, Uniq>; autonumber: (opts?: O) => AppField, true, Uniq>; createdTime: (opts?: O) => AppField, true, Uniq>; modifiedTime: (opts?: O) => AppField, true, Uniq>; }; type AppFields = Record; /** The keys of `F` whose field is unique — the only keys an upsert may find a record by. */ type UniqueKeys = { [K in keyof F]: F[K] extends AppField ? K : never; }[keyof F] & string; interface TypedTableInput> { /** What a person sees the table called. */ name: string; /** The token the table is found by, in every organization. */ slug: string; scope: TypedTableScope; /** The feature that keeps it, one lower-case word (`decisions`, `kits`). */ kept_for: string; /** Who answers for it (`lane:PLATFORM-APP-DATA`, a team, a role). Optional. */ owner?: string; /** A unique field that says which record a write is (`upsert` finds by it). */ key?: K; /** * The file(s) that declare this table (`matrx-frontend:features/kits/kit-installs.typed-table.ts`). * Stored on the table as `app_table.declared_in`, and named in the store's refusal when someone * tries to archive, rename or move a table the code depends on. Optional. */ declared_in?: string | readonly string[]; fields: F; /** * GRADUATED (contract: common-docs …/CONTRACT-PLATFORM-APP-DATA-GRADUATION.md). The feature's * rows now live in the standard entity table `token` (`.
`); `map` says where every * declared field went — a column, `"custom_fields"`, or (a relation) `"association"`. Nothing is * dropped. `pnpm tables:graduate` moves the rows; `check:typed-tables` then expects every * organization's copy archived. Not part of the spec hash. */ graduatedTo?: TypedTableGraduation; /** * CONFIDENTIAL (the access ladder's level: "the owner and the people the record's own rules name"). * Each organization's copy is made Confidential by a SERVER step on the store owner's connection * (`custom.set_table_confidential_arman_explicitly_approved` is no client's door), carrying the * recorded approval below. Until the copy reports Confidential with exactly these readers, every * write through this package refuses and says why (`confidentialGate`). Not part of the spec hash. */ confidential?: TypedTableConfidential; } /** One reader rule: the person (or team) a field names may read the row at `level`, when `when` holds. */ interface TypedTableReader { /** A declared field naming a person: a `member` field (or a text field holding a user id). */ field: string; level: "viewer" | "editor"; /** The store's flat filter on THIS row (`{ shared: true }`); the reader applies only while it is true. */ when?: Readonly>; } interface TypedTableConfidential { readers: readonly TypedTableReader[]; /** * true: the person whose first use made the organization's copy owns nothing more than a reader * does (the store's `maker_is_reader`). Always true for a table whose rows must stay blind to the * person who happened to make the copy. */ makerIsReader: boolean; /** Arman's own words approving this table family as Confidential, verbatim, and the day he gave them. */ approval: { words: string; approvedOn: string; covers: string; }; } interface TypedTableDef { readonly name: string; readonly slug: string; readonly scope: TypedTableScope; readonly kept_for: string; readonly owner: string | null; readonly key: K | null; /** Where the code declares it (`TypedTableInput.declared_in`), as a list; empty when not given. */ readonly declared_in: readonly string[]; readonly fields: Readonly; /** Each field as `ensureTable` takes it, in declaration order (a relation's target id is added at ensure time). */ readonly specs: readonly Readonly[]; /** The canonical field spec the hash is taken over (sorted, display order excluded). */ readonly canonicalSpec: string; /** SHA-256 (hex) of `canonicalSpec`. Moves when — and only when — a column's stored shape would. */ readonly specHash: string; /** Where the rows went when the feature graduated (`TypedTableInput.graduatedTo`); `null` while it has not. */ readonly graduatedTo: TypedTableGraduation | null; /** The Confidential declaration (`TypedTableInput.confidential`); `null` for an ordinary typed table. */ readonly confidential: TypedTableConfidential | null; } type AnyTypedTableDef = TypedTableDef; type FieldsOf = D extends TypedTableDef ? F : never; type ValueOf = X extends AppField ? T : never; type Simplify = { [K in keyof T]: T[K]; } & {}; /** A row as the store answers it: required fields are `T`, every other is `T | null`. */ type RowOf = Simplify<{ readonly _id: Uuid; readonly _organizationId: Uuid; } & { [K in keyof FieldsOf]: FieldsOf[K] extends AppField ? (R extends true ? T : T | null) : never; }>; type RequiredKeys = { [K in keyof F]: F[K] extends AppField ? K : never; }[keyof F]; type WritableKeys = { [K in keyof F]: F[K] extends AppField ? never : K; }[keyof F]; /** * What a write takes: required fields must be given, every other writable field may be (or be * `null`), a computed field cannot be. `_id` names the record to update on a table with no `key`. */ type InsertOf = Simplify<{ [K in RequiredKeys>]: ValueOf[K]>; } & { [K in Exclude>, RequiredKeys>>]?: ValueOf[K]> | null; } & { _id?: Uuid; }>; /** * DECLARE AN TYPED TABLE. Pure: no request, no clock, no global. Refuses — by throwing, at the line * that declares it — a definition the store would refuse later: a slug or `kept_for` that is not a * token, a `key` that is not a unique field, no fields. */ declare function defineTypedTable = never>(input: TypedTableInput): TypedTableDef; interface TypedTableEnsured { table: Uuid; homeId: Uuid; organizationId: Uuid; /** This call made the table (the organization's first use). */ created: boolean; /** How the stored columns differ from the definition — reported, never applied. `null` = not compared. */ drift: FieldDrift[] | null; } interface TypedTableOrgOptions { /** The organization to act in. Default: the client's own (the active organization). */ organizationId?: Uuid | null; } /** * MAKE THIS ORGANIZATION'S COPY OF AN TYPED TABLE, OR FIND IT. Idempotent: a later call adds any * column the definition gained and reports (never applies) every other difference as `drift`. * A relation's target typed table is ensured first, in the same organization. */ declare function ensureTypedTable(client: RecordsClient, def: AnyTypedTableDef, options?: TypedTableOrgOptions): Promise>; /** The most rows one read holds in memory, across organizations. More is said (`truncated`), never dropped silently. */ declare const APP_ROWS_CEILING = 10000; /** What a read of an typed table answers. */ interface AppRows { rows: RowOf[]; /** Rows the store holds that this person may see (summed over the organizations read). */ total: number; /** True when `rows` stopped at `APP_ROWS_CEILING` and `total` is larger: never a silent cut. */ truncated: boolean; } /** * Every row of this typed table the person may see, across all their organizations (or the one * `organizationId` names). An organization with no copy yet adds no rows; a refusal from one * organization is reported by its door and the others still answer; only when NONE answers is * the read a refusal (on a store without `table_find`: `door_absent`). */ declare function listAppRows(client: RecordsClient, def: D, options?: TypedTableOrgOptions): Promise>>; interface AppUpsertOptions extends TypedTableOrgOptions { /** The record's version the caller decided on; a newer write refuses with `stale_write`. */ expectedVersion?: number; } /** * WRITE A ROW. With a `key` in the definition: the record that key names is updated, or written * when there is none (`custom.record_upsert`, race-safe). Without one: `_id` updates that record, * no `_id` writes a new one. The organization's copy is ensured first (once per page). Answers the * record's id. The store refuses — by name — a key the definition never declared (23514). */ declare function upsertAppRow(client: RecordsClient, def: D, data: InsertOf, options?: AppUpsertOptions): Promise>; /** ARCHIVE A ROW — the store's soft delete; restorable from the archive. */ declare function removeAppRow(client: RecordsClient, def: AnyTypedTableDef, rowId: Uuid, options?: TypedTableOrgOptions): Promise>; type TypedTableStatus = "ok" | "missing" | "archived" | "drifted"; interface TypedTableChecked { status: TypedTableStatus; /** The table's id (live or archived); `null` when missing. */ table: Uuid | null; organizationId: Uuid; /** * Every difference; a declared column the table lacks is `{ aspect: "spec", stored: null, declared: }`, * a stored column the definition no longer declares is `{ aspect: "extra", stored: , declared: null }`. */ drift: FieldDrift[]; /** * Live rows in THIS organization's copy that this reader may see (the store's own count); * `null` when the table is missing or archived. The gate is about size (Arman, 2026-10-02): the * release check sums this across organizations and compares it with the size knob. */ rowCount: number | null; /** * The copy's access level as the store holds it: `confidential` once the server step made it so, * else `organization`; `null` when missing or archived. A Confidential definition's writes wait on * this (and on the readers matching — `confidentialGate`). */ level: "confidential" | "organization" | null; } declare function checkTypedTable(client: RecordsClient, def: AnyTypedTableDef, options?: TypedTableOrgOptions): Promise>; interface UseTypedTableOptions { /** Narrow the rows to one organization, and write there. Default: all rows; writes to the active organization. */ organizationId?: Uuid | null; } interface UseTypedTable { rows: RowOf[]; /** Rows the store holds that this person may see; `null` until read. */ total: number | null; /** `rows` stopped at the ceiling and `total` is larger. */ truncated: boolean; loading: boolean; error: RecordsError | null; status: TypedTableStatus | null; upsert(data: InsertOf, options?: Pick): Promise>; /** Archive a row (restorable). */ remove(rowId: Uuid): Promise>; reload(): void; } declare function useTypedTable(def: D, options?: UseTypedTableOptions): UseTypedTable; /** One column of a typed custom table, as `pnpm tables:types` writes it. */ interface StoreTableColumn { fieldId: string; /** The key the store keeps the value under. */ key: string; label: string; type: string; required: boolean; choices?: readonly string[]; } /** A typed view of an existing custom table. `Row` / `Insert` ride as phantom types. */ interface StoreTable, Insert = Partial> { readonly id: Uuid; readonly organizationId: Uuid; readonly name: string; readonly slug: string; readonly columns: Readonly>; /** Never set: carries the row type so `StoreRowOf` can read it. */ readonly __row?: Row; /** Never set: carries the insert type so `StoreInsertOf` can read it. */ readonly __insert?: Insert; } /** The generated file's one call: the definition, typed by its row and insert types. */ declare function storeTable>(def: { id: string; organizationId: string; name: string; slug: string; columns: Record; }): StoreTable; type AnyStoreTable = StoreTable; type StoreRowOf = T extends StoreTable ? R : never; type StoreInsertOf = T extends StoreTable ? I : never; type ColumnOf = Extract, string>; /** A flat condition: column → the value it must hold (`null` = empty). All must hold. */ type StoreTableWhere = Partial<{ [K in ColumnOf]: string | number | boolean | null; }>; interface StoreTableSort { column: ColumnOf | "_id"; direction?: "asc" | "desc"; as?: RecordPageSort["as"]; } interface ListTableRowsOptions { where?: StoreTableWhere; /** Words over every column this reader may see. */ search?: string | null; sort?: readonly StoreTableSort[]; /** At most this many rows (default and ceiling: STORE_ROWS_CEILING). */ limit?: number; } interface StoreTableRows { rows: StoreRowOf[]; /** Rows matching the condition that this person may see. */ total: number; /** `rows` stopped short of `total`. */ truncated: boolean; } /** The most rows one read holds; more is said (`truncated`), never dropped silently. */ declare const STORE_ROWS_CEILING = 10000; /** One stored document → a row keyed by column names (a column the reader cannot see is null). */ declare function rowFromDocument(table: T, id: Uuid, document: Record): StoreRowOf; /** Rows of the table this person may see, keyed by column name, in the store's order. */ declare function listTableRows(client: RecordsClient, table: T, options?: ListTableRowsOptions): Promise>>; /** A new row. Answers its id. The store refuses a value it cannot hold, by name. */ declare function writeTableRow(client: RecordsClient, table: T, data: StoreInsertOf): Promise>; /** Change some columns of one row. `expectedVersion` refuses a write over a newer one (`stale_write`). */ declare function updateTableRow(client: RecordsClient, table: T, rowId: Uuid, patch: Partial>, options?: { expectedVersion?: number; }): Promise>; /** Archive one row (the store's soft delete; restorable from the archive). */ declare function archiveTableRow(client: RecordsClient, table: T, rowId: Uuid): Promise>; interface UseStoreTable { rows: StoreRowOf[]; total: number | null; truncated: boolean; loading: boolean; error: RecordsError | null; write(data: StoreInsertOf): Promise>; update(rowId: Uuid, patch: Partial>, options?: { expectedVersion?: number; }): Promise>; /** Archive one row (the store's soft delete; restorable). Taken out of every list at once, put back if refused. */ archive(rowId: Uuid): Promise>; reload(): void; } declare function useStoreTable(table: T, options?: ListTableRowsOptions): UseStoreTable; interface ArchiveDeliberatelyArgs { /** The table to archive (the organization is the client's own). */ tableId: Uuid; /** The table's slug, as the person TYPED it. Must match exactly. */ typedSlug: string; /** Why; kept with the archive event. */ reason: string; /** Each pass's answer, for a progress line. */ onPass?: (pass: TableArchiveProgress) => void; } declare function archiveTypedTableDeliberately(client: RecordsClient, args: ArchiveDeliberatelyArgs): Promise>; /** What the host's server step takes to make one organization's copy Confidential. */ interface ConfidentialRequest { organization_id: Uuid; slug: string; kept_for: string; readers: TypedTableReader[]; maker_is_reader: boolean; approval: { words: string; approved_on: string; covers: string; }; } declare function confidentialRequest(def: AnyTypedTableDef, organizationId: Uuid): ConfidentialRequest; /** Do the stored readers say exactly what the definition declares? */ declare function readersMatch(declared: readonly TypedTableReader[], stored: unknown): boolean; interface ConfidentialState { table: Uuid | null; /** `confidential` once the server step ran; `organization` before; `null` when the copy is missing. */ level: "confidential" | "organization" | null; readersMatch: boolean; makerIsReader: boolean; } /** The sentence a write is refused with, or `null` when the copy is Confidential as declared. */ declare function confidentialRefusal(def: AnyTypedTableDef, state: ConfidentialState): string | null; /** Read the copy's Confidential state through the store's own find (a reader seat is enough). */ declare function confidentialState(client: RecordsClient, def: AnyTypedTableDef, options?: TypedTableOrgOptions): Promise>; /** FAIL CLOSED: the table id when a write may go ahead; otherwise the refusal naming why. */ declare function confidentialGate(client: RecordsClient, def: AnyTypedTableDef, options?: TypedTableOrgOptions): Promise>; /** A field of the triggering table by key, or of another typed table (`{ def, field }`). */ type AppFieldRef = string; /** An automation written with field KEYS; `tables` names the typed tables an action reaches by def. */ interface AppAutomationSpec { name: string; trigger: { on: "row_added"; } | { on: "property_edited"; field: AppFieldRef; to?: unknown; } | { on: "form_answered"; }; condition?: Record | null; actions: Array<{ do: "set"; values: Record; } | { do: "edit_rows"; table: AnyTypedTableDef; where: Record; values: Record; limit?: number; } | { do: "notify"; to: { person: Uuid; } | { field: AppFieldRef; } | { author: true; }; text: string; /** The notice's subject line (in-app and email); defaults to the automation's name. Same `{{key}}` words as `text`. */ subject?: string; /** Where the notice opens: a path (`/hr/performance/{{record_id}}?org={{organization_id}}`) or a URL field's `{{key}}`. */ link?: string; }>; } /** * DECLARE A FEATURE'S AUTOMATIONS ON ITS TYPED TABLE, IDEMPOTENTLY: each spec is matched to the live * automation of the same name and updated in place, or added. Nothing is ever archived here. */ declare function ensureAppAutomations(client: RecordsClient, def: AnyTypedTableDef, specs: readonly AppAutomationSpec[], options?: TypedTableOrgOptions): Promise>; export { AI_FIELD_PRESETS, APP_ROWS_CEILING, AggregateRow, CaptureFileRef, CaptureOutcome, CoercibleField, Delivery, EVERY_RECORD_TYPE, EntityBackLinkItem, EntityBackLinks, EntityFieldRights, EntityRecordRead, EntityRef, EntityRefWithWords, EntityReferenceKind, EntityTableFacts, Field, FieldDrift, FieldPatch, FieldTypeWord, Freshness, GRADUATION_BASE_COLUMNS, KernelTargets, MergeFieldModifier, MergeFieldSemanticType, MergeFieldSource, NewEntityFieldDeclaration, NewFieldDeclaration, OverridePolicy, PermissionLevel, RECORDS_CACHE_GRACE_MS, REFUSALS_WORTH_REPEATING, RELATIVE_DAY_KINDS, ReadRow, RecordDocument, RecordPageSort, RecordRead, RecordsConfig, RecordsDataSource, RecordsError, RecordsHoldScope, RecordsResult, RecordsSeedProvider, ReverseColumn, ReverseLinks, RowAction, SEED_FRESH_MS, STORE_ROWS_CEILING, StoreFilter, TO_ASSOCIATION, TO_CUSTOM_FIELDS, Table, TableArchiveProgress, TableDuplicateProgress, TableDuplicated, Timestamp, Uuid, WHERE_ID_OPENS_DOOR, WriteConflict, aiFieldPreset, alternatePatch, archiveTableRow, archiveTypedTableDeliberately, autonumberJoin, autonumberPrefixOf, autonumberSearchOf, autonumberWords, baseCopyName, checkTypedTable, chooseAlternate, confidentialGate, confidentialRefusal, confidentialRequest, confidentialState, copyIdOfRefusal, defaultEnrichInputs, defineTypedTable, derivedLookOf, duplicateBase, ensureAppAutomations, ensureTypedTable, f, fieldAppliesToEveryType, fieldAppliesToType, filterWithAutonumber, formulaLookOf, graduatedRow, graduationProblems, holdsRelativeDays, indexedDbStore, instantFromWallInZone, isAutonumberField, isDecided, isDerivedField, listAppRows, listTableRows, localeDateOrder, lookupFromFields, memoryStore, mintClientKey, openCaptureQueue, periodInForce, pickedLookOf, presetInputs, presetInstruction, presetsFor, rankTypedMatches, readObjectOrganizationAnswer, readOpeningViewShape, readTypedDate, readTypedNumber, readTypedTime, readersMatch, readersTimeZone, recordTypeOf, recordsCacheCounters, relativeWindowBounds, removeAppRow, resolveObjectOrganization, resolveRelativeDays, restoreSnapshot, restoredBaseName, rowFromDocument, setReadersTimeZone, setValuePeriods, snapshotBase, storeTable, tableShapeChanged, twoDigitYear, typedDateText, typedMatchScore, typedTimeText, typesOfField, updateTableRow, upsertAppRow, useEntityBackLinks, useEntityFieldMutation, useEntityFieldRights, useEntityFields, useEntityRecord, useEntityReferenceKinds, useEntityReferenceSearch, useEntityReferenceWords, useEntityTable, useFieldMutation, useFields, useMergeField, useMyLevel, useMyLevels, useRecord, useRecordChangeRevision, useRecordMutation, useRecordPage, useRecordWrites, useRecords, useRecordsHold, useReverseColumns, useReverseLinks, useRowActions, useSeededAggregate, useSeededAnswer, useSeededAnswerAt, useSeededSource, useStoreTable, useTable, useTableArchive, useTables, useTypedTable, valuePeriodsOf, valuePeriodsPatch, valuePeriodsProblem, wallPartsInZone, weekStartIndexOf, whereIdOpensPort, withDerivedLooks, withFormulaLooks, withinSensitivityCeiling, writeTableRow }; export type { AiAutofillKind, AiFieldPreset, AiPresetAsk, AiPresetContext, AiPresetKey, AnyStoreTable, AnyTypedTableDef, AppAutomationSpec, AppField, AppFields, AppRows, AppUpsertOptions, ArchiveDeliberatelyArgs, BaseCopied, BaseCopyProgress, BaseCopyResult, BasePort, BaseSnapshotRecord, BaseTable, CaptureQueue, CaptureQueueCounts, CaptureQueueOptions, CaptureQueuePorts, CaptureQueueStore, CaptureSyncReport, ChooseAlternateArgs, ConfidentialRequest, ConfidentialState, EnrichInputField, EntityReferenceRead, FieldOptions, GraduatedRelation, GraduatedRow, InsertOf, ListTableRowsOptions, MergeField, MergeFieldProvenance, MergeFieldResolution, MergeFieldTransform, MissingBehavior, NamesRecordTypes, ObjectKind, ObjectOrganizationAnswer, OpeningViewShape, QueuedCapture, QueuedCaptureFile, QueuedCaptureState, RecordOrganizationPort, RecordPageData, RecordsSeedProviderProps, RelativeDayKind, RelativeFieldLookup, RelativeWindowOptions, ResolutionTriple, RowOf, SetValuePeriodsArgs, StoreInsertOf, StoreRowOf, StoreRowSnapshot, StoreTable, StoreTableColumn, StoreTableRows, StoreTableSort, StoreTableWhere, TypedDate, TypedMatchScore, TypedNumber, TypedTableChecked, TypedTableConfidential, TypedTableDef, TypedTableEnsured, TypedTableGraduation, TypedTableInput, TypedTableOrgOptions, TypedTableReader, TypedTableScope, TypedTableStatus, TypedTime, UniqueKeys, UseEntityBackLinks, UseEntityFieldMutation, UseFieldMutation, UseRecordMutation, UseRecordOptions, UseRecordPageOptions, UseRecordPageState, UseRecordsOptions, UseRecordsState, UseStoreTable, UseTableArchive, UseTypedTable, UseTypedTableOptions, ValuePeriod, WallParts };