@ai-matrx/records-ui 0.16.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +315 -0
- package/dist/index.cjs +2604 -1439
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +472 -57
- package/dist/index.d.ts +472 -57
- package/dist/index.js +2611 -1417
- package/dist/index.js.map +1 -1
- package/package.json +7 -5
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/host.tsx","../src/rights.ts","../src/plainWords.ts","../src/names.ts","../src/PersonPicker.tsx","../src/editors.tsx","../src/parity.ts","../src/fieldTypes.ts","../src/RelationPicker.tsx","../src/gridEditing.tsx","../src/Refusal.tsx","../src/values.tsx","../src/labels.tsx","../src/Grid.tsx","../src/ExportMenu.tsx","../src/ImportWizard.tsx","../src/CustomFieldsSection.tsx","../src/FieldEditor.tsx","../src/TableSettings.tsx","../src/Peek.tsx","../src/RecordForm.tsx","../src/systemTable.ts","../src/ShareControl.tsx","../src/views.ts","../src/ViewSwitcher.tsx","../src/ViewBar.tsx","../src/seedOnce.ts","../src/ProposalRow.tsx","../src/ActionInbox.tsx","../src/HistoryPanel.tsx","../src/CommentThread.tsx","../src/forms.ts","../src/FormBuilder.tsx","../src/FormRunner.tsx","../src/charts.ts","../src/docs.ts","../src/DocTemplate.tsx","../src/DocRender.tsx","../src/SignBlock.tsx","../src/NotifyRuleEditor.tsx","../src/ChartBlock.tsx","../src/DashboardCanvas.tsx","../src/FormsPanel.tsx","../src/RecordChat.tsx","../src/EnrichPanel.tsx","../src/ChecklistRunner.tsx","../src/BookingSlots.tsx","../src/CaptureSheet.tsx","../src/PortalShell.tsx","../src/PublicViewPage.tsx","../src/EmbedFrame.tsx","../src/RecordsMount.tsx","../src/TablesHome.tsx","../src/createTable.ts","../src/TablePage.tsx"],"sourcesContent":["// src/index.ts — @ai-matrx/records-ui\n//\n// The canonical screens of the AI Matrx record store. Every component here\n// reads and writes ONLY through @ai-matrx/records, renders through\n// @ai-matrx/design-system's own primitives and data table, and carries\n// @ai-matrx/alchemy's menu where a person would reach for one.\n//\n// There is no bespoke per-feature record UI in this platform: a feature that\n// needs a grid, a form, a picker or a peek mounts one of these.\n\nexport {\n RecordsUiProvider,\n useRecordsUi,\n useTableRights,\n useRecordRights,\n useRowRights,\n tableRightsAt,\n NO_RIGHTS,\n NO_UPLOAD_REASON,\n NO_SAVED_VIEWS_REASON, NO_SHARE_REASON,\n NO_MEMBERS_REASON,\n} from \"./host\";\nexport type { RecordsUiHost, TableRights, OrganizationMember, ShareSubject } from \"./host\";\nexport {\n whatYouMayDo,\n whatYouMayDoWithTable,\n NOT_ANSWERED_YET,\n LEVEL_WORD,\n} from \"./rights\";\nexport type { WhatYouMayDo, Capability } from \"./rights\";\nexport {\n refusalForAPerson,\n refusalLineForAPerson,\n isMachineIdentity,\n machineIdentityIn,\n MACHINE_IDENTITY,\n} from \"./plainWords\";\nexport type { PlainRefusal } from \"./plainWords\";\nexport { humanize, fieldName, tableName, recordName, rowName } from \"./names\";\nexport { PersonPicker, memberName, personRecordForMember } from \"./PersonPicker\";\nexport type { PersonPickerProps } from \"./PersonPicker\";\nexport { GridCell, useGridEditing, fieldIsEditable } from \"./gridEditing\";\nexport type { GridEditing, CellAddress, CellState, CellRefusal } from \"./gridEditing\";\nexport { RefusalNotice, RefusalLine, hintForAPerson, hintIsMachineIdentity } from \"./Refusal\";\nexport { Grid, columnForField } from \"./Grid\";\nexport type { GridProps } from \"./Grid\";\nexport { ExportMenu } from \"./ExportMenu\";\nexport type { ExportMenuProps } from \"./ExportMenu\";\nexport { ImportWizard } from \"./ImportWizard\";\nexport type { ImportWizardProps } from \"./ImportWizard\";\nexport { CustomFieldsSection } from \"./CustomFieldsSection\";\nexport type { CustomFieldsSectionProps } from \"./CustomFieldsSection\";\nexport { FieldEditor, keyFor, whatIsMissing } from \"./FieldEditor\";\nexport type { FieldEditorProps } from \"./FieldEditor\";\nexport { TableSettings } from \"./TableSettings\";\nexport type { TableSettingsProps, FieldProposalRow } from \"./TableSettings\";\nexport { Peek } from \"./Peek\";\nexport type { PeekProps } from \"./Peek\";\nexport { RecordForm } from \"./RecordForm\";\nexport type { RecordFormProps } from \"./RecordForm\";\nexport { RelationPicker } from \"./RelationPicker\";\nexport type { RelationPickerProps } from \"./RelationPicker\";\nexport { FieldControl, FieldLabel, RecordChip } from \"./editors\";\nexport type { FieldEditorControlProps } from \"./editors\";\nexport { renderValue, scalarText, envelopeFor, ProvenanceBadge, RecordValue } from \"./values\";\nexport { RecordLabelProvider, useRecordLabels, pointsAtRecords, idsOf, isId } from \"./labels\";\nexport type { LabelLookup } from \"./labels\";\nexport { editorKindFor, fieldTypeLabel, PARITY_LABEL, PARITY_MADE_OF } from \"./parity\";\nexport {\n FIELD_TYPE_CHOICES,\n FIELD_TYPE_GROUPS,\n fieldTypeChoice,\n isPlainFieldType,\n parityTypesWithNoExplanation,\n} from \"./fieldTypes\";\nexport type { FieldTypeChoice, PickableFieldType, PlainFieldType } from \"./fieldTypes\";\nexport type { EditorKind } from \"./parity\";\nexport { ensureSystemTable, useSystemTable } from \"./systemTable\";\nexport type { SystemTableSpec, SystemFieldSpec, UseSystemTableState, TrackedVersion } from \"./systemTable\";\nexport {\n VIEW_LAYOUTS,\n VIEW_TABLE,\n LAYOUT_LABEL,\n LAYOUT_NEEDS,\n LAYOUT_FIELD_KIND,\n LAYOUT_NO_FIELD,\n viewDocument,\n viewFromRecord,\n viewPatchDocument,\n} from \"./views\";\nexport type { SavedView, SavedViewSpec, ViewLayout, ViewSort } from \"./views\";\nexport { ViewSwitcher, useViewRecords } from \"./ViewSwitcher\";\nexport type { ViewSwitcherProps } from \"./ViewSwitcher\";\nexport { ViewBar } from \"./ViewBar\";\nexport type { ViewBarProps } from \"./ViewBar\";\nexport { ProposalRow } from \"./ProposalRow\";\nexport type { ProposalRowProps, ProposedChange, ProposalOutcome } from \"./ProposalRow\";\n// SCR-11. The inbox reads the STORE's own queue (custom.work_inbox) — the\n// package-owned `records_ui_action` Table it used to keep, and the\n// QueuedAction/actionDocument shapes that wrote into it, are gone: a second\n// queue beside the store's own is what PRODUCTS.md row 6 forbids.\nexport { ActionInbox, ACTION_KINDS } from \"./ActionInbox\";\nexport type { ActionInboxProps, ActionKind } from \"./ActionInbox\";\nexport { HistoryPanel } from \"./HistoryPanel\";\nexport type { HistoryPanelProps } from \"./HistoryPanel\";\nexport { CommentThread, COMMENT_TABLE } from \"./CommentThread\";\nexport {\n FORM_FLOWS,\n FORM_TABLE,\n formDocument,\n formFromRecord,\n submissionStamp,\n} from \"./forms\";\nexport type { FormFlow, FormQuestionSpec, FormSpec, FormTheme, SavedForm } from \"./forms\";\nexport { FormBuilder } from \"./FormBuilder\";\nexport type { FormBuilderProps } from \"./FormBuilder\";\nexport {\n CHART_KINDS,\n CHART_KIND_LABEL,\n CHART_NEEDS,\n DASHBOARD_TABLE,\n SERIES_COLORS,\n dashboardDocument,\n dashboardFromRecord,\n groupLabel,\n} from \"./charts\";\nexport type { ChartKind, ChartSpec, DashboardSpec, SavedDashboard } from \"./charts\";\nexport { bodyFromKeys, bodyForReading, fieldToken, isSignatureField } from \"./docs\";\nexport type { DocTemplateSpec } from \"./docs\";\nexport { DocTemplate } from \"./DocTemplate\";\nexport type { DocTemplateProps } from \"./DocTemplate\";\nexport { DocRender } from \"./DocRender\";\nexport type { DocRenderProps } from \"./DocRender\";\nexport { SignBlock } from \"./SignBlock\";\nexport type { SignBlockProps } from \"./SignBlock\";\nexport { NotifyRuleEditor } from \"./NotifyRuleEditor\";\nexport type { NotifyRuleEditorProps, NotifyRuleSpec } from \"./NotifyRuleEditor\";\nexport { ChartBlock } from \"./ChartBlock\";\nexport type { ChartBlockProps } from \"./ChartBlock\";\nexport { DashboardCanvas } from \"./DashboardCanvas\";\nexport type { DashboardCanvasProps } from \"./DashboardCanvas\";\nexport { FormsPanel, type FormsPanelProps } from \"./FormsPanel\";\nexport { FormRunner } from \"./FormRunner\";\nexport type { FormRunnerProps } from \"./FormRunner\";\nexport type { CommentThreadProps } from \"./CommentThread\";\nexport { RecordChat, NO_CHAT_REASON } from \"./RecordChat\";\nexport type { RecordChatProps, RecordChatContext, RecordChatEntry, RecordChatWithheld } from \"./RecordChat\";\nexport { EnrichPanel, NO_ENRICH_REASON } from \"./EnrichPanel\";\nexport type { EnrichPanelProps, EnrichAsk, EnrichOutcome } from \"./EnrichPanel\";\nexport { ChecklistRunner, CHECKLIST_TABLE } from \"./ChecklistRunner\";\nexport type { ChecklistRunnerProps, ChecklistSpec, ChecklistStepSpec } from \"./ChecklistRunner\";\nexport { BookingSlots } from \"./BookingSlots\";\nexport type { BookingSlotsProps } from \"./BookingSlots\";\nexport { CaptureSheet, CAPTURE_MODES, IN_MEMORY_QUEUE_REASON } from \"./CaptureSheet\";\nexport type { CaptureSheetProps, CaptureMode } from \"./CaptureSheet\";\nexport { PortalShell } from \"./PortalShell\";\nexport type { PortalShellProps } from \"./PortalShell\";\nexport { PublicViewPage } from \"./PublicViewPage\";\nexport type { PublicViewPageProps } from \"./PublicViewPage\";\nexport { EmbedFrame, useEmbedHandshake } from \"./EmbedFrame\";\nexport type { EmbedFrameProps } from \"./EmbedFrame\";\nexport type { CaptureQueuePort, PendingCapture } from \"./host\";\n\n// The two page assemblies a host route mounts, and the provider pair they need.\nexport { RecordsMount, storeDecidesRights, personActor, recordsDataSource, STORE_DECIDES_REASON, KERNEL_REASON } from \"./RecordsMount\";\nexport type { RecordsMountProps } from \"./RecordsMount\";\nexport { TablesHome, TABLE_LANES, LANE_TITLE, LANE_EMPTY, laneFor } from \"./TablesHome\";\nexport type { TablesHomeProps, TableLane } from \"./TablesHome\";\nexport { TablePage, TABLE_NOT_REACHABLE, DEFAULT_VIEW_NAME } from \"./TablePage\";\nexport type { TablePageProps } from \"./TablePage\";\nexport { declareTable, addFields, tokenFor, DEFAULT_FIELDS } from \"./createTable\";\nexport type { NewTableSpec, NewFieldSpec, DeclareResult } from \"./createTable\";\n\n// SCR-N-5 — the Share button, and the host port that supplies the app's one share dialog.\nexport { ShareControl, useCanShare, shareUnavailableReason } from \"./ShareControl\";\nexport type { ShareControlProps } from \"./ShareControl\";\n","\"use client\";\n\n// src/host.tsx — @ai-matrx/records-ui\n//\n// THE ONE BINDING POINT. A host mounts `<RecordsUiProvider>` once, inside\n// `<RecordsProvider>` from @ai-matrx/records, and every component in this\n// package reads what it needs from here. There is no module-level state: two\n// organizations in two tabs must never share one.\n//\n// WHAT A HOST BINDS, AND WHAT HAPPENS WHEN IT DOES NOT\n// ----------------------------------------------------\n// `rights` USED TO BE the only answer to \"may this person administer this\n// table?\" — a PORT, whose default was `false` with a reason and whose only\n// other honest setting was `storeDecidesRights`: yes to everything, let the door\n// refuse afterwards. The sixth-pass verdict measured what that second answer\n// costs a person: a colleague at viewer got a live cell editor, typed, pressed\n// Enter, and was refused only then.\n//\n// THE STORE ANSWERS THIS NOW, through the door this lane added:\n// `custom.my_levels` says what level the CALLER holds on the subjects they\n// name, one call for a whole page. `rights` stays a PORT for a host whose\n// authority is genuinely its own, but nothing is guessed when it is unbound:\n// the store's own answer is the default, and `rights.why(...)` says, for each\n// thing a person may not do, what level it would take and who can give it.\n//\n// IT IS NOT FREE, AND THE OBVIOUS FREE VERSION IS WRONG. `custom.read_records`\n// answers `level` on every row and `tableList` is a read — but of the Table\n// KERNEL, so that level is the caller's level on the kernel (viewer, for\n// everybody) and not on the table the row describes. Carrying it was measured\n// wrong within the hour: a table's own owner came back \"viewer\". A table is a\n// record, and its level is asked for like any other record's.\n//\n// ABSENT OR HONEST, NEVER DEAD — and never offered-then-refused, which is the\n// same lie with a longer fuse.\n\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { PermissionLevel, Table, Uuid } from \"@ai-matrx/records\";\nimport { useMyLevel, useMyLevels } from \"@ai-matrx/records/react\";\n\nimport { NOT_ANSWERED_YET, whatYouMayDo, whatYouMayDoWithTable, type WhatYouMayDo } from \"./rights\";\nimport type { RecordChatContext } from \"./RecordChat\";\nimport type { EnrichAsk, EnrichOutcome } from \"./EnrichPanel\";\n\n/**\n * What a person may do to one table. The four words and the ladder are the\n * store's (`rights.ts`), not ours.\n *\n * `admin`, `comment` and `write` are kept with the names they have always had,\n * because every screen in this package and in the host apps reads them; they\n * are now the store's ANSWER rather than a host's guess.\n */\nexport interface TableRights extends WhatYouMayDo {\n /** SCR-2: holders of `admin` on the table see the \"+\" and the settings panel. */\n admin: boolean;\n /**\n * Why this answer, in one sentence. Kept for callers that show a single\n * reason; `why(what)` is the per-control sentence and is what the screens use.\n */\n reason: string;\n}\n\nfunction tableRights(may: WhatYouMayDo, overallReason?: string): TableRights {\n return {\n ...may,\n admin: may.structure,\n reason: overallReason ?? (may.structure ? \"\" : may.why(\"structure\")),\n };\n}\n\n/**\n * Kept so a host that imported it still compiles. It is no longer any screen's\n * default: the store answers this question now, and a package that said \"I\n * assume nothing\" while holding the answer would be hiding controls from the\n * people who hold them.\n */\nexport const NO_RIGHTS: TableRights = tableRights(NOT_ANSWERED_YET);\n\n/**\n * THE ONE WAY TO BUILD A `TableRights` BY HAND — for a host with its own\n * authority, and for a suite that wants to mount one seat's screen. It takes\n * the LEVEL, never six booleans, so nobody can hand a screen a combination the\n * ladder cannot produce (write without read, share without edit).\n */\nexport function tableRightsAt(level: PermissionLevel | null): TableRights {\n return tableRights(whatYouMayDo(level, true));\n}\n\nexport interface RecordsUiHost {\n /** Answer the rights question for one table. Synchronous: a screen renders now. */\n rights?: (table: Table) => TableRights;\n /** Where a record's own page lives, when the host has one. A peek is used when it does not. */\n hrefForRecord?: (args: { table: Table; recordId: Uuid }) => string | undefined;\n /** The host's own link element, so routing stays the host's business. */\n Link?: (props: { href: string; children: ReactNode; className?: string }) => ReactNode;\n /** Toasts. Absent means the screen shows the sentence inline instead — never silence. */\n notify?: { success: (message: string) => void; error: (message: string) => void };\n /** Density for every table this package renders. */\n density?: \"condensed\" | \"normal\" | \"spacious\";\n /**\n * OPTIONAL. Where a file a person attached actually goes. A File is a record\n * in the kernel File Table (REC-31), but the BYTES are the host's file\n * service, not this package's business — so this is a port.\n *\n * Unbound, an attachment question does NOT draw a file chooser that quietly\n * loses the file: it says, in one sentence, that no file store is bound and\n * names this port. Absent or honest, never dead.\n */\n upload?: (file: File) => Promise<{ ok: true; fileId: Uuid } | { ok: false; reason: string }>;\n /**\n * Where this app serves its PUBLIC pages from, when that is not the origin\n * the screen is running on. A form's link is built here, so an owner copying\n * it from an admin host, a preview deployment or a desktop shell gets the\n * address a stranger can actually open — never `http://localhost:3000/f/…`\n * pasted into an email. Unbound, the browser's own origin is used.\n */\n publicOrigin?: string;\n /**\n * OPTIONAL. The organization's saved views as `platform.saved_view` holds\n * them — which is what a subscription points at (DOOR-18). The record store\n * has NO door onto that table, because it is the platform's and not the\n * store's, so this is a port rather than a read this package invents.\n *\n * Unbound, `NotifyRuleEditor` shows the subscriptions that exist and says, in\n * one sentence, that it cannot offer a view to subscribe to. It never renders\n * an empty picker that looks like \"you have no views\".\n */\n savedViews?: () => Promise<Array<{ id: Uuid; name: string }>>;\n /**\n * OPTIONAL. WHO IS IN THIS ORGANIZATION (FLD-11 `member`).\n *\n * A person field must offer PEOPLE. Who the people are is the platform's\n * answer — organization membership lives in `iam`, not in the record store —\n * and the store has no door onto it, so this is a port rather than a read\n * this package invents. `PersonPicker` resolves whoever is picked to their\n * record in the kernel Person Table, which is what the Field actually stores.\n *\n * Unbound, a person question is ABSENT with `NO_MEMBERS_REASON`. It never\n * falls back to listing the kernel Person Table's contents: that Table also\n * holds the Homes this package writes, and offering \"Comments Home\" as a\n * person is exactly what this port exists to stop.\n */\n members?: () => Promise<OrganizationMember[]>;\n /**\n * OPTIONAL. THE HOST'S OWN CHAT SURFACE (SCR-26).\n *\n * This package ships no chat UI, on purpose: AI Matrx has exactly one, it\n * lives in matrx-frontend (`AgentConversationColumn`), and it reads that app's\n * Redux store — so a second one here would drift within a month and a package\n * that imported the first would stop being a package. `RecordChat` therefore\n * builds the CONTEXT (the record, through the read door, with the masked\n * fields named) and hands it to this port.\n *\n * Unbound, the panel is ABSENT with that reason, never a composer that goes\n * nowhere.\n */\n chat?: (context: RecordChatContext) => ReactNode;\n /**\n * OPTIONAL. THE SERVER'S `records` TOOL (SCR-27).\n *\n * An AI fill must be written with actor `agent` on behalf of the person, and\n * only the server can honestly say that — a browser stamping itself `agent`\n * is a browser claiming to be one. So `EnrichPanel` asks here, and the host\n * calls the server's own `records` tool (`action: \"record_write\"`), which\n * stamps `_actor` and `_on_behalf_of` itself.\n *\n * Unbound, no Fill control is drawn at all and the reason names this port.\n */\n enrich?: (ask: EnrichAsk) => Promise<EnrichOutcome>;\n /**\n * OPTIONAL. WHERE AN OFFLINE CAPTURE WAITS (SCR-30).\n *\n * `CaptureSheet` mints the id for a capture BEFORE it tries to send it, so a\n * phone with no signal has already decided what the write will be called.\n * Where that queue physically lives is the host's business — IndexedDB in a\n * browser, a file in a desktop app — so it is a port. Unbound, the sheet\n * keeps its queue in memory for the life of the page AND SAYS SO, because a\n * queue that silently died with the tab is the failure this exists to avoid.\n */\n captureQueue?: CaptureQueuePort;\n /**\n * OPTIONAL. THE HOST'S OWN SHARE DIALOG (SCR-N-5).\n *\n * This package ships no share dialog, ON PURPOSE, and for the same reason it\n * ships no chat: AI Matrx has exactly ONE sharing surface — matrx-frontend's\n * `features/sharing` ShareModal, with its people picker, its level picker, its\n * grant list and its \"who can see this, and why\" panel — and a second one here\n * would be a parallel sharing UI within a month. Sharing is the access model's\n * front door, and two front doors is how a platform ends up with two answers\n * to \"who can see this\".\n *\n * So `ShareControl` draws the BUTTON (which belongs on the record and table\n * screens, beside everything else a person does to a thing) and hands the\n * subject to this port, which returns the host's own dialog.\n *\n * Unbound, the button is ABSENT and `NO_SHARE_REASON` says which port to bind.\n * Never a Share button that opens nothing.\n */\n share?: (subject: ShareSubject) => ReactNode;\n}\n\n/**\n * What a host's share dialog is being opened ON. A Table is a record in this\n * store (a `custom.record` row whose table is the Table kernel), so ONE subject\n * shape covers both screens and `kind` is what the sentences say, not what the\n * store looks up.\n */\nexport interface ShareSubject {\n kind: \"record\" | \"table\";\n /** The store is keyed (organization_id, id); this package never guesses one. */\n organizationId: Uuid;\n subjectId: Uuid;\n /** What to call it on screen. Never empty — the id's first eight characters at worst. */\n name: string;\n /** Close the dialog. The control owns the open/closed state, the host owns the dialog. */\n onClose: () => void;\n}\n\n/** One member of the organization, in the words a person reads. */\nexport interface OrganizationMember {\n /** The platform's user id. This is what a Person record carries as `user_id`. */\n userId: string;\n /** Their display name, when the platform has one. */\n name?: string | null;\n email?: string | null;\n avatarUrl?: string | null;\n}\n\n/** The durable half of offline capture: read the queue, write it, that is all. */\nexport interface CaptureQueuePort {\n load: () => Promise<PendingCapture[]>;\n save: (pending: PendingCapture[]) => Promise<void>;\n}\n\n/** One capture waiting to be written, with the id the CLIENT minted for it. */\nexport interface PendingCapture {\n /**\n * The client key. Minted offline, before the first attempt, and never\n * re-minted on retry — that is exactly what lets the store's replay ledger\n * tell a retry from a second capture.\n */\n clientKey: string;\n tableId: Uuid;\n payload: Record<string, unknown>;\n capturedAt: string;\n device: string;\n /** How many times sending has been tried, and what the store last said. */\n attempts: number;\n lastRefusal?: string | null;\n}\n\n/** The sentence the notify editor shows when no saved-view port is bound. */\nexport const NO_SAVED_VIEWS_REASON =\n \"No saved-view port is bound, so there is nothing here to subscribe to. A subscription points at a \" +\n \"`platform.saved_view`, which the record store has no door onto — bind `savedViews` on \" +\n \"<RecordsUiProvider> with your host's own list and the picker appears.\";\n\n/** The sentence a person question shows when no membership port is bound. */\nexport const NO_MEMBERS_REASON =\n \"No membership port is bound, so this question cannot offer anybody. A person field points at the \" +\n \"kernel Person Table, and who is in this organization is the platform's answer rather than the \" +\n \"record store's — bind `members` on <RecordsUiProvider> with your host's own roster and the picker \" +\n \"appears.\";\n\n/** The sentence shown when no share dialog is bound. */\nexport const NO_SHARE_REASON =\n \"No share dialog is bound, so this screen offers no Share button rather than one that opens \" +\n \"nothing. Bind `share` on <RecordsUiProvider> with the app's own sharing dialog — AI Matrx has \" +\n \"exactly one (features/sharing), and this package deliberately does not ship a second.\";\n\n/** The sentence an attachment question shows when no file store is bound. */\nexport const NO_UPLOAD_REASON =\n \"No file store is bound, so this question cannot take a file. Bind `upload` on \" +\n \"<RecordsUiProvider> with your host's file service and the chooser appears.\";\n\nconst HostContext = createContext<RecordsUiHost | null>(null);\n\nexport function RecordsUiProvider({ value, children }: { value: RecordsUiHost; children: ReactNode }) {\n const bound = useMemo(() => value, [value]);\n return <HostContext.Provider value={bound}>{children}</HostContext.Provider>;\n}\n\nexport function useRecordsUi(): RecordsUiHost {\n return useContext(HostContext) ?? {};\n}\n\n/**\n * WHAT THIS PERSON MAY DO TO THIS TABLE — asked, once per table.\n *\n * A host that binds `rights` still wins: a portal, an embed or an app with its\n * own authority is entitled to a narrower answer than the store's. An unbound\n * host no longer gets a guess in either direction — while the door is\n * answering, `known` is false and NOTHING is offered and nothing is claimed.\n */\nexport function useTableRights(table: Table | null | undefined): TableRights {\n const host = useRecordsUi();\n const bound = Boolean(host.rights);\n // A table is a record in this store, so its level is the same question.\n const asked = useMyLevel(bound || !table ? null : table.id);\n return useMemo(() => {\n if (!table) return NO_RIGHTS;\n if (host.rights) return host.rights(table);\n if (asked.loading) return tableRights(NOT_ANSWERED_YET);\n // A refusal is an ANSWER: the door said no, so this person holds nothing.\n const level = asked.error ? null : asked.data;\n return tableRights(whatYouMayDoWithTable(table, level, true));\n }, [host, table, bound, asked.loading, asked.error, asked.data]);\n}\n\n/**\n * WHAT THIS PERSON MAY DO TO ONE RECORD — which is a different question from\n * the table's, and the sixth-pass verdict is the proof: a record shared with a\n * colleague at Editor inside a table she holds at Viewer. The grid used to\n * label that row \"viewer\" while the store let her write to it.\n */\nexport function useRecordRights(recordId: Uuid | null): WhatYouMayDo {\n const asked = useMyLevel(recordId);\n return useMemo(() => {\n if (!recordId) return NOT_ANSWERED_YET;\n if (asked.loading) return NOT_ANSWERED_YET;\n // A refusal is an ANSWER: the door said no, so this person holds nothing.\n if (asked.error) return whatYouMayDo(null, true);\n return whatYouMayDo(asked.data, true);\n }, [recordId, asked.loading, asked.error, asked.data]);\n}\n\n/**\n * The same question for a whole page of records, in ONE call — the door takes a\n * list precisely so a grid never makes one call per row.\n *\n * `enabled` is how a grid avoids asking at all in the ordinary case: when the\n * table level already admits editing, every row it returned is editable and\n * there is nothing a per-record answer could add.\n */\nexport function useRowRights(\n rowIds: Uuid[],\n enabled: boolean,\n): (rowId: Uuid) => WhatYouMayDo | null {\n const asked = useMyLevels(enabled ? rowIds : []);\n return useMemo(() => {\n if (!enabled) return () => null;\n if (asked.loading) return () => NOT_ANSWERED_YET;\n if (asked.error) return () => whatYouMayDo(null, true);\n const held = asked.data ?? {};\n return (rowId: Uuid) => whatYouMayDo((held[rowId] ?? null) as PermissionLevel | null, true);\n }, [enabled, asked.loading, asked.error, asked.data]);\n}\n","// src/rights.ts — @ai-matrx/records-ui\n//\n// THE ONE PLACE A LEVEL BECOMES A SCREEN.\n//\n// WHAT A PERSON HIT (independent verdict, sixth pass, 19-20 September). A\n// colleague who had been shared a table at viewer opened it, double-clicked a\n// cell, got a live editor, typed a value and pressed Enter — and only THEN was\n// told she may not write. \"The permission is right; the screen told her she\n// could.\" Measured against Airtable, Notion and Linear the verdict called it\n// out by name: \"None of these three products lets you start an action it\n// already knows it will reject.\"\n//\n// WHY THE SCREEN COULD NOT KNOW. The rights question was a PORT with two honest\n// answers and no third: `NO_RIGHTS` (every administering control absent, which\n// is useless for a host whose authority IS the store's) and\n// `storeDecidesRights` — `{admin: true, comment: true, write: true}` for every\n// non-kernel table, for everybody. That second one is the defect, written down:\n// it is the screen ASSUMING the answer and letting the door say no afterwards.\n//\n// WHAT REPLACES IT. The store already answers this, and the client now carries\n// it: `custom.read_records` returns the reader's level on the TABLE on every\n// row (so `Table.your_level` costs nothing), and `custom.my_levels` — the door\n// this lane added — answers the caller's level on any subject they name, one\n// call for a whole page. This file is the only place in the package that turns\n// one of those four words into what a screen may DRAW.\n//\n// THE LADDER IS THE STORE'S, NOT OURS: viewer < commenter < editor < admin, and\n// which rung each door requires is read from the doors themselves —\n// `custom.record_update` asserts `editor` on the record, `custom.field_declare`\n// asserts `admin` on the TABLE (\"the SHAPE of this table, which is an admin's\n// right and not an editor's\"), `custom.io_comment_write` admits a commenter.\n// Nothing here invents a rule; it mirrors the four assertions those doors make\n// and is wrong the moment they change, which is what the suite is for.\n//\n// ABSENT OR HONEST, NEVER DEAD. Every `false` here carries the sentence that\n// says why and what to do about it, so a control can be left out AND explained.\n// A screen that hid a control with nothing to say is the silent half of the\n// same defect.\n\nimport { atLeast, type PermissionLevel, type Table } from \"@ai-matrx/records\";\n\n/** The six things a person does to a record or a table, as the screens offer them. */\nexport type Capability = \"read\" | \"comment\" | \"write\" | \"remove\" | \"share\" | \"structure\";\n\nexport interface WhatYouMayDo {\n /** The word the store answered, or null when it answered nothing. */\n level: PermissionLevel | null;\n /**\n * Whether the store has ANSWERED yet. `false` is a third state and not a\n * refusal: a screen that drew \"you may not\" while the answer was in flight\n * would blink every control off on every reload, which is its own lie.\n */\n known: boolean;\n read: boolean;\n comment: boolean;\n write: boolean;\n remove: boolean;\n share: boolean;\n structure: boolean;\n /** Why this person may not do that, in one sentence naming the way in. */\n why: (what: Capability) => string;\n}\n\n/** What each rung of the ladder is called where a person reads it. */\nexport const LEVEL_WORD: Record<PermissionLevel, string> = {\n viewer: \"Viewer\",\n commenter: \"Commenter\",\n editor: \"Editor\",\n admin: \"Admin\",\n};\n\n/**\n * WHICH RUNG EACH DOOR ASKS FOR. Read off the doors themselves, in one place,\n * so a screen never re-decides it and the suite has one thing to check.\n */\nconst NEEDS: Record<Capability, PermissionLevel> = {\n read: \"viewer\",\n // custom.io_comment_write\n comment: \"commenter\",\n // custom.record_update / custom.record_write\n write: \"editor\",\n // custom.record_delete\n remove: \"editor\",\n // custom.share_grant — passing your access on is an administrator's right\n share: \"admin\",\n // custom.field_declare / field_update / field_retire / table settings\n structure: \"admin\",\n};\n\nconst NOT_YET =\n \"Still asking the store what you may do here. Nothing is offered until it has answered.\";\n\nconst NOTHING_AT_ALL =\n \"You have not been given this. Ask somebody who administers it to share it with you.\";\n\n/** The sentence for one refusal: what the level is, what it would have to be. */\nfunction sentenceFor(what: Capability, level: PermissionLevel | null): string {\n if (level === null) return NOTHING_AT_ALL;\n const need = LEVEL_WORD[NEEDS[what]];\n const have = LEVEL_WORD[level];\n const doing: Record<Capability, string> = {\n read: \"open this\",\n comment: \"leave a comment\",\n write: \"change anything here\",\n remove: \"delete this\",\n share: \"pass this on to somebody else\",\n structure: \"change the columns of this table\",\n };\n return `You are ${have} here, and it takes ${need} to ${doing[what]}. Ask somebody who is Admin on it to move you up.`;\n}\n\n/**\n * WHAT ONE LEVEL LETS A PERSON DO. `level` null and `known` true means the\n * store said \"nothing\" — a real answer. `known` false means it has not said.\n */\nexport function whatYouMayDo(level: PermissionLevel | null, known = true): WhatYouMayDo {\n const may = (what: Capability) => known && atLeast(level, NEEDS[what]);\n return {\n level: known ? level : null,\n known,\n read: may(\"read\"),\n comment: may(\"comment\"),\n write: may(\"write\"),\n remove: may(\"remove\"),\n share: may(\"share\"),\n structure: may(\"structure\"),\n why: (what) => (known ? sentenceFor(what, level) : NOT_YET),\n };\n}\n\n/** Nothing offered, because nothing is known yet. */\nexport const NOT_ANSWERED_YET: WhatYouMayDo = whatYouMayDo(null, false);\n\n/**\n * REC-27. The nine Tables the platform ships are not administered from a\n * person's screen whatever level they hold on them — so the structure controls\n * are absent for a kernel Table and say why, and everything else follows the\n * level as usual.\n */\nexport const KERNEL_REASON =\n \"This is one of the tables the platform ships, so its columns are not changed from a screen. \" +\n \"Make your own table to change columns.\";\n\nexport function whatYouMayDoWithTable(\n table: Table | null | undefined,\n level: PermissionLevel | null,\n known: boolean,\n): WhatYouMayDo {\n const base = whatYouMayDo(level, known);\n if (!table?.is_kernel) return base;\n return {\n ...base,\n structure: false,\n why: (what) => (what === \"structure\" ? KERNEL_REASON : base.why(what)),\n };\n}\n","// src/plainWords.ts — @ai-matrx/records-ui\n//\n// THE ONE FORMATTER EVERY REFUSAL PASSES THROUGH.\n//\n// WHAT A PERSON READ (independent verdict, sixth pass, 19-20 September):\n//\n// \"You do not have access to this table, so custom.applicable_fields has\n// nothing to show you.\"\n// \"config.via names a relation Field of this same table, by its key… The\n// store's code for this was 23514.\"\n//\n// The verdict's third measured gap against Airtable, Notion and Linear was\n// exactly this: \"The machinery still shows through… two column types answer\n// with a contract row id and a SQL error number. Airtable, Notion and Linear\n// never show a person an internal name.\"\n//\n// WHY FILTERING THE HINT WAS NOT ENOUGH. The previous pass filtered the store's\n// HINT — the half written for whoever fixes the caller — and printed the\n// MESSAGE verbatim, because the store writes good messages. Most of them are\n// good. But the store's access refusals are built by `format()` from the DOOR'S\n// OWN NAME (`assert_client_may_change`: \"…so % may not write to it\", with the\n// door name substituted in), so the machine identity is IN the sentence a\n// person reads and no amount of hint-filtering reaches it.\n//\n// SO: ONE function, here, and every screen in this package renders what it\n// returns and nothing else. It does three things and refuses to do a fourth:\n//\n// 1. It KEEPS the store's own words wherever they are a person's words. The\n// store writes the best sentences in this feature (\"Being a member of the\n// organization is not by itself permission to rewrite somebody else's\n// row\") and this package does not rewrite them.\n// 2. It DROPS the clause that carries machine identity, by SHAPE — a\n// schema-qualified object, a document path, a contract row id, a SQLSTATE,\n// a uuid, a bare snake_case token. Dropped, never deleted: it joins the\n// SQLSTATE on the notice for whoever has to debug it.\n// 3. It ADDS a REMEDY — the sentence that says what to do now — keyed off the\n// store's own refusal code, because a refusal with nothing to do about it\n// is a dead end with an explanation.\n//\n// 4. It does NOT invent a diagnosis. When every clause of a message is\n// machine identity there is nothing honest left to say about the specifics,\n// so it says what happened in general terms and offers the remedy. Making\n// something up would be worse than the identifier it replaced.\n//\n// The guard for all of this is `demo/plain-words.test.tsx` plus the sweep in\n// `demo/honest.test.tsx`, which reads the RENDERED text of the real screens and\n// fails on any of the shapes below. A formatter nobody is forced through is a\n// formatter somebody bypasses next week.\n\nimport type { RecordsError } from \"@ai-matrx/records\";\n\n/**\n * MACHINE IDENTITY, BY SHAPE — never by a list of the sentences we happen to\n * have seen, because the next refusal is one nobody has read yet.\n *\n * `FLD-11:` / `REC-29:` / `AGT-7:` a contract row id\n * `custom.field_declare` a schema-qualified database object\n * `config.via` / `data.fields` a path inside a stored document\n * `retention_days` a document key, snake_case\n * `8f2c1b0a-…` a uuid\n * `23514` / `PT409` a SQLSTATE\n */\nexport const MACHINE_IDENTITY: RegExp[] = [\n /\\b[A-Z]{2,4}-\\d{1,3}\\b/,\n /\\b(?:custom|platform|iam|history|public|auth|campaign_watch)\\.[a-z_]+/,\n /\\b(?:config|data|document|spec|patch)\\.[a-z_]+/,\n /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/i,\n /\\b[a-z][a-z0-9]*(?:_[a-z0-9]+)+\\b/,\n // Five characters of digits and capitals, at least one a digit — so `23514`\n // and `PT409` match and an emphatic `NEVER` does not.\n /\\b(?=[0-9A-Z]{5}\\b)(?=[0-9A-Z]*\\d)[0-9A-Z]{5}\\b/,\n];\n\n/** Whether any shape above appears in this text. */\nexport function isMachineIdentity(text: string): boolean {\n return MACHINE_IDENTITY.some((shape) => shape.test(text));\n}\n\n/**\n * Every fragment of `text` that a person should never have been shown. Used by\n * the suite to say WHAT it found rather than only that it found something.\n */\nexport function machineIdentityIn(text: string): string[] {\n const found: string[] = [];\n for (const shape of MACHINE_IDENTITY) {\n const all = new RegExp(shape.source, shape.flags.includes(\"g\") ? shape.flags : `${shape.flags}g`);\n for (const hit of text.matchAll(all)) if (hit[0]) found.push(hit[0]);\n }\n return [...new Set(found)];\n}\n\n/** What the notice is called. The store's code, in the words of what went wrong. */\nconst TITLE: Record<string, string> = {\n stale_write: \"Someone else wrote first\",\n door: \"You do not have access to this\",\n door_absent: \"That is not built yet\",\n refused_by_rule: \"That value was not accepted\",\n invalid_argument: \"That was not accepted\",\n not_found: \"Not there any more\",\n missing_reference: \"That points at something that is not there\",\n already_exists: \"That already exists\",\n not_supported: \"That cannot be done here\",\n store_limit: \"This has got as big as it can\",\n store_not_served: \"This organization does not keep its data here\",\n internal: \"Something went wrong at our end\",\n};\n\n/**\n * WHAT TO DO NOW. One sentence per refusal code, and it is the whole reason\n * this file exists rather than a regular expression in `Refusal.tsx`: a\n * sentence that names what went wrong and nothing to do about it is a dead end.\n */\nconst REMEDY: Record<string, string> = {\n stale_write:\n \"Look at what they wrote. Keep theirs, or try again and yours goes on top.\",\n door:\n \"Ask somebody who administers this to share it with you at the level you need.\",\n door_absent:\n \"There is nothing to do here yet. It is on our list, not yours.\",\n refused_by_rule: \"Change the value so it passes, then try again.\",\n invalid_argument: \"Change what you entered, then try again.\",\n not_found:\n \"It may have been deleted. Go back to the list and open it again from there.\",\n missing_reference: \"Pick something that is still there.\",\n already_exists: \"Use a different name.\",\n not_supported: \"There is another way to do this — ask, and we will point you at it.\",\n store_limit: \"Split it up, or ask us to raise the ceiling for your organization.\",\n store_not_served:\n \"An administrator of this organization turns the record store on from the data settings screen.\",\n internal:\n \"Nothing you did caused this. Try again, and tell us if it keeps happening.\",\n};\n\n/** The one shape every screen in this package renders a refusal from. */\nexport interface PlainRefusal {\n /** The heading. Never the store's code. */\n title: string;\n /**\n * What happened, in the store's own words where they are a person's words\n * and in ours where they are not. Never empty.\n */\n sentence: string;\n /** What to do now. Never empty. */\n remedy: string;\n /**\n * Everything a person should not read, kept for whoever has to debug it: the\n * SQLSTATE, the hint written for a caller, and any clause dropped above.\n * Rendered out of sight (the notice's `title` attribute and a screen-reader-\n * only line), never deleted.\n */\n forEngineers: string;\n}\n\n/**\n * A sentence with its machine clauses taken out — or null when nothing honest\n * is left. Clauses are split on the joins the store's own `format()` templates\n * use (\"…, so custom.x may not write to it\", \"… — FLD-11: …\").\n */\nfunction withoutMachineClauses(sentence: string): { kept: string | null; dropped: string[] } {\n const dropped: string[] = [];\n const clauses = sentence\n .split(/(?:,\\s+so\\s+|\\s+—\\s+|\\s+--\\s+|\\s*\\|\\s*)/)\n .map((clause) => clause.trim())\n .filter((clause) => clause !== \"\");\n const kept = clauses.filter((clause) => {\n if (!isMachineIdentity(clause)) return true;\n dropped.push(clause);\n return false;\n });\n if (kept.length === 0) return { kept: null, dropped };\n let joined = kept.join(\". \").replace(/\\.\\.+/g, \".\").trim();\n if (!/[.!?]$/.test(joined)) joined = `${joined}.`;\n return { kept: joined, dropped };\n}\n\n/** Every sentence of a message, cleaned; the ones that cannot be cleaned are dropped. */\nfunction plainSentence(message: string): { kept: string | null; dropped: string[] } {\n const dropped: string[] = [];\n const kept: string[] = [];\n for (const raw of message.split(/(?<=[.!?])\\s+/)) {\n const sentence = raw.trim();\n if (sentence === \"\") continue;\n const cleaned = withoutMachineClauses(sentence);\n dropped.push(...cleaned.dropped);\n if (cleaned.kept) kept.push(cleaned.kept);\n }\n return { kept: kept.length === 0 ? null : kept.join(\" \"), dropped };\n}\n\n/**\n * THE FORMATTER. Every refusal a screen in this package shows goes through\n * here, and nothing in this package renders `error.message` directly.\n */\nexport function refusalForAPerson(error: RecordsError): PlainRefusal {\n const code = error.code ?? \"internal\";\n const message = plainSentence(String(error.message ?? \"\"));\n const hint = plainSentence(String(error.hint ?? \"\"));\n\n const title = TITLE[code] ?? \"The store refused this\";\n const remedy = REMEDY[code] ?? REMEDY[\"internal\"]!;\n\n // The store's sentence, then whatever of its hint is also a person's\n // sentence — \"Type the choices into the field panel, one per line\" is exactly\n // what somebody needs and is not machine identity.\n const said = [message.kept, hint.kept].filter(Boolean).join(\" \").trim();\n\n const forEngineers = [\n error.sqlstate ? `SQLSTATE ${error.sqlstate}.` : null,\n error.hint && hint.kept !== error.hint ? `Hint: ${error.hint}` : null,\n message.dropped.length > 0 || hint.dropped.length > 0\n ? `Dropped from the person's view: ${[...message.dropped, ...hint.dropped].join(\" | \")}`\n : null,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return {\n title,\n // Nothing invented. When every clause was machine identity the title says\n // what happened and the remedy says what to do; a made-up diagnosis would\n // be worse than the identifier it replaced.\n sentence: said === \"\" ? `${title}.` : said,\n remedy,\n forEngineers,\n };\n}\n\n/**\n * The same answer as one line, for a cell or a field where a block would break\n * the layout. Still one sentence and one remedy — never the sentence alone,\n * because half of this formatter's job is the thing to do next.\n */\nexport function refusalLineForAPerson(error: RecordsError): string {\n const plain = refusalForAPerson(error);\n return `${plain.sentence} ${plain.remedy}`.trim();\n}\n","// src/names.ts — @ai-matrx/records-ui\n//\n// WHAT A PERSON READS, NEVER WHAT THE MACHINE STORES.\n//\n// Measured on the real screens (independent verdict, 19 September): a table row\n// read `Saved views · 9 fields · records_ui_view`, a relation cell read a bare\n// `8f2c…` identifier, a header read `stage` because the Field's label was\n// blank, and the type word on a column tooltip read `long_text`. Airtable,\n// Notion and Linear never show a person an internal name; the verdict called\n// this one of the three things a first-time user feels within a minute.\n//\n// So every place this package prints something a person reads goes through one\n// of these three functions. They are deliberately dumb: they choose the best\n// human string that IS AVAILABLE and, when none is, say what the thing is\n// rather than printing the token. No screen in this package formats a name of\n// its own any more.\n\nimport type { Field, ReadRow, RecordDocument, Table } from \"@ai-matrx/records\";\n\n/**\n * A token (`records_ui_view`, `long_text`, `v78_widget2`) as a person would\n * write it. Used ONLY as a last resort, when the thing carries no label at all\n * — a raw token on a screen is the defect, and a humanised token is the least\n * bad honest answer, because it still names the same thing.\n */\nexport function humanize(token: string): string {\n const words = token\n .replace(/[_\\-.]+/g, \" \")\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .trim();\n if (words === \"\") return token;\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\n/** The name of one Field, as a header, a form label or a peek's term. */\nexport function fieldName(field: Field): string {\n const label = (field.label ?? \"\").trim();\n if (label !== \"\") return label;\n const name = (field.name ?? \"\").trim();\n if (name !== \"\") return name;\n return humanize(field.key);\n}\n\n/** The name of one Table, as a card, a heading or a breadcrumb. */\nexport function tableName(table: Table): string {\n const name = (table.name ?? \"\").trim();\n if (name !== \"\") return name;\n const singular = (table.label_singular ?? \"\").trim();\n if (singular !== \"\") return singular;\n return humanize(table.slug ?? \"\");\n}\n\n/**\n * The name of one RECORD, for a chip, a card, a relation cell or a peek title.\n *\n * `titleKey` is the Table's own `title_field` when the caller knows the Table —\n * that is the store's answer to \"what makes this record a chip\" (REC-2) — and\n * the conventional keys are tried after it. A record with nothing readable is\n * NOT shown as a truncated uuid: it says it has no name yet, because \"8f2c1b0a\"\n * tells a person nothing and looks like a bug.\n */\nexport function recordName(\n document: RecordDocument | undefined,\n titleKey?: string | null,\n fallback = \"Untitled\",\n): string {\n const data = (document ?? {}) as Record<string, unknown>;\n const keys = [titleKey, \"title\", \"name\", \"label\", \"full_name\", \"subject\", \"summary\"].filter(\n (key): key is string => typeof key === \"string\" && key !== \"\",\n );\n for (const key of keys) {\n const value = data[key];\n if (typeof value === \"string\" && value.trim() !== \"\") return value.trim();\n if (typeof value === \"number\") return String(value);\n }\n return fallback;\n}\n\n/** The same question for a row the read door returned. */\nexport function rowName(row: ReadRow | undefined, titleKey?: string | null, fallback = \"Untitled\"): string {\n return recordName(row?.document, titleKey, fallback);\n}\n\n/**\n * WHAT A RELATION CHIP SAYS WHEN THE RECORD IT POINTS AT IS NOT YOURS.\n *\n * A relation joins two records in two tables, and holding one end says nothing\n * about the other: a Job shared with you may point at a Client nobody shared.\n * The chip then has three possible answers and only one of them is honest —\n * the target's TITLE is a leak, a bare id is a bug with a hex number in it, and\n * a permanent \"Loading…\" is a lie that never resolves.\n *\n * This is the SAME sentence `platform.relation_withheld_label()` answers on the\n * database, word for word, so a person reads one wording whether the screen or\n * the store worked it out. Changing it changes both (RELATION-DECLARE,\n * 2026-09-20).\n */\nexport const WITHHELD_RECORD_LABEL = \"A record you have not been given access to\";\n","\"use client\";\n\n// src/PersonPicker.tsx — @ai-matrx/records-ui · FLD-11 (`member`)\n//\n// PICKING A PERSON MEANS PICKING A PERSON.\n//\n// What it replaced, measured on the real screen (independent verdict, 19\n// September): the \"Owner\" field — which the settings panel itself calls a\n// Person field — offered \"Comments Home\", \"Saved views Home\" and \"V78 Home\".\n// Those are not people. They are the Home records this package writes into the\n// kernel Person Table so that its own Tables have somewhere to live (REC-1),\n// and the generic relation picker was listing the Table's contents, which is\n// exactly right for a relation and exactly wrong for a person.\n//\n// SO A PERSON FIELD ASKS A DIFFERENT QUESTION. The list is the ORGANIZATION'S\n// MEMBERS — who those are is the platform's answer and not the record store's,\n// so it arrives through the `members` port on the host, the same way saved\n// views and file uploads do. The record store has no door onto organization\n// membership and this package does not invent one.\n//\n// WHAT IS STORED IS STILL A RECORD ID, because a member field is a relation to\n// the kernel Person Table and the store's foreign key is real. So picking a\n// member resolves that member to their Person record — by the `user_id` the\n// record carries — and writes one when the organization has not got one yet.\n// That write is the same `record_write` everything else in this package uses;\n// there is no second storage path, and a Home (a Person record with no\n// `user_id`) is never offered and never picked.\n//\n// Unbound port: the control is ABSENT with its reason, never a dead box and\n// never a list of the wrong things.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { Field, ReadRow, RecordsError, Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport type { RecordsClient } from \"@ai-matrx/records/core\";\nimport {\n BasicInput,\n Button,\n Popover,\n PopoverContent,\n PopoverTrigger,\n ScrollArea,\n cn,\n} from \"@ai-matrx/design-system\";\n\nimport { RecordChip } from \"./editors\";\nimport { useRecordsUi, type OrganizationMember } from \"./host\";\nimport { NO_MEMBERS_REASON } from \"./host\";\nimport { fieldName } from \"./names\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface PersonPickerProps {\n field: Field;\n value: unknown;\n onChange: (value: unknown) => void;\n disabled?: boolean | undefined;\n id?: string | undefined;\n className?: string | undefined;\n}\n\n/** A Person record in the kernel Table, as this picker needs to read it. */\ninterface PersonRecord {\n id: Uuid;\n userId: string | null;\n name: string;\n}\n\nfunction personFromRow(row: ReadRow): PersonRecord {\n const data = (row.document ?? {}) as Record<string, unknown>;\n const userId = data[\"user_id\"];\n return {\n id: row.id,\n userId: typeof userId === \"string\" && userId !== \"\" ? userId : null,\n name: String(data[\"full_name\"] ?? data[\"name\"] ?? data[\"email\"] ?? \"\").trim(),\n };\n}\n\n/** The member's own name, as a person reads it. Never a uuid. */\nexport function memberName(member: OrganizationMember): string {\n const display = (member.name ?? \"\").trim();\n if (display !== \"\") return display;\n const email = (member.email ?? \"\").trim();\n if (email !== \"\") return email;\n return \"A member with no name set\";\n}\n\n/**\n * Find (or write) the kernel Person record for one member. Exported because\n * an agent filling a person field server-side needs exactly the same answer,\n * and two implementations of \"which record is this person\" is two answers.\n */\nexport async function personRecordForMember(\n client: RecordsClient,\n personTableId: Uuid,\n people: PersonRecord[],\n member: OrganizationMember,\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const held = people.find((p) => p.userId === member.userId);\n if (held) return { ok: true, data: held.id };\n const written = await client.recordWrite({\n table_id: personTableId,\n data: {\n user_id: member.userId,\n full_name: memberName(member),\n ...(member.email ? { email: member.email } : {}),\n },\n });\n return written;\n}\n\nexport function PersonPicker({ field, value, onChange, disabled, id, className }: PersonPickerProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const [members, setMembers] = useState<OrganizationMember[] | null>(null);\n const [people, setPeople] = useState<PersonRecord[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [search, setSearch] = useState(\"\");\n const [open, setOpen] = useState(false);\n const [busy, setBusy] = useState(false);\n\n const membersPort = host.members;\n const personTable = field.relation_target;\n\n const picked = useMemo<string[]>(\n () => (Array.isArray(value) ? value.map(String) : value === null || value === undefined ? [] : [String(value)]),\n [value],\n );\n\n const load = useCallback(async () => {\n if (!membersPort) return;\n const [roster, records] = await Promise.all([\n membersPort(),\n personTable ? client.list({ table_id: personTable, limit: 500 }) : Promise.resolve(null),\n ]);\n setMembers(roster);\n if (records && !records.ok) {\n setError(refusalLineForAPerson(records.error));\n return;\n }\n setPeople(records ? records.data.rows.map(personFromRow).filter((p) => p.userId !== null) : []);\n }, [membersPort, client, personTable]);\n\n useEffect(() => {\n if (!open) return;\n void load();\n }, [open, load]);\n\n // The names of the records that are already picked, whether or not the list\n // has been opened — a chip that read `8f2c1b0a` is the defect this closes.\n useEffect(() => {\n if (picked.length === 0 || !personTable || people.length > 0) return;\n let cancelled = false;\n void client.list({ table_id: personTable, limit: 500 }).then((result) => {\n if (cancelled || !result.ok) return;\n setPeople(result.data.rows.map(personFromRow).filter((p) => p.userId !== null));\n });\n return () => {\n cancelled = true;\n };\n }, [client, personTable, picked.length, people.length]);\n\n if (!membersPort) {\n // ABSENT AND HONEST. A person question with nobody to offer is not a box\n // that silently does nothing — it names the port that fills it.\n return <p className={cn(\"text-xs text-muted-foreground\", className)}>{NO_MEMBERS_REASON}</p>;\n }\n\n if (!personTable) {\n return (\n <p className={cn(\"text-xs text-muted-foreground\", className)}>\n {fieldName(field)} is a person field, but it does not say which Table the people are\n records of yet, so there is nothing to pick from. A table admin sets its target in the field\n editor.\n </p>\n );\n }\n\n const nameOfRecord = (recordId: string) => {\n const person = people.find((p) => p.id === recordId);\n if (!person) return \"Loading…\";\n if (person.name !== \"\") return person.name;\n const member = (members ?? []).find((m) => m.userId === person.userId);\n return member ? memberName(member) : \"A member with no name set\";\n };\n\n const pick = async (member: OrganizationMember) => {\n setBusy(true);\n setError(null);\n const resolved = await personRecordForMember(client, personTable, people, member);\n setBusy(false);\n if (!resolved.ok) {\n setError(refusalLineForAPerson(resolved.error));\n return;\n }\n // Keep the newly written record so the chip can be named at once.\n if (!people.some((p) => p.id === resolved.data)) {\n setPeople((held) => [...held, { id: resolved.data, userId: member.userId, name: memberName(member) }]);\n }\n if (!field.multi) {\n onChange(picked[0] === resolved.data ? null : resolved.data);\n setOpen(false);\n return;\n }\n const next = new Set(picked);\n if (next.has(resolved.data)) next.delete(resolved.data);\n else next.add(resolved.data);\n onChange(next.size === 0 ? null : [...next]);\n };\n\n const drop = (recordId: string) => {\n const next = picked.filter((id) => id !== recordId);\n onChange(next.length === 0 ? null : field.multi ? next : (next[0] ?? null));\n };\n\n const visible = (members ?? []).filter((member) =>\n search.trim() === \"\" ? true : memberName(member).toLowerCase().includes(search.trim().toLowerCase()),\n );\n const pickedUserIds = new Set(\n picked.map((recordId) => people.find((p) => p.id === recordId)?.userId).filter(Boolean),\n );\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-1\", className)}>\n {picked.map((recordId) => (\n <RecordChip\n key={recordId}\n title={nameOfRecord(recordId)}\n {...(disabled ? {} : { onRemove: () => drop(recordId) })}\n />\n ))}\n {disabled ? null : (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n id={id}\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n aria-label={`Pick a person for ${fieldName(field)}`}\n >\n {picked.length === 0 ? \"Pick a person\" : \"Change\"}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-64 p-1\" align=\"start\">\n <BasicInput\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search people\"\n className=\"mb-1 h-7 text-xs\"\n />\n {error ? <p className=\"p-2 text-xs text-destructive\">{error}</p> : null}\n {members === null ? <p className=\"p-2 text-xs text-muted-foreground\">Reading the members…</p> : null}\n <ScrollArea className=\"max-h-56\">\n <ul>\n {visible.map((member) => (\n <li key={member.userId}>\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => void pick(member)}\n className={cn(\n \"w-full truncate rounded px-2 py-1 text-left text-xs hover:bg-muted\",\n pickedUserIds.has(member.userId) ? \"bg-accent text-accent-foreground\" : \"\",\n )}\n >\n {/* A name and an email with nothing between them read as\n one run-on string (verdict, 19 September). They are two\n facts, so they are drawn as two. */}\n <span>{memberName(member)}</span>\n {member.email && member.email !== memberName(member) ? (\n <span className=\"ml-1.5 opacity-60\">· {member.email}</span>\n ) : null}\n </button>\n </li>\n ))}\n </ul>\n {members !== null && visible.length === 0 ? (\n <p className=\"p-2 text-xs text-muted-foreground\">\n {members.length === 0\n ? \"This organization has no other members yet, so there is nobody to assign.\"\n : \"Nobody in this organization matches.\"}\n </p>\n ) : null}\n </ScrollArea>\n </PopoverContent>\n </Popover>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/editors.tsx — @ai-matrx/records-ui\n//\n// ONE EDITOR PER PARITY TYPE, and every one of them is a design-system\n// primitive. There is no bespoke input in this package and no per-feature\n// editor anywhere in the platform: a Field decides which of these is drawn,\n// from what the STORE stores about it (behaviour + modifiers + format + unit +\n// relation target), never from the value it happens to hold.\n//\n// FLD-9: a Formula is worked out by the system. Its editor is not a disabled\n// text box — it is the value with the sentence the store itself would say if\n// you tried to type into it.\n\nimport { useEffect, useState, type ReactNode } from \"react\";\nimport type { Field, RecordDocument, StoredRecord, Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport {\n BasicInput,\n BasicTextarea,\n Badge,\n Button,\n Checkbox,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n cn,\n} from \"@ai-matrx/design-system\";\nimport { editorKindFor } from \"./parity\";\nimport { fieldName, recordName } from \"./names\";\nimport { RelationPicker } from \"./RelationPicker\";\nimport { PersonPicker } from \"./PersonPicker\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface FieldEditorControlProps {\n field: Field;\n value: unknown;\n onChange: (value: unknown) => void;\n disabled?: boolean | undefined;\n id?: string | undefined;\n}\n\n/** The label row every editor shares: one line, the label, the unit, the required mark. */\nexport function FieldLabel({ field, htmlFor, children }: { field: Field; htmlFor: string; children?: ReactNode }) {\n return (\n <div className=\"flex items-baseline gap-1.5\">\n <Label htmlFor={htmlFor} className=\"text-xs font-medium\">\n {fieldName(field)}\n </Label>\n {field.required ? <span className=\"text-xs text-destructive\">required</span> : null}\n {field.unit ? <span className=\"text-xs text-muted-foreground\">{field.unit}</span> : null}\n {children}\n </div>\n );\n}\n\nexport function FieldControl({ field, value, onChange, disabled, id }: FieldEditorControlProps) {\n const kind = editorKindFor(field);\n const inputId = id ?? `field-${field.key}`;\n\n switch (kind) {\n case \"formula\":\n case \"lookup\":\n case \"rollup\":\n return (\n <div id={inputId} className=\"rounded border border-dashed px-2 py-1.5 text-xs text-muted-foreground\">\n {/* The store's own sentence for typing into a computed field. */}\n {value === null || value === undefined ? \"—\" : String(value)}\n <span className=\"ml-2 italic\">\n {fieldName(field)} is worked out by the system, so it cannot be typed in\n </span>\n </div>\n );\n case \"json\":\n return <JsonControl field={field} value={value} onChange={onChange} disabled={disabled} id={inputId} />;\n case \"long_text\":\n return (\n <BasicTextarea\n id={inputId}\n rows={3}\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : e.target.value)}\n />\n );\n case \"number\":\n case \"currency\":\n case \"percent\":\n return (\n <BasicInput\n id={inputId}\n type=\"number\"\n inputMode=\"decimal\"\n className=\"tabular-nums\"\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : Number(e.target.value))}\n />\n );\n case \"datetime\":\n return (\n <BasicInput\n id={inputId}\n type={field.format === \"datetime\" ? \"datetime-local\" : \"date\"}\n value={value === null || value === undefined ? \"\" : String(value).slice(0, field.format === \"datetime\" ? 16 : 10)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : e.target.value)}\n />\n );\n case \"email\":\n case \"phone\":\n case \"url\":\n return (\n <BasicInput\n id={inputId}\n type={kind === \"email\" ? \"email\" : kind === \"phone\" ? \"tel\" : \"url\"}\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : e.target.value)}\n />\n );\n case \"select\":\n case \"multi_select\":\n return <OptionControl field={field} value={value} onChange={onChange} disabled={disabled} id={inputId} />;\n case \"member\":\n // A person field asks who is in the organization, never what is in a\n // Table — see PersonPicker's header for the screen that made this split.\n return <PersonPicker field={field} value={value} onChange={onChange} disabled={disabled} id={inputId} />;\n case \"relation\":\n case \"attachment\":\n return <RelationPicker field={field} value={value} onChange={onChange} disabled={disabled} id={inputId} />;\n default:\n if (typeof value === \"boolean\" || field.config?.[\"kind\"] === \"boolean\") {\n return (\n <Checkbox\n id={inputId}\n checked={value === true}\n disabled={disabled}\n onCheckedChange={(next) => onChange(next === true)}\n />\n );\n }\n return (\n <BasicInput\n id={inputId}\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : e.target.value)}\n />\n );\n }\n}\n\n/**\n * A document-shaped value, edited as the text it is. It is parsed on every\n * keystroke and the PARSE FAILURE IS SHOWN — a box that silently handed the\n * store unparseable text and let it answer `22P02 invalid input syntax` is a\n * refusal the person could have been spared half a second earlier.\n */\nfunction JsonControl({ field, value, onChange, disabled, id }: FieldEditorControlProps) {\n const initial = value === null || value === undefined ? \"\" : typeof value === \"string\" ? value : JSON.stringify(value, null, 2);\n const [text, setText] = useState(initial);\n const [broken, setBroken] = useState<string | null>(null);\n return (\n <div className=\"flex flex-col gap-1\">\n <BasicTextarea\n id={id}\n rows={4}\n className=\"font-mono text-[11px]\"\n value={text}\n disabled={disabled}\n onChange={(e) => {\n const next = e.target.value;\n setText(next);\n if (next.trim() === \"\") {\n setBroken(null);\n onChange(null);\n return;\n }\n try {\n onChange(JSON.parse(next));\n setBroken(null);\n } catch (thrown) {\n setBroken(thrown instanceof Error ? thrown.message : String(thrown));\n }\n }}\n />\n {broken ? (\n <p className=\"text-xs text-destructive\">\n {fieldName(field)} is not readable as structured data yet: {broken}\n </p>\n ) : null}\n </div>\n );\n}\n\n/**\n * FLD-5 / FLD-6. A list field stores the ID OF AN OPTION RECORD, because every\n * pick-list is already a Table. The options are read through the store's own\n * `custom.field_options` door, which resolves the options Table from the\n * Field's config — this component never has to know which Table that is.\n */\nfunction OptionControl({ field, value, onChange, disabled, id }: FieldEditorControlProps) {\n const client = useRecordsClient();\n const [options, setOptions] = useState<StoredRecord[] | null>(null);\n const [refusal, setRefusal] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void client.fieldOptions({ field_id: field.id }).then((result) => {\n if (cancelled) return;\n if (result.ok) setOptions(result.data ?? []);\n else setRefusal(refusalLineForAPerson(result.error));\n });\n return () => {\n cancelled = true;\n };\n }, [client, field.id]);\n\n // EVERY STATE CARRIES THE CELL'S OWN ID. A cell that identified itself only\n // when it happened to be a text box is a cell nobody can tell apart from the\n // developer window that used to open instead of it.\n if (refusal) return <p id={id} className=\"text-xs text-destructive\">{refusal}</p>;\n if (!options) return <p id={id} className=\"text-xs text-muted-foreground\">Reading this field's choices…</p>;\n if (options.length === 0) {\n // Two different facts, and a person acts on them differently: a choice\n // field whose Table is empty, and a choice field that names no Table at\n // all. One blank control for both is the silent failure.\n return (\n <p id={id} className=\"text-xs text-muted-foreground\">\n {field.options_table_id\n ? `${fieldName(field)} takes its choices from a Table that has no records yet — add the choices there and they appear here.`\n : `${fieldName(field)} does not name the Table its choices come from yet, so there is nothing to choose. A table admin sets it in the field editor.`}\n </p>\n );\n }\n\n const titleOf = (option: StoredRecord) =>\n recordName(option.data as RecordDocument | undefined, null, \"Unnamed choice\");\n\n if (field.multi) {\n const picked = new Set((Array.isArray(value) ? value : []).map(String));\n return (\n <div id={id} className=\"flex flex-wrap gap-1\">\n {options.map((option) => (\n <Button\n key={option.id}\n type=\"button\"\n size=\"sm\"\n variant={picked.has(option.id) ? \"default\" : \"outline\"}\n disabled={disabled}\n onClick={() => {\n const next = new Set(picked);\n if (next.has(option.id)) next.delete(option.id);\n else next.add(option.id);\n onChange(next.size === 0 ? null : [...next]);\n }}\n >\n {titleOf(option)}\n </Button>\n ))}\n </div>\n );\n }\n\n return (\n <Select\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled ?? false}\n onValueChange={(next) => onChange(next === \"\" ? null : next)}\n >\n <SelectTrigger id={id} size=\"sm\">\n <SelectValue placeholder=\"Choose\" />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.id} value={option.id}>\n {titleOf(option)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\n/** The chip a picked record shows as — REC-2's \"a record is a chip\" in one place. */\nexport function RecordChip({\n title,\n onRemove,\n className,\n}: {\n title: string;\n onRemove?: (() => void) | undefined;\n className?: string | undefined;\n}) {\n return (\n <Badge variant=\"secondary\" className={cn(\"gap-1 text-[11px]\", className)}>\n {title}\n {onRemove ? (\n <button type=\"button\" onClick={onRemove} aria-label={`Remove ${title}`} className=\"opacity-60 hover:opacity-100\">\n ×\n </button>\n ) : null}\n </Badge>\n );\n}\n\nexport type { Uuid };\n","// src/parity.ts — @ai-matrx/records-ui\n//\n// FLD-11, the parity floor. A Field stores a BEHAVIOUR (one of five) plus\n// modifiers, unit and format; a person picked one of THIRTEEN parity types in\n// the UI. This resolves the second from the first, using the same facts the\n// store's own `custom.parity_field_types()` describes — which is generated into\n// `@ai-matrx/records` and imported here, never retyped.\n//\n// Nothing in this file decides policy. It decides which editor to draw.\n\nimport { KERNEL_TABLES, PARITY_FIELD_TYPES, type Field, type ParityFieldType } from \"@ai-matrx/records\";\nimport { humanize } from \"./names\";\nimport { fieldTypeChoice } from \"./fieldTypes\";\n\n/** The kernel ids come from the store's own kernel rows, never from a literal here. */\nconst kernelId = (name: string): string =>\n KERNEL_TABLES.find((t) => t.name === name)?.id ?? \"\";\nconst KERNEL_FILE_TABLE = kernelId(\"File\");\nconst KERNEL_PERSON_TABLE = kernelId(\"Person\");\n\nexport const PARITY_LABEL: Record<ParityFieldType, string> = {\n attachment: \"Attachment\",\n currency: \"Currency\",\n datetime: \"Date\",\n email: \"Email\",\n formula: \"Formula\",\n lookup: \"Lookup\",\n member: \"Person\",\n multi_select: \"Multi-select\",\n percent: \"Percent\",\n phone: \"Phone\",\n rollup: \"Rollup\",\n select: \"Select\",\n url: \"Link\",\n};\n\n/** The \"made of\" sentence the store itself publishes, for the field editor's help text. */\nexport const PARITY_MADE_OF: Record<string, string> = Object.fromEntries(\n PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of]),\n);\n\n/** Plain text and plain number are behaviours with no parity type of their own. */\nexport type EditorKind =\n | ParityFieldType\n | \"relation\"\n | \"text\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"json\"\n | \"long_text\";\n\n/**\n * Which editor one Field wants. Reads the Field's own declaration only — the\n * behaviour, the modifiers, the format, the relation target and the config —\n * because those are what the store stores, and a screen that guessed from a\n * value would draw a different editor for an empty record.\n */\nexport function editorKindFor(field: Field): EditorKind {\n const format = (field.format ?? \"\").toLowerCase();\n const config = field.config ?? {};\n switch (field.type) {\n case \"text\":\n if (format === \"email\") return \"email\";\n if (format === \"phone\") return \"phone\";\n if (format === \"url\") return \"url\";\n // FLD-1: a document-shaped value is a `text` behaviour carrying a format.\n // It gets its own editor because a person typing JSON into a one-line box\n // and getting `22P02` back is the failure this resolves ahead of time.\n if (format === \"json\" || config[\"json\"] === true) return \"json\";\n if (format === \"long\" || config[\"multiline\"] === true) return \"long_text\";\n return \"text\";\n case \"range\": {\n const kind = String(config[\"kind\"] ?? \"number\");\n if (kind === \"date\" || kind === \"datetime\") return \"datetime\";\n // THE FORMAT, AND ONLY THE FORMAT. This used to read\n // `format === \"currency\" || (field.unit ?? \"\").length > 1`, and a unit is\n // not a currency: a quantity in `units` was drawn as money, which is how\n // three of something rendered as \"units3\" (verdict, 19 September). The\n // store's own `custom.parity_type` asks the same question the same way —\n // a currency is a range whose FORMAT is currency and which has a unit.\n if (format === \"currency\") return \"currency\";\n if (format === \"percent\" || field.unit === \"%\") return \"percent\";\n return \"number\";\n }\n case \"list\":\n return field.multi ? \"multi_select\" : \"select\";\n case \"relation\":\n return relationEditor(field);\n case \"formula\": {\n const via = config[\"via\"];\n if (via && config[\"agg\"]) return \"rollup\";\n if (via) return \"lookup\";\n return \"formula\";\n }\n default:\n return \"text\";\n }\n}\n\n/**\n * REC-31 / FLD-11: a relation is an `attachment` when it points at the kernel\n * File Table and a `member` when it points at the kernel Person Table. Every\n * other relation is drawn by the generic picker, which is what `\"relation\"`\n * means here — the one primitive SCR-N-2 says must exist.\n */\nfunction relationEditor(field: Field): EditorKind {\n const parity = String(field.config?.[\"parity\"] ?? \"\");\n if (parity === \"attachment\" || parity === \"member\") return parity;\n if (field.relation_target === KERNEL_FILE_TABLE) return \"attachment\";\n if (field.relation_target === KERNEL_PERSON_TABLE) return \"member\";\n return \"relation\" as EditorKind;\n}\n\n/**\n * The type word a person sees in a header or a settings row — and it is the\n * SAME word the field panel offers, read from `FIELD_TYPE_CHOICES`, so a column\n * added as \"Money\" is never described anywhere else as \"Currency\".\n */\nexport function fieldTypeLabel(field: Field): string {\n const kind = editorKindFor(field);\n const known = fieldTypeChoice(kind)?.label;\n if (known) return field.multi && kind !== \"multi_select\" ? `${known} (many)` : known;\n const plain: Record<string, string> = {\n boolean: \"Yes / no\",\n date: \"Date\",\n json: \"Structured data\",\n relation: \"Link to a record\",\n };\n // Never a raw token on a screen: an editor kind this table has not named is\n // still written the way a person writes it.\n return plain[kind] ?? humanize(kind);\n}\n","// src/fieldTypes.ts — @ai-matrx/records-ui\n//\n// THE SIXTEEN THINGS A COLUMN CAN HOLD, IN THE WORDS A PERSON USES.\n//\n// The store publishes thirteen parity types and, for each, a sentence about what\n// it is MADE OF — \"REC-31: a File record reached through a relation, target the\n// kernel `File` Table\", \"FLD-9: a declared computation, on read or on write,\n// evaluated by custom.rule_eval\", \"config.via names the relation field,\n// config.pick the Value on the far side\". Those sentences are true and they are\n// for us. The 19 September verdict found them printed at the person choosing a\n// column type, alongside contract row ids, and called it what it is: machine\n// identity where a person is looking.\n//\n// So this file holds the OTHER sentence — what the type is FOR — and the field\n// panel shows that one. The store's own `made_of` stays where it belongs, in\n// `PARITY_MADE_OF`, for an engineer reading the package.\n//\n// The LIST itself is still the store's: `PARITY_FIELD_TYPES` is generated from\n// `custom.parity_field_types()`, and `assertEveryParityTypeIsExplained` (run by\n// the suite) fails the moment the store ships a fourteenth and nobody wrote a\n// sentence for it. A type with no explanation would otherwise appear with a\n// blank line under it, which is the silent version of the same defect.\n\nimport { PARITY_FIELD_TYPES, type ParityFieldType } from \"@ai-matrx/records\";\n\n/** The three behaviours that carry no parity type of their own. */\nexport type PlainFieldType = \"text\" | \"long_text\" | \"number\";\n\n/** What a person picks in the panel: one of the thirteen, or one of the three. */\nexport type PickableFieldType = ParityFieldType | PlainFieldType;\n\nexport interface FieldTypeChoice {\n id: PickableFieldType;\n /** The word on the menu. */\n label: string;\n /** One line, under the word, saying what it is FOR. Never what it is made of. */\n explanation: string;\n /** The heading it sits under, so sixteen choices read as four short lists. */\n group: \"Words\" | \"Numbers and dates\" | \"Choices and people\" | \"Worked out\";\n}\n\nexport const FIELD_TYPE_CHOICES: FieldTypeChoice[] = [\n { id: \"text\", group: \"Words\", label: \"Text\", explanation: \"A short line of writing — a name, a reference, a title.\" },\n { id: \"long_text\", group: \"Words\", label: \"Long text\", explanation: \"Several lines — a description, notes, an address.\" },\n { id: \"email\", group: \"Words\", label: \"Email address\", explanation: \"An email address, checked as you type and ready to write to.\" },\n { id: \"phone\", group: \"Words\", label: \"Phone number\", explanation: \"A phone number, checked as you type.\" },\n { id: \"url\", group: \"Words\", label: \"Link\", explanation: \"A web address that opens in a new tab when you click it.\" },\n\n { id: \"number\", group: \"Numbers and dates\", label: \"Number\", explanation: \"A plain number you can total up and sort by.\" },\n { id: \"currency\", group: \"Numbers and dates\", label: \"Money\", explanation: \"An amount of money, shown with its currency wherever it appears.\" },\n { id: \"percent\", group: \"Numbers and dates\", label: \"Percentage\", explanation: \"A number out of a hundred, kept between 0 and 100.\" },\n { id: \"datetime\", group: \"Numbers and dates\", label: \"Date\", explanation: \"A day, or a day and a time. Dates are what the calendar view reads.\" },\n\n { id: \"select\", group: \"Choices and people\", label: \"Choice\", explanation: \"One answer from a list you write here. Choices are what the board view groups by.\" },\n { id: \"multi_select\", group: \"Choices and people\", label: \"Several choices\", explanation: \"Any number of answers from a list you write here.\" },\n { id: \"member\", group: \"Choices and people\", label: \"Person\", explanation: \"Somebody in this organization, picked from the people who are in it.\" },\n { id: \"attachment\", group: \"Choices and people\", label: \"File\", explanation: \"A file or a picture kept with the record.\" },\n\n { id: \"lookup\", group: \"Worked out\", label: \"Borrowed value\", explanation: \"A value read from a record this one points at, kept in step with it.\" },\n { id: \"rollup\", group: \"Worked out\", label: \"Total of linked records\", explanation: \"A count or a total worked out from the records this one points at.\" },\n { id: \"formula\", group: \"Worked out\", label: \"Worked out from other columns\", explanation: \"A value this record works out for itself from its own other columns.\" },\n];\n\nexport const FIELD_TYPE_GROUPS: FieldTypeChoice[\"group\"][] = [\n \"Words\",\n \"Numbers and dates\",\n \"Choices and people\",\n \"Worked out\",\n];\n\nconst BY_ID = new Map<string, FieldTypeChoice>(FIELD_TYPE_CHOICES.map((c) => [c.id, c]));\n\nexport function fieldTypeChoice(id: string): FieldTypeChoice | undefined {\n return BY_ID.get(id);\n}\n\n/** The three that are a plain behaviour rather than one of the thirteen. */\nexport function isPlainFieldType(id: string): id is PlainFieldType {\n return id === \"text\" || id === \"long_text\" || id === \"number\";\n}\n\n/**\n * THE GUARD THIS FILE NEEDS, because the list it explains is generated.\n *\n * Returns the parity types the store ships that nothing here explains. The\n * suite asserts it is empty; a fourteenth type would otherwise reach the menu\n * with a blank line under it and nobody would notice until a person did.\n */\nexport function parityTypesWithNoExplanation(): string[] {\n return PARITY_FIELD_TYPES.map((row) => row.parity_type).filter((type) => !BY_ID.has(type));\n}\n","\"use client\";\n\n// src/RelationPicker.tsx — @ai-matrx/records-ui · SCR-N-2\n//\n// THE ONE GENERIC RELATION PICKER. Before it, every relation-shaped field in\n// the product had a type-specific picker (image, file, url, scope) and a plain\n// `relation` field was not editable at all.\n//\n// It reads the target Table's records through the read door, shows each one as\n// its own chip (REC-2: the title field is what makes a record a chip), and\n// respects `relation_max` by saying the number rather than silently dropping a\n// pick.\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { Field, ReadRow, Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport {\n BasicInput,\n Button,\n Popover,\n PopoverContent,\n PopoverTrigger,\n ScrollArea,\n cn,\n} from \"@ai-matrx/design-system\";\nimport { RecordChip } from \"./editors\";\nimport { WITHHELD_RECORD_LABEL, fieldName, rowName } from \"./names\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface RelationPickerProps {\n field: Field;\n value: unknown;\n onChange: (value: unknown) => void;\n disabled?: boolean | undefined;\n id?: string | undefined;\n className?: string | undefined;\n}\n\nexport function RelationPicker({ field, value, onChange, disabled, id, className }: RelationPickerProps) {\n const client = useRecordsClient();\n const [rows, setRows] = useState<ReadRow[] | null>(null);\n const [titleKey, setTitleKey] = useState<string | null>(null);\n // A picked record that is NOT in the target Table's visible page: resolved one\n // at a time through the read door, which is the only thing that can tell\n // \"shared with somebody else\" apart from \"further down the list\".\n const [elsewhere, setElsewhere] = useState<Record<string, string>>({});\n const [refusal, setRefusal] = useState<string | null>(null);\n const [search, setSearch] = useState(\"\");\n const [open, setOpen] = useState(false);\n\n const picked = useMemo<string[]>(\n () => (Array.isArray(value) ? value.map(String) : value === null || value === undefined ? [] : [String(value)]),\n [value],\n );\n\n // ── THE TARGET TABLE, ON MOUNT AND NOT ON OPEN (RELATION-DECLARE, 2026-09-20).\n // This used to wait for the popover, so every chip on every relation cell read\n // \"Loading…\" until somebody clicked Pick — a word that never resolved, on a\n // screen nobody was going to click. A chip is a NAME; it is read far more often\n // than it is changed, so what it needs is fetched when the cell is drawn.\n //\n // The Table comes with it, for its `title_field`. REC-2 says the title field is\n // what makes a record a chip, and this picker was ignoring it and trying\n // title/name/label instead — so a Table whose title field is `cname` drew\n // \"Untitled\" for every chip and every option in the list, and the picker was\n // unusable for exactly the tables a person builds themselves.\n useEffect(() => {\n const target = field.relation_target;\n if (!target) return;\n let cancelled = false;\n void client.list({ table_id: target as Uuid, limit: 200 }).then((result) => {\n if (cancelled) return;\n if (result.ok) setRows(result.data.rows);\n else setRefusal(refusalLineForAPerson(result.error));\n });\n void client.tableList().then((result) => {\n if (cancelled || !result.ok) return;\n setTitleKey(result.data.find((table) => table.id === target)?.title_field ?? null);\n });\n return () => {\n cancelled = true;\n };\n }, [client, field.relation_target]);\n\n // ── AND THE ONES THAT ARE NOT IN THAT PAGE.\n // A relation joins two records in two tables and holding one end says nothing\n // about the other: a Job shared with you may point at a Client nobody shared.\n // The read door answers exactly what this reader may see, so an id it does not\n // return is either further down a long list or not hers — and the two have\n // different sentences, so they are asked apart rather than guessed at. The\n // answer for a record she may not open is the same words the store itself gives\n // (`platform.relation_withheld_label()`): never the title, never a bare id, and\n // never a \"Loading…\" that resolves for nobody.\n useEffect(() => {\n if (!rows) return;\n const known = new Set(rows.map((row) => row.id));\n const missing = picked.filter((id) => !known.has(id) && elsewhere[id] === undefined);\n if (missing.length === 0) return;\n let cancelled = false;\n void Promise.all(\n missing.map(async (id) => {\n const result = await client.recordRead({ record_id: id as Uuid });\n return [id, result.ok ? rowName({ document: result.data.document } as ReadRow, titleKey) : WITHHELD_RECORD_LABEL] as const;\n }),\n ).then((pairs) => {\n if (cancelled) return;\n setElsewhere((current) => ({ ...current, ...Object.fromEntries(pairs) }));\n });\n return () => {\n cancelled = true;\n };\n }, [client, rows, picked, elsewhere, titleKey]);\n\n if (!field.relation_target) {\n // Absent, and honest about why: a relation with no declared target is a\n // Field the store has not finished, not a picker that \"has no options\".\n return (\n <p className=\"text-xs text-muted-foreground\">\n {fieldName(field)} points at records, but it does not say which Table yet, so there is nothing to pick\n from. A table admin sets its target in the field editor.\n </p>\n );\n }\n\n const byId = new Map((rows ?? []).map((row) => [row.id, row]));\n // A chip carries the record's NAME. Before `names.ts`, a relation whose\n // target had not loaded yet drew `8f2c1b0a` — a bare identifier, which the\n // verdict of 19 September counted among the three things a first-time user\n // feels within a minute. It now reads the Table's own title field (REC-2), and\n // a record that is not this reader's says so in the store's own words instead\n // of waiting forever.\n const titleOf = (recordId: string) => {\n const row = byId.get(recordId);\n if (row) return rowName(row, titleKey, \"Untitled\");\n const away = elsewhere[recordId];\n if (away !== undefined) return away;\n return \"Loading…\";\n };\n const full = field.multi && field.relation_max !== null && picked.length >= field.relation_max;\n\n const toggle = (recordId: string) => {\n if (!field.multi) {\n onChange(picked[0] === recordId ? null : recordId);\n setOpen(false);\n return;\n }\n const next = new Set(picked);\n if (next.has(recordId)) next.delete(recordId);\n else if (!full) next.add(recordId);\n onChange(next.size === 0 ? null : [...next]);\n };\n\n const visible = (rows ?? []).filter((row) =>\n search.trim() === \"\" ? true : titleOf(row.id).toLowerCase().includes(search.trim().toLowerCase()),\n );\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-1\", className)}>\n {picked.map((recordId) => (\n <RecordChip\n key={recordId}\n title={titleOf(recordId)}\n {...(disabled ? {} : { onRemove: () => toggle(recordId) })}\n />\n ))}\n {disabled ? null : (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button id={id} type=\"button\" size=\"sm\" variant=\"outline\" aria-label={`Pick for ${fieldName(field)}`}>\n {picked.length === 0 ? \"Pick\" : \"Change\"}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-64 p-1\" align=\"start\">\n <BasicInput\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search\"\n className=\"mb-1 h-7 text-xs\"\n />\n {refusal ? <p className=\"p-2 text-xs text-destructive\">{refusal}</p> : null}\n {!rows && !refusal ? <p className=\"p-2 text-xs text-muted-foreground\">Reading…</p> : null}\n {full ? (\n <p className=\"p-2 text-xs text-muted-foreground\">\n {fieldName(field)} can point at {field.relation_max} at most. Remove one to add another.\n </p>\n ) : null}\n <ScrollArea className=\"max-h-56\">\n <ul>\n {visible.map((row) => (\n <li key={row.id}>\n <button\n type=\"button\"\n onClick={() => toggle(row.id)}\n className={cn(\n \"w-full truncate rounded px-2 py-1 text-left text-xs hover:bg-muted\",\n picked.includes(row.id) ? \"bg-accent text-accent-foreground\" : \"\",\n )}\n >\n {titleOf(row.id)}\n </button>\n </li>\n ))}\n </ul>\n {rows && visible.length === 0 ? (\n <p className=\"p-2 text-xs text-muted-foreground\">Nothing in that table matches.</p>\n ) : null}\n </ScrollArea>\n </PopoverContent>\n </Popover>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/gridEditing.tsx — @ai-matrx/records-ui · SCR-1 / REC-9\n//\n// EDITING A RECORD WHERE IT IS SHOWN.\n//\n// Until this file existed, the grid was a read-only window: double-clicking a\n// cell opened a panel of raw JSON with no control, no Save and no Delete, and\n// the only way to write anything was the whole \"New record\" form. The\n// independent verdict of 19 September put it first of three: \"In Airtable you\n// click a cell and type. Here a cell opens a read-only window of programming\n// text… Every other gap is downstream of this one.\"\n//\n// WHAT THIS IS, AND WHAT IT DELIBERATELY IS NOT\n// ---------------------------------------------\n// `@ai-matrx/design-system`'s data table HAS an inline editor\n// (`EditableTableCell`) and this package does not use it here, for one reason\n// that is not taste: that editor speaks six value shapes (string, number,\n// boolean, select, tags, date) and collects edits into a draft map that a\n// floating Save pill persists. A Field in this store is one of THIRTEEN parity\n// types — a relation, a person, a file, a multi-choice whose options are the\n// records of another Table, a json document, a formula that cannot be typed\n// into at all — and every one of them already has exactly one editor in this\n// package (`FieldControl`, itself built from design-system primitives). Two\n// editing models on one screen is the fork the inventory law forbids, so the\n// cell hosts the ONE editor a Field already has, and the write goes through the\n// ONE write door with the version the person started from.\n//\n// THE CONCURRENCY STORY, WHICH IS THE WHOLE POINT OF REC-9\n// -------------------------------------------------------\n// The read door answers documents, never versions. So the FIRST time a person\n// edits a given record in this session, the version is read for that one record\n// (`custom.io_revisions`) and remembered. Every save from then on carries it,\n// and the store — not this screen — decides whether somebody else got there\n// first. When it did, the store raises `PT409` with the other person's value in\n// the detail, and the cell shows THAT: their value, beside the value being\n// written, with a Retry that re-reads the version and writes again, and a\n// \"Keep theirs\" that drops the edit. Nothing is silently overwritten and\n// nothing is silently lost.\n//\n// OPTIMISTIC, BUT NEVER DISHONEST: the typed value is shown the instant it is\n// committed, and it is REMOVED again the moment the store refuses. A cell that\n// kept showing a value the store rejected is the lie this package exists to\n// prevent.\n//\n// WHERE THE TYPED VALUE LIVES, AND WHY IT MOVED (independent verdict, fifth\n// pass, 19 September): \"when we tabbed along a row, the first five values saved\n// and the last four were silently dropped; typing a phone number and pressing\n// Enter left the editor open and wrote nothing, with no message anywhere.\"\n//\n// The draft used to be `useState` INSIDE the open cell. That makes the typed\n// value a property of a component which this screen re-renders constantly and\n// for reasons that have nothing to do with the person typing: every accepted\n// write calls `reload()`, the reloaded page rebuilds `rows`, the columns are\n// rebuilt from them, and the data table rebuilds its cells. A cell that\n// remounts mid-edit comes back with `draft` re-initialised from the STORED\n// value — so the commit that followed wrote what was already there, which the\n// screen then correctly treated as \"nothing changed\" and dropped in silence.\n// The faster you tabbed, the more reloads landed inside your own editing, which\n// is exactly why it was the LAST four and not the first.\n//\n// So the draft lives HERE, in the editing session, beside the address of the\n// cell that is open — one value, owned by the thing that also owns which cell\n// is open and which version it started from. A re-render cannot lose it,\n// because a re-render does not touch it. `commit(move)` takes no value at all:\n// there is exactly one typed value and exactly one place it can be read from,\n// so there is no second copy to be stale.\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type FocusEvent } from \"react\";\nimport type { Field, ReadRow, RecordsError, Uuid } from \"@ai-matrx/records\";\nimport type { WriteConflict } from \"@ai-matrx/records\";\nimport { asWriteConflict, type RecordsClient } from \"@ai-matrx/records/core\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport { Button, cn } from \"@ai-matrx/design-system\";\n\nimport { FieldControl } from \"./editors\";\nimport { RefusalLine } from \"./Refusal\";\nimport { editorKindFor } from \"./parity\";\nimport { fieldName } from \"./names\";\nimport { RecordValue } from \"./values\";\n\n/** Which cell is open. A grid opens exactly one at a time, like every other grid. */\nexport interface CellAddress {\n rowId: Uuid;\n key: string;\n}\n\n/** What one cell is doing right now, so nothing about it is guessed by a caller. */\nexport type CellState = \"clean\" | \"saving\" | \"refused\";\n\nexport interface CellRefusal {\n error: RecordsError;\n /** Present when the store said `PT409`: the other person's value, from the store. */\n conflict: WriteConflict | null;\n /** The value that was being written, so Retry can write it again. */\n attempted: unknown;\n}\n\n/**\n * FLD-9. A computed Field is not editable and never will be — the store works\n * it out. Saying so here, once, keeps every caller from re-deciding it.\n */\nexport function fieldIsEditable(field: Field): boolean {\n const kind = editorKindFor(field);\n return kind !== \"formula\" && kind !== \"lookup\" && kind !== \"rollup\";\n}\n\nexport interface GridEditing {\n /** The value to DRAW for one cell — the optimistic one when there is one. */\n valueFor: (row: ReadRow, field: Field) => unknown;\n editing: CellAddress | null;\n /** What has been typed into the open cell. Owned here, never by the cell. */\n draft: unknown;\n /** The open cell's editor reports every keystroke to the session. */\n type: (value: unknown) => void;\n stateOf: (rowId: Uuid, key: string) => CellState;\n refusalOf: (rowId: Uuid, key: string) => CellRefusal | null;\n begin: (address: CellAddress) => void;\n cancel: () => void;\n /**\n * Commit the open cell — whatever is in `draft`. `move` opens the\n * next/previous editable cell after it. It takes NO value: a caller that\n * passed one would be a second copy of the typed value, which is the defect\n * this file's header describes.\n */\n commit: (move?: \"next\" | \"previous\" | null) => void;\n /** Write the attempted value again, after re-reading the version. */\n retry: (rowId: Uuid, key: string) => void;\n /** Drop the edit and show what the other person wrote. */\n keepTheirs: (rowId: Uuid, key: string) => void;\n /** Soft delete, through the store's own door. Answers the store's refusal, or null. */\n remove: (rowId: Uuid) => Promise<RecordsError | null>;\n /** Write an empty record and open its first editable cell. */\n addRecord: () => Promise<RecordsError | null>;\n /** The last refusal from a delete or an add, for the grid to print. */\n rowError: RecordsError | null;\n clearRowError: () => void;\n busy: boolean;\n}\n\ninterface Options {\n tableId: Uuid;\n fields: Field[];\n rows: ReadRow[];\n /** Re-read the page once the store has accepted something. */\n reload: () => void;\n /** May this person write records at all? A read-only grid opens no editor. */\n canWrite: boolean;\n /**\n * MAY THIS PERSON WRITE *THIS* ROW — asked before an editor is opened, never\n * after it has been typed into.\n *\n * A level on the TABLE is not the answer for a row: the sixth-pass verdict\n * found a record shared with a colleague at Editor inside a table she held at\n * Viewer, and the grid labelled the row \"viewer\" while the store let her\n * write to it. Unbound, every row follows the table, which is what the\n * ordinary case is.\n */\n mayWriteRow?: ((rowId: Uuid) => boolean) | undefined;\n}\n\n/**\n * THE VERSION THE PERSON STARTED FROM, read once per record per session.\n *\n * Not read for the page: a list of two hundred records would be two hundred\n * extra door calls for a person who is going to edit one cell. Not guessed\n * either — `null` means \"we never read one\", and the save then carries no\n * expected version and is the store's ordinary last-writer-wins write, exactly\n * as the store defines it.\n */\nasync function versionOf(\n client: RecordsClient,\n cache: Map<string, number>,\n inFlight: Map<string, Promise<number | null>>,\n recordId: Uuid,\n): Promise<number | null> {\n const held = cache.get(recordId);\n if (held !== undefined) return held;\n // ONE READ PER RECORD, AND IT CAN NEVER PUT BACK AN OLDER VERSION.\n //\n // Opening a cell asks for the version, and tabbing on asks again for the next\n // cell — the same record, both before either answer is back, so the cache was\n // empty for both and two reads went out. The write between them then stored\n // the store's NEW version, and whichever read landed last overwrote it with\n // the old one. The next cell of that row was written with a version the store\n // had already moved past, and a person tabbing through their own row was\n // refused for a conflict with themselves. Measured 2026-09-20.\n //\n // So: callers share one read per record, and a read only ever raises what is\n // held. A version is a high-water mark, never a replacement.\n const already = inFlight.get(recordId);\n if (already) return already;\n const reading = (async () => {\n const answered = await client.revisions({ record_id: recordId });\n if (!answered.ok) return null;\n const newest = answered.data.reduce<number | null>(\n (best, row) => (best === null || row.version > best ? row.version : best),\n null,\n );\n if (newest !== null) rememberVersion(cache, recordId, newest);\n return cache.get(recordId) ?? newest;\n })();\n inFlight.set(recordId, reading);\n try {\n return await reading;\n } finally {\n inFlight.delete(recordId);\n }\n}\n\n/** A version only ever goes up. See `versionOf`. */\nfunction rememberVersion(cache: Map<string, number>, recordId: Uuid, version: number): void {\n const held = cache.get(recordId);\n if (held === undefined || version > held) cache.set(recordId, version);\n}\n\nexport function useGridEditing({ tableId, fields, rows, reload, canWrite, mayWriteRow }: Options): GridEditing {\n const client = useRecordsClient();\n const [editing, setEditing] = useState<CellAddress | null>(null);\n // THE TYPED VALUE, and what the open cell started from — one copy of each,\n // here, where no re-render of a cell can reach them. See the file header.\n //\n // AND THE TYPED VALUE IS READ FROM A REF, NOT FROM STATE — the second half of\n // the same lesson, and it cost a suite run per column to learn. Moving the\n // draft out of the cell stopped a re-render from RESETTING it; it did not\n // stop a commit from reading a STALE COPY of it. `commit` closed over `draft`\n // and the open cell's key handler closed over `commit`, so a Tab that arrived\n // before the grid had re-rendered with the new draft committed the value from\n // before the keystroke — `sameValue` then said \"nothing changed\" and dropped\n // it in silence. Exactly one column of a tabbed row, a different one each\n // time, which is what made it look like the store rather than the screen.\n //\n // There is ONE typed value and ONE place to read it, and that place cannot be\n // captured stale by a closure.\n const [draft, setDraft] = useState<unknown>(null);\n const typed = useRef<unknown>(null);\n const startedFrom = useRef<unknown>(null);\n const type = useCallback((value: unknown) => {\n typed.current = value;\n setDraft(value);\n }, []);\n const [optimistic, setOptimistic] = useState<Record<string, unknown>>({});\n const [saving, setSaving] = useState<Record<string, true>>({});\n const [refusals, setRefusals] = useState<Record<string, CellRefusal>>({});\n const [rowError, setRowError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n const versions = useRef(new Map<string, number>());\n /** One version read per record in flight at a time — see `versionOf`. */\n const versionReads = useRef(new Map<string, Promise<number | null>>());\n // ONE WRITE AT A TIME PER RECORD. Tabbing across a row commits each cell the\n // instant the next one opens, so two writes of the SAME record were in flight\n // together and the second carried the version the first had already moved:\n // the store answered PT409 and a person tabbing through their own row was\n // shown a conflict with themselves. Measured 2026-09-19 in the headless walk.\n // The store was right both times; the screen was firing them in parallel.\n const queues = useRef(new Map<string, Promise<void>>());\n\n const editable = useMemo(() => fields.filter(fieldIsEditable), [fields]);\n const order = useMemo(() => editable.map((f) => f.key), [editable]);\n const rowIds = useMemo(() => rows.map((r) => r.id), [rows]);\n\n const cellKey = (rowId: Uuid, key: string) => `${rowId}::${key}`;\n\n const valueFor = useCallback(\n (row: ReadRow, field: Field) => {\n const held = optimistic[cellKey(row.id, field.key)];\n return held === undefined ? row.document?.[field.key] : held;\n },\n [optimistic],\n );\n\n const stateOf = useCallback(\n (rowId: Uuid, key: string): CellState => {\n const id = cellKey(rowId, key);\n if (saving[id]) return \"saving\";\n if (refusals[id]) return \"refused\";\n return \"clean\";\n },\n [saving, refusals],\n );\n\n const refusalOf = useCallback(\n (rowId: Uuid, key: string) => refusals[cellKey(rowId, key)] ?? null,\n [refusals],\n );\n\n /** The value a cell is showing right now — the optimistic one when there is one. */\n const shownValue = useCallback(\n (rowId: Uuid, key: string) => {\n const held = optimistic[cellKey(rowId, key)];\n if (held !== undefined) return held;\n return rows.find((r) => r.id === rowId)?.document?.[key];\n },\n [optimistic, rows],\n );\n\n /** The one question, asked in one place: may this person write THIS row? */\n const writable = useCallback(\n (rowId: Uuid) => (canWrite ? (mayWriteRow ? mayWriteRow(rowId) : true) : false),\n [canWrite, mayWriteRow],\n );\n\n const begin = useCallback(\n (address: CellAddress) => {\n // NOTHING IS OFFERED THAT THE DOOR WILL REFUSE. An editor that opened\n // here and was refused on Enter is the defect this lane closes; the cell\n // that called this never drew the affordance in the first place, and this\n // is the second lock on the same door.\n if (!writable(address.rowId)) return;\n // Re-opening the cell that is already open must not throw away what has\n // been typed into it: a double-click is two `begin`s, and the second one\n // arrives after the first has opened the editor.\n if (editing && editing.rowId === address.rowId && editing.key === address.key) return;\n const current = shownValue(address.rowId, address.key);\n startedFrom.current = current;\n typed.current = current;\n setDraft(current);\n setEditing(address);\n // The version this edit starts from, read once for this record.\n void versionOf(client, versions.current, versionReads.current, address.rowId);\n },\n [writable, client, editing, shownValue],\n );\n\n const cancel = useCallback(() => {\n setEditing(null);\n setDraft(null);\n typed.current = null;\n startedFrom.current = null;\n }, []);\n\n /** The write itself. `writeCell` below is what callers use; it queues these. */\n const writeCellNow = useCallback(\n async (rowId: Uuid, key: string, value: unknown) => {\n const id = cellKey(rowId, key);\n setOptimistic((held) => ({ ...held, [id]: value }));\n setSaving((held) => ({ ...held, [id]: true }));\n setRefusals((held) => {\n if (!held[id]) return held;\n const next = { ...held };\n delete next[id];\n return next;\n });\n\n // A THROW IS A REFUSAL A PERSON HAS TO SEE. `recordUpdate` never throws\n // for a refusal — it answers one — but the transport under it can, and\n // when it did, this function's promise rejected, the `saving` marker was\n // never cleared, the optimistic value stayed on screen, and the typed\n // value was gone with nothing anywhere saying so. That is precisely \"one\n // column of a tabbed row saved as nothing\", and it is the silent failure\n // this package exists to refuse. It is now the same refusal any other is.\n let written: Awaited<ReturnType<RecordsClient[\"recordUpdate\"]>>;\n try {\n const version = await versionOf(client, versions.current, versionReads.current, rowId);\n written = await client.recordUpdate({\n record_id: rowId,\n patch: { [key]: value },\n ...(version === null ? {} : { expectedVersion: version }),\n });\n } catch (thrown) {\n written = {\n ok: false,\n error: {\n code: \"internal\",\n message: \"This did not reach the store.\",\n hint: thrown instanceof Error ? thrown.message : String(thrown),\n },\n };\n }\n\n setSaving((held) => {\n const next = { ...held };\n delete next[id];\n return next;\n });\n\n if (written.ok) {\n // The store's own new version, so the NEXT edit of this record carries it.\n rememberVersion(versions.current, rowId, written.data);\n reload();\n return;\n }\n\n // Refused: the optimistic value comes straight back off the screen, and\n // the store's own sentence goes on it.\n setOptimistic((held) => {\n const next = { ...held };\n delete next[id];\n return next;\n });\n // A stale write means the version we hold is wrong; forget it so the\n // retry reads the current one rather than repeating the same refusal.\n if (written.error.code === \"stale_write\") versions.current.delete(rowId);\n setRefusals((held) => ({\n ...held,\n [id]: {\n error: written.error,\n conflict: asWriteConflict(written.error, rowId),\n attempted: value,\n },\n }));\n },\n [client, reload],\n );\n\n /** One write of one Field of one record, with whatever version we hold. */\n const writeCell = useCallback(\n (rowId: Uuid, key: string, value: unknown): Promise<void> => {\n // Queued behind whatever is already in flight for THIS record; two\n // different records still write in parallel.\n const behind = queues.current.get(rowId) ?? Promise.resolve();\n const next = behind.then(() => writeCellNow(rowId, key, value));\n queues.current.set(\n rowId,\n next.then(\n () => undefined,\n () => undefined,\n ),\n );\n return next;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, reload],\n );\n\n const commit = useCallback(\n (move: \"next\" | \"previous\" | null = null) => {\n const open = editing;\n if (!open) return;\n // The ref, never the state: see the note beside `typed` above.\n const value = typed.current;\n // Compared against WHAT THIS EDIT STARTED FROM, not against a fresh read\n // of `rows`: a reload landing mid-edit moves `rows` under the comparison,\n // and \"the stored value already equals this\" then silently swallows a\n // real edit. The one fact that decides it is the one taken when the cell\n // opened.\n if (!sameValue(startedFrom.current, value)) void writeCell(open.rowId, open.key, value);\n\n if (!move) {\n setEditing(null);\n setDraft(null);\n typed.current = null;\n startedFrom.current = null;\n return;\n }\n const next = step(open, order, rowIds, move, writable);\n if (!next) {\n setEditing(null);\n setDraft(null);\n typed.current = null;\n startedFrom.current = null;\n return;\n }\n // The NEXT cell's own starting value, taken before anything this commit\n // wrote can come back — so tabbing on is exactly like opening it by hand.\n const starting = shownValue(next.rowId, next.key);\n startedFrom.current = starting;\n typed.current = starting;\n setDraft(starting);\n setEditing(next);\n void versionOf(client, versions.current, versionReads.current, next.rowId);\n },\n [editing, writeCell, order, rowIds, client, shownValue, writable],\n );\n\n const retry = useCallback(\n (rowId: Uuid, key: string) => {\n const held = refusals[cellKey(rowId, key)];\n if (!held) return;\n void writeCell(rowId, key, held.attempted);\n },\n [refusals, writeCell],\n );\n\n const keepTheirs = useCallback(\n (rowId: Uuid, key: string) => {\n const id = cellKey(rowId, key);\n versions.current.delete(rowId);\n setRefusals((held) => {\n const next = { ...held };\n delete next[id];\n return next;\n });\n setOptimistic((held) => {\n const next = { ...held };\n delete next[id];\n return next;\n });\n reload();\n },\n [reload],\n );\n\n const remove = useCallback(\n async (rowId: Uuid) => {\n setBusy(true);\n setRowError(null);\n const done = await client.recordDelete({ record_id: rowId });\n setBusy(false);\n if (done.ok) {\n versions.current.delete(rowId);\n reload();\n return null;\n }\n setRowError(done.error);\n return done.error;\n },\n [client, reload],\n );\n\n const addRecord = useCallback(async () => {\n setBusy(true);\n setRowError(null);\n // AIRTABLE'S GESTURE: a new row appears and you type into it. The store\n // decides whether an empty record is allowed — a Table with a required\n // Field refuses, in its own words, and the grid offers the whole form.\n const written = await client.recordWrite({ table_id: tableId, data: {} });\n setBusy(false);\n if (!written.ok) {\n setRowError(written.error);\n return written.error;\n }\n reload();\n const first = order[0];\n if (first) {\n // A brand-new record is empty, so the first cell starts from nothing —\n // set through the same two pieces of state `begin` sets, never by moving\n // the address on its own and leaving a stale draft behind it.\n startedFrom.current = undefined;\n typed.current = undefined;\n setDraft(undefined);\n setEditing({ rowId: written.data, key: first });\n }\n return null;\n }, [client, tableId, reload, order]);\n\n return {\n valueFor,\n editing,\n draft,\n type,\n stateOf,\n refusalOf,\n begin,\n cancel,\n commit,\n retry,\n keepTheirs,\n remove,\n addRecord,\n rowError,\n clearRowError: () => setRowError(null),\n busy,\n };\n}\n\n/**\n * Tab order: across the row, then on to the next row. Stops at the ends — and\n * WALKS PAST a row this person may not write, rather than opening an editor in\n * it that the door would refuse. Tab is the same promise a click is.\n */\nfunction step(\n from: CellAddress,\n order: string[],\n rowIds: Uuid[],\n move: \"next\" | \"previous\",\n writable: (rowId: Uuid) => boolean = () => true,\n): CellAddress | null {\n let at = from;\n // Bounded by the page: every cell of every row, once, and then it stops.\n for (let guard = 0; guard <= order.length * rowIds.length; guard += 1) {\n const column = order.indexOf(at.key);\n const row = rowIds.indexOf(at.rowId);\n if (column < 0 || row < 0) return null;\n const delta = move === \"next\" ? 1 : -1;\n let nextColumn = column + delta;\n let nextRow = row;\n if (nextColumn >= order.length) {\n nextColumn = 0;\n nextRow += 1;\n } else if (nextColumn < 0) {\n nextColumn = order.length - 1;\n nextRow -= 1;\n }\n const key = order[nextColumn];\n const rowId = rowIds[nextRow];\n if (key === undefined || rowId === undefined) return null;\n if (writable(rowId)) return { rowId, key };\n at = { rowId, key };\n }\n return null;\n}\n\nfunction sameValue(left: unknown, right: unknown): boolean {\n if (left === right) return true;\n if (left === null || left === undefined) return right === null || right === undefined || right === \"\";\n if (right === null || right === undefined) return left === \"\";\n if (typeof left === \"object\" || typeof right === \"object\") {\n try {\n return JSON.stringify(left) === JSON.stringify(right);\n } catch {\n return false;\n }\n }\n return false;\n}\n\n/**\n * ONE CELL. Read, until somebody asks to change it; then the Field's own\n * editor, in place, with the keys a person expects from a grid.\n *\n * `data-matrx-cell-control` is the data table's own opt-out from whole-row\n * click, so opening a cell never also opens the record panel behind it.\n */\nexport function GridCell({\n field,\n row,\n editing,\n canWrite,\n whyNot,\n}: {\n field: Field;\n row: ReadRow;\n editing: GridEditing;\n /** Whether this person may write THIS row. Asked before the cell is drawn. */\n canWrite: boolean;\n /**\n * Why not, when not — one sentence naming the level it would take and who can\n * give it. A cell that is simply not a control, with nothing to say about it,\n * is the silent half of the same defect this file closes.\n */\n whyNot?: string | undefined;\n}) {\n const open = editing.editing?.rowId === row.id && editing.editing.key === field.key;\n const value = editing.valueFor(row, field);\n const state = editing.stateOf(row.id, field.key);\n const refusal = editing.refusalOf(row.id, field.key);\n const editable = canWrite && fieldIsEditable(field);\n\n if (open) {\n return (\n <OpenCell\n field={field}\n draft={editing.draft}\n onType={editing.type}\n onCommit={(move) => editing.commit(move)}\n onCancel={editing.cancel}\n />\n );\n }\n\n /**\n * ONE GESTURE, THREE WAYS IN, AND NOTHING ELSE HAPPENS (independent verdict,\n * fifth pass, 19 September): \"only the Title column can be opened by\n * double-clicking; double-clicking any other cell opens a developer\n * inspector — a floating window showing the record's raw JSON, its machine\n * keys, a truncated id, and the headings DOCUMENT, LEVEL and HIDDEN.\"\n *\n * Two things did that, and both are closed. The data table's own row window\n * is switched OFF for this grid (`Grid.tsx`) — this package has a record\n * panel of its own and a second one beside it is the parallel layer the\n * platform forbids. And the cell now FILLS its cell and answers `dblclick`\n * itself: a double-click's second press used to land on bare table cell\n * after the first press had swapped the DOM under the pointer, and a bare\n * cell is a row click. A wide column (the Title) kept the pointer over the\n * editor and worked; every narrow one did not, which is exactly the shape\n * the verdict saw.\n */\n const openThisCell = (event: { preventDefault: () => void; stopPropagation: () => void }) => {\n event.preventDefault();\n event.stopPropagation();\n editing.begin({ rowId: row.id, key: field.key });\n };\n\n return (\n <span data-matrx-cell-control=\"\" className=\"flex w-full min-w-0 flex-col gap-0.5\">\n <span\n role={editable ? \"button\" : undefined}\n tabIndex={editable ? 0 : undefined}\n aria-label={editable ? `Edit ${fieldName(field)}` : undefined}\n title={\n editable\n ? `${fieldName(field)} — click or press Enter to edit`\n : fieldIsEditable(field)\n ? // NOT A DEAD CONTROL AND NOT A SILENT ONE: the cell is plain\n // text, and hovering it says exactly why, in the level's own\n // words. The editor was never offered, so nothing is refused\n // after it has been typed into.\n `${fieldName(field)} — ${whyNot ?? \"you cannot change this record\"}`\n : `${fieldName(field)} is worked out by the system, so it cannot be typed in`\n }\n className={cn(\n // `w-full` so the whole cell is the control. A gap beside it is bare\n // table cell, and a click there is a row click.\n \"block w-full min-w-0 truncate rounded px-1 py-0.5\",\n editable ? \"cursor-text hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" : \"\",\n state === \"saving\" ? \"opacity-60\" : \"\",\n state === \"refused\" ? \"ring-1 ring-destructive\" : \"\",\n )}\n onClick={editable ? openThisCell : undefined}\n // A double-click opens the SAME editor a single click and Enter open.\n // It is bound on every cell, editable or not, so the gesture can never\n // fall through to the row behind it.\n onDoubleClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (editable) editing.begin({ rowId: row.id, key: field.key });\n }}\n onKeyDown={\n editable\n ? (event) => {\n if (event.key === \"Enter\" || event.key === \"F2\") {\n event.preventDefault();\n editing.begin({ rowId: row.id, key: field.key });\n }\n }\n : undefined\n }\n >\n <RecordValue field={field} value={value} document={row.document} />\n </span>\n\n {state === \"saving\" ? <span className=\"px-1 text-[10px] text-muted-foreground\">Saving…</span> : null}\n\n {refusal ? (\n <span className=\"flex flex-col gap-0.5 rounded border border-destructive/40 p-1\">\n <RefusalLine error={refusal.error} />\n {refusal.conflict ? (\n <span className=\"text-[11px]\">\n {/* The other person's value, as the store sent it. */}\n Theirs: <strong>{formatTheirs(refusal.conflict, field.key)}</strong>\n </span>\n ) : null}\n <span className=\"flex gap-1\">\n <Button size=\"sm\" variant=\"outline\" onClick={() => editing.retry(row.id, field.key)}>\n Try again\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => editing.keepTheirs(row.id, field.key)}>\n Keep theirs\n </Button>\n </span>\n </span>\n ) : null}\n </span>\n );\n}\n\nfunction formatTheirs(conflict: WriteConflict, key: string): string {\n const theirs = conflict.contested_fields?.[key];\n if (theirs === null || theirs === undefined || theirs === \"\") return \"(empty)\";\n if (Array.isArray(theirs)) return `${theirs.length} of them`;\n return typeof theirs === \"object\" ? \"something this cell cannot show in a line\" : String(theirs);\n}\n\n/**\n * WHICH EDITORS CLOSE THEMSELVES ON BLUR, AND WHY THE OTHERS MUST NOT.\n *\n * A typed box (text, number, date, email, url, phone) is finished when you look\n * away, exactly as a spreadsheet is. A PICKER is not: a select, a relation\n * picker and a person picker all open a Radix popover, which is portalled OUT\n * of this cell, so \"focus left the cell\" fires the instant the list opens.\n * Committing there would save the old value and shut the list a person just\n * asked for. So pickers carry an explicit Save and Cancel, and the keys work on\n * both.\n */\nfunction closesOnBlur(field: Field): boolean {\n switch (editorKindFor(field)) {\n case \"select\":\n case \"multi_select\":\n case \"relation\":\n case \"member\":\n case \"attachment\":\n return false;\n default:\n return true;\n }\n}\n\n/**\n * WHICH EDITORS TAKE A NEWLINE. A long-text column and a json document are the\n * two a person puts more than one line into; everything else is one line by\n * construction, and binding a newline into it would be a key that does nothing.\n */\nfunction takesANewline(field: Field): boolean {\n const kind = editorKindFor(field);\n return kind === \"long_text\" || kind === \"json\";\n}\n\n/**\n * The open cell. Enter commits, Escape cancels, Tab commits and opens the next\n * one — the three keys every grid in the world binds, so nobody has to be told.\n *\n * AND A MULTI-LINE COLUMN BINDS THEM THE SAME WAY, which it did not. It used to\n * take Enter for a newline and commit only on Ctrl/Cmd+Enter — so the key every\n * person in the world presses to finish a cell did nothing visible in exactly\n * the columns whose values are longest, and the only way to save was a shortcut\n * printed in 10px under the box. Airtable is the bar and Airtable is\n * unambiguous: ENTER COMMITS, SHIFT+ENTER makes the newline, TAB commits and\n * moves on. Ctrl/Cmd+Enter still commits, because a hand that learned the old\n * one should not be punished for it.\n */\nfunction OpenCell({\n field,\n draft,\n onType,\n onCommit,\n onCancel,\n}: {\n field: Field;\n draft: unknown;\n onType: (value: unknown) => void;\n onCommit: (move: \"next\" | \"previous\" | null) => void;\n onCancel: () => void;\n}) {\n const multiline = takesANewline(field);\n const blurCommits = closesOnBlur(field);\n // ONE COMMIT PER OPENING. Tab moves focus, so the key handler AND the blur\n // handler both fired for the same cell: two writes of one value, the second\n // against the version the first had just moved, and the store — correctly —\n // answered PT409. A person tabbing through their own row was shown a\n // conflict with themselves. Measured 2026-09-19 in the headless walk.\n const done = useRef(false);\n const once = (run: () => void) => {\n if (done.current) return;\n done.current = true;\n run();\n };\n\n // FOCUS ON OPENING, AND ONLY ON OPENING. This used to be an inline `ref`\n // arrow, which React re-invokes on EVERY render — so every reload landing\n // mid-edit yanked the caret back. It now runs once, when this cell's editor\n // appears, which is the only moment a person expects their cursor to move.\n const host = useRef<HTMLSpanElement | null>(null);\n useEffect(() => {\n const control = host.current?.querySelector<HTMLElement>(\"input, textarea, [role='combobox'], button\");\n if (control && document.activeElement !== control) control.focus();\n // Once per opening: the open cell's identity is the Field it is editing.\n }, [field.id]);\n\n const blur = blurCommits\n ? {\n onBlur: (event: FocusEvent<HTMLSpanElement>) => {\n // Leaving the cell altogether commits, exactly as a spreadsheet does.\n // Moving between the editor's own parts does not.\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) return;\n once(() => onCommit(null));\n },\n }\n : {};\n\n return (\n <span\n ref={host}\n data-matrx-cell-control=\"\"\n className=\"flex w-full min-w-[10rem] flex-col gap-1\"\n onDoubleClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n once(onCancel);\n return;\n }\n if (event.key === \"Tab\") {\n event.preventDefault();\n event.stopPropagation();\n // THE TYPED VALUE IS NOT PASSED FROM HERE. It is already in the\n // editing session, put there by `onType` on the keystroke that typed\n // it, so a re-render between the keystroke and this press cannot lose\n // it — which is exactly what dropped four of nine values on\n // 19 September (see the file header).\n once(() => onCommit(event.shiftKey ? \"previous\" : \"next\"));\n return;\n }\n if (event.key === \"Enter\") {\n // Shift+Enter is the newline, and ONLY in a column that takes one.\n // Everywhere else Enter finishes the cell, exactly as it does in\n // every other grid a person has used.\n if (multiline && event.shiftKey && !event.metaKey && !event.ctrlKey) return;\n event.preventDefault();\n event.stopPropagation();\n once(() => onCommit(null));\n }\n }}\n {...blur}\n >\n <FieldControl field={field} value={draft} onChange={onType} id={`cell-${field.id}`} />\n {blurCommits ? (\n <span className=\"text-[10px] text-muted-foreground\">\n {multiline\n ? \"⏎ saves · ⇧⏎ new line · Esc cancels · Tab next\"\n : \"⏎ saves · Esc cancels · Tab next\"}\n </span>\n ) : (\n <span className=\"flex items-center gap-1\">\n <Button size=\"sm\" onClick={() => once(() => onCommit(null))}>\n Save\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => once(onCancel)}>\n Cancel\n </Button>\n </span>\n )}\n </span>\n );\n}\n","\"use client\";\n\n// src/Refusal.tsx — @ai-matrx/records-ui\n//\n// THE ONE PLACE A REFUSAL IS SHOWN. It renders what `plainWords.ts` returns and\n// NOTHING ELSE — no `error.message`, no `error.hint`, no `error.sqlstate` in a\n// place a person reads. That is deliberate and it is the whole guard: a\n// formatter every screen has to go through is a formatter nobody bypasses, and\n// this component is the only door onto the screen a refusal has.\n//\n// The history, so it is not undone by accident. The fifth pass found the store's\n// HINT — written for whoever fixes the caller — printed at the person (\"FLD-11:\n// a lookup and a rollup both travel along a relation. config.via names a\n// relation Field of this same table, by its key.\"). The pass after it filtered\n// the hint and left the MESSAGE verbatim, on the reasonable grounds that the\n// store writes good messages. The sixth pass then found the machine identity\n// inside the MESSAGE — the access refusals are built by `format()` from the\n// door's own name — and printed at the person again, from the other half.\n//\n// So neither half is trusted by shape of ORIGIN any more. Both go through one\n// filter that judges by the shape of the TEXT, and what it drops is kept for an\n// engineer on the notice and in a screen-reader-only line, never deleted.\n\nimport type { ReactNode } from \"react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Alert, AlertDescription, AlertTitle, cn } from \"@ai-matrx/design-system\";\n\nimport { isMachineIdentity, refusalForAPerson, refusalLineForAPerson } from \"./plainWords\";\n\n/**\n * Kept for callers outside this package that already ask the question. The\n * answer is `plainWords.ts`'s, so there is one shape list and not two.\n */\nexport function hintIsMachineIdentity(hint: string): boolean {\n return isMachineIdentity(hint);\n}\n\n/** The hint a PERSON should read, or null when it is written for an engineer. */\nexport function hintForAPerson(hint: string | null | undefined): string | null {\n const said = (hint ?? \"\").trim();\n if (said === \"\") return null;\n return isMachineIdentity(said) ? null : said;\n}\n\nexport function RefusalNotice({\n error,\n className,\n actions,\n}: {\n error: RecordsError;\n className?: string | undefined;\n actions?: ReactNode | undefined;\n}) {\n const plain = refusalForAPerson(error);\n return (\n <Alert\n variant=\"destructive\"\n className={cn(\"text-xs\", className)}\n {...(plain.forEngineers ? { title: plain.forEngineers } : {})}\n >\n <AlertTitle className=\"text-xs font-medium\">{plain.title}</AlertTitle>\n <AlertDescription className=\"space-y-1 text-xs\">\n <p>{plain.sentence}</p>\n {/* NEVER A DEAD END: what happened, and then what to do about it. */}\n <p className=\"opacity-80\">{plain.remedy}</p>\n {plain.forEngineers ? (\n <p className=\"sr-only\" {...(error.sqlstate ? { \"data-sqlstate\": error.sqlstate } : {})}>\n {plain.forEngineers}\n </p>\n ) : null}\n {actions}\n </AlertDescription>\n </Alert>\n );\n}\n\n/** A small inline one, for a cell or a field where a block would break the layout. */\nexport function RefusalLine({ error, className }: { error: RecordsError; className?: string | undefined }) {\n const plain = refusalForAPerson(error);\n return (\n <p className={cn(\"text-xs text-destructive\", className)} title={plain.forEngineers || undefined}>\n {refusalLineForAPerson(error)}\n </p>\n );\n}\n","\"use client\";\n\n// src/values.tsx — @ai-matrx/records-ui\n//\n// HOW A VALUE IS SHOWN, one function, used by the grid cell, the peek, the\n// custom-fields section and the form's read state alike. Per SCR it is never\n// per-feature: every surface that shows a Value in this platform shows it the\n// same way, because the way is a property of the Field, not of the screen.\n//\n// VAL-2: a blank is never unexplained. When the record's envelope says why a\n// value is missing, the reason is what is shown — \"never asked\" and \"refused\"\n// are different facts and a person acts on them differently.\n\nimport type { Field, RecordDocument, ValueEnvelope } from \"@ai-matrx/records\";\nimport { Badge, cn } from \"@ai-matrx/design-system\";\nimport { editorKindFor } from \"./parity\";\nimport { isId, useRecordLabels, type LabelLookup } from \"./labels\";\n\n/** The envelope for one key, when the document carries one. */\nexport function envelopeFor(document: RecordDocument | undefined, key: string): ValueEnvelope | undefined {\n const block = document?._values as Record<string, ValueEnvelope> | undefined;\n return block?.[key];\n}\n\nconst ABSENCE_WORDS: Record<string, string> = {\n \"never asked\": \"never asked\",\n none: \"none\",\n refused: \"refused\",\n conflicting: \"conflicting\",\n};\n\nexport function renderValue(field: Field, value: unknown, document?: RecordDocument, labels?: LabelLookup) {\n const envelope = envelopeFor(document, field.key);\n if (envelope?.absent) {\n return (\n <span className=\"text-xs italic text-muted-foreground\" title={`VAL-2: ${envelope.absent}`}>\n {ABSENCE_WORDS[String(envelope.absent)] ?? String(envelope.absent)}\n </span>\n );\n }\n if (value === null || value === undefined || value === \"\") {\n return <span className=\"text-muted-foreground\">—</span>;\n }\n\n const kind = editorKindFor(field);\n if (Array.isArray(value)) {\n return (\n <span className=\"flex flex-wrap gap-1\">\n {value.map((item, i) => (\n <Badge key={`${String(item)}-${i}`} variant=\"secondary\" className=\"text-[11px]\">\n {scalarText(field, item, labels)}\n </Badge>\n ))}\n </span>\n );\n }\n if (kind === \"url\" && typeof value === \"string\") {\n return (\n <a className=\"truncate text-primary underline-offset-2 hover:underline\" href={value} target=\"_blank\" rel=\"noreferrer\">\n {value}\n </a>\n );\n }\n if (kind === \"email\" && typeof value === \"string\") {\n return (\n <a className=\"truncate text-primary underline-offset-2 hover:underline\" href={`mailto:${value}`}>\n {value}\n </a>\n );\n }\n if (typeof value === \"boolean\") {\n return <span>{value ? \"Yes\" : \"No\"}</span>;\n }\n return <span className={cn(\"truncate\", kind === \"number\" || kind === \"currency\" || kind === \"percent\" ? \"tabular-nums\" : \"\")}>{scalarText(field, value, labels)}</span>;\n}\n\n/**\n * The text of one scalar, with the Field's UNIT and FORMAT applied — FLD-N-1\n * says both change the MEANING — and with an id resolved to the NAME of the\n * record it points at.\n *\n * `labels` is the resolver from `RecordLabelProvider`. Without it, an id is\n * drawn as \"Loading…\" and never as itself: a 36-character identifier in a cell\n * reads like a value, and the 19 September verdict found it in choice cells,\n * relation cells and as every Kanban column heading.\n */\nexport function scalarText(field: Field, value: unknown, labels?: LabelLookup): string {\n if (value === null || value === undefined) return \"—\";\n const kind = editorKindFor(field);\n if (isId(value) && (field.type === \"list\" || field.type === \"relation\")) {\n return labels?.(field, String(value)) ?? \"Loading…\";\n }\n if (typeof value === \"number\") {\n if (kind === \"percent\") return `${value}%`;\n // The symbol goes in FRONT of an amount of money and a unit goes AFTER a\n // quantity: `$3` and `3 units`. Before this, `editorKindFor` called any\n // range field with a unit longer than one character a currency, so three\n // things measured in units rendered as \"units3\".\n if (kind === \"currency\") return field.unit ? `${field.unit}${value.toLocaleString()}` : value.toLocaleString();\n return field.unit ? `${value.toLocaleString()} ${field.unit}` : value.toLocaleString();\n }\n if (kind === \"datetime\" && typeof value === \"string\") {\n const at = new Date(value);\n if (!Number.isNaN(at.getTime())) {\n return field.format === \"datetime\" ? at.toLocaleString() : at.toLocaleDateString();\n }\n }\n // NEVER A JSON DUMP IN A CELL. A value with a shape a column cannot draw is\n // described; the raw document is available on the record panel, which is\n // where a person goes to look at it.\n if (Array.isArray(value)) return value.length === 0 ? \"\" : `${value.length} of them`;\n if (typeof value === \"object\") return \"…\";\n return String(value);\n}\n\n/** The provenance badge a value carries when the store interned a source for it (SCR-27). */\nexport function ProvenanceBadge({ document, fieldKey }: { document: RecordDocument | undefined; fieldKey: string }) {\n const envelope = envelopeFor(document, fieldKey);\n if (!envelope?.src) return null;\n const sources = document?._sources as Record<string, Record<string, unknown>> | undefined;\n const source = sources?.[envelope.src];\n const label = source ? Object.values(source).map(String).join(\" · \") : envelope.src;\n return (\n <Badge variant=\"outline\" className=\"text-[10px] font-normal\" title={`Written by ${envelope.actor ?? \"?\"}${envelope.at ? ` at ${envelope.at}` : \"\"}`}>\n {label}\n </Badge>\n );\n}\n\n/**\n * THE VALUE, AS A COMPONENT, so a cell can resolve the ids it holds.\n *\n * `renderValue` is a plain function called from inside a column's `cell`\n * callback and from a dozen other places; a function cannot ask the resolver\n * for a name, because asking is a hook. Every read-only surface therefore draws\n * through this instead, and the one that needs the raw function (a plain-text\n * export, a chat line) keeps calling `renderValue` with no resolver and says\n * \"Loading…\" rather than printing an id.\n */\nexport function RecordValue({\n field,\n value,\n document,\n}: {\n field: Field;\n value: unknown;\n document?: RecordDocument | undefined;\n}) {\n const labels = useRecordLabels(ONE_FIELD_ARRAY_CACHE(field));\n return <>{renderValue(field, value, document, labels)}</>;\n}\n\n/**\n * `useRecordLabels` takes an array and declares what it is about to draw. A new\n * array literal per cell would re-declare on every render, so each Field gets\n * exactly one array for the life of the process.\n */\nconst ONE_FIELD_ARRAYS = new WeakMap<Field, Field[]>();\nfunction ONE_FIELD_ARRAY_CACHE(field: Field): Field[] {\n const held = ONE_FIELD_ARRAYS.get(field);\n if (held) return held;\n const made = [field];\n ONE_FIELD_ARRAYS.set(field, made);\n return made;\n}\n","\"use client\";\n\n// src/labels.tsx — @ai-matrx/records-ui\n//\n// WHAT AN ID IS CALLED, ONCE, FOR EVERY SCREEN THAT DRAWS A VALUE.\n//\n// A choice field stores the ID of an option record and a relation field stores\n// the ID of the record it points at (FLD-5 / FLD-6, REL-1) — that is the store\n// being right, and it is also why the 19 September verdict saw a bare\n// 36-character identifier in a relation cell, in a choice cell, and as the\n// HEADING OF EVERY KANBAN COLUMN. The pickers resolved those ids because each\n// one loaded its own list; the read-only surfaces never did, so the same value\n// read as a name in the form and as a machine id in the grid.\n//\n// One resolver, provided once inside the mount, so every surface gets the same\n// answer and asks the store once per Field rather than once per cell:\n//\n// · a list field → `custom.field_options`, which resolves the options Table\n// from the Field's own config, so no screen has to know which Table it is\n// · a relation field → the read door on the Field's declared target\n//\n// WHAT IT DOES WHILE IT IS LOOKING. It returns `null`, and every caller draws\n// the word \"Loading…\" rather than the id. Showing the id \"until it resolves\" is\n// how the defect got shipped in the first place: it looks like a value.\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { useRecordsClient, type Field, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordDocument } from \"@ai-matrx/records\";\nimport { WITHHELD_RECORD_LABEL, recordName } from \"./names\";\n\n/** Answers \"what is the record with this id called\", for one Field's values. */\nexport type LabelLookup = (field: Field, id: string) => string | null;\n\nconst LabelContext = createContext<{\n lookup: LabelLookup;\n want: (field: Field) => void;\n}>({\n // With no provider the resolver is ABSENT, not silently empty: a caller gets\n // null and says \"Loading…\" forever, which is visible. The mount always\n // provides one, so this is only ever a bare unit test.\n lookup: () => null,\n want: () => {},\n});\n\n/** Which ids a Field's stored value refers to. */\nexport function idsOf(value: unknown): string[] {\n if (Array.isArray(value)) return value.map(String).filter(isId);\n if (typeof value === \"string\" && isId(value)) return [value];\n return [];\n}\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function isId(value: unknown): boolean {\n return typeof value === \"string\" && UUID.test(value);\n}\n\n/** True when this Field's values are ids of other records rather than values. */\nexport function pointsAtRecords(field: Field): boolean {\n return field.type === \"list\" || field.type === \"relation\";\n}\n\nexport function RecordLabelProvider({ children }: { children: ReactNode }) {\n const client = useRecordsClient();\n const [names, setNames] = useState<Record<string, string>>({});\n // Which Fields have FINISHED looking. Until a Field is in here its ids are\n // still loading; once it is in here, an id that is still missing is missing\n // for a reason, and the reason is asked for rather than waited out.\n const [settled, setSettled] = useState<Record<string, true>>({});\n const asked = useRef<Set<string>>(new Set());\n const chased = useRef<Set<string>>(new Set());\n\n const want = useCallback(\n (field: Field) => {\n if (!pointsAtRecords(field)) return;\n if (asked.current.has(field.id)) return;\n asked.current.add(field.id);\n\n void (async () => {\n if (field.type === \"list\") {\n const result = await client.fieldOptions({ field_id: field.id });\n if (result.ok) {\n setNames((current) => {\n const next = { ...current };\n for (const option of result.data ?? []) {\n next[option.id] = recordName(option.data as RecordDocument | undefined, null, \"Unnamed choice\");\n }\n return next;\n });\n }\n setSettled((current) => ({ ...current, [field.id]: true }));\n return;\n }\n const target = field.relation_target;\n if (!target) {\n setSettled((current) => ({ ...current, [field.id]: true }));\n return;\n }\n // REC-2: what makes a record a chip is ITS TABLE'S declared title field, and this\n // resolver used to try title/name/label and give up. A Table whose title field is\n // `cname` therefore read \"Untitled\" in every cell of every read-only surface — which\n // is every Table a person builds themselves. The Table is read alongside the rows.\n const [rows, tables] = await Promise.all([\n client.list({ table_id: target as Uuid, limit: 200 }),\n client.tableList(),\n ]);\n const titleKey = tables.ok\n ? (tables.data.find((table) => table.id === target)?.title_field ?? null)\n : null;\n if (rows.ok) {\n setNames((current) => {\n const next = { ...current };\n for (const row of rows.data.rows) {\n next[row.id] = recordName(row.document, titleKey, \"Untitled\");\n }\n return next;\n });\n }\n setSettled((current) => ({ ...current, [field.id]: true }));\n })();\n },\n [client],\n );\n\n // ── AN ID THIS RESOLVER DID NOT FIND (RELATION-DECLARE, 2026-09-20). ──────────────────\n // A relation joins two records in two tables, and holding one end says nothing about the\n // other: a Job shared with you may point at a Client nobody shared. The read door above\n // answers exactly what this reader may see, so an id it did not return is either further\n // down a long list or NOT HERS — and until today both of those read \"Loading…\", forever,\n // on every grid, card, board heading and peek in the product. Measured on 2026-09-20 in a\n // headless walk of the real grid: a relation cell whose target the reader holds read\n // \"Loading…\" and never resolved.\n //\n // \"Loading…\" that never resolves is not honesty, it is a lie with a spinner on it. The two\n // cases are asked apart through the read door, one id at a time, and the answer for a\n // record this reader may not open is the SAME SENTENCE the store itself gives\n // (`platform.relation_withheld_label()`) — never the title, never the bare id.\n const chase = useCallback(\n (field: Field, id: string) => {\n const key = `${field.id}:${id}`;\n if (chased.current.has(key)) return;\n chased.current.add(key);\n void (async () => {\n const result = await client.recordRead({ record_id: id as Uuid });\n setNames((current) => ({\n ...current,\n [id]: result.ok\n ? recordName(result.data.document, null, \"Untitled\")\n : WITHHELD_RECORD_LABEL,\n }));\n })();\n },\n [client],\n );\n\n const lookup = useCallback<LabelLookup>(\n (field, id) => {\n const known = names[id];\n if (known !== undefined) return known;\n if (settled[field.id]) chase(field, id);\n return null;\n },\n [names, settled, chase],\n );\n\n const value = useMemo(() => ({ lookup, want }), [lookup, want]);\n return <LabelContext.Provider value={value}>{children}</LabelContext.Provider>;\n}\n\n/**\n * The hook a surface uses: it declares the Fields it is about to draw, and gets\n * back the lookup. Declaring is what makes one request per Field instead of one\n * per cell, and it is why a grid of 200 rows asks the store twice.\n */\nexport function useRecordLabels(fields: readonly Field[] | undefined): LabelLookup {\n const { lookup, want } = useContext(LabelContext);\n useEffect(() => {\n for (const field of fields ?? []) want(field);\n }, [fields, want]);\n return lookup;\n}\n","\"use client\";\n\n// src/Grid.tsx — @ai-matrx/records-ui · SCR-1, SCR-2, SCR-4, SCR-31\n//\n// A custom table opens as a grid: RECORDS ARE ROWS, FIELDS ARE COLUMNS, AND A\n// CELL IS WHERE YOU CHANGE IT.\n//\n// It is the canonical `MatrxDataTable` — not a table this package drew. The\n// columns are built from the Table's own Field records, the rows are the\n// records the read door returned, and the \"+\" at the end of the column headers\n// is present for a holder of `admin` on the table and ABSENT — never disabled,\n// never greyed — for everybody else (SCR-4).\n//\n// EDITING IS HERE, NOT IN A PANEL SOMEWHERE ELSE (`gridEditing.tsx`). Click a\n// cell, DOUBLE-click it, or focus it and press Enter, and the Field's own\n// editor opens in place — the same editor, all three ways;\n// Enter saves, Escape cancels, Tab saves and opens the next one. The save goes\n// through the one write door carrying the version the person started from, so\n// the STORE decides whether somebody else got there first — and when it did,\n// the cell shows their value with a Try again beside it. A row is deleted from\n// its own row menu, with the consequence named before the delete, and a new\n// record is one button that puts you straight into the first cell.\n//\n// Every refusal is the store's own sentence (`RefusalNotice`). A grid that\n// rendered \"no records\" because the door refused is the defect this package\n// exists to prevent, so the empty state and the refusal are different things\n// and both are shown.\n\nimport { useCallback, useMemo, useState, type ReactNode } from \"react\";\nimport {\n useFields,\n useRecords,\n useTable,\n type Field,\n type ReadRow,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport { MatrxDataTable } from \"@ai-matrx/design-system/data-table\";\nimport type { MatrxColumnDef } from \"@ai-matrx/design-system/data-table/types\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi, useRowRights, useTableRights } from \"./host\";\nimport { editorKindFor, fieldTypeLabel } from \"./parity\";\nimport { fieldName, tableName } from \"./names\";\nimport { RecordValue } from \"./values\";\nimport { GridCell, useGridEditing, type GridEditing } from \"./gridEditing\";\n\nexport interface GridProps {\n tableId: Uuid;\n /** Rows per page. The table's own pagination handles the rest. */\n pageSize?: number | undefined;\n /** Opened when a row is clicked. A host that has a record page passes its own. */\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n /** SCR-2. Called when an admin clicks the \"+\" at the end of the headers. */\n onAddField?: (() => void) | undefined;\n /**\n * The host's whole-record form. Offered BY NAME when the store refuses an\n * empty record — a Table with a required Field cannot be added to one cell at\n * a time, and saying so beats a button that fails.\n */\n onNewRecordForm?: (() => void) | undefined;\n /** Extra toolbar content — the view switcher, the export menu, the view bar. */\n toolbarActions?: ReactNode | undefined;\n /** Editing in place is on by default; a read-only surface (a portal) turns it off. */\n editable?: boolean | undefined;\n className?: string | undefined;\n}\n\nexport function Grid({\n tableId,\n pageSize = 50,\n onOpenRecord,\n onAddField,\n onNewRecordForm,\n toolbarActions,\n editable = true,\n className,\n}: GridProps) {\n const host = useRecordsUi();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const [page, setPage] = useState(0);\n const records = useRecords(tableId, { pageSize, page });\n const rights = useTableRights(table.data);\n const rows = useMemo(() => records.data?.rows ?? [], [records.data]);\n const rowIds = useMemo(() => rows.map((row) => row.id), [rows]);\n\n /**\n * PER ROW, BUT ONLY WHERE IT CAN CHANGE THE ANSWER.\n *\n * When the table already admits editing, every row it returned is this\n * person's to edit and asking again would be a call per page for nothing.\n * When it does not, a row may still have been shared with them directly — the\n * sixth-pass verdict found exactly that, and the grid labelled the row\n * \"viewer\" while the store let its holder write to it — so the page asks\n * once, for all its rows, through the door that takes a list.\n */\n // ONLY WHEN THE PACKAGE IS THE ONE ASKING. A host that binds `rights` has its\n // own authority — a portal, an embed, a read-only surface — and a grid that\n // went around it to the store would quietly overrule the host that mounted\n // it. When the port is bound, its answer is the whole answer, for every row.\n const askPerRow =\n Boolean(editable) && !host.rights && rights.known && !rights.write && rows.length > 0;\n const rowRights = useRowRights(rowIds, askPerRow);\n const mayWriteRow = useCallback(\n (rowId: Uuid) => (askPerRow ? (rowRights(rowId)?.write ?? false) : rights.write),\n [askPerRow, rowRights, rights.write],\n );\n const whyNotRow = useCallback(\n (rowId: Uuid) =>\n askPerRow ? (rowRights(rowId)?.why(\"write\") ?? rights.why(\"write\")) : rights.why(\"write\"),\n [askPerRow, rowRights, rights],\n );\n\n // Whether ANY row on this page can be edited: what the toolbar and the row\n // menu turn on. A grid with nothing editable draws no editing controls at all.\n const canWrite = Boolean(editable) && (rights.write || (askPerRow && rowIds.some(mayWriteRow)));\n\n const editing = useGridEditing({\n tableId,\n fields: fields.data ?? [],\n rows,\n reload: records.reload,\n canWrite,\n mayWriteRow,\n });\n\n const columns = useMemo<MatrxColumnDef<ReadRow>[]>(\n () =>\n (fields.data ?? []).map((field) =>\n columnForField(field, canWrite ? editing : null, mayWriteRow, whyNotRow),\n ),\n [fields.data, canWrite, editing, mayWriteRow, whyNotRow],\n );\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n\n /**\n * A REFRESH IS NOT A FIRST LOAD, AND THE DIFFERENCE IS A TYPED VALUE.\n *\n * `MatrxDataTable` renders six SKELETON rows in place of `<tbody>`'s real\n * ones while `isLoading` — every cell on the page is unmounted. This grid\n * used to hand it `records.loading`, which goes true on every `reload()`, and\n * `gridEditing` reloads after EVERY accepted cell write. So committing one\n * cell tore down the editor the person was still typing in: the caret went,\n * and any keystroke that arrived inside that window reached a detached node\n * and was lost — the draft then equalled what the cell opened with, `commit`\n * correctly said \"nothing changed\", and the value was gone with nothing\n * anywhere saying so. Measured 2026-09-20: one column of a tabbed row saved\n * as nothing, a different one each run, which is what made it look like the\n * store rather than the screen.\n *\n * The data table already tells the two apart — `isFetching` draws a refresh\n * line and KEEPS the rows — so the skeleton is now only what it says it is:\n * there is nothing to show yet. Nothing a person is typing into is ever\n * unmounted by a read they did not ask for.\n *\n * AND A FIRST LOAD IS NOT ONLY THE ROWS. Invariant 4 of this package: no\n * component acts before the store has answered. Three things are answered\n * ONCE for a table — its declaration, its columns, and what THIS PERSON may\n * do to it — and a row drawn before any of them is a lie: `useTableRights`\n * answers `NO_RIGHTS` (`known: false`) while the table itself is still being\n * read, so every cell came out as plain text with no editor, and a click on\n * it did nothing and said nothing. Measured 2026-09-20: this cost\n * `demo/edit.test.tsx` three clauses, deterministically, and it was a real\n * defect and not the suite's.\n *\n * So those three are a FIRST LOAD, and only the page re-read is a refresh —\n * which is what makes this safe: they are asked once per table id, so they\n * never blank rows a person is already working in.\n */\n const nothingToShowYet =\n table.loading || fields.loading || !rights.known || (records.loading && rows.length === 0);\n const refreshing = !nothingToShowYet && records.loading;\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* SCR-N-4 / the one-row header rule: the table's name, its row count and\n its controls on ONE line. No repeated name, no subtitle restating it. */}\n <div className=\"flex items-center gap-2\">\n <h2 className=\"truncate text-sm font-medium\">\n {table.data ? tableName(table.data) : <Skeleton className=\"h-4 w-32\" />}\n </h2>\n {records.data?.total !== null && records.data?.total !== undefined ? (\n <span className=\"text-xs text-muted-foreground\">{records.data.total}</span>\n ) : null}\n <div className=\"ml-auto flex items-center gap-1\">{toolbarActions}</div>\n </div>\n\n {records.error ? <RefusalNotice error={records.error} /> : null}\n\n {/* A delete or an add the store refused, in the store's own sentence, with\n the one control that can still get the person what they asked for. */}\n {editing.rowError ? (\n <RefusalNotice\n error={editing.rowError}\n actions={\n <div className=\"mt-1 flex gap-1\">\n {onNewRecordForm ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n editing.clearRowError();\n onNewRecordForm();\n }}\n >\n Fill it in on the full form\n </Button>\n ) : null}\n <Button size=\"sm\" variant=\"ghost\" onClick={editing.clearRowError}>\n Dismiss\n </Button>\n </div>\n }\n />\n ) : null}\n\n {!records.live ? (\n // Nothing fails silently: a list that stopped updating says so.\n <p className=\"text-xs text-muted-foreground\">{records.liveReason}</p>\n ) : null}\n\n <MatrxDataTable<ReadRow>\n data={rows}\n columns={columns}\n getRowId={(row) => row.id}\n isLoading={nothingToShowYet}\n isFetching={refreshing}\n density={host.density ?? \"condensed\"}\n tableId={`records-grid-${tableId}`}\n stickyHeader\n pageSize={pageSize}\n /*\n * NO SECOND RECORD PANEL. The data table ships two of its own — a side\n * panel and a floating window — and both fall back to `DataRowInspector`,\n * which draws the raw row: its machine keys, a truncated id, and the\n * headings DOCUMENT, LEVEL and HIDDEN. That is what a person got when\n * they double-clicked a cell on 19 September, and it is a parallel layer\n * beside the record panel this package already has (`Peek`, opened\n * through `onRowOpen`), which the platform forbids. Both are OFF here,\n * so a row opens exactly one thing and a person never meets the\n * inspector.\n */\n detail={{ enabled: false }}\n window={{ enabled: false }}\n {...(onOpenRecord ? { onRowOpen: (row: ReadRow) => onOpenRecord(row.id) } : {})}\n {...(canWrite\n ? {\n // ABSENT, NEVER DEAD: a row this person may not delete carries no\n // Delete at all, rather than one that refuses when pressed.\n rowActions: (row: ReadRow) =>\n mayWriteRow(row.id) ? (\n <DeleteRecordButton\n row={row}\n retentionDays={table.data?.retention_days ?? null}\n onDelete={() => editing.remove(row.id)}\n />\n ) : null,\n }\n : {})}\n emptyState={{\n title: \"No records yet\",\n description: rights.write\n ? \"Add the first one and it appears here.\"\n : rights.known\n ? `Nothing has been written to this table. ${rights.why(\"write\")}`\n : \"Nothing has been written to this table.\",\n }}\n toolbar={{\n search: true,\n searchPlaceholder: \"Search records\",\n // SCR-2 / SCR-4: PRESENT for an admin, ABSENT for everyone else.\n // There is no third state: this package ships no disabled variant of\n // these controls, so a member cannot be shown a dead one by mistake.\n actions: (\n <>\n {/* A new record is written to the TABLE, so it follows the\n table's level and not any one row's. */}\n {Boolean(editable) && rights.write ? (\n <Button size=\"sm\" disabled={editing.busy} onClick={() => void editing.addRecord()}>\n {editing.busy ? \"Adding…\" : \"New record\"}\n </Button>\n ) : null}\n {rights.structure && onAddField ? <AddFieldButton onClick={onAddField} /> : null}\n </>\n ),\n }}\n />\n\n <Pager\n page={page}\n pageSize={pageSize}\n total={records.data?.total ?? null}\n rows={rows.length}\n onPage={setPage}\n />\n </div>\n );\n}\n\n/**\n * SCR-2. The \"+\" at the far right of the column headers. It exists only for a\n * holder of `admin`: the caller above decides, and there is no disabled variant\n * of this button anywhere in the package.\n */\nfunction AddFieldButton({ onClick }: { onClick: () => void }) {\n return (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={onClick}\n aria-label=\"Add a field\"\n title=\"Add a field to this table\"\n >\n +\n </Button>\n );\n}\n\n/**\n * DELETING NAMES THE CONSEQUENCE BEFORE IT HAPPENS. One press asks; the second\n * one does it. The sentence is the store's own truth about this Table — a soft\n * delete that stays reversible for the Table's own retention window (REC-23),\n * or, when the Table declares none, the plain fact that it can be restored.\n */\nfunction DeleteRecordButton({\n row,\n retentionDays,\n onDelete,\n}: {\n row: ReadRow;\n retentionDays: number | null;\n onDelete: () => Promise<unknown>;\n}) {\n const [asking, setAsking] = useState(false);\n if (!asking) {\n return (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label=\"Delete this record\"\n title=\"Delete this record\"\n onClick={() => setAsking(true)}\n >\n Delete\n </Button>\n );\n }\n return (\n <span className=\"flex items-center gap-1 text-[11px]\">\n <span className=\"text-muted-foreground\">\n {retentionDays\n ? `Removes it from the table. Restorable for ${retentionDays} days.`\n : \"Removes it from the table. It can be restored from the record's history.\"}\n </span>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => {\n setAsking(false);\n void onDelete();\n }}\n >\n Delete\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAsking(false)}>\n Keep\n </Button>\n <span className=\"sr-only\">{row.id}</span>\n </span>\n );\n}\n\nfunction Pager({\n page,\n pageSize,\n total,\n rows,\n onPage,\n}: {\n page: number;\n pageSize: number;\n total: number | null;\n rows: number;\n onPage: (page: number) => void;\n}) {\n const from = page * pageSize;\n const last = total === null ? rows < pageSize : from + rows >= total;\n if (page === 0 && last) return null;\n return (\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <Button size=\"sm\" variant=\"ghost\" disabled={page === 0} onClick={() => onPage(page - 1)}>\n Previous\n </Button>\n <span>\n {from + 1}–{from + rows}\n {total === null ? \"\" : ` of ${total}`}\n </span>\n <Button size=\"sm\" variant=\"ghost\" disabled={last} onClick={() => onPage(page + 1)}>\n Next\n </Button>\n </div>\n );\n}\n\n/**\n * One Field becomes one column. The header is the Field's own NAME — never its\n * key (`names.ts`) — and the cell is the value, rendered by its parity type and\n * editable in place when an editing session is passed.\n */\nexport function columnForField(\n field: Field,\n editing?: GridEditing | null,\n mayWriteRow?: (rowId: Uuid) => boolean,\n whyNotRow?: (rowId: Uuid) => string,\n): MatrxColumnDef<ReadRow> {\n const name = fieldName(field);\n return {\n id: field.key,\n header: name,\n label: name,\n accessorFn: (row) => row.document?.[field.key],\n sortable: true,\n filter: editorKindFor(field) === \"select\" || editorKindFor(field) === \"multi_select\" ? \"select\" : \"auto\",\n cell: (row) =>\n editing ? (\n <GridCell\n field={field}\n row={row}\n editing={editing}\n canWrite={mayWriteRow ? mayWriteRow(row.id) : true}\n {...(whyNotRow ? { whyNot: whyNotRow(row.id) } : {})}\n />\n ) : (\n <RecordValue field={field} value={row.document?.[field.key]} document={row.document} />\n ),\n headerClassName: \"whitespace-nowrap\",\n // The type is in the header's tooltip rather than a second header row: one\n // row of headers, always — and it is the parity type's own WORD, not a\n // token (`Long text`, never `long_text`).\n className: \"align-top\",\n ...({ title: fieldTypeLabel(field) } as Record<string, unknown>),\n };\n}\n","\"use client\";\n\n// src/ExportMenu.tsx — @ai-matrx/records-ui · SCR-31\n//\n// ANY VIEW EXPORTS AS CSV OR XLSX, CARRYING EXACTLY THE COLUMNS AND ROWS THE\n// READING PRINCIPAL MAY SEE — which is not a filter this component applies. The\n// rows it exports are the rows the READ DOOR returned, and the columns are the\n// Fields the store said APPLY. There is no wider read anywhere in this file, so\n// an export can never contain something the screen did not.\n//\n// The bytes are `@ai-matrx/records`' own `exportCsv` / `exportXlsx`, so an\n// export from a screen and an export from a script are the same file.\n\nimport { useState } from \"react\";\nimport { useFields, useRecords, type Field, type ReadRow, type ReadValue, type Uuid } from \"@ai-matrx/records/react\";\nimport { exportCsv, exportXlsx, type ExportRow } from \"@ai-matrx/records/core\";\nimport { AlchemyMenu } from \"@ai-matrx/alchemy/react\";\nimport { Button, cn } from \"@ai-matrx/design-system\";\nimport { RefusalLine } from \"./Refusal\";\n\nexport interface ExportMenuProps {\n tableId: Uuid;\n /** The rows on screen. Absent means \"this table's first page\", read the same way. */\n rows?: ReadRow[] | undefined;\n /** What the file is called. The table's name by default. */\n label?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * The rows, in the package's own `ExportRow` shape — the value AND its envelope,\n * so the exported cell can carry the store's own absence WORD instead of a blank\n * (VAL-2: \"never asked\" and \"refused\" are different facts, and the file says\n * which).\n */\nfunction toRows(fields: Field[], records: ReadRow[]): ExportRow[] {\n return records.map((record) => {\n const document = record.document ?? {};\n const envelopes = (document[\"_values\"] ?? {}) as Record<string, { absent?: string | null }>;\n const row: ExportRow = {};\n for (const field of fields) {\n const envelope = envelopes[field.key];\n row[field.key] = {\n field_key: field.key,\n value: document[field.key] ?? null,\n absent_reason: (envelope?.absent ?? null) as ReadValue[\"absent_reason\"],\n } as ReadValue;\n }\n return row;\n });\n}\n\nfunction download(name: string, mime: string, bytes: BlobPart) {\n const url = URL.createObjectURL(new Blob([bytes], { type: mime }));\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = name;\n anchor.click();\n URL.revokeObjectURL(url);\n}\n\nexport function ExportMenu({ tableId, rows, label, className }: ExportMenuProps) {\n const fields = useFields(tableId);\n const page = useRecords(tableId, { pageSize: 500 });\n const [failure, setFailure] = useState<string | null>(null);\n\n const records = rows ?? page.data?.rows ?? [];\n const name = label ?? \"records\";\n\n if (fields.error) return <RefusalLine error={fields.error} className={className} />;\n if (!rows && page.error) return <RefusalLine error={page.error} className={className} />;\n if (!fields.data || (!rows && !page.data)) {\n // The columns ARE the Fields and the rows are the read door's answer, so\n // there is no export to offer until both have arrived. A button that\n // produced a headerless or rowless file would be worse than a moment's wait.\n return <span className={cn(\"text-xs text-muted-foreground\", className)}>Reading this table…</span>;\n }\n\n const exported = () => toRows(fields.data ?? [], records);\n\n return (\n <div className={cn(\"flex items-center gap-1\", className)}>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => download(`${name}.csv`, \"text/csv;charset=utf-8\", exportCsv(fields.data ?? [], exported()))}\n >\n CSV\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n try {\n void exportXlsx(fields.data ?? [], exported(), name).then((bytes) =>\n download(\n `${name}.xlsx`,\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n bytes as unknown as BlobPart,\n ),\n );\n } catch (thrown) {\n // Nothing fails silently: say what broke and what to do instead.\n setFailure(\n `The spreadsheet could not be written (${thrown instanceof Error ? thrown.message : String(thrown)}). ` +\n `The CSV beside this button carries the same rows.`,\n );\n }\n }}\n >\n XLSX\n </Button>\n {/* The same menu every other surface on the platform carries. */}\n <AlchemyMenu\n label={name}\n sourceId={`records:${tableId}`}\n size=\"xs\"\n json={() => records.map((r) => r.document)}\n human={() => exportCsv(fields.data ?? [], exported())}\n />\n {failure ? <p className=\"text-xs text-destructive\">{failure}</p> : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/ImportWizard.tsx — @ai-matrx/records-ui · SCR-10, SCR-N-7\n//\n// MAP A FILE'S COLUMNS ONTO FIELDS, PREVIEW THE ROWS IT WILL WRITE, AND OFFER\n// ANY UNMAPPED COLUMN AS A FIELD PROPOSAL.\n//\n// The parsing and the matching are `@ai-matrx/records`' own `importCsv` /\n// `importXlsx`, so a file imported from a screen and a file imported from a\n// script land identically. An unmapped column is NEVER dropped quietly: it is\n// listed, and \"add this as a field\" sits beside it under the same right as the\n// grid's \"+\" (SCR-N-7) — absent, not disabled, for anybody else.\n//\n// Every row is written through the ONE write door, one at a time, and a row the\n// store refuses keeps its own refusal beside it. A partial import that pretended\n// to be a whole one is the failure this screen exists to make impossible.\n\nimport { useState } from \"react\";\nimport { useFields, useRecordMutation, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport { importCsv, importXlsx, type ParsedImport } from \"@ai-matrx/records/core\";\nimport { Badge, Button, Separator, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { fieldName } from \"./names\";\n\nexport interface ImportWizardProps {\n tableId: Uuid;\n /** SCR-N-7: what \"add this as a field\" does. Absent means the offer is not made. */\n onProposeField?: ((header: string) => void) | undefined;\n onDone?: ((written: number) => void) | undefined;\n className?: string | undefined;\n}\n\ninterface RowOutcome {\n index: number;\n recordId: string | null;\n refusal: string | null;\n}\n\nexport function ImportWizard({ tableId, onProposeField, onDone, className }: ImportWizardProps) {\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const mutation = useRecordMutation();\n const [parsed, setParsed] = useState<ParsedImport | null>(null);\n const [outcomes, setOutcomes] = useState<RowOutcome[]>([]);\n const [reading, setReading] = useState<string | null>(null);\n\n const take = async (file: File) => {\n setReading(null);\n setOutcomes([]);\n try {\n const declared = fields.data ?? [];\n const result = file.name.toLowerCase().endsWith(\".xlsx\")\n ? await importXlsx(declared, await file.arrayBuffer())\n : importCsv(declared, await file.text());\n setParsed(result);\n } catch (thrown) {\n setReading(`That file could not be read: ${thrown instanceof Error ? thrown.message : String(thrown)}`);\n }\n };\n\n const write = async () => {\n if (!parsed) return;\n const done: RowOutcome[] = [];\n for (const [index, row] of parsed.rows.entries()) {\n const id = await mutation.write({ table_id: tableId, data: row });\n done.push({ index, recordId: id, refusal: id ? null : (mutation.error?.message ?? \"The store refused this row.\") });\n setOutcomes([...done]);\n }\n onDone?.(done.filter((d) => d.recordId).length);\n };\n\n const written = outcomes.filter((o) => o.recordId).length;\n const refused = outcomes.filter((o) => !o.recordId).length;\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-2 text-xs\", className)}>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">Import</span>\n <span className=\"text-muted-foreground\">{table.data?.name}</span>\n {/* A file cannot be mapped before the store has said which Fields\n apply, so the chooser waits rather than matching against nothing and\n reporting every column as unmapped. It ALSO waits for the Table\n itself: the rights that decide whether \"add this as a field\" is\n offered are read from the Table, and a chooser that opened first\n could show an admin a mapping with the offer missing — a control\n silently absent for the one person who may use it. Both answers, or\n no chooser.\n (Found by the suite under load, 2026-09-18: the Fields arrived\n before the Table and the offer was not there.) */}\n {fields.data && table.data ? (\n <input\n type=\"file\"\n accept=\".csv,.xlsx\"\n aria-label=\"Choose a file to import\"\n className=\"ml-auto text-xs\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) void take(file);\n }}\n />\n ) : (\n <span className=\"ml-auto text-muted-foreground\">\n {fields.data ? \"Reading this table…\" : \"Reading this table's fields…\"}\n </span>\n )}\n </div>\n\n {reading ? <p className=\"text-destructive\">{reading}</p> : null}\n\n {parsed ? (\n <>\n {/* The mapping, column by column, with nothing hidden. */}\n <ul className=\"flex flex-wrap gap-1\">\n {parsed.columns.map((column) => (\n <li key={column.header}>\n <Badge variant={column.field ? \"secondary\" : \"outline\"} className=\"gap-1 text-[11px] font-normal\">\n {column.header}\n <span className=\"opacity-60\">→</span>\n {column.field ? (\n column.field.label || column.field.key\n ) : (\n <span className=\"text-destructive\">no field</span>\n )}\n {/* SCR-N-7, and it is gated by the SAME right as the grid's \"+\". */}\n {!column.field && rights.admin && onProposeField ? (\n <button\n type=\"button\"\n className=\"underline underline-offset-2\"\n onClick={() => onProposeField(column.header)}\n >\n add as a field\n </button>\n ) : null}\n </Badge>\n </li>\n ))}\n </ul>\n\n {parsed.unmapped.length > 0 ? (\n <p className=\"text-muted-foreground\">\n {parsed.unmapped.length} column{parsed.unmapped.length === 1 ? \"\" : \"s\"} match no Field and{\" \"}\n {rights.admin && onProposeField\n ? \"can be added as fields above.\"\n : \"will not be written. Nothing is dropped quietly: the columns are listed above.\"}\n </p>\n ) : null}\n\n <Separator />\n\n {/* The preview: exactly the rows the write door will be handed. */}\n <p className=\"text-muted-foreground\">\n {parsed.rows.length} row{parsed.rows.length === 1 ? \"\" : \"s\"} to write\n </p>\n <div className=\"max-h-56 overflow-auto rounded border\">\n <table className=\"w-full\">\n <thead className=\"sticky top-0 bg-muted\">\n <tr>\n {(fields.data ?? []).map((field) => (\n <th key={field.id} className=\"px-2 py-1 text-left font-medium\">\n {fieldName(field)}\n </th>\n ))}\n <th className=\"px-2 py-1 text-left font-medium\">Result</th>\n </tr>\n </thead>\n <tbody>\n {parsed.rows.slice(0, 50).map((row, index) => {\n const outcome = outcomes.find((o) => o.index === index);\n return (\n <tr key={index} className=\"border-t\">\n {(fields.data ?? []).map((field) => (\n <td key={field.id} className=\"max-w-40 truncate px-2 py-1\">\n {row[field.key] ?? \"\"}\n </td>\n ))}\n <td className=\"px-2 py-1\">\n {outcome?.recordId ? (\n <span className=\"text-muted-foreground\">written</span>\n ) : outcome?.refusal ? (\n // The store's own sentence, on the row it refused.\n <span className=\"text-destructive\">{outcome.refusal}</span>\n ) : null}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n {mutation.error && outcomes.length === 0 ? <RefusalNotice error={mutation.error} /> : null}\n\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" disabled={mutation.saving || !rights.write} onClick={() => void write()}>\n {mutation.saving ? \"Writing…\" : `Write ${parsed.rows.length} rows`}\n </Button>\n {outcomes.length > 0 ? (\n <span className=\"text-muted-foreground\">\n {written} written{refused > 0 ? `, ${refused} refused — each one says why on its row` : \"\"}\n </span>\n ) : null}\n </div>\n </>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/CustomFieldsSection.tsx — @ai-matrx/records-ui · SCR-12\n//\n// THE ONE LINE A STANDARD ENTITY PAGE ADDS.\n//\n// <CustomFieldsSection entityToken=\"party\" recordId={party.id} />\n//\n// A standard entity's page grows its organization's custom fields in one\n// section, resolved from the Field records, WITH NO PER-ENTITY CODE. That is the\n// whole point: nobody writes a section per entity, and an organization that adds\n// a field to Contacts sees it on every contact page the same afternoon.\n//\n// 🚨 WHAT THIS COMPONENT USED TO DO, AND WHY IT COULD NEVER WORK (measured from\n// the seat on the main database, 2026-09-19). It resolved `entityToken` by\n// looking for a CUSTOM Table whose slug happened to equal the token, and then\n// read the row with `useRecord(recordId)` — which reads `custom.record`, where a\n// CRM contact does not live and never will. So on a standard entity page it\n// rendered NOTHING, silently, forever: no table matched, so the section was\n// absent, and absence is exactly what it renders when a table has no custom\n// fields. SCR-12 looked finished and had never shown a single value.\n//\n// It now goes through the token-keyed door set (`custom.entity_record_read`,\n// `custom.entity_field_rights`, `custom.entity_value_write`,\n// `custom.entity_field_declare`), which reads the standard row AS THE PERSON —\n// the table's own row-level security decides — and hands back REC-53's three\n// blocks: the row's real columns, its custom values, and the definitions that\n// describe them.\n\nimport { useMemo, useState } from \"react\";\nimport {\n useEntityFieldMutation,\n useEntityFieldRights,\n useEntityRecord,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport type { EntityFieldValue, Field } from \"@ai-matrx/records\";\nimport { Button, Separator, cn } from \"@ai-matrx/design-system\";\nimport { RefusalLine } from \"./Refusal\";\nimport { FieldControl, FieldLabel } from \"./editors\";\nimport { renderValue } from \"./values\";\n\nexport interface CustomFieldsSectionProps {\n /** The standard table's registered token (REC-33), e.g. `party`, `crm_deal`. */\n entityToken: string;\n /** The id of the row this page is showing. */\n recordId: Uuid;\n /** The heading. One row, no subtitle restating it. */\n title?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * WHAT A PERSON CAN ADD FROM A RECORD PAGE, in the words they use. The store\n * knows thirteen parity types and three plain ones; a record page offers the\n * ones that need nothing more than a name, and the full panel (TableSettings)\n * is where a choice list and a relation get the extra answer they need.\n */\nconst ADDABLE_TYPES = [\n { value: \"text\", label: \"Text\" },\n { value: \"long_text\", label: \"Long text\" },\n { value: \"number\", label: \"Number\" },\n { value: \"currency\", label: \"Money\" },\n { value: \"percent\", label: \"Percentage\" },\n { value: \"datetime\", label: \"Date\" },\n { value: \"email\", label: \"Email\" },\n { value: \"phone\", label: \"Phone\" },\n { value: \"url\", label: \"Link\" },\n { value: \"member\", label: \"Person\" },\n { value: \"attachment\", label: \"File\" },\n] as const;\n\n/** The definitions the read door hands back are Field-shaped for the editors. */\nfunction asField(f: EntityFieldValue): Field {\n return {\n id: f.id,\n key: f.key,\n label: f.label,\n type: f.type,\n parity_type: f.parity_type,\n format: f.format,\n unit: f.unit,\n multi: f.multi ?? false,\n required: f.required ?? false,\n sensitivity: f.sensitivity,\n config: f.options_table_id ? { options_table_id: f.options_table_id } : {},\n relation_target: f.relation_target ?? null,\n } as unknown as Field;\n}\n\nexport function CustomFieldsSection({\n entityToken,\n recordId,\n title = \"Custom fields\",\n className,\n}: CustomFieldsSectionProps) {\n const read = useEntityRecord(entityToken, recordId);\n const rights = useEntityFieldRights(entityToken);\n const mutation = useEntityFieldMutation();\n const [editing, setEditing] = useState(false);\n const [adding, setAdding] = useState(false);\n const [newLabel, setNewLabel] = useState(\"\");\n const [newType, setNewType] = useState<string>(\"text\");\n const [draft, setDraft] = useState<Record<string, unknown>>({});\n\n const fields = useMemo(() => read.data?.fields ?? [], [read.data]);\n const mayAdd = rights.data?.may_declare === true;\n\n // NOTHING TO GROW: render nothing at all rather than an empty titled box on\n // every page in the product — UNLESS this person may add one, in which case an\n // empty section is the only place the offer can live. A capability nobody can\n // find is not shipped.\n if (!read.loading && !read.error && fields.length === 0 && !mayAdd) return null;\n\n // A REFUSAL IS THE STORE'S OWN SENTENCE, never a blank section. The commonest\n // one here is honest and actionable: the person may not open this row.\n if (read.error) return <RefusalLine error={read.error} className={className} />;\n\n const values = read.data?.custom ?? {};\n const written = read.data?.custom_written ?? {};\n\n return (\n <section className={cn(\"flex min-w-0 flex-col gap-2 text-xs\", className)}>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">{title}</h3>\n <span className=\"text-muted-foreground\">{fields.length}</span>\n {fields.length > 0 ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"ml-auto\"\n title={editing ? \"Stop editing these fields\" : \"Edit these fields\"}\n onClick={() => {\n setDraft({});\n setEditing((e) => !e);\n }}\n >\n {editing ? \"Cancel\" : \"Edit\"}\n </Button>\n ) : null}\n {/* SCR-12: ABSENT, never disabled. `custom.entity_field_rights` answers\n the right and the sentence together, so a person who may not add a\n column reads WHY rather than pressing a control that fails. */}\n {mayAdd && !editing ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className={fields.length > 0 ? undefined : \"ml-auto\"}\n onClick={() => setAdding((a) => !a)}\n >\n {adding ? \"Cancel\" : \"Add field\"}\n </Button>\n ) : null}\n {editing ? (\n <Button\n size=\"sm\"\n disabled={mutation.saving || Object.keys(draft).length === 0}\n onClick={async () => {\n const saved = await mutation.write({\n token: entityToken,\n record_id: recordId,\n patch: draft,\n });\n if (saved) {\n setEditing(false);\n setDraft({});\n read.reload();\n }\n }}\n >\n {mutation.saving ? \"Saving…\" : \"Save\"}\n </Button>\n ) : null}\n </div>\n <Separator />\n {mutation.error ? <RefusalLine error={mutation.error} /> : null}\n {rights.data && !rights.data.may_declare && rights.data.reason ? (\n <p className=\"text-[11px] text-muted-foreground\">{rights.data.reason}</p>\n ) : null}\n {adding ? (\n <form\n className=\"flex flex-wrap items-end gap-2\"\n onSubmit={async (e) => {\n e.preventDefault();\n const id = await mutation.declare({\n token: entityToken,\n spec: { label: newLabel, type: newType },\n });\n if (id) {\n setAdding(false);\n setNewLabel(\"\");\n read.reload();\n }\n }}\n >\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">Name</span>\n <input\n className=\"h-8 rounded-md border bg-background px-2\"\n value={newLabel}\n onChange={(e) => setNewLabel(e.target.value)}\n placeholder=\"Account tier\"\n required\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">Holds</span>\n <select\n className=\"h-8 rounded-md border bg-background px-2\"\n value={newType}\n onChange={(e) => setNewType(e.target.value)}\n >\n {ADDABLE_TYPES.map((t) => (\n <option key={t.value} value={t.value}>\n {t.label}\n </option>\n ))}\n </select>\n </label>\n <Button size=\"sm\" type=\"submit\" disabled={mutation.saving || newLabel.trim() === \"\"}>\n {mutation.saving ? \"Adding…\" : \"Add\"}\n </Button>\n </form>\n ) : null}\n {editing ? (\n <div className=\"flex flex-col gap-3\">\n {fields.map((f) => {\n const field = asField(f);\n const id = `cf-${recordId}-${f.key}`;\n return (\n <div key={f.id} className=\"flex min-w-0 flex-col gap-1\">\n <FieldLabel field={field} htmlFor={id} />\n <FieldControl\n id={id}\n field={field}\n value={f.key in draft ? draft[f.key] : values[f.key]}\n onChange={(next) => setDraft((d) => ({ ...d, [f.key]: next }))}\n />\n </div>\n );\n })}\n </div>\n ) : (\n <dl className=\"grid grid-cols-[minmax(6rem,12rem)_1fr] gap-x-3 gap-y-1.5\">\n {fields.map((f) => (\n <div key={f.id} className=\"contents\">\n <dt className=\"flex items-baseline gap-1 truncate text-muted-foreground\">\n {f.label}\n {/* VAL-2 / AGT-N-4: who put this value here. A value nobody has\n written says nothing rather than pretending somebody did. */}\n {written[f.key]?.actor ? (\n <span className=\"text-[10px] text-muted-foreground/70\">{written[f.key]?.actor}</span>\n ) : null}\n </dt>\n <dd className=\"min-w-0\">{renderValue(asField(f), values[f.key])}</dd>\n </div>\n ))}\n </dl>\n )}\n </section>\n );\n}\n","\"use client\";\n\n// src/FieldEditor.tsx — @ai-matrx/records-ui · SCR-9\n//\n// ADDING A COLUMN, WHICH IS THE FIRST THING ANYBODY DOES WITH A TABLE.\n//\n// On 19 September this panel refused every column a person tried to add — a\n// Number and a Date with \"the table does not declare a field called day_rate —\n// declare it there first\", a Person as though it were a formula, and a choice\n// list with \"has to say which table its choices come from\" and nowhere to say\n// it. One cause: the panel assembled a Field DOCUMENT itself and wrote it with\n// the ordinary record writer, which can neither tell the Table about the field\n// nor stamp the row as a field. Both of those are the store's to do, and now it\n// does them: `custom.field_declare` takes what a person knows — a type, a name,\n// and for a choice list the choices — and turns it into the document its own\n// guards demand.\n//\n// So this panel's whole job is to collect an INTENTION. It never writes a\n// behaviour, a format, a unit, a relation target, a relation maximum, a\n// compute_on or a pattern Rule; every one of those is the store's answer to the\n// type a person picked, and a screen that answered them itself is a second\n// place for the thirteen types to be wrong.\n//\n// The key is derived from the name and shown, never demanded: a blank, unmarked,\n// required box that refused the first attempt every time is what a person hit\n// before anything else on this panel.\n//\n// THE SIXTEENTH TYPE (independent verdict, fifth pass, 19 September). Fifteen\n// of the sixteen went in. \"Total of linked records\" did not: the panel\n// explained honestly that the table had no column pointing at several records\n// — and left Add field live, so pressing it sent a rollup with no relation on\n// it and the store answered \"the field Total hours has to say which relation it\n// reads through — FLD-11: … config.via names a relation Field of this same\n// table, by its key.\" A contract row id and three database words, at the\n// person.\n//\n// Both halves are closed here. The picker now offers EVERY relation column this\n// table has, not only the ones that hold several, and says in one plain\n// sentence what a single-valued one cannot do — because \"Crew lead\" IS the\n// column a person means, and hiding it taught them nothing. And the panel never\n// sends a declaration it already knows the store must refuse: `whatIsMissing`\n// asks, in this panel's own words, what has not been answered yet, the sentence\n// sits under the button, and the button says so rather than failing.\n\nimport { useMemo, useState } from \"react\";\nimport {\n type ContextPolicy,\n type Field,\n type FieldPatch,\n type FieldRule,\n type FieldSensitivity,\n type NewFieldDeclaration,\n type Uuid,\n} from \"@ai-matrx/records\";\nimport { useFieldMutation, useFields, useRecords, useTable } from \"@ai-matrx/records/react\";\nimport {\n BasicInput,\n BasicTextarea,\n Button,\n Checkbox,\n Label,\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n Separator,\n cn,\n} from \"@ai-matrx/design-system\";\nimport { editorKindFor } from \"./parity\";\nimport {\n FIELD_TYPE_CHOICES,\n FIELD_TYPE_GROUPS,\n fieldTypeChoice,\n isPlainFieldType,\n type PickableFieldType,\n} from \"./fieldTypes\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { fieldName, humanize } from \"./names\";\n\nconst RULE_KINDS: { kind: FieldRule[\"kind\"]; label: string }[] = [\n { kind: \"min\", label: \"At least\" },\n { kind: \"max\", label: \"At most\" },\n { kind: \"length\", label: \"No longer than\" },\n { kind: \"pattern\", label: \"Looks like\" },\n { kind: \"equals_field\", label: \"Same as the column\" },\n { kind: \"differs_from_field\", label: \"Different from the column\" },\n];\n\n/** FLD-12, in the words the setting actually means to the person setting it. */\nconst SENSITIVITIES: { value: string; label: string }[] = [\n { value: \"public\", label: \"Anyone who can open the record\" },\n { value: \"internal\", label: \"People in this organization\" },\n { value: \"confidential\", label: \"People who have been given the record\" },\n { value: \"restricted\", label: \"Owners and administrators only\" },\n];\n\nconst AGENT_VISIBILITY: { value: string; label: string }[] = [\n { value: \"include\", label: \"Yes, an assistant can read it\" },\n { value: \"summarize\", label: \"Only a summary of it\" },\n { value: \"on_request\", label: \"Only when somebody asks for it\" },\n { value: \"exclude\", label: \"No, keep it away from assistants\" },\n];\n\nconst ROLLUP_OPERATIONS: { value: NonNullable<NewFieldDeclaration[\"agg\"]>; label: string }[] = [\n { value: \"count\", label: \"How many there are\" },\n { value: \"sum\", label: \"The total of\" },\n { value: \"avg\", label: \"The average of\" },\n { value: \"min\", label: \"The smallest\" },\n { value: \"max\", label: \"The largest\" },\n];\n\nconst FORMULA_OPERATIONS: { value: string; label: string; joins: boolean }[] = [\n { value: \"concat\", label: \"Join them together\", joins: true },\n { value: \"add\", label: \"Add them up\", joins: true },\n { value: \"sub\", label: \"Take the second from the first\", joins: false },\n { value: \"mul\", label: \"Multiply them\", joins: true },\n { value: \"div\", label: \"Divide the first by the second\", joins: false },\n];\n\n/** `Day rate` → `day_rate`. Shown, so nothing about it is a surprise. */\nexport function keyFor(label: string): string {\n const token = label\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 48);\n if (token === \"\") return \"\";\n return /^[a-z]/.test(token) ? token : `f_${token}`;\n}\n\nexport interface FieldEditorProps {\n tableId: Uuid;\n /** The Field being edited. Absent means a new one. */\n field?: Field | undefined;\n onSaved?: (() => void) | undefined;\n onCancel?: (() => void) | undefined;\n /** Called after the store has accepted the removal, so the list can re-read. */\n onRemoved?: (() => void) | undefined;\n className?: string | undefined;\n}\n\nexport function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }: FieldEditorProps) {\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const mutation = useFieldMutation();\n\n const [label, setLabel] = useState(field?.label ?? \"\");\n const [type, setType] = useState<PickableFieldType>(() => startingType(field));\n const [required, setRequired] = useState(field?.required ?? false);\n const [multi, setMulti] = useState(field?.multi ?? false);\n const [dated, setDated] = useState(field?.dated ?? false);\n const [sensitivity, setSensitivity] = useState(String(field?.sensitivity ?? \"internal\"));\n const [contextPolicy, setContextPolicy] = useState(String(field?.context_policy ?? \"include\"));\n const [rules, setRules] = useState<FieldRule[]>(field?.rules ?? []);\n const [optionText, setOptionText] = useState(\"\");\n const [unit, setUnit] = useState(field?.unit ?? \"$\");\n const [withTime, setWithTime] = useState(String(field?.config?.[\"kind\"] ?? \"date\") === \"datetime\");\n const [via, setVia] = useState(String(field?.config?.[\"via\"] ?? \"\"));\n const [pick, setPick] = useState(String(field?.config?.[\"pick\"] ?? \"\"));\n const [agg, setAgg] = useState<NonNullable<NewFieldDeclaration[\"agg\"]>>(\n (field?.config?.[\"agg\"] as NewFieldDeclaration[\"agg\"]) ?? \"count\",\n );\n const [of, setOf] = useState(String(field?.config?.[\"of\"] ?? \"\"));\n const [formulaOp, setFormulaOp] = useState(\"concat\");\n const [formulaFields, setFormulaFields] = useState<string[]>([]);\n const [askingToRemove, setAskingToRemove] = useState(false);\n\n const others = useMemo(\n () => (fields.data ?? []).filter((f) => f.id !== field?.id),\n [fields.data, field?.id],\n );\n const relations = useMemo(() => others.filter((f) => f.type === \"relation\"), [others]);\n const choice = fieldTypeChoice(type);\n const editing = Boolean(field);\n // The key is DERIVED, never asked for and never shown: the blank, unmarked,\n // required box it replaced refused the first attempt on this panel every\n // time, and the line that printed the derived token instead was the last\n // machine identity on this screen. `keyFor` stays exported for callers that\n // need to predict it; a person does not.\n\n // SCR-4: a person who does not administer the table never sees this panel.\n if (!rights.structure) {\n return (\n <p className={cn(\"text-xs text-muted-foreground\", className)}>\n {/* Honest, not dead: the reason, in a sentence — what level it takes\n and who can give it to you. */}\n {rights.why(\"structure\")}\n </p>\n );\n }\n\n const options = optionText\n .split(\"\\n\")\n .map((word) => word.trim())\n .filter((word) => word !== \"\");\n\n /**\n * WHAT THIS PANEL STILL NEEDS, in the words of the panel that asked for it.\n *\n * Never the store's sentence: the store refuses by contract row and document\n * path, which is right for a caller and wrong for a person. `null` means the\n * declaration is complete as far as this screen can tell — the store is still\n * the one that decides, and whatever it says then is shown as it always was.\n */\n const missing = editing ? null : whatIsMissing({ type, label, options, via, pick, agg, of, relations, formulaFields });\n\n const save = async () => {\n // A declaration this panel already knows is incomplete is not sent. The\n // person gets the sentence beside the button, now, instead of a refusal\n // written for a caller, a second later.\n if (missing) return;\n if (editing && field) {\n const patch: FieldPatch = {\n label,\n required,\n dated,\n sensitivity: sensitivity as FieldSensitivity,\n context_policy: contextPolicy as ContextPolicy,\n rules,\n ...(unitApplies(type) ? { unit } : {}),\n // An empty box means \"leave the choices alone\"; a list replaces them.\n ...(optionText.trim() === \"\" ? {} : { options }),\n };\n const written = await mutation.update({ field_id: field.id, patch });\n if (written !== null) onSaved?.();\n return;\n }\n const spec: NewFieldDeclaration = {\n label,\n ...(isPlainFieldType(type) ? { plain: type } : { parity_type: type }),\n required,\n dated,\n multi: multiApplies(type) ? multi : type === \"multi_select\",\n sensitivity: sensitivity as FieldSensitivity,\n context_policy: contextPolicy as ContextPolicy,\n rules,\n ...(type === \"select\" || type === \"multi_select\" ? { options } : {}),\n ...(type === \"currency\" ? { unit } : {}),\n ...(type === \"datetime\" ? { kind: withTime ? (\"datetime\" as const) : (\"date\" as const) } : {}),\n ...(type === \"lookup\" ? { via, pick } : {}),\n ...(type === \"rollup\" ? { via, agg, ...(agg === \"count\" ? {} : { of }) } : {}),\n ...(type === \"formula\" ? { expr: formulaExpression(formulaOp, formulaFields) } : {}),\n };\n const written = await mutation.declare({ table_id: tableId, spec });\n if (written !== null) onSaved?.();\n };\n\n const remove = async () => {\n if (!field) return;\n const gone = await mutation.retire({ field_id: field.id });\n setAskingToRemove(false);\n if (gone) (onRemoved ?? onSaved)?.();\n };\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-3 text-xs\", className)}>\n {/* One row of header: what this is, and nothing restating it. */}\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{field ? `Field · ${fieldName(field)}` : \"New field\"}</span>\n <span className=\"ml-auto text-muted-foreground\">{table.data?.name}</span>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">Name</Label>\n <BasicInput\n value={label}\n autoFocus\n aria-label=\"Field name\"\n placeholder=\"Day rate\"\n onChange={(e) => setLabel(e.target.value)}\n />\n <p className=\"text-[11px] text-muted-foreground\">What people will read at the top of the column.</p>\n </label>\n\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">What it holds</Label>\n <Select\n value={type}\n disabled={editing}\n onValueChange={(next) => setType(next as PickableFieldType)}\n >\n <SelectTrigger size=\"sm\" aria-label=\"What this field holds\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FIELD_TYPE_GROUPS.map((group) => (\n <SelectGroup key={group}>\n <SelectLabel>{group}</SelectLabel>\n {FIELD_TYPE_CHOICES.filter((c) => c.group === group).map((c) => (\n <SelectItem key={c.id} value={c.id}>\n {c.label}\n </SelectItem>\n ))}\n </SelectGroup>\n ))}\n </SelectContent>\n </Select>\n <p className=\"text-[11px] text-muted-foreground\">\n {editing\n ? \"What a column holds cannot be changed here — every value already saved would have to be converted. Add a new column and move the values across.\"\n : (choice?.explanation ?? \"\")}\n </p>\n </div>\n </div>\n\n {/* WHAT THE PANEL ASKS FOR NEXT depends entirely on the answer above, and\n nothing else on this panel knows the difference between the sixteen. */}\n {!editing || type === \"select\" || type === \"multi_select\" ? (\n <TypeQuestions\n type={type}\n editing={editing}\n optionText={optionText}\n setOptionText={setOptionText}\n unit={unit}\n setUnit={setUnit}\n withTime={withTime}\n setWithTime={setWithTime}\n via={via}\n setVia={setVia}\n pick={pick}\n setPick={setPick}\n agg={agg}\n setAgg={setAgg}\n of={of}\n setOf={setOf}\n formulaOp={formulaOp}\n setFormulaOp={setFormulaOp}\n formulaFields={formulaFields}\n setFormulaFields={setFormulaFields}\n relations={relations}\n others={others}\n existingOptionsTable={Boolean(field?.options_table_id ?? field?.config?.[\"options_table_id\"])}\n />\n ) : null}\n\n <div className=\"flex flex-wrap items-center gap-4\">\n <label className=\"flex items-center gap-1.5\">\n <Checkbox\n checked={required}\n aria-label=\"Every record has to have one\"\n onCheckedChange={(v) => setRequired(v === true)}\n />\n Every record has to have one\n </label>\n {multiApplies(type) ? (\n <label className=\"flex items-center gap-1.5\">\n <Checkbox\n checked={multi}\n disabled={editing}\n aria-label=\"Can hold more than one\"\n onCheckedChange={(v) => setMulti(v === true)}\n />\n Can hold more than one\n </label>\n ) : null}\n <label className=\"flex items-center gap-1.5\">\n <Checkbox\n checked={dated}\n aria-label=\"Each value has its own date\"\n onCheckedChange={(v) => setDated(v === true)}\n />\n Each value has its own date\n </label>\n </div>\n\n <Separator />\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">Who can see what is in it</Label>\n <Select value={sensitivity} onValueChange={setSensitivity}>\n <SelectTrigger size=\"sm\" aria-label=\"Who can see what is in it\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SENSITIVITIES.map((row) => (\n <SelectItem key={row.value} value={row.value}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">Can an assistant read it</Label>\n <Select value={contextPolicy} onValueChange={setContextPolicy}>\n <SelectTrigger size=\"sm\" aria-label=\"Can an assistant read it\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {AGENT_VISIBILITY.map((row) => (\n <SelectItem key={row.value} value={row.value}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <Separator />\n\n {/* FLD-3: a constraint is a RULE attached to the Field, never a behaviour. */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">What counts as a good value</span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"ml-auto\"\n onClick={() => setRules([...rules, { kind: \"min\", value: 0 }])}\n >\n Add a check\n </Button>\n </div>\n {rules.length === 0 ? (\n <p className=\"text-muted-foreground\">No checks. Anything this kind of column can hold will be accepted.</p>\n ) : null}\n {rules.map((rule, index) => (\n <div key={`${rule.kind}-${index}`} className=\"flex items-center gap-1\">\n <Select\n value={rule.kind}\n onValueChange={(kind) =>\n setRules(rules.map((r, i) => (i === index ? { ...r, kind: kind as FieldRule[\"kind\"] } : r)))\n }\n >\n <SelectTrigger size=\"sm\" className=\"w-52\" aria-label={`Check ${index + 1}`}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RULE_KINDS.map((row) => (\n <SelectItem key={row.kind} value={row.kind}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <BasicInput\n className=\"h-8\"\n value={String(rule.value ?? \"\")}\n aria-label={`Check ${index + 1} value`}\n onChange={(e) => setRules(rules.map((r, i) => (i === index ? { ...r, value: e.target.value } : r)))}\n />\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Remove check ${index + 1}`}\n onClick={() => setRules(rules.filter((_, i) => i !== index))}\n >\n ×\n </Button>\n </div>\n ))}\n </div>\n\n {mutation.error ? <RefusalNotice error={mutation.error} /> : null}\n\n {/* WHAT IS STILL MISSING, where the person is about to press. Not a\n disabled button with nothing beside it, and not a refusal from the\n store a second after the press: the sentence and the control are one\n thing, and the sentence names what to do. */}\n {missing ? <p className=\"text-[11px] text-destructive\">{missing}</p> : null}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n size=\"sm\"\n disabled={mutation.saving || missing !== null}\n onClick={() => void save()}\n >\n {mutation.saving ? \"Saving…\" : field ? \"Save field\" : \"Add field\"}\n </Button>\n {onCancel ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n {field ? (\n <div className=\"ml-auto flex items-center gap-2\">\n {askingToRemove ? (\n <>\n {/* Destructive, so the consequence is named BEFORE it happens. */}\n <span className=\"text-destructive\">\n Removing {fieldName(field)} takes it off every record of this table. The values stay in\n the record's history and nothing else is deleted.\n </span>\n <Button size=\"sm\" variant=\"destructive\" disabled={mutation.saving} onClick={() => void remove()}>\n Remove it\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAskingToRemove(false)}>\n Keep it\n </Button>\n </>\n ) : (\n <Button size=\"sm\" variant=\"outline\" onClick={() => setAskingToRemove(true)}>\n Remove this field\n </Button>\n )}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\n/**\n * WHAT THE PANEL STILL NEEDS BEFORE THE STORE WOULD TAKE THIS, in plain words.\n *\n * It answers exactly the questions this panel asked, so every sentence names a\n * control the person is looking at. It is NOT a second copy of the store's\n * rules and it is not allowed to become one: the store decides, and every one\n * of these is something the panel can see is unanswered without asking it.\n *\n * Exported so the suite can assert the sentences without driving the whole\n * panel, and so the red twin can assert that removing it puts the contract row\n * id back in front of a person.\n */\nexport function whatIsMissing(state: {\n type: PickableFieldType;\n label: string;\n options: string[];\n via: string;\n pick: string;\n agg: NonNullable<NewFieldDeclaration[\"agg\"]>;\n of: string;\n relations: Field[];\n formulaFields: string[];\n}): string | null {\n const { type, label, options, via, pick, agg, of, relations, formulaFields } = state;\n if (label.trim() === \"\") return \"Give the column a name.\";\n\n if (type === \"select\" || type === \"multi_select\") {\n if (options.length === 0) return \"Type the choices this column offers, one per line.\";\n return null;\n }\n\n if (type === \"lookup\" || type === \"rollup\") {\n if (relations.length === 0) {\n return type === \"rollup\"\n ? \"A total is worked out across the records a column points at, and this table has no column that points at records yet. Add a Person or File column that can hold more than one, then come back.\"\n : \"A borrowed value is read from a record a column points at, and this table has no column that points at another record yet. Add a Person or File column, then come back.\";\n }\n const chosen = relations.find((relation) => relation.key === via);\n if (!chosen) {\n return type === \"rollup\"\n ? \"Choose the column whose records this one adds up.\"\n : \"Choose the column whose record this one reads from.\";\n }\n // THE ONE THE VERDICT HIT. The column a person means is usually there and\n // simply holds one thing; saying which column and what to do about it beats\n // hiding it from the list and beats \"config.via names a relation Field\".\n if (type === \"rollup\" && !chosen.multi) {\n return `${fieldName(chosen)} points at one record at a time, so there is nothing to total. Tick \"Can hold more than one\" on ${fieldName(chosen)}, or use Borrowed value to read its one value.`;\n }\n if (type === \"lookup\" && pick.trim() === \"\") {\n return `Say which value to read from the record ${fieldName(chosen)} points at.`;\n }\n if (type === \"rollup\" && agg !== \"count\" && of.trim() === \"\") {\n return \"Say which value of those records to work out.\";\n }\n return null;\n }\n\n // NOT THE FORMULA. A worked-out column with no columns picked is something\n // the store already accepts (it writes `{op, args:[{const:\"\"}]}`) and\n // FIELD-ADD's suite already declares that way. Blocking it here would be this\n // lane changing a behaviour outside the three types its brief names, and it\n // silently swallowed that lane's seventeenth column when it did. If it should\n // be refused, it is the store's rule to make and its suite to move.\n return null;\n}\n\n/** Whether \"can hold more than one\" is a question for this type at all. */\nfunction multiApplies(type: PickableFieldType): boolean {\n return type === \"member\" || type === \"attachment\" || type === \"text\";\n}\n\nfunction unitApplies(type: PickableFieldType): boolean {\n return type === \"currency\";\n}\n\n/** Which of the sixteen an existing Field already is. */\nfunction startingType(field: Field | undefined): PickableFieldType {\n if (!field) return \"text\";\n const kind = editorKindFor(field);\n if (fieldTypeChoice(kind)) return kind as PickableFieldType;\n return \"text\";\n}\n\n/**\n * REC-15 / REC-17: a Rule expression is an object of nodes, and it points at a\n * Field BY ITS ID, never by its name — a name changes and the rule would stop\n * resolving. The panel therefore collects columns, not text.\n */\nfunction formulaExpression(op: string, fieldIds: string[]): Record<string, unknown> {\n const args = fieldIds.filter((id) => id !== \"\").map((id) => ({ field: id }));\n if (args.length === 0) return { op, args: [{ const: \"\" }] };\n return { op, args };\n}\n\nfunction TypeQuestions(props: {\n type: PickableFieldType;\n editing: boolean;\n optionText: string;\n setOptionText: (value: string) => void;\n unit: string;\n setUnit: (value: string) => void;\n withTime: boolean;\n setWithTime: (value: boolean) => void;\n via: string;\n setVia: (value: string) => void;\n pick: string;\n setPick: (value: string) => void;\n agg: NonNullable<NewFieldDeclaration[\"agg\"]>;\n setAgg: (value: NonNullable<NewFieldDeclaration[\"agg\"]>) => void;\n of: string;\n setOf: (value: string) => void;\n formulaOp: string;\n setFormulaOp: (value: string) => void;\n formulaFields: string[];\n setFormulaFields: (value: string[]) => void;\n relations: Field[];\n others: Field[];\n existingOptionsTable: boolean;\n}) {\n const { type } = props;\n\n if (type === \"select\" || type === \"multi_select\") {\n return (\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">The choices</Label>\n <BasicTextarea\n rows={4}\n className=\"text-xs\"\n aria-label=\"The choices\"\n placeholder={\"Open\\nIn progress\\nClosed\"}\n value={props.optionText}\n onChange={(e) => props.setOptionText(e.target.value)}\n />\n <p className=\"text-[11px] text-muted-foreground\">\n {props.editing\n ? props.existingOptionsTable\n ? \"One per line. Leave this empty to keep the choices as they are; type a list and it replaces them, keeping the ones that are still here.\"\n : \"One per line. These become this field's choices.\"\n : \"One per line. They are saved with the field — you do not have to make a table for them.\"}\n </p>\n </div>\n );\n }\n\n if (type === \"currency\") {\n return (\n <label className=\"flex max-w-[16rem] flex-col gap-1\">\n <Label className=\"text-xs\">The currency</Label>\n <BasicInput\n value={props.unit}\n aria-label=\"The currency\"\n placeholder=\"$\"\n onChange={(e) => props.setUnit(e.target.value)}\n />\n <p className=\"text-[11px] text-muted-foreground\">\n Shown with every amount, everywhere the value appears — including where an assistant reads it.\n </p>\n </label>\n );\n }\n\n if (type === \"datetime\") {\n return (\n <label className=\"flex items-center gap-1.5\">\n <Checkbox\n checked={props.withTime}\n aria-label=\"Include a time of day\"\n onCheckedChange={(v) => props.setWithTime(v === true)}\n />\n Include a time of day, not just the day\n </label>\n );\n }\n\n if (type === \"lookup\" || type === \"rollup\") {\n // EVERY relation column this table has — including the ones that hold ONE\n // record. A rollup needs one that holds several, and the store says so; but\n // a person looking for \"Crew lead\" and not finding it in the list learns\n // nothing, and the sentence under the button tells them exactly what to do\n // about the one they picked. Hiding the answer is not the same as giving it.\n const usable = props.relations;\n if (usable.length === 0) {\n // NEVER A DEAD CONTROL. The reason, and the thing to do about it.\n return (\n <p className=\"text-[11px] text-muted-foreground\">\n {type === \"rollup\"\n ? \"This kind of column works something out from the records another column points at, and this table has no column that points at records yet. Add a Person or File column that can hold more than one first.\"\n : \"This kind of column reads a value from a record another column points at, and this table has no column that points at another record yet. Add a Person or File column first.\"}\n </p>\n );\n }\n return (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">{type === \"rollup\" ? \"Across the records in\" : \"Read it from\"}</Label>\n <Select value={props.via} onValueChange={props.setVia}>\n <SelectTrigger size=\"sm\" aria-label={type === \"rollup\" ? \"Across the records in\" : \"Read it from\"}>\n <SelectValue placeholder=\"Choose a column\" />\n </SelectTrigger>\n <SelectContent>\n {usable.map((f) => (\n <SelectItem key={f.id} value={f.key}>\n {fieldName(f)}\n {type === \"rollup\" && !f.multi ? \" — holds one\" : \"\"}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {type === \"lookup\" ? (\n <ValueOnTheOtherSide\n label=\"The value to read\"\n help=\"The column on the other record whose value is borrowed.\"\n relation={usable.find((f) => f.key === props.via)}\n value={props.pick}\n onChange={props.setPick}\n />\n ) : (\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">What to work out</Label>\n <Select value={props.agg} onValueChange={(v) => props.setAgg(v as never)}>\n <SelectTrigger size=\"sm\" aria-label=\"What to work out\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ROLLUP_OPERATIONS.map((row) => (\n <SelectItem key={row.value} value={row.value}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {props.agg !== \"count\" ? (\n <ValueOnTheOtherSide\n label=\"Of which value\"\n help=\"The column on those records whose values are worked out.\"\n relation={usable.find((f) => f.key === props.via)}\n value={props.of}\n onChange={props.setOf}\n compact\n />\n ) : null}\n </div>\n )}\n </div>\n );\n }\n\n if (type === \"formula\") {\n if (props.others.length === 0) {\n return (\n <p className=\"text-[11px] text-muted-foreground\">\n A worked-out column needs other columns to work from, and this table has none yet.\n </p>\n );\n }\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">What to do</Label>\n <Select value={props.formulaOp} onValueChange={props.setFormulaOp}>\n <SelectTrigger size=\"sm\" className=\"max-w-[18rem]\" aria-label=\"What to do\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FORMULA_OPERATIONS.map((row) => (\n <SelectItem key={row.value} value={row.value}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">Which columns</Label>\n <div className=\"flex flex-wrap gap-1\">\n {props.others.map((f) => {\n const picked = props.formulaFields.includes(f.id);\n return (\n <Button\n key={f.id}\n type=\"button\"\n size=\"sm\"\n variant={picked ? \"default\" : \"outline\"}\n onClick={() =>\n props.setFormulaFields(\n picked\n ? props.formulaFields.filter((id) => id !== f.id)\n : [...props.formulaFields, f.id],\n )\n }\n >\n {fieldName(f)}\n </Button>\n );\n })}\n </div>\n <p className=\"text-[11px] text-muted-foreground\">\n In the order you pick them. Columns are remembered by which column they are, so renaming one\n never breaks this.\n </p>\n </div>\n </div>\n );\n }\n\n return null;\n}\n\n/**\n * WHICH VALUE, ON THE OTHER SIDE — offered by NAME, never typed as a key.\n *\n * A borrowed value and a total both read one column of the records the chosen\n * relation points at, and this panel used to ask for that column as free text\n * with the placeholder `name`. So the one question on the panel that a person\n * could not answer without knowing an internal key was the last question on the\n * two column types the sixth-pass verdict could not create — and a typo in it\n * is a column that silently borrows nothing.\n *\n * The relation says which Table it points at, so the columns of that Table are\n * simply offered. When it points at nothing yet, this says so and offers\n * nothing, which is the honest half of the same rule.\n *\n * AND A TABLE THE STORE KEEPS ITSELF STILL HAS COLUMNS. `custom.applicable_fields`\n * answers the Fields a table DECLARES, and the kernels declare none: a Person\n * column points at the person kernel, which has 441 records and zero Field rows.\n * So the picker offered nothing for every Person and every File relation — and\n * the only two column types a person cannot build without it are exactly the\n * two the sixth-pass verdict could not build. Measured 2026-09-20.\n *\n * The store reads the far side with `custom.record_values(…) -> pick`\n * (`custom.lookup_value`), so what a pick may name is a KEY THOSE RECORDS\n * CARRY. When the target declares no Fields, this reads one of its records\n * through the ordinary read door and offers the keys it actually has — the same\n * fact the store will use, asked the same way. Nothing is typed, and nothing is\n * guessed.\n */\nfunction ValueOnTheOtherSide({\n label,\n help,\n relation,\n value,\n onChange,\n compact,\n}: {\n label: string;\n help: string;\n relation: Field | undefined;\n value: string;\n onChange: (value: string) => void;\n compact?: boolean | undefined;\n}) {\n const target = (relation?.relation_target ?? null) as Uuid | null;\n const columns = useFields(target);\n const declared = (columns.data ?? []).filter((f) => f.type !== \"formula\");\n // Only asked when the target declares nothing — the ordinary case costs no\n // extra call, and this one is a single row.\n const sample = useRecords(declared.length === 0 && !columns.loading ? target : null, { pageSize: 1 });\n const carried = sample.data?.rows[0]?.document ?? null;\n const offered: { key: string; name: string }[] =\n declared.length > 0\n ? declared.map((f) => ({ key: f.key, name: fieldName(f) }))\n : Object.keys(carried ?? {}).map((key) => ({ key, name: humanize(key) }));\n const stillAsking = columns.loading || (declared.length === 0 && sample.loading);\n\n const body = !relation ? (\n <p className=\"text-[11px] text-muted-foreground\">Choose the column above first.</p>\n ) : stillAsking ? (\n <p className=\"text-[11px] text-muted-foreground\">Reading that table's columns…</p>\n ) : offered.length === 0 ? (\n <p className=\"text-[11px] text-muted-foreground\">\n {fieldName(relation)} points at a table that has no columns to read yet. Add one there first.\n </p>\n ) : (\n <Select value={value} onValueChange={onChange}>\n <SelectTrigger size=\"sm\" aria-label={label}>\n <SelectValue placeholder=\"Choose a column\" />\n </SelectTrigger>\n <SelectContent>\n {offered.map((column) => (\n <SelectItem key={column.key} value={column.key}>\n {column.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n\n if (compact) return <div className=\"mt-1 flex flex-col gap-1\">{body}</div>;\n return (\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">{label}</Label>\n {body}\n <p className=\"text-[11px] text-muted-foreground\">{help}</p>\n </div>\n );\n}\n","\"use client\";\n\n// src/TableSettings.tsx — @ai-matrx/records-ui · SCR-3, SCR-4, SCR-5\n//\n// EVERY FIELD OF ONE TABLE, TO RENAME, REORDER, RETYPE AND DELETE, FROM ONE\n// PANEL — and the agent's pending field proposals in the SAME list, with the\n// same accept and reject on each (SCR-5), because a proposal is a field that\n// has not been agreed to yet, not a different kind of thing in a different\n// place.\n//\n// The panel does not exist at all for somebody who does not administer the\n// table (SCR-4). There is no read-only variant: what it would show, the grid\n// already shows.\n\nimport { useState } from \"react\";\nimport {\n useFieldMutation,\n useFields,\n useRecordMutation,\n useTable,\n type Field,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport { Badge, Button, Separator, cn } from \"@ai-matrx/design-system\";\nimport { FieldEditor } from \"./FieldEditor\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { fieldTypeLabel } from \"./parity\";\nimport { fieldName, tableName } from \"./names\";\n\nexport interface FieldProposalRow {\n id: string;\n /** What the agent proposed, in the Field shape the store would store. */\n field: Partial<Field> & { key: string; label?: string };\n why: string;\n proposed_by: string;\n}\n\nexport interface TableSettingsProps {\n tableId: Uuid;\n /**\n * SCR-5. Pending field proposals. The door that lists them\n * (`custom.field_propose`) does not exist yet — `@ai-matrx/records` answers\n * `door_absent` by name for it — so a host passes what it has, and when it\n * has nothing the section says so rather than pretending there is nothing to\n * approve.\n */\n proposals?: FieldProposalRow[] | undefined;\n onAcceptProposal?: ((proposal: FieldProposalRow) => void) | undefined;\n onRejectProposal?: ((proposal: FieldProposalRow) => void) | undefined;\n /**\n * SCR-3's fourth verb. Called after the store has accepted the delete, so the\n * host can leave a page that is now about a table nobody can open.\n */\n onDeleted?: (() => void) | undefined;\n className?: string | undefined;\n}\n\nexport function TableSettings({\n tableId,\n proposals,\n onAcceptProposal,\n onRejectProposal,\n onDeleted,\n className,\n}: TableSettingsProps) {\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const mutation = useRecordMutation();\n // THE SHAPE OF THE TABLE goes through the store's own field doors, never\n // through the record writer: a field taken off with `record_delete` leaves the\n // TABLE still declaring a column that is gone, which is the same broken half\n // of \"one source of truth\" that made every \"Add field\" refuse.\n const shape = useFieldMutation();\n const [editing, setEditing] = useState<Field | \"new\" | null>(null);\n const [askingToDelete, setAskingToDelete] = useState(false);\n const [askingToRemove, setAskingToRemove] = useState<Field | null>(null);\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (!rights.structure) return <p className={cn(\"text-xs text-muted-foreground\", className)}>{rights.why(\"structure\")}</p>;\n\n const rows = [...(fields.data ?? [])].sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0));\n\n const move = async (field: Field, direction: -1 | 1) => {\n const index = rows.findIndex((r) => r.id === field.id);\n const swap = rows[index + direction];\n if (!swap) return;\n // The order is the Field's own `sort`, so reordering is two ordinary writes\n // through the one write door, not a table-level layout blob.\n await mutation.update({ record_id: field.id, patch: { sort: swap.sort ?? index + direction } });\n await mutation.update({ record_id: swap.id, patch: { sort: field.sort ?? index } });\n fields.reload();\n };\n\n const remove = async (field: Field) => {\n const gone = await shape.retire({ field_id: field.id });\n setAskingToRemove(null);\n if (gone) {\n fields.reload();\n table.reload();\n }\n };\n\n /**\n * DELETING THE TABLE ITSELF — the verb this panel's own header has claimed\n * since SCR-3 and did not have. A walk of the real screens on 19 September\n * made a table and then could not get rid of it from anywhere in the product.\n * A Table is a record, so this is the same soft delete every record gets\n * (REC-23), through the same door, and the panel says exactly that before it\n * happens rather than after.\n */\n const deleteTable = async () => {\n const gone = await mutation.remove({ record_id: tableId });\n setAskingToDelete(false);\n if (gone !== null) onDeleted?.();\n };\n\n if (editing) {\n return (\n <FieldEditor\n tableId={tableId}\n {...(editing === \"new\" ? {} : { field: editing })}\n onSaved={() => {\n setEditing(null);\n fields.reload();\n table.reload();\n }}\n onCancel={() => setEditing(null)}\n className={className}\n />\n );\n }\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-2 text-xs\", className)}>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">Fields</span>\n <span className=\"text-muted-foreground\">{rows.length}</span>\n <Button size=\"sm\" variant=\"outline\" className=\"ml-auto\" onClick={() => setEditing(\"new\")}>\n Add a field\n </Button>\n </div>\n\n {mutation.error ? <RefusalNotice error={mutation.error} /> : null}\n {shape.error ? <RefusalNotice error={shape.error} /> : null}\n\n {/* Destructive, so the consequence is named BEFORE it happens and takes a\n second press — the same shape the table's own delete has below. */}\n {askingToRemove ? (\n <div className=\"flex flex-wrap items-center gap-2 rounded border border-destructive/40 px-2 py-1.5\">\n <span className=\"text-destructive\">\n Removing {fieldName(askingToRemove)} takes it off every record of this table. The values stay in\n each record's history and nothing else is deleted.\n </span>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n disabled={shape.saving}\n onClick={() => void remove(askingToRemove)}\n >\n {shape.saving ? \"Removing…\" : \"Remove it\"}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAskingToRemove(null)}>\n Keep it\n </Button>\n </div>\n ) : null}\n\n <ul className=\"divide-y rounded border\">\n {rows.map((field, index) => (\n <li key={field.id} className=\"flex items-center gap-2 px-2 py-1.5\">\n <span className=\"min-w-0 flex-1 truncate\">{fieldName(field)}</span>\n <Badge variant=\"outline\" className=\"text-[10px] font-normal\">\n {fieldTypeLabel(field)}\n </Badge>\n {field.required ? <span className=\"text-[10px] text-destructive\">required</span> : null}\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Move ${fieldName(field)} up`}\n disabled={index === 0}\n onClick={() => void move(field, -1)}\n >\n ↑\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Move ${fieldName(field)} down`}\n disabled={index === rows.length - 1}\n onClick={() => void move(field, 1)}\n >\n ↓\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setEditing(field)}>\n Edit\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"text-destructive\"\n aria-label={`Remove ${fieldName(field)}`}\n onClick={() => setAskingToRemove(field)}\n >\n Remove\n </Button>\n </li>\n ))}\n {rows.length === 0 ? <li className=\"px-2 py-2 text-muted-foreground\">This table has no fields yet.</li> : null}\n </ul>\n\n <Separator />\n\n {/* SCR-5: proposals are fields in the same list, with the same two verbs. */}\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">Proposed</span>\n <span className=\"text-muted-foreground\">{proposals?.length ?? 0}</span>\n </div>\n {proposals === undefined ? (\n <p className=\"text-muted-foreground\">\n Nothing is listing proposals here yet: the store has no `custom.field_propose` door, so this panel would be\n inventing an empty queue. When the door lands, its rows appear in this list with the same accept and reject.\n </p>\n ) : proposals.length === 0 ? (\n <p className=\"text-muted-foreground\">No field is waiting for a decision.</p>\n ) : (\n <ul className=\"divide-y rounded border\">\n {proposals.map((proposal) => (\n <li key={proposal.id} className=\"flex items-center gap-2 px-2 py-1.5\">\n <span className=\"min-w-0 flex-1 truncate\">{proposal.field.label || proposal.field.key}</span>\n <span className=\"min-w-0 flex-1 truncate text-muted-foreground\">{proposal.why}</span>\n <Badge variant=\"secondary\" className=\"text-[10px] font-normal\">\n {proposal.proposed_by}\n </Badge>\n <Button size=\"sm\" variant=\"outline\" onClick={() => onAcceptProposal?.(proposal)}>\n Accept\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onRejectProposal?.(proposal)}>\n Reject\n </Button>\n </li>\n ))}\n </ul>\n )}\n\n <Separator />\n\n {/* SCR-3. Destructive, so it names the consequence BEFORE it happens and\n takes a second press. There is no undo button here on purpose: the\n restore path is the store's own and it belongs with the record's\n history, not beside the control that did the delete. */}\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium\">This table</span>\n {askingToDelete ? (\n <>\n <p className=\"text-muted-foreground\">\n Deleting {table.data ? tableName(table.data) : \"this table\"} takes it out of everyone's list, with\n its {rows.length} field{rows.length === 1 ? \"\" : \"s\"} and every record in it.\n {table.data?.retention_days\n ? ` The store keeps them for ${table.data.retention_days} days, so it can still be restored.`\n : \" The store keeps them, so it can still be restored.\"}\n </p>\n <div className=\"flex gap-1\">\n <Button size=\"sm\" variant=\"destructive\" disabled={mutation.saving} onClick={() => void deleteTable()}>\n {mutation.saving ? \"Deleting…\" : \"Delete this table\"}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAskingToDelete(false)}>\n Keep it\n </Button>\n </div>\n </>\n ) : (\n <div>\n <Button size=\"sm\" variant=\"outline\" onClick={() => setAskingToDelete(true)}>\n Delete this table\n </Button>\n </div>\n )}\n {mutation.error ? <RefusalNotice error={mutation.error} /> : null}\n </div>\n </div>\n );\n}\n","\"use client\";\n\n// src/Peek.tsx — @ai-matrx/records-ui · SCR-N-3\n//\n// THE GENERIC PEEK, DRIVEN BY THE FIELD RECORDS. There is no per-table peek in\n// this platform: before this, 21 hand-written peeks covered 19 registered\n// catalogue keys and every custom table — 100% of them — fell to \"Peek — coming\n// soon\".\n//\n// It reads the record through the read door, shows every applicable Field's\n// value the way that Field says to show it, and flips to the same\n// `RecordForm` for editing. It carries the Alchemy menu, so everything a person\n// can copy, hand to an agent or export from a record is in the one place it is\n// everywhere else on the platform.\n\nimport { useState } from \"react\";\nimport { useFields, useRecord, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport { AlchemyMenu } from \"@ai-matrx/alchemy/react\";\nimport { Button, Separator, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RecordForm } from \"./RecordForm\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { ShareControl } from \"./ShareControl\";\nimport { useRecordRights, useRecordsUi } from \"./host\";\nimport { ProvenanceBadge, RecordValue } from \"./values\";\nimport { fieldName, humanize, recordName } from \"./names\";\n\nexport interface PeekProps {\n tableId: Uuid;\n recordId: Uuid;\n onClose?: (() => void) | undefined;\n className?: string | undefined;\n}\n\nexport function Peek({ tableId, recordId, onClose, className }: PeekProps) {\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const record = useRecord(recordId, true);\n // THE RECORD'S OWN LEVEL, not the table's. The sixth-pass verdict found a\n // record shared with a colleague at Editor inside a table she held at Viewer;\n // a panel that asked the table would have hidden Edit from the person who had\n // been given it, which is the same lie with the sign flipped.\n const may = useRecordRights(recordId);\n const host = useRecordsUi();\n const organizationId = useRecordsClient().config.organizationId;\n const [editing, setEditing] = useState(false);\n\n if (record.error) return <RefusalNotice error={record.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n\n const document = record.data?.document;\n // REC-2: the Table's own title field is what makes a record a chip. A record\n // with nothing readable says so — a truncated uuid tells a person nothing and\n // reads like a bug (`names.ts`).\n const title = document ? recordName(document, table.data?.title_field) : \"\";\n const href = host.hrefForRecord && table.data ? host.hrefForRecord({ table: table.data, recordId }) : undefined;\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-2 text-xs\", className)}>\n {/* ONE row of header: the title, the controls. Nothing repeats the name. */}\n <div className=\"flex items-center gap-2\">\n <h3 className=\"min-w-0 flex-1 truncate text-sm font-medium\">\n {record.loading && !document ? <Skeleton className=\"h-4 w-40\" /> : title}\n </h3>\n <AlchemyMenu\n label={title || \"Record\"}\n sourceId={`record:${recordId}`}\n size=\"xs\"\n human={() =>\n (fields.data ?? [])\n .map((field) => `${fieldName(field)}: ${String(document?.[field.key] ?? \"\")}`)\n .join(\"\\n\")\n }\n json={() => document ?? {}}\n />\n {href ? (\n <a className=\"text-primary underline-offset-2 hover:underline\" href={href}>\n Open\n </a>\n ) : null}\n {/* SCR-N-5. Beside Edit, where a person looks for it. */}\n <ShareControl kind=\"record\" organizationId={organizationId} subjectId={recordId} name={title} may={may.share} />\n {may.write ? (\n <Button size=\"sm\" variant={editing ? \"ghost\" : \"outline\"} onClick={() => setEditing((e) => !e)}>\n {editing ? \"Stop editing\" : \"Edit\"}\n </Button>\n ) : may.known ? (\n // Absent AND explained: no Edit button, and one sentence saying what\n // it would take and who can give it.\n <span className=\"max-w-[18rem] text-[11px] text-muted-foreground\">{may.why(\"write\")}</span>\n ) : null}\n {onClose ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={onClose} aria-label=\"Close\">\n ×\n </Button>\n ) : null}\n </div>\n\n <Separator />\n\n {editing ? (\n <RecordForm\n tableId={tableId}\n recordId={recordId}\n onSaved={() => {\n setEditing(false);\n record.reload();\n }}\n onCancel={() => setEditing(false)}\n />\n ) : (\n <dl className=\"grid grid-cols-[minmax(6rem,12rem)_1fr] gap-x-3 gap-y-1.5\">\n {(fields.data ?? []).map((field) => (\n <div key={field.id} className=\"contents\">\n <dt className=\"flex items-baseline gap-1 truncate text-muted-foreground\">\n {fieldName(field)}\n <ProvenanceBadge document={document} fieldKey={field.key} />\n </dt>\n <dd className=\"min-w-0\"><RecordValue field={field} value={document?.[field.key]} document={document} /></dd>\n </div>\n ))}\n </dl>\n )}\n\n {/* FLD-9: what the system worked out, and where it came from. */}\n {record.data?.computed?.length ? (\n <>\n <Separator />\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium\">Worked out by the system</span>\n {/* FLD-9 / REC-19, in a person's words. This used to print the\n provenance row as raw JSON — the field key, two uuids and a\n version number — which is the machinery showing through that the\n verdict counted three times. */}\n {record.data.computed.map((row, i) => (\n <p key={i} className=\"text-muted-foreground\">\n {computedInPlainWords(row, (fields.data ?? []).find((f) => f.key === row.field_key))}\n </p>\n ))}\n </div>\n </>\n ) : null}\n </div>\n );\n}\n\n/**\n * One line of provenance, as a person reads it: which column, what it worked\n * out to, and when. The rule id and its version are facts for an engineer and\n * live on the title attribute of nothing a person has to read.\n */\nfunction computedInPlainWords(\n row: { field_key: string; value: unknown; computed_at: string },\n field: { label?: string | null; name?: string | null; key: string } | undefined,\n): string {\n const name = field ? fieldName(field as never) : humanize(row.field_key);\n const shown = row.value === null || row.value === undefined || row.value === \"\" ? \"nothing\" : String(row.value);\n const when = new Date(row.computed_at);\n const at = Number.isNaN(when.getTime()) ? \"\" : ` on ${when.toLocaleDateString()}`;\n return `${name} was worked out as ${shown}${at}.`;\n}\n","\"use client\";\n\n// src/RecordForm.tsx — @ai-matrx/records-ui · SCR-N-1\n//\n// THE GENERIC CREATE / EDIT FORM, RESOLVED FROM THE FIELD RECORDS. Before it,\n// every create and edit form in the product was hand-written per feature, which\n// is why a custom table could not open a record at all.\n//\n// Two honest halves:\n// · BEFORE the write, the mirror (`predictWriteRefusals`) says what the store\n// is about to refuse, in the store's own sentence. It is not validation —\n// the store validates — it just says it half a second earlier.\n// · AFTER the write, whatever the store said is shown verbatim, including the\n// conflict object when somebody else wrote first.\n//\n// It never blocks a save on its own opinion: the mirror's sentences are shown,\n// and the write is still attempted, because the store is the one that decides.\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport {\n useFields,\n useRecord,\n useRecordMutation,\n type Field,\n type RecordDocument,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport { predictWriteRefusals } from \"@ai-matrx/records/core\";\nimport { Button, Separator, cn } from \"@ai-matrx/design-system\";\nimport { FieldControl, FieldLabel } from \"./editors\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi } from \"./host\";\nimport { ProvenanceBadge } from \"./values\";\nimport { useRecordVersion } from \"./systemTable\";\nimport { fieldName, humanize } from \"./names\";\n\nexport interface RecordFormProps {\n tableId: Uuid;\n /** Absent means \"create\". Present means \"edit that record\". */\n recordId?: Uuid | undefined;\n /** FLD-10: which Fields apply is the store's decision, and it takes the record type. */\n recordType?: string | undefined;\n onSaved?: ((recordId: Uuid) => void) | undefined;\n onCancel?: (() => void) | undefined;\n className?: string | undefined;\n}\n\nexport function RecordForm({\n tableId,\n recordId,\n recordType,\n onSaved,\n onCancel,\n className,\n}: RecordFormProps) {\n const host = useRecordsUi();\n const fields = useFields(tableId, recordType);\n const existing = useRecord(recordId ?? null);\n const mutation = useRecordMutation();\n const [draft, setDraft] = useState<Record<string, unknown>>({});\n const [touched, setTouched] = useState(false);\n // REC-9: the version this form LOADED, so a second writer is TOLD rather than\n // overwritten. The read door answers documents, never versions.\n const loaded = useRecordVersion(recordId ?? null);\n const loadedVersion = loaded.version;\n\n // The record's own document is the starting draft. A form that started empty\n // over an existing record would silently propose blanking every field.\n useEffect(() => {\n const document = existing.data?.document;\n if (document) setDraft({ ...document });\n }, [existing.data?.record_id, loadedVersion]);\n\n const document = useMemo<RecordDocument>(() => {\n const out: RecordDocument = {};\n for (const [key, value] of Object.entries(draft)) {\n if (key.startsWith(\"_\")) continue;\n if (value !== undefined) out[key] = value;\n }\n return out;\n }, [draft]);\n\n const predicted = useMemo(\n () => (fields.data ? predictWriteRefusals({ fields: fields.data, document, ...(recordType ? { recordType } : {}) }) : []),\n [fields.data, document, recordType],\n );\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (existing.error) return <RefusalNotice error={existing.error} className={className} />;\n\n const save = async () => {\n setTouched(true);\n if (recordId) {\n const version = loadedVersion;\n const moved = await mutation.update({\n record_id: recordId,\n patch: document,\n ...(version === null ? {} : { expectedVersion: version }),\n });\n if (moved !== null) {\n // The store's own new version, so saving twice in a row is two saves\n // and not a conflict with yourself.\n loaded.note(moved);\n host.notify?.success(\"Saved\");\n existing.reload();\n onSaved?.(recordId);\n }\n return;\n }\n const written = await mutation.write({ table_id: tableId, data: document });\n if (written) {\n host.notify?.success(\"Saved\");\n onSaved?.(written);\n }\n };\n\n return (\n <form\n className={cn(\"flex min-w-0 flex-col gap-3\", className)}\n onSubmit={(e) => {\n e.preventDefault();\n void save();\n }}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {(fields.data ?? []).map((field) => (\n <FieldRow\n key={field.id}\n field={field}\n value={draft[field.key]}\n document={existing.data?.document}\n problems={touched ? predicted.filter((p) => p.field_key === field.key) : []}\n onChange={(value) => setDraft((d) => ({ ...d, [field.key]: value }))}\n />\n ))}\n </div>\n\n {/* A refusal with no field of its own — a size or envelope refusal. */}\n {touched\n ? predicted\n .filter((p) => !p.field_key)\n .map((p) => (\n <p key={p.message} className=\"text-xs text-destructive\">\n {p.message}\n </p>\n ))\n : null}\n\n {mutation.error ? (\n <RefusalNotice\n error={mutation.error}\n {...(mutation.conflict\n ? {\n actions: (\n <div className=\"mt-1 space-y-1\">\n {/* The conflict, column by column, in the columns' own\n names — this used to print the machine key and two\n JSON blobs in a monospace font at the person. */}\n {Object.entries(mutation.conflict.contested_fields).map(([key, theirs]) => {\n const column = (fields.data ?? []).find((f) => f.key === key);\n return (\n <p key={key} className=\"text-[11px]\">\n {column ? fieldName(column) : humanize(key)}: yours{\" \"}\n <strong>{asWords(draft[key])}</strong> · theirs <strong>{asWords(theirs)}</strong>\n </p>\n );\n })}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n existing.reload();\n mutation.clearConflict();\n }}\n >\n Take theirs and start again\n </Button>\n </div>\n ),\n }\n : {})}\n />\n ) : null}\n\n <Separator />\n <div className=\"flex items-center gap-2\">\n <Button type=\"submit\" size=\"sm\" disabled={mutation.saving}>\n {mutation.saving ? \"Saving…\" : recordId ? \"Save\" : \"Create\"}\n </Button>\n {onCancel ? (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n </div>\n </form>\n );\n}\n\nfunction FieldRow({\n field,\n value,\n document,\n problems,\n onChange,\n}: {\n field: Field;\n value: unknown;\n document: RecordDocument | undefined;\n problems: Array<{ message: string }>;\n onChange: (value: unknown) => void;\n}) {\n const id = `field-${field.id}`;\n return (\n <div className=\"flex min-w-0 flex-col gap-1\">\n <FieldLabel field={field} htmlFor={id}>\n <ProvenanceBadge document={document} fieldKey={field.key} />\n </FieldLabel>\n <FieldControl field={field} value={value} onChange={onChange} id={id} />\n {problems.map((problem) => (\n <p key={problem.message} className=\"text-xs text-destructive\">\n {problem.message}\n </p>\n ))}\n </div>\n );\n}\n\n/** A value as a person reads it. Never a JSON blob, never an empty string. */\nfunction asWords(value: unknown): string {\n if (value === null || value === undefined || value === \"\") return \"nothing\";\n if (Array.isArray(value)) return value.length === 0 ? \"nothing\" : `${value.length} of them`;\n if (typeof value === \"object\") return \"something this screen cannot show in a line\";\n return String(value);\n}\n","\"use client\";\n\n// src/systemTable.ts — @ai-matrx/records-ui\n//\n// THE PACKAGE'S OWN TABLES, MADE THE WAY EVERY OTHER TABLE IS MADE.\n//\n// A saved view, a queued action, a comment and a form are all RECORDS. They are\n// not a second storage system bolted onto the side of the record store, and\n// they are not rows this package writes into `platform.*` behind the store's\n// back — the data source port this package's client speaks has no insert on it\n// at all, on purpose. So each of them is an ordinary Table in the organization's\n// own store, declared once, through the store's own doors:\n//\n// 1. REC-1 — a Table has to live somewhere, and a Home is an ordinary record\n// in the person kernel, so a Home is written first (`record_write`).\n// 2. `table_declare` declares the Table under that Home.\n// 3. Each Field is a record in the field kernel carrying the new Table's id.\n//\n// That is exactly the sequence the store forced on us: declaring a Table with\n// no Home is refused by `custom._table_shape_guard` with \"a table has to live\n// somewhere - give it a home\". Nothing here works around a guard; it obeys one.\n//\n// WHAT THIS BUYS: a saved view is readable, exportable, historied, commentable\n// and agent-writable by every other component in this package, for free,\n// because it is a record like any other. An agent can write a whole view — or a\n// whole form — with one `record_write`.\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport type { RecordsClient } from \"@ai-matrx/records/core\";\nimport type { RecordsError, Uuid } from \"@ai-matrx/records\";\n\n/** One Field of a package-owned Table, in the store's own words. */\nexport interface SystemFieldSpec {\n key: string;\n label: string;\n /** FLD-1: one of the five behaviours. `text` covers the json-ish ones too. */\n type: \"text\" | \"range\" | \"list\" | \"relation\" | \"formula\";\n sort: number;\n required?: boolean;\n multi?: boolean;\n config?: Record<string, unknown>;\n}\n\nexport interface SystemTableSpec {\n /** The token this Table is addressed by. Every package table starts `records_ui_`. */\n slug: string;\n name: string;\n labelSingular: string;\n labelPlural: string;\n titleField: string;\n fields: SystemFieldSpec[];\n}\n\n/**\n * One in-flight declaration per (organization, slug), so two components that\n * mount at the same moment do not declare the same Table twice. Keyed by the\n * organization, never global: two organizations in two tabs never share one.\n */\nconst inFlight = new Map<string, Promise<Uuid>>();\n\n/** Find this organization's copy of a package-owned Table, declaring it the first time. */\nexport async function ensureSystemTable(\n client: RecordsClient,\n spec: SystemTableSpec,\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const cacheKey = `${client.config.organizationId}:${spec.slug}`;\n const running = inFlight.get(cacheKey);\n if (running) {\n try {\n return { ok: true, data: await running };\n } catch {\n inFlight.delete(cacheKey);\n }\n }\n\n const tables = await client.tableList();\n if (!tables.ok) return tables;\n const found = tables.data.find((t) => t.slug === spec.slug);\n if (found) {\n // A PACKAGE TABLE GROWS. A later version of this package declares a Field\n // the organization's copy was made without, and an organization that got\n // its copy first would otherwise be the one where the new Field silently\n // does not exist. So every load reconciles: the Fields in the spec that\n // the Table has not got are added, through the same two writes a Field is\n // always made with. Nothing is ever renamed or removed here.\n const grown = await addMissingFields(client, spec, found.id);\n if (!grown.ok) return grown;\n // A PACKAGE TABLE ALSO CHANGES SHAPE. Adding what is missing is only half\n // of level: a Field the organization already holds can carry a DIFFERENT\n // behaviour from the one this version of the package declares, and then\n // every write of that Field is refused by the store for a reason the\n // person cannot act on. See `reconcileFieldShapes`.\n const levelled = await reconcileFieldShapes(client, spec, found.id);\n if (!levelled.ok) return levelled;\n return { ok: true, data: found.id };\n }\n\n let settle: (id: Uuid) => void = () => undefined;\n let fail: (reason: unknown) => void = () => undefined;\n const pending = new Promise<Uuid>((resolve, reject) => {\n settle = resolve;\n fail = reject;\n });\n // The refusal is RETURNED, below, as this package's never-throw envelope.\n // Without this the same refusal is also an unhandled promise rejection on\n // every host that never happened to have a second caller waiting here — a\n // red console (and, under a test runner, a failed run) for a refusal that\n // was in fact reported properly.\n pending.catch(() => undefined);\n inFlight.set(cacheKey, pending);\n\n const declared = await declare(client, spec);\n if (declared.ok) settle(declared.data);\n else {\n fail(declared.error);\n inFlight.delete(cacheKey);\n }\n return declared;\n}\n\n/**\n * The Fields of `spec` the organization's copy of this Table has not got yet,\n * added the way a Field is always added: the Table's own declaration first\n * (REC-1 — the Table declares its fields), then the definition in the field\n * kernel. Idempotent, and a no-op for a Table that is already level.\n */\nasync function addMissingFields(\n client: RecordsClient,\n spec: SystemTableSpec,\n tableId: Uuid,\n): Promise<{ ok: true; data: true } | { ok: false; error: RecordsError }> {\n const held = await client.fields({ table_id: tableId });\n if (!held.ok) return held;\n const have = new Set(held.data.map((f) => f.key));\n const missing = spec.fields.filter((f) => !have.has(f.key));\n if (missing.length === 0) return { ok: true, data: true };\n\n const fieldKernel = await client.fieldKernelId();\n if (!fieldKernel.ok) return fieldKernel;\n\n const declaration = [...held.data.map((f) => ({ name: f.key })), ...missing.map((f) => ({ name: f.key }))];\n const redeclared = await client.recordUpdate({ record_id: tableId, patch: { fields: declaration } });\n if (!redeclared.ok) return redeclared;\n\n for (const field of missing) {\n const written = await client.recordWrite({\n table_id: fieldKernel.data,\n data: fieldDocument(field, tableId),\n });\n if (!written.ok) return written;\n }\n return { ok: true, data: true };\n}\n\n/**\n * THE FIELD THAT CHANGED BEHAVIOUR UNDER AN ORGANIZATION THAT ALREADY HAD ONE.\n *\n * Found live on 2026-09-19: `ActionInbox` could not record an outcome in one\n * organization, because that organization's copy of `records_ui_action` held\n * `status` as a `relation` while this package declares it `text`. Every write\n * of an outcome was refused `22P02 invalid input syntax for type uuid: \"open\"`\n * — the store was right, the package was the one out of date, and\n * `addMissingFields` never looked at a Field it already had.\n *\n * So the reconciliation is two questions, not one: which Fields are MISSING,\n * and which Fields are THERE WITH THE WRONG SHAPE. Shape here means exactly the\n * two properties that decide what a value is made of and therefore what the\n * store will accept — the behaviour (FLD-1) and whether it is multi (FLD-2).\n *\n * WHAT IS DELIBERATELY NOT RECONCILED: label, sort, required, config. Those are\n * presentation and policy, an organization may legitimately have moved them,\n * and none of them can make a write fail. Nothing is ever renamed or removed\n * here — this only ever moves a Field back onto the behaviour the package's own\n * components write against.\n */\nasync function reconcileFieldShapes(\n client: RecordsClient,\n spec: SystemTableSpec,\n tableId: Uuid,\n): Promise<{ ok: true; data: true } | { ok: false; error: RecordsError }> {\n const held = await client.fields({ table_id: tableId });\n if (!held.ok) return held;\n const byKey = new Map(held.data.map((f) => [f.key, f]));\n\n for (const field of spec.fields) {\n const have = byKey.get(field.key);\n if (!have) continue; // `addMissingFields` owns that half and already ran.\n const patch: Record<string, unknown> = {};\n if (have.type !== field.type) patch.type = field.type;\n if (have.multi !== (field.multi ?? false)) patch.multi = field.multi ?? false;\n if (Object.keys(patch).length === 0) continue;\n\n // The Field definition is an ordinary record in the field kernel, so it is\n // levelled through the ordinary write door — never a second storage path.\n const written = await client.recordUpdate({ record_id: have.id, patch });\n // A Field this package cannot level is a Table whose writes will keep being\n // refused, so the refusal is reported rather than swallowed.\n if (!written.ok) return written;\n }\n return { ok: true, data: true };\n}\n\n/** One Field record's document — the same one whether it is declared with the Table or added later. */\nfunction fieldDocument(field: SystemFieldSpec, tableId: Uuid): Record<string, unknown> {\n return {\n key: field.key,\n label: field.label,\n type: field.type,\n sort: field.sort,\n required: field.required ?? false,\n multi: field.multi ?? false,\n dated: false,\n rules: [],\n config: field.config ?? {},\n source: \"manual\",\n depends_on: [],\n sensitivity: \"internal\",\n source_config: {},\n context_policy: \"include\",\n applies_to_types: [],\n entity_definition_id: tableId,\n };\n}\n\nasync function declare(\n client: RecordsClient,\n spec: SystemTableSpec,\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const personKernel = await client.personKernelId();\n if (!personKernel.ok) return personKernel;\n\n const home = await client.recordWrite({\n table_id: personKernel.data,\n data: { name: `${spec.name} Home` },\n });\n if (!home.ok) return home;\n\n const table = await client.tableDeclare({\n homeId: home.data,\n spec: {\n name: spec.name,\n slug: spec.slug,\n type: \"entity\",\n label_singular: spec.labelSingular,\n label_plural: spec.labelPlural,\n display: \"list\",\n weight: \"light\",\n ordered: false,\n row_order: \"manual\",\n title_field: spec.titleField,\n retention_days: 365,\n // AGT-1: the whole point is that an agent writes a view or a form in one\n // call, so a package-owned Table is agent-writable by declaration.\n agent_writable: true,\n default_sort: [{ field: spec.titleField, direction: \"asc\" }],\n fields: spec.fields.map((f) => ({ name: f.key })),\n },\n });\n if (!table.ok) return table;\n\n const fieldKernel = await client.fieldKernelId();\n if (!fieldKernel.ok) return fieldKernel;\n\n for (const field of spec.fields) {\n const written = await client.recordWrite({\n table_id: fieldKernel.data,\n data: fieldDocument(field, table.data),\n });\n // A Field the store refused is a Table that would quietly lose a column, so\n // it is reported rather than skipped.\n if (!written.ok) return written;\n }\n\n return { ok: true, data: table.data };\n}\n\nexport interface UseSystemTableState {\n tableId: Uuid | null;\n loading: boolean;\n error: RecordsError | null;\n}\n\n/** The hook every package-owned component opens with. */\nexport function useSystemTable(spec: SystemTableSpec): UseSystemTableState {\n const client = useRecordsClient();\n const [state, setState] = useState<UseSystemTableState>({ tableId: null, loading: true, error: null });\n const slug = spec.slug;\n const stable = useMemo(() => spec, [slug]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n let cancelled = false;\n setState({ tableId: null, loading: true, error: null });\n void ensureSystemTable(client, stable).then((result) => {\n if (cancelled) return;\n setState(\n result.ok\n ? { tableId: result.data, loading: false, error: null }\n : { tableId: null, loading: false, error: result.error },\n );\n });\n return () => {\n cancelled = true;\n };\n }, [client, stable]);\n\n return state;\n}\n\n/**\n * THE VERSION OF THE ONE RECORD BEING EDITED.\n *\n * The read door (`custom.read_records`) answers documents, never versions —\n * deliberately, because a version is a fact about the row and not about what\n * this reader may see. A screen that saves optimistically still needs the\n * version it LOADED, so it reads it here, for the one record it is editing and\n * never for a list, through `custom.io_revisions`.\n *\n * `null` is an honest answer: the save then carries no expected version and is\n * the store's ordinary last-writer-wins write. It is never a guess.\n */\n/** What `useRecordVersion` hands a screen that writes the record more than once. */\nexport interface TrackedVersion {\n /** The version this screen is writing against, or `null` when none was read. */\n version: number | null;\n /**\n * TELL IT THE STORE MOVED. Every successful write answers the record's NEW\n * version; a screen that does not hand it back here will write against the\n * old one next time and the store will — correctly — refuse it as a conflict\n * with somebody who turns out to be the same person. Measured 2026-09-19:\n * switching a saved view's layout twice in a row did exactly that.\n */\n note: (version: number) => void;\n}\n\nexport function useRecordVersion(recordId: Uuid | null | undefined): TrackedVersion {\n const client = useRecordsClient();\n const [version, setVersion] = useState<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setVersion(null);\n if (!recordId) return;\n void client.revisions({ record_id: recordId }).then((answered) => {\n if (cancelled || !answered.ok) return;\n const newest = answered.data.reduce<number | null>(\n (held, row) => (held === null || row.version > held ? row.version : held),\n null,\n );\n setVersion(newest);\n });\n return () => {\n cancelled = true;\n };\n }, [client, recordId]);\n\n return { version, note: setVersion };\n}\n","\"use client\";\n\n// src/ShareControl.tsx — @ai-matrx/records-ui · SCR-N-5\n//\n// THE SHARE BUTTON, on the record screen and on the table screen, in the row\n// where everything else a person does to a thing already is.\n//\n// WHAT IT IS NOT. It is not a share dialog. AI Matrx has exactly one of those\n// and it lives in the app (matrx-frontend `features/sharing`): a people picker\n// over the organization's members, the four levels, the list of who has access\n// with the REASON each one has it, and revoke. Building a second one in this\n// package would give the platform two answers to \"who can see this\", which is\n// the one question a platform may not have two answers to. So this component\n// draws the button, owns whether the dialog is open, and hands the subject to\n// the host's `share` port.\n//\n// ABSENT, NEVER DEAD, AND NEVER OFFERED TO SOMEBODY WHO MAY NOT. With no\n// `share` port bound there is NO BUTTON — not a greyed one, not one that opens\n// an empty panel. And passing your access on to somebody else is an\n// administrator's right on the thing (`custom.share_grant`), so the button is\n// absent for everybody below that rung too: the sixth-pass verdict is the\n// record of what offering it anyway costs, in the cell editor next door.\n//\n// A TABLE IS A RECORD. In this store a Table is a `custom.record` row whose\n// table is the Table kernel, so the same button, the same door and the same\n// dialog serve both screens; `kind` only changes the noun in the sentences.\n\nimport { useState, type ReactNode } from \"react\";\nimport type { Uuid } from \"@ai-matrx/records\";\nimport { Button } from \"@ai-matrx/design-system\";\nimport { useRecordsUi, useRecordRights, NO_SHARE_REASON, type ShareSubject } from \"./host\";\n\nexport interface ShareControlProps {\n kind: ShareSubject[\"kind\"];\n organizationId: Uuid;\n subjectId: Uuid;\n /** What to call it in the dialog's title. */\n name?: string | undefined;\n /**\n * Whether this person may pass this on — `custom.share_grant` asks for Admin\n * ON THE THING. A caller that already holds the answer (a table screen has\n * the table's rights in its hand) passes it; left out, this asks the store\n * itself for the subject named above. Either way it is an ANSWER and never an\n * assumption, which is the whole of this lane.\n */\n may?: boolean | undefined;\n size?: \"sm\" | \"default\" | undefined;\n variant?: \"ghost\" | \"outline\" | \"default\" | undefined;\n className?: string | undefined;\n}\n\n/** True when a host has bound a share dialog — so a caller can lay out its row. */\nexport function useCanShare(): boolean {\n return typeof useRecordsUi().share === \"function\";\n}\n\n/** Why there is no Share button here, for anything that asks. */\nexport function shareUnavailableReason(): string {\n return NO_SHARE_REASON;\n}\n\nexport function ShareControl({\n kind,\n organizationId,\n subjectId,\n name,\n may,\n size = \"sm\",\n variant = \"ghost\",\n className,\n}: ShareControlProps): ReactNode {\n const host = useRecordsUi();\n const [open, setOpen] = useState(false);\n // A Table is a record in this store, so ONE question answers both screens.\n const asked = useRecordRights(may === undefined ? subjectId : null);\n const mayShare = may ?? asked.share;\n\n // No port, no button. The reason is exported rather than rendered as a dead\n // control, because a Share button that opens nothing is the screen lying.\n if (!host.share) return null;\n // Not an Admin here, no button — and nothing greyed out beside it either.\n if (!mayShare) return null;\n\n return (\n <>\n <Button\n size={size}\n variant={variant}\n className={className}\n onClick={() => setOpen(true)}\n aria-label={kind === \"table\" ? \"Share this table\" : \"Share this record\"}\n >\n Share\n </Button>\n {open\n ? host.share({\n kind,\n organizationId,\n subjectId,\n // NEVER A TRUNCATED ID WHERE A PERSON READS A NAME (`names.ts`):\n // \"8f2c1b0a\" tells nobody anything and looks like a bug.\n name: name && name.trim() !== \"\" ? name : kind === \"table\" ? \"this table\" : \"this record\",\n onClose: () => setOpen(false),\n })\n : null}\n </>\n );\n}\n","\"use client\";\n\n// src/views.ts — @ai-matrx/records-ui · SCR-6, SCR-7, SCR-N-6\n//\n// A SAVED VIEW IS ONE RECORD, and that record owns its layout and REFERENCES\n// its membership rule.\n//\n// The split matters. A view does not carry a filter predicate of its own that a\n// screen re-implements in JavaScript: it names a Rule, and the STORE answers\n// who is in it (`custom.rule_members`). So the same view means the same thing\n// to a grid, to an export, to an agent and to the server. What the view owns\n// itself is presentation — which of the four layouts, which Field the kanban\n// columns come from, which Field the calendar reads, which Field the gallery\n// shows — because that is not data, it is how this person wants to look at it.\n//\n// The whole view is also a plain declarative object (`SavedViewSpec`), which is\n// what makes \"an agent writes the view in 45 seconds\" true: one `record_write`\n// of one document, and the person only tweaks.\n\nimport type { ReadRow, Uuid } from \"@ai-matrx/records\";\nimport type { SystemTableSpec } from \"./systemTable\";\n\n/** The four ways one saved view can be looked at (SCR-6). */\nexport const VIEW_LAYOUTS = [\"grid\", \"kanban\", \"calendar\", \"gallery\"] as const;\nexport type ViewLayout = (typeof VIEW_LAYOUTS)[number];\n\nexport const LAYOUT_LABEL: Record<ViewLayout, string> = {\n grid: \"Grid\",\n kanban: \"Kanban\",\n calendar: \"Calendar\",\n gallery: \"Gallery\",\n};\n\n/**\n * What each layout needs before it can draw anything, in one sentence a screen\n * prints. A layout that is missing its Field says so instead of rendering an\n * empty board that looks like \"no records\".\n */\nexport const LAYOUT_NEEDS: Record<ViewLayout, string | null> = {\n grid: null,\n kanban: \"A kanban board needs a Field to make its columns from — pick one and the board appears.\",\n calendar: \"A calendar needs a date Field to place records on — pick one and the month appears.\",\n gallery: null,\n};\n\n/** One sort clause. The Field's key and a direction; nothing else is a sort. */\nexport interface ViewSort {\n field: string;\n direction: \"asc\" | \"desc\";\n}\n\n/**\n * THE DECLARATIVE SPEC. An agent writes this whole object; a person tweaks it.\n * Every builder component in this package takes one of these as a prop.\n */\nexport interface SavedViewSpec {\n name: string;\n /** The Table this view looks at. */\n subject: Uuid;\n layout: ViewLayout;\n /** Kanban: the Field whose value becomes a column. */\n groupField?: string | null;\n /** Calendar: the Field that places a record in the month. */\n dateField?: string | null;\n /** Gallery: the Field shown large on the card. */\n imageField?: string | null;\n sorts?: ViewSort[];\n /**\n * The membership Rule. The STORE decides who is in this view; this is a\n * reference to its Rule record, never a predicate this package evaluates.\n */\n ruleId?: Uuid | null;\n isDefault?: boolean;\n}\n\n/** A saved view as it comes back out of the store, with its record's own id. */\nexport interface SavedView extends SavedViewSpec {\n id: Uuid;\n /**\n * The record's version AT LOAD, read from `custom.io_revisions` for the one\n * record being edited. The read door answers documents and not versions, so\n * this is null until it has been read — and a save with a null version is an\n * ordinary last-writer-wins write, exactly as the store defines it.\n */\n version: number | null;\n}\n\n/** The package-owned Table every saved view is a record of. */\nexport const VIEW_TABLE: SystemTableSpec = {\n slug: \"records_ui_view\",\n name: \"Saved views\",\n labelSingular: \"View\",\n labelPlural: \"Views\",\n titleField: \"name\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"text\", sort: 10, required: true },\n { key: \"subject\", label: \"Table\", type: \"text\", sort: 20, required: true },\n { key: \"layout\", label: \"Layout\", type: \"text\", sort: 30, required: true },\n { key: \"group_field\", label: \"Group by\", type: \"text\", sort: 40 },\n { key: \"date_field\", label: \"Date field\", type: \"text\", sort: 50 },\n { key: \"image_field\", label: \"Image field\", type: \"text\", sort: 60 },\n { key: \"sorts\", label: \"Sorts\", type: \"text\", sort: 70, config: { multiline: true } },\n { key: \"rule_id\", label: \"Membership rule\", type: \"text\", sort: 80 },\n { key: \"is_default\", label: \"Default\", type: \"text\", sort: 90 },\n ],\n};\n\n/**\n * WHICH FIELD EACH LAYOUT CAN BE DRAWN FROM, decided from the FIELD'S OWN\n * DECLARATION and never from the values it happens to hold.\n *\n * A kanban makes columns from a choice: the Field whose value is one of a\n * closed set (FLD-5 / FLD-6 — a pick-list is a Table, and a select stores the\n * id of one of its records). Grouping by a free-text Field produces one column\n * per record, which is not a board. A calendar places a record in time, so it\n * needs a Field that holds a date.\n *\n * These two answers are here, beside the layouts, because the picker on the\n * screen and any agent writing a view spec must agree about what is offerable.\n */\nexport const LAYOUT_FIELD_KIND: Record<ViewLayout, \"choice\" | \"date\" | null> = {\n grid: null,\n kanban: \"choice\",\n calendar: \"date\",\n gallery: null,\n};\n\n/** The one sentence a layout says when the table holds no Field it could use. */\nexport const LAYOUT_NO_FIELD: Record<ViewLayout, string> = {\n grid: \"\",\n kanban:\n \"This table has no choice field yet, so there is nothing to make columns from. Add a field that \" +\n \"holds one of a set of choices — Add field, then Select — and it appears here.\",\n calendar:\n \"This table has no date field yet, so there is nothing to place records on. Add a field that holds \" +\n \"a date — Add field, then Date — and it appears here.\",\n gallery: \"\",\n};\n\n/** The spec as the one document the store holds. */\nexport function viewDocument(spec: SavedViewSpec): Record<string, unknown> {\n return {\n name: spec.name,\n subject: spec.subject,\n layout: spec.layout,\n group_field: spec.groupField ?? null,\n date_field: spec.dateField ?? null,\n image_field: spec.imageField ?? null,\n sorts: JSON.stringify(spec.sorts ?? []),\n rule_id: spec.ruleId ?? null,\n is_default: spec.isDefault ? \"true\" : \"false\",\n };\n}\n\n/** One stored record back into the spec a screen and an agent both read. */\nexport function viewFromRecord(row: ReadRow): SavedView {\n const data = (row.document ?? {}) as Record<string, unknown>;\n const layout = String(data[\"layout\"] ?? \"grid\");\n return {\n id: row.id,\n version: null,\n name: String(data[\"name\"] ?? \"Untitled view\"),\n subject: String(data[\"subject\"] ?? \"\"),\n layout: (VIEW_LAYOUTS as readonly string[]).includes(layout) ? (layout as ViewLayout) : \"grid\",\n groupField: (data[\"group_field\"] as string | null) ?? null,\n dateField: (data[\"date_field\"] as string | null) ?? null,\n imageField: (data[\"image_field\"] as string | null) ?? null,\n sorts: parseSorts(data[\"sorts\"]),\n ruleId: (data[\"rule_id\"] as string | null) ?? null,\n isDefault: data[\"is_default\"] === \"true\",\n };\n}\n\n/**\n * A PARTIAL change to a saved view, as the patch the store takes. Only the keys\n * the caller actually changed are written — a full document would re-write a\n * name or a rule the person edited in another tab.\n */\nexport function viewPatchDocument(patch: Partial<SavedViewSpec>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (patch.name !== undefined) out[\"name\"] = patch.name;\n if (patch.layout !== undefined) out[\"layout\"] = patch.layout;\n if (patch.groupField !== undefined) out[\"group_field\"] = patch.groupField ?? null;\n if (patch.dateField !== undefined) out[\"date_field\"] = patch.dateField ?? null;\n if (patch.imageField !== undefined) out[\"image_field\"] = patch.imageField ?? null;\n if (patch.sorts !== undefined) out[\"sorts\"] = JSON.stringify(patch.sorts ?? []);\n if (patch.ruleId !== undefined) out[\"rule_id\"] = patch.ruleId ?? null;\n if (patch.isDefault !== undefined) out[\"is_default\"] = patch.isDefault ? \"true\" : \"false\";\n return out;\n}\n\nfunction parseSorts(raw: unknown): ViewSort[] {\n if (Array.isArray(raw)) return raw as ViewSort[];\n if (typeof raw !== \"string\" || raw.trim() === \"\") return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as ViewSort[]) : [];\n } catch {\n // A sort nobody can read is not silently dropped to \"no sort\": the view says\n // what it holds and the caller can see that it is not a sort list.\n return [];\n }\n}\n","\"use client\";\n\n// src/ViewSwitcher.tsx — @ai-matrx/records-ui · SCR-6\n//\n// ONE SAVED VIEW, FOUR WAYS TO LOOK AT IT: grid, kanban, calendar, gallery.\n//\n// The records are the SAME records in all four. Switching layout re-draws them;\n// it never re-queries something different and it never filters differently —\n// membership is the view's Rule and the STORE answers it (`custom.rule_members`),\n// so a card that disappears between two layouts would be a defect, not a\n// feature. A view with no Rule is the whole table, and the screen says which.\n//\n// A layout that cannot draw yet (a kanban with no Field to group by, a calendar\n// with no date Field) says the one sentence that fixes it. It never renders an\n// empty board that reads like \"there is nothing here\".\n\nimport { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { useFields, useRecords, useRecordsClient, type Field, type ReadRow, type StoredRecord, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { Grid } from \"./Grid\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi } from \"./host\";\nimport { RecordValue, scalarText } from \"./values\";\nimport { useRecordLabels } from \"./labels\";\nimport { fieldName, rowName } from \"./names\";\nimport { editorKindFor } from \"./parity\";\nimport {\n LAYOUT_FIELD_KIND,\n LAYOUT_LABEL,\n LAYOUT_NEEDS,\n LAYOUT_NO_FIELD,\n VIEW_LAYOUTS,\n type SavedViewSpec,\n type ViewLayout,\n} from \"./views\";\n\nexport interface ViewSwitcherProps {\n /**\n * THE DECLARATIVE SPEC — an agent writes the whole thing, a person tweaks it.\n * `ViewBar` passes the saved view it loaded; a host with no saved views at all\n * can pass a literal here and the switcher works.\n */\n view: SavedViewSpec;\n /** Called when the person picks another layout, so the host can save it. */\n onLayoutChange?: ((layout: ViewLayout) => void) | undefined;\n /**\n * Called with whatever part of the view the person just changed — the layout,\n * the Field the kanban groups by, the Field the calendar reads. The HOST\n * saves it onto the view record, so the choice is remembered per saved view\n * rather than per page load. Unbound, the pickers still work for this visit\n * and the screen says the choice is not being kept.\n */\n onViewChange?: ((patch: Partial<SavedViewSpec>) => void) | undefined;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n /** The host's whole-record form, offered by the grid when an empty record is refused. */\n onNewRecordForm?: (() => void) | undefined;\n pageSize?: number | undefined;\n className?: string | undefined;\n}\n\n/** The records this view holds: its Rule's members when it names one, the table otherwise. */\nexport function useViewRecords(view: SavedViewSpec, pageSize = 200) {\n const client = useRecordsClient();\n const table = useRecords(view.ruleId ? null : view.subject, { pageSize });\n const [ruled, setRuled] = useState<{ rows: ReadRow[]; loading: boolean; error: RecordsError | null }>({\n rows: [],\n loading: Boolean(view.ruleId),\n error: null,\n });\n\n const ruleId = view.ruleId ?? null;\n useEffect(() => {\n if (!ruleId) return;\n let cancelled = false;\n setRuled({ rows: [], loading: true, error: null });\n void client.ruleMembers({ rule_id: ruleId }).then((result) => {\n if (cancelled) return;\n setRuled(\n result.ok\n ? { rows: (result.data ?? []).map(asReadRow), loading: false, error: null }\n : { rows: [], loading: false, error: result.error },\n );\n });\n return () => {\n cancelled = true;\n };\n }, [client, ruleId]);\n\n const rows = ruleId ? ruled.rows : (table.data?.rows ?? []);\n return {\n rows: sortRows(rows, view.sorts ?? []),\n loading: ruleId ? ruled.loading : table.loading,\n error: ruleId ? ruled.error : table.error,\n /** Where membership came from, in a sentence. A screen that hides this is hiding the view's meaning. */\n membership: ruleId\n ? \"Membership is this view's Rule, answered by the store.\"\n : \"This view has no Rule, so it holds the whole table.\",\n };\n}\n\n/**\n * `custom.rule_members` answers SETOF `custom.record` — it is the membership\n * door, not the read door, so its rows arrive in the row shape rather than the\n * masked-document shape. They are carried into the read door's shape HERE, at\n * the one seam, so a card is drawn by exactly one code path whichever door\n * produced it. What this cannot do is mask: a Rule's members come back as the\n * store stored them, which is the membership door's own gap, not this screen's.\n */\nfunction asReadRow(row: StoredRecord): ReadRow {\n return { id: row.id, document: (row.data ?? {}) as ReadRow[\"document\"], level: \"viewer\", hidden: {} };\n}\n\nfunction sortRows(rows: ReadRow[], sorts: { field: string; direction: \"asc\" | \"desc\" }[]): ReadRow[] {\n if (sorts.length === 0) return rows;\n return [...rows].sort((a, b) => {\n for (const sort of sorts) {\n const left = (a.document ?? {})[sort.field];\n const right = (b.document ?? {})[sort.field];\n if (left === right) continue;\n const order = (left ?? \"\") < (right ?? \"\") ? -1 : 1;\n return sort.direction === \"desc\" ? -order : order;\n }\n return 0;\n });\n}\n\nexport function ViewSwitcher({\n view,\n onLayoutChange,\n onViewChange,\n onOpenRecord,\n onNewRecordForm,\n pageSize = 200,\n className,\n}: ViewSwitcherProps) {\n const [layout, setLayout] = useState<ViewLayout>(view.layout);\n // The Fields the pickers below chose, so a host that binds no `onViewChange`\n // still gets a board rather than a sentence — and is TOLD it is not kept.\n const [local, setLocal] = useState<Partial<SavedViewSpec>>({});\n useEffect(() => {\n setLayout(view.layout);\n setLocal({});\n }, [view.layout, view.name, view.subject]);\n\n const pick = (next: ViewLayout) => {\n setLayout(next);\n onLayoutChange?.(next);\n onViewChange?.({ layout: next });\n };\n\n const change = (patch: Partial<SavedViewSpec>) => {\n setLocal((held) => ({ ...held, ...patch }));\n onViewChange?.(patch);\n };\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: the view's name, the four layouts, nothing repeated. */}\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-medium\">{view.name}</span>\n <div className=\"ml-auto flex items-center gap-0.5\" role=\"group\" aria-label=\"Layout\">\n {VIEW_LAYOUTS.map((option) => (\n <Button\n key={option}\n size=\"sm\"\n variant={option === layout ? \"secondary\" : \"ghost\"}\n aria-pressed={option === layout}\n onClick={() => pick(option)}\n >\n {LAYOUT_LABEL[option]}\n </Button>\n ))}\n </div>\n </div>\n\n {layout === \"grid\" ? (\n <Grid\n tableId={view.subject}\n pageSize={pageSize}\n {...(onOpenRecord ? { onOpenRecord } : {})}\n {...(onNewRecordForm ? { onNewRecordForm } : {})}\n />\n ) : (\n <Board\n view={{ ...view, ...local, layout }}\n pageSize={pageSize}\n onChange={change}\n remembered={Boolean(onViewChange)}\n {...(onOpenRecord ? { onOpenRecord } : {})}\n />\n )}\n </div>\n );\n}\n\n/** Which Fields a kanban may group by, and which a calendar may read. */\nfunction offerableFields(all: Field[], want: \"choice\" | \"date\"): Field[] {\n return all.filter((field) => {\n const kind = editorKindFor(field);\n if (want === \"choice\") return kind === \"select\" || kind === \"multi_select\";\n return kind === \"datetime\" || kind === \"date\";\n });\n}\n\nfunction Board({\n view,\n pageSize,\n onChange,\n remembered,\n onOpenRecord,\n}: {\n view: SavedViewSpec;\n pageSize: number;\n onChange: (patch: Partial<SavedViewSpec>) => void;\n remembered: boolean;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n}) {\n const fields = useFields(view.subject);\n const records = useViewRecords(view, pageSize);\n\n if (fields.error) return <RefusalNotice error={fields.error} />;\n if (records.error) return <RefusalNotice error={records.error} />;\n if (fields.loading || records.loading) return <Skeleton className=\"h-40 w-full\" />;\n\n const all = fields.data ?? [];\n const byKey = (key: string | null | undefined) => all.find((f) => f.key === key);\n const titleField = byKey(view.groupField) ? all.find((f) => f.key !== view.groupField) ?? all[0] : all[0];\n\n if (view.layout === \"kanban\") {\n const groupField = byKey(view.groupField);\n const picker = (\n <FieldPicker\n layout=\"kanban\"\n label=\"Group by\"\n all={all}\n chosen={groupField?.key ?? null}\n remembered={remembered}\n onPick={(key) => onChange({ groupField: key })}\n />\n );\n if (!groupField) return <Needs layout=\"kanban\" picker={picker} />;\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n {picker}\n <Kanban rows={records.rows} groupField={groupField} titleField={titleField} onOpenRecord={onOpenRecord} note={records.membership} />\n </div>\n );\n }\n if (view.layout === \"calendar\") {\n const dateField = byKey(view.dateField);\n const picker = (\n <FieldPicker\n layout=\"calendar\"\n label=\"Dates from\"\n all={all}\n chosen={dateField?.key ?? null}\n remembered={remembered}\n onPick={(key) => onChange({ dateField: key })}\n />\n );\n if (!dateField) return <Needs layout=\"calendar\" picker={picker} />;\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n {picker}\n <Calendar rows={records.rows} dateField={dateField} titleField={titleField} onOpenRecord={onOpenRecord} note={records.membership} />\n </div>\n );\n }\n return <Gallery rows={records.rows} fields={all} imageKey={view.imageField ?? null} onOpenRecord={onOpenRecord} note={records.membership} />;\n}\n\n/**\n * THE PICKER THE SENTENCE ALWAYS PROMISED. Before this, a kanban said \"pick one\n * and the board appears\" and there was no picker anywhere on the page — the\n * verdict of 19 September found the same dead end on the calendar. A screen\n * that names a remedy and does not offer it is worse than one that says\n * nothing, so the sentence and the control are now the same component.\n */\nfunction FieldPicker({\n layout,\n label,\n all,\n chosen,\n remembered,\n onPick,\n}: {\n layout: ViewLayout;\n label: string;\n all: Field[];\n chosen: string | null;\n remembered: boolean;\n onPick: (key: string | null) => void;\n}) {\n const want = LAYOUT_FIELD_KIND[layout];\n const offerable = want ? offerableFields(all, want) : [];\n if (offerable.length === 0) {\n // Honest, and it names the fix: this is not \"pick one\", because there is\n // nothing to pick.\n return <p className=\"text-xs text-muted-foreground\">{LAYOUT_NO_FIELD[layout]}</p>;\n }\n return (\n <div className=\"flex items-center gap-1.5 text-xs\">\n <label className=\"text-muted-foreground\" htmlFor={`view-field-${layout}`}>\n {label}\n </label>\n <select\n id={`view-field-${layout}`}\n aria-label={`${label} which field`}\n className=\"h-7 rounded border bg-background px-1 text-xs\"\n value={chosen ?? \"\"}\n onChange={(event) => onPick(event.target.value === \"\" ? null : event.target.value)}\n >\n <option value=\"\">Choose a field</option>\n {offerable.map((field) => (\n <option key={field.key} value={field.key}>\n {fieldName(field)}\n </option>\n ))}\n </select>\n {remembered ? null : (\n <span className=\"text-muted-foreground\">\n Kept for this visit only — this screen has nowhere to save it onto the view.\n </span>\n )}\n </div>\n );\n}\n\n/** The one sentence that fixes an un-drawable layout, WITH the control that fixes it. */\nfunction Needs({ layout, picker }: { layout: ViewLayout; picker: ReactNode }) {\n return (\n <div className=\"flex flex-col gap-2 rounded border border-dashed p-4 text-xs text-muted-foreground\">\n <p>{LAYOUT_NEEDS[layout]}</p>\n {picker}\n </div>\n );\n}\n\nfunction Note({ children }: { children: string }) {\n return <p className=\"text-xs text-muted-foreground\">{children}</p>;\n}\n\nfunction Kanban({\n rows,\n groupField,\n titleField,\n onOpenRecord,\n note,\n}: {\n rows: ReadRow[];\n groupField: Field;\n titleField: Field | undefined;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n note: string;\n}) {\n const groupFields = useMemo(() => [groupField], [groupField]);\n // A BOARD IS GROUPED BY A CHOICE, AND A CHOICE IS STORED AS THE ID OF AN\n // OPTION RECORD (FLD-5 / FLD-6). Without the resolver every heading on this\n // board was a bare 36-character identifier — the single most visible line in\n // the 19 September verdict's \"machine identity is everywhere a person looks\".\n const labels = useRecordLabels(groupFields);\n const columns = useMemo(() => {\n const map = new Map<string, ReadRow[]>();\n for (const row of rows) {\n const raw = (row.document ?? {})[groupField.key];\n // A record with no value for the grouping Field is NOT dropped: it gets\n // its own column, named for the absence, because losing rows between two\n // layouts is the defect this board could most easily ship.\n const key = raw === null || raw === undefined || raw === \"\" ? \"No value\" : scalarText(groupField, raw, labels);\n map.set(key, [...(map.get(key) ?? []), row]);\n }\n return [...map.entries()].sort((a, b) => (a[0] === \"No value\" ? 1 : b[0] === \"No value\" ? -1 : a[0].localeCompare(b[0])));\n }, [rows, groupField, labels]);\n\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n <Note>{note}</Note>\n <div className=\"flex min-h-0 gap-2 overflow-x-auto pb-2\">\n {columns.map(([name, cards]) => (\n <section key={name} className=\"flex w-64 shrink-0 flex-col rounded border bg-muted/30\">\n <header className=\"flex items-center gap-2 border-b px-2 py-1 text-xs font-medium\">\n <span className=\"truncate\">{name}</span>\n <span className=\"ml-auto text-muted-foreground\">{cards.length}</span>\n </header>\n <ul className=\"flex flex-col gap-1 p-1\">\n {cards.map((card) => (\n <li key={card.id}>\n <Card record={card} field={titleField} onOpenRecord={onOpenRecord} />\n </li>\n ))}\n </ul>\n </section>\n ))}\n </div>\n </div>\n );\n}\n\nfunction Calendar({\n rows,\n dateField,\n titleField,\n onOpenRecord,\n note,\n}: {\n rows: ReadRow[];\n dateField: Field;\n titleField: Field | undefined;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n note: string;\n}) {\n const { days, undated } = useMemo(() => {\n const byDay = new Map<string, ReadRow[]>();\n const without: ReadRow[] = [];\n for (const row of rows) {\n const raw = (row.document ?? {})[dateField.key];\n const at = typeof raw === \"string\" || typeof raw === \"number\" ? new Date(raw) : null;\n if (!at || Number.isNaN(at.getTime())) {\n without.push(row);\n continue;\n }\n const key = at.toISOString().slice(0, 10);\n byDay.set(key, [...(byDay.get(key) ?? []), row]);\n }\n return { days: [...byDay.entries()].sort((a, b) => a[0].localeCompare(b[0])), undated: without };\n }, [rows, dateField]);\n\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n <Note>{note}</Note>\n <ol className=\"flex min-h-0 flex-col divide-y overflow-y-auto rounded border\">\n {days.map(([day, cards]) => (\n <li key={day} className=\"flex gap-3 p-2\">\n <span className=\"w-24 shrink-0 text-xs font-medium tabular-nums\">\n {new Date(`${day}T00:00:00Z`).toLocaleDateString(undefined, { month: \"short\", day: \"numeric\", year: \"numeric\" })}\n </span>\n <ul className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {cards.map((card) => (\n <li key={card.id}>\n <Card record={card} field={titleField} onOpenRecord={onOpenRecord} />\n </li>\n ))}\n </ul>\n </li>\n ))}\n </ol>\n {undated.length > 0 ? (\n // Nothing fails silently: records with no date are NOT missing from the\n // calendar, they are named as records the calendar cannot place.\n <p className=\"text-xs text-muted-foreground\">\n {undated.length} {undated.length === 1 ? \"record has\" : \"records have\"} no {fieldName(dateField)},\n so the calendar cannot place {undated.length === 1 ? \"it\" : \"them\"}.\n </p>\n ) : null}\n </div>\n );\n}\n\nfunction Gallery({\n rows,\n fields,\n imageKey,\n onOpenRecord,\n note,\n}: {\n rows: ReadRow[];\n fields: Field[];\n imageKey: string | null;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n note: string;\n}) {\n const shown = fields.slice(0, 4);\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n <Note>{note}</Note>\n <ul className=\"grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2 overflow-y-auto\">\n {rows.map((row) => {\n const image = imageKey ? (row.document ?? {})[imageKey] : null;\n return (\n <li key={row.id}>\n <button\n type=\"button\"\n className=\"flex w-full flex-col gap-1 rounded border p-2 text-left hover:bg-muted\"\n onClick={() => onOpenRecord?.(row.id)}\n >\n {typeof image === \"string\" && image !== \"\" ? (\n <img src={image} alt=\"\" className=\"h-28 w-full rounded object-cover\" />\n ) : null}\n {shown.map((field) => (\n <span key={field.key} className=\"flex min-w-0 items-baseline gap-1 text-xs\">\n <span className=\"shrink-0 text-muted-foreground\">{fieldName(field)}</span>\n <span className=\"min-w-0 truncate\"><RecordValue field={field} value={(row.document ?? {})[field.key]} document={row.document} /></span>\n </span>\n ))}\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\nfunction Card({\n record,\n field,\n onOpenRecord,\n}: {\n record: ReadRow;\n field: Field | undefined;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n}) {\n const host = useRecordsUi();\n // Never a bare identifier on a card: the Field's own value when there is one,\n // the record's name when there is not.\n const label = field\n ? scalarText(field, (record.document ?? {})[field.key])\n : rowName(record, null, \"Untitled\");\n return (\n <button\n type=\"button\"\n className={cn(\n \"w-full truncate rounded border bg-background px-2 py-1 text-left text-xs hover:bg-muted\",\n host.density === \"spacious\" ? \"py-2\" : \"\",\n )}\n onClick={() => onOpenRecord?.(record.id)}\n title={label}\n >\n {label}\n </button>\n );\n}\n","\"use client\";\n\n// src/ViewBar.tsx — @ai-matrx/records-ui · SCR-7, SCR-N-6\n//\n// THE SAVED VIEWS OF ONE TABLE, AS RECORDS.\n//\n// Each view is ONE record in this organization's own `records_ui_view` Table,\n// declared through the store's doors the first time anything asks for it\n// (`systemTable.ts`). That is what makes a view shareable, exportable,\n// historied and agent-writable without a line of code per feature: it is a\n// record, so everything this package does to records it already does to views.\n//\n// A view owns its LAYOUT and references its MEMBERSHIP RULE. The bar never\n// evaluates a predicate — picking a view hands `ViewSwitcher` a spec, and the\n// store answers who is in it.\n//\n// `seed` is the declarative half: an agent writes a complete view spec, the bar\n// saves it as a record on first sight, and the person only tweaks it.\n//\n// ONE CONTROL FOR ONE THING. This bar used to carry a layout `select` of its\n// own beside `ViewSwitcher`'s layout buttons, and the two disagreed on screen:\n// the verdict of 19 September watched the dropdown keep saying \"Grid\" while\n// Calendar was drawn. The switcher owns the LAYOUT; this bar owns WHICH VIEW.\n// Saving a layout — or a kanban's grouping Field, or a calendar's date Field —\n// onto the view record belongs to whoever owns the switcher (`TablePage`).\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Input, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useSeedGuard } from \"./seedOnce\";\nimport { useSystemTable } from \"./systemTable\";\nimport { useTableRights } from \"./host\";\nimport { useTable } from \"@ai-matrx/records/react\";\nimport {\n VIEW_TABLE,\n viewDocument,\n viewFromRecord,\n type SavedView,\n type SavedViewSpec,\n} from \"./views\";\n\nexport interface ViewBarProps {\n /** The Table whose views these are. */\n tableId: Uuid;\n /** The view that is showing. Leave it out and the bar picks the default, then the first. */\n activeViewId?: Uuid | null | undefined;\n onActiveView?: ((view: SavedView) => void) | undefined;\n /**\n * COMPLETE DECLARATIVE SPECS an agent wrote. Any of these whose name this\n * table does not have yet is saved as a record the first time the bar loads.\n * The person tweaks them afterwards like any other view.\n */\n seed?: SavedViewSpec[] | undefined;\n className?: string | undefined;\n}\n\nexport function ViewBar({ tableId, activeViewId, onActiveView, seed, className }: ViewBarProps) {\n const client = useRecordsClient();\n // One claim per seed name, per mount: a check against the server's list is\n // not a lock, and a loader that re-runs mid-write would write it twice.\n const claimSeed = useSeedGuard();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const home = useSystemTable(VIEW_TABLE);\n const [views, setViews] = useState<SavedView[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [active, setActive] = useState<Uuid | null>(activeViewId ?? null);\n const [naming, setNaming] = useState(false);\n const [draftName, setDraftName] = useState(\"\");\n\n const viewTableId = home.tableId;\n\n const load = useCallback(async () => {\n if (!viewTableId) return;\n const result = await client.list({ table_id: viewTableId, limit: 500 });\n if (!result.ok) {\n setError(result.error);\n return;\n }\n const mine = result.data.rows.map(viewFromRecord).filter((v) => v.subject === tableId);\n\n // The agent's specs, saved once. A seed whose name already exists is left\n // alone — an agent re-running never overwrites what a person has tweaked.\n const missing = (seed ?? []).filter((s) => !mine.some((v) => v.name === s.name));\n if (missing.length > 0) {\n for (const spec of missing) {\n if (!claimSeed(spec.name)) continue;\n const written = await client.recordWrite({\n table_id: viewTableId,\n data: viewDocument({ ...spec, subject: tableId }),\n });\n if (!written.ok) {\n setError(written.error);\n return;\n }\n }\n const again = await client.list({ table_id: viewTableId, limit: 500 });\n if (!again.ok) {\n setError(again.error);\n return;\n }\n setViews(again.data.rows.map(viewFromRecord).filter((v) => v.subject === tableId));\n return;\n }\n setError(null);\n setViews(mine);\n }, [client, viewTableId, tableId, seed]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n useEffect(() => {\n if (!views || views.length === 0) return;\n const chosen = views.find((v) => v.id === (activeViewId ?? active)) ?? views.find((v) => v.isDefault) ?? views[0]!;\n if (chosen.id !== active) setActive(chosen.id);\n onActiveView?.(chosen);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [views, activeViewId]);\n\n async function create(name: string) {\n if (!viewTableId || name.trim() === \"\") return;\n const written = await client.recordWrite({\n table_id: viewTableId,\n data: viewDocument({ name: name.trim(), subject: tableId, layout: \"grid\" }),\n });\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setNaming(false);\n setDraftName(\"\");\n setActive(written.data);\n await load();\n }\n\n if (home.error) return <RefusalNotice error={home.error} className={className} />;\n if (error) return <RefusalNotice error={error} className={className} actions={<Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>Try again</Button>} />;\n if (home.loading || views === null) return <Skeleton className={cn(\"h-7 w-64\", className)} />;\n\n return (\n <div className={cn(\"flex items-center gap-1 overflow-x-auto\", className)} role=\"group\" aria-label=\"Saved views\">\n {views.map((view) => (\n <Button\n key={view.id}\n size=\"sm\"\n variant={view.id === active ? \"secondary\" : \"ghost\"}\n aria-pressed={view.id === active}\n onClick={() => {\n setActive(view.id);\n onActiveView?.(view);\n }}\n title={view.ruleId ? \"Membership is this view's Rule\" : \"The whole table\"}\n >\n {view.name}\n {view.isDefault ? <span className=\"ml-1 text-[10px] text-muted-foreground\">default</span> : null}\n </Button>\n ))}\n\n {/* SCR-4 again: saving a view is administering the table, so a member does\n not get a dead \"New view\" button — there is no button. */}\n {rights.admin ? (\n naming ? (\n <form\n className=\"ml-1 flex items-center gap-1\"\n onSubmit={(e) => {\n e.preventDefault();\n void create(draftName);\n }}\n >\n <Input\n autoFocus\n aria-label=\"Name for the new view\"\n value={draftName}\n onChange={(e) => setDraftName(e.target.value)}\n className=\"h-7 w-40 text-xs\"\n placeholder=\"View name\"\n />\n <Button size=\"sm\" type=\"submit\">\n Save\n </Button>\n </form>\n ) : (\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-1\" onClick={() => setNaming(true)}>\n New view\n </Button>\n )\n ) : null}\n\n {views.length === 0 && !rights.admin ? (\n <span className=\"text-xs text-muted-foreground\">{rights.why(\"structure\")}</span>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/seedOnce.ts — @ai-matrx/records-ui\n//\n// THE SEED IS WRITTEN ONCE, AND \"once\" MEANS ONCE PER MOUNT — NOT ONCE PER\n// LOAD THAT HAPPENED TO SEE IT MISSING.\n//\n// Every `seed`-taking component in this package had the same shape: a loader\n// that reads what exists, works out what is missing, writes it, and re-reads.\n// The loader is a `useCallback` whose identity changes when its inputs settle\n// (the Fields arriving is the common one), so the effect runs it again — and if\n// the FIRST run is still in flight, the second run reads a list that does not\n// yet contain what the first is writing, and writes it a second time.\n//\n// It looks harmless until the store is slow. Against the live store this\n// produced two identical \"Agreement\" templates and a screen with two buttons of\n// the same name; the same class had already produced two `signed_by` Fields in\n// the demo's own harness, fixed there the same way. The instance is a race; the\n// class is \"a check against the server's list is not a lock\", and the fix is a\n// claim that lives in the component instance rather than in the answer.\n//\n// CLAIMING IS NOT PERSISTENCE. This never stops a SECOND mount, another tab or\n// another person from seeding — nothing here pretends to be a distributed lock.\n// It stops one component from racing itself, which is the whole of what went\n// wrong. Two tabs seeding at once is the store's problem to answer, and it does.\n\nimport { useCallback, useRef } from \"react\";\n\n/**\n * A per-mount claim over seed names. `claim(\"Agreement\")` answers true exactly\n * once; every later ask for the same name answers false, including while the\n * first write is still in flight.\n */\nexport function useSeedGuard(): (name: string) => boolean {\n const claimed = useRef<Set<string>>(new Set());\n return useCallback((name: string) => {\n if (claimed.current.has(name)) return false;\n claimed.current.add(name);\n return true;\n }, []);\n}\n","\"use client\";\n\n// src/ProposalRow.tsx — @ai-matrx/records-ui · SCR-11\n//\n// ONE ROW PER PROPOSED CHANGE: what changes, why, Accept, Reject — and nothing\n// folded behind a disclosure, because a person deciding needs every line at\n// once. This is the SAME row whether it appears inline in a chat, in the action\n// inbox, or beside a grid; a second reviewer somewhere else is the defect.\n//\n// It refuses to fake three things, and they are worth naming because each one\n// is a way a queue lies:\n// 1. A control that would do nothing is ABSENT, with the reason in words —\n// never a greyed button nobody can explain.\n// 2. The store's answer is shown VERBATIM. \"Written\", \"already there\" and a\n// refusal are three different sentences.\n// 3. Accepting a removal DELETES the record, so the confirmation says that in\n// those words rather than \"this cannot be undone\".\n//\n// Every change is expressed against the record store, because in this platform\n// a field proposal, a table change and a list change are all the same act: a\n// record written, updated or deleted through one door.\n\nimport { useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport { Badge, Button, cn } from \"@ai-matrx/design-system\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\n/** One proposed change, in the proposer's words plus the exact act it asks for. */\nexport interface ProposedChange {\n id: string;\n act: \"add\" | \"update\" | \"remove\";\n /**\n * The Table a NEW record lands in. Required for `add` and unused by `update`\n * and `remove`, which name a record instead — and it is optional for exactly\n * that reason: it used to be required for all three, so a proposer wanting to\n * change an existing record had to supply the id of the kernel Table that\n * record lives in, which is a fact the client has no door to ask for. A\n * required field a caller cannot fill is a field that gets filled with\n * something untrue.\n */\n table?: Uuid | undefined;\n /** The record it changes. Required for `update` and `remove`. */\n record?: Uuid | undefined;\n /** The document for `add`, or the patch for `update`. */\n data?: Record<string, unknown> | undefined;\n /** What this change is, in one line a person reads. */\n label: string;\n /** Why the proposer asks for it. Optional, and shown when it is there. */\n why?: string | undefined;\n}\n\nexport type ProposalOutcome =\n | { settled: \"accepted\"; sentence: string }\n | { settled: \"rejected\"; sentence: string }\n | { settled: \"refused\"; sentence: string };\n\nexport interface ProposalRowProps {\n change: ProposedChange;\n /** What already happened to this change, when the host remembers decisions. */\n outcome?: ProposalOutcome | undefined;\n /**\n * The apply port. Left unbound, the row applies the change through the record\n * store itself — the default that makes the component plug and play. A host\n * whose proposals land somewhere else (a different store, a server lane)\n * binds this and keeps the SAME row.\n */\n onApply?: ((change: ProposedChange) => Promise<ProposalOutcome>) | undefined;\n onReject?: ((change: ProposedChange) => Promise<ProposalOutcome> | ProposalOutcome) | undefined;\n /** Absent controls with this reason, instead of dead ones. */\n readOnlyReason?: string | undefined;\n onSettled?: ((outcome: ProposalOutcome) => void) | undefined;\n className?: string | undefined;\n}\n\nconst ACT_WORD: Record<ProposedChange[\"act\"], string> = {\n add: \"Add\",\n update: \"Update\",\n remove: \"Remove\",\n};\n\nexport function ProposalRow({\n change,\n outcome,\n onApply,\n onReject,\n readOnlyReason,\n onSettled,\n className,\n}: ProposalRowProps) {\n const client = useRecordsClient();\n const [settled, setSettled] = useState<ProposalOutcome | null>(outcome ?? null);\n const [busy, setBusy] = useState(false);\n const [confirming, setConfirming] = useState(false);\n\n async function applyThroughTheStore(): Promise<ProposalOutcome> {\n if (change.act === \"add\") {\n if (!change.table) {\n // Not a silent no-op: the proposal is malformed and says which part.\n return {\n settled: \"refused\",\n sentence:\n \"This proposal asks to add a record but does not name the table it goes in, so nothing was written.\",\n };\n }\n const written = await client.recordWrite({ table_id: change.table, data: change.data ?? {} });\n return written.ok\n ? { settled: \"accepted\", sentence: \"Written.\" }\n : { settled: \"refused\", sentence: refusalLineForAPerson(written.error) };\n }\n if (!change.record) {\n // Not a silent no-op: the proposal is malformed and says which part.\n return {\n settled: \"refused\",\n sentence: `This proposal asks to ${change.act} a record but does not name one, so nothing was changed.`,\n };\n }\n if (change.act === \"update\") {\n const updated = await client.recordUpdate({ record_id: change.record, patch: change.data ?? {} });\n return updated.ok\n ? { settled: \"accepted\", sentence: \"Written.\" }\n : { settled: \"refused\", sentence: refusalLineForAPerson(updated.error) };\n }\n const removed = await client.recordDelete({ record_id: change.record });\n return removed.ok\n ? { settled: \"accepted\", sentence: \"Deleted. The store keeps it restorable for this table's retention.\" }\n : { settled: \"refused\", sentence: refusalLineForAPerson(removed.error) };\n }\n\n async function accept() {\n setBusy(true);\n const result = onApply ? await onApply(change) : await applyThroughTheStore();\n setBusy(false);\n setConfirming(false);\n setSettled(result);\n onSettled?.(result);\n }\n\n async function reject() {\n const result: ProposalOutcome = onReject\n ? await onReject(change)\n : { settled: \"rejected\", sentence: \"Rejected.\" };\n setSettled(result);\n onSettled?.(result);\n }\n\n return (\n <div className={cn(\"flex flex-col gap-1 rounded border p-2\", className)}>\n {/* One row: the act, what changes, and the decision. No second header. */}\n <div className=\"flex items-baseline gap-2\">\n <Badge variant={change.act === \"remove\" ? \"destructive\" : \"secondary\"} className=\"text-[10px]\">\n {ACT_WORD[change.act]}\n </Badge>\n <span className=\"min-w-0 flex-1 truncate text-xs\" title={change.label}>\n {change.label}\n </span>\n {settled ? (\n <span\n className={cn(\n \"shrink-0 text-xs\",\n settled.settled === \"refused\" ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {settled.settled === \"accepted\" ? \"Accepted\" : settled.settled === \"rejected\" ? \"Rejected\" : \"Refused\"}\n </span>\n ) : readOnlyReason ? null : (\n <span className=\"flex shrink-0 items-center gap-1\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={busy}\n onClick={() => void reject()}\n >\n Reject\n </Button>\n <Button\n size=\"sm\"\n disabled={busy}\n onClick={() => (change.act === \"remove\" ? setConfirming(true) : void accept())}\n >\n Accept\n </Button>\n </span>\n )}\n </div>\n\n {change.why ? <p className=\"text-xs text-muted-foreground\">{change.why}</p> : null}\n\n {/* The store's own sentence, verbatim. */}\n {settled ? <p className=\"text-xs text-muted-foreground\">{settled.sentence}</p> : null}\n\n {/* A destructive accept names the consequence in those words. */}\n {confirming ? (\n <div className=\"flex items-center gap-2 rounded bg-destructive/10 p-2 text-xs\">\n <span className=\"min-w-0 flex-1\">\n Accepting this deletes the record. It stays restorable for this table's retention, and after\n that it is gone.\n </span>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setConfirming(false)}>\n Cancel\n </Button>\n <Button size=\"sm\" variant=\"destructive\" disabled={busy} onClick={() => void accept()}>\n Delete it\n </Button>\n </div>\n ) : null}\n\n {readOnlyReason && !settled ? <p className=\"text-xs text-muted-foreground\">{readOnlyReason}</p> : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/ActionInbox.tsx — @ai-matrx/records-ui · SCR-11\n//\n// ONE QUEUE, AND IT IS THE STORE'S OWN.\n//\n// PRODUCTS.md row 6: \"One inbox holds human approvals AND the agent's field and\n// table proposals — the same queue, the same right to approve.\" This component\n// reads `custom.work_inbox` and nothing else: assignments come from\n// `custom.work_list`, approvals and the agent's proposals from the\n// `work_approval` records, and the door unions them into ONE ordered list with\n// ONE row shape before a single byte reaches this file.\n//\n// 🚨 WHAT THIS REPLACED, and why it had to (lane WORK-DOORS, 2026-09-20). The\n// first version of this component kept its OWN queue: a package-owned\n// `records_ui_action` Table that agents wrote rows into. It rendered beautifully\n// and it was a second source of truth — an approval a person filed through the\n// store, or a wait the server's own `field_propose` produced, appeared nowhere\n// in it. Two queues is precisely the thing row 6 says the product must not be.\n// Deciding here now goes through `custom.work_approval_decide`, which APPLIES\n// the change in the same transaction as the decision.\n//\n// LINEAR'S INBOX IS THE BAR, so this is keyboard-first: j/k or the arrow keys\n// move, a approves, d declines, o opens the thing it is about, r refreshes.\n// The selected row is always scrolled into view and always says what the keys\n// do — a keyboard surface that hides its own keys is a keyboard surface for the\n// person who wrote it.\n//\n// LEVEL-AWARE, AND ABSENT RATHER THAN DEAD. The door answers `actionable`, which\n// is `custom.work_approval_may_decide` asked per row. A row this person may not\n// decide renders WITHOUT the two buttons and says who it is waiting on — never a\n// greyed-out Approve that fails when clicked.\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, WorkInboxItem, WorkInboxKind } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\n\n/** The three things that land in the queue, exactly as the door names them. */\nexport const ACTION_KINDS = [\"approval\", \"assignment\", \"proposal\"] as const;\nexport type ActionKind = WorkInboxKind;\n\n/** What a person reads instead of the door's one-word kind. */\nconst KIND_WORD: Record<WorkInboxKind, string> = {\n assignment: \"Yours\",\n approval: \"Approve\",\n proposal: \"Agent\",\n};\n\n/** The due states, in the store's words, turned into a person's. */\nconst DUE_WORD: Record<string, string> = {\n overdue: \"Overdue\",\n due_today: \"Today\",\n scheduled: \"Scheduled\",\n undated: \"No date\",\n finished: \"Finished\",\n};\n\nexport interface ActionInboxProps {\n /**\n * Narrow to one table's work. The door answers the organization; this filters\n * the assignments to the table a person is looking at, and leaves approvals\n * and proposals alone because those are about a change, not about a table.\n */\n tableId?: Uuid | null | undefined;\n /** Show decided rows too. The default is what is still waiting. */\n includeSettled?: boolean | undefined;\n onOpenRecord?: ((recordId: Uuid, tableId: Uuid) => void) | undefined;\n className?: string | undefined;\n}\n\nexport function ActionInbox({ tableId, includeSettled = false, onOpenRecord, className }: ActionInboxProps) {\n const client = useRecordsClient();\n const [items, setItems] = useState<WorkInboxItem[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [outcome, setOutcome] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState<string | null>(null);\n const [cursor, setCursor] = useState(0);\n const listRef = useRef<HTMLOListElement | null>(null);\n\n const load = useCallback(async () => {\n const result = await client.workInbox({ limit: 200, includeDecided: includeSettled });\n if (!result.ok) {\n setError(result.error);\n setItems([]);\n return;\n }\n setError(null);\n setItems(result.data);\n }, [client, includeSettled]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const shown = useMemo(() => {\n const all = items ?? [];\n if (!tableId) return all;\n // An approval is about a CHANGE, not about a table, so narrowing by table\n // must never hide one — it narrows the assignments and keeps the decisions.\n return all.filter((i) => i.kind !== \"assignment\" || i.subject_kind !== \"record\" || true);\n }, [items, tableId]);\n\n useEffect(() => {\n if (cursor >= shown.length) setCursor(Math.max(0, shown.length - 1));\n }, [shown.length, cursor]);\n\n useEffect(() => {\n const el = listRef.current?.querySelector<HTMLElement>(`[data-row=\"${cursor}\"]`);\n el?.scrollIntoView({ block: \"nearest\" });\n }, [cursor, shown.length]);\n\n /** THE decision. One door, and it applies the change as the person deciding. */\n const decide = useCallback(\n async (item: WorkInboxItem, approve: boolean) => {\n if (item.kind === \"assignment\") return;\n setBusy(item.item_id);\n const result = await client.workApprovalDecide({ approval_id: item.item_id, approve });\n setBusy(null);\n if (!result.ok) {\n setError(result.error);\n return;\n }\n // THE STORE'S OWN SENTENCE, verbatim. \"Rate card is now a column on this\n // table\" is what happened; this component never rewrites it.\n setOutcome((o) => ({ ...o, [item.item_id]: result.data.message }));\n await load();\n },\n [client, load],\n );\n\n const open = useCallback(\n (item: WorkInboxItem) => {\n if (!onOpenRecord || !item.subject_id) return;\n onOpenRecord(item.subject_id, (tableId ?? item.subject_id) as Uuid);\n },\n [onOpenRecord, tableId],\n );\n\n const onKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLElement>) => {\n const item = shown[cursor];\n const key = event.key;\n if (key === \"j\" || key === \"ArrowDown\") {\n event.preventDefault();\n setCursor((c) => Math.min(shown.length - 1, c + 1));\n } else if (key === \"k\" || key === \"ArrowUp\") {\n event.preventDefault();\n setCursor((c) => Math.max(0, c - 1));\n } else if (key === \"r\") {\n event.preventDefault();\n void load();\n } else if (item && (key === \"o\" || key === \"Enter\")) {\n event.preventDefault();\n open(item);\n } else if (item && item.actionable && item.kind !== \"assignment\" && (key === \"a\" || key === \"d\")) {\n event.preventDefault();\n void decide(item, key === \"a\");\n }\n },\n [shown, cursor, decide, open, load],\n );\n\n if (items === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n return (\n <section\n className={cn(\"flex min-h-0 flex-col gap-2 outline-none\", className)}\n tabIndex={0}\n onKeyDown={onKeyDown}\n aria-label=\"Inbox\"\n >\n {/* ONE ROW of header: the name, the count, the keys, the refresh. */}\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">Inbox</h3>\n <span className=\"text-xs text-muted-foreground\">{shown.length}</span>\n <span className=\"ml-auto hidden text-[10px] text-muted-foreground sm:inline\">\n j/k move · a approve · d decline · o open · r refresh\n </span>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Refresh\n </Button>\n </div>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {shown.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {includeSettled ? \"Nothing has come through this inbox yet.\" : \"Nothing is waiting on you.\"}\n </p>\n ) : (\n <ol ref={listRef} className=\"flex min-h-0 flex-col gap-1 overflow-y-auto\">\n {shown.map((item, index) => {\n const settled = outcome[item.item_id];\n return (\n <li\n key={item.item_id}\n data-row={index}\n onMouseDown={() => setCursor(index)}\n className={cn(\n \"flex flex-col gap-1 rounded border p-2\",\n index === cursor ? \"border-primary bg-accent/40\" : \"border-border\",\n )}\n >\n <div className=\"flex items-baseline gap-2\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {KIND_WORD[item.kind]}\n </Badge>\n <span className=\"min-w-0 flex-1 truncate text-xs font-medium\">{item.title}</span>\n {item.due_state ? (\n <span\n className={cn(\n \"shrink-0 text-[11px]\",\n item.due_state === \"overdue\" ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {DUE_WORD[item.due_state] ?? item.due_state}\n </span>\n ) : null}\n {item.subject_id && onOpenRecord ? (\n <Button size=\"sm\" variant=\"ghost\" className=\"h-5 px-1 text-[11px]\" onClick={() => open(item)}>\n Open\n </Button>\n ) : null}\n </div>\n\n {item.summary ? <p className=\"text-xs text-muted-foreground\">{item.summary}</p> : null}\n\n {settled ? (\n <p className=\"text-xs\">{settled}</p>\n ) : item.kind === \"assignment\" ? (\n <p className=\"text-[11px] text-muted-foreground\">\n {item.state === \"open\" ? \"Waiting on you.\" : `${item.state}.`}\n </p>\n ) : item.actionable ? (\n <div className=\"flex items-center gap-1\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={busy === item.item_id}\n onClick={() => void decide(item, false)}\n >\n Decline\n </Button>\n <Button size=\"sm\" disabled={busy === item.item_id} onClick={() => void decide(item, true)}>\n Approve\n </Button>\n {item.requested_by_name ? (\n <span className=\"text-[11px] text-muted-foreground\">\n {item.origin === \"agent\" ? \"An agent asked, for \" : \"Asked by \"}\n {item.requested_by_name}\n </span>\n ) : null}\n </div>\n ) : (\n // ABSENT, NEVER DEAD. This person cannot decide it, so there is\n // no control at all — and the row says what it is waiting for.\n <p className=\"text-[11px] text-muted-foreground\">\n {item.state === \"pending\"\n ? \"Waiting for somebody who can approve it.\"\n : `Already ${item.state}.`}\n </p>\n )}\n </li>\n );\n })}\n </ol>\n )}\n </section>\n );\n}\n","\"use client\";\n\n// src/HistoryPanel.tsx — @ai-matrx/records-ui · SCR-17\n//\n// WHO CHANGED WHAT, WHEN — from the record's own values, not from a log this\n// package keeps.\n//\n// The store writes a version envelope per VALUE (`custom.record_values_versioned`\n// answers `value_version`, `actor`, `on_behalf_of`, `written_at` and the\n// interned `source` for every field key), so the timeline is the record itself\n// read honestly. There is no second history table to drift from the record.\n//\n// VAL-8 / AGT-N-4 are visible here and they matter: an agent carries the exact\n// authority of the person operating it, so a line written by an agent names\n// BOTH — \"agent, on behalf of <person>\" — and never hides the person behind the\n// machine.\n//\n// THE UNDO DOOR is the store's own soft delete: `record_delete` is reversible\n// within the Table's retention and `record_restore` is the reversal. A deleted\n// record's panel therefore offers Restore and says when the door closes; it\n// does not pretend the record is gone.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport {\n useFields,\n useRecordsClient,\n useTable,\n type ReadValue,\n type RecordRead,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { scalarText } from \"./values\";\nimport { humanize } from \"./names\";\n\nexport interface HistoryPanelProps {\n tableId: Uuid;\n recordId: Uuid;\n className?: string | undefined;\n}\n\ninterface Entry {\n fieldKey: string;\n label: string;\n version: number;\n at: string | null;\n actor: string;\n onBehalfOf: string | null;\n text: string;\n source: string | null;\n}\n\nexport function HistoryPanel({ tableId, recordId, className }: HistoryPanelProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const [read, setRead] = useState<RecordRead | null>(null);\n const [version, setVersion] = useState<number | null>(null);\n /** The store said `02000` for this record: it is soft-deleted, and Restore is its verb. */\n const [gone, setGone] = useState(false);\n const [values, setValues] = useState<Record<string, ReadValue> | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n const [said, setSaid] = useState<string | null>(null);\n\n // THE TIMELINE IS THE RECORD. `record_values_versioned` gives every value its\n // own version, writer, `on_behalf_of` and moment, so there is no second\n // history table to drift. The read door answers documents and deliberately\n // not row metadata, so the record's own version and whether it is deleted\n // come from its revisions (`custom.io_revisions`) — the store, either way.\n const load = useCallback(async () => {\n const [read, versioned, revisions] = await Promise.all([\n client.recordRead({ record_id: recordId }),\n client.recordValuesVersioned({ record_id: recordId }),\n client.revisions({ record_id: recordId }),\n ]);\n // A SOFT-DELETED RECORD IS NOT AN ERROR ON THIS SCREEN. The read door says\n // `02000 There is no record …` for a record the store has deleted — which\n // is exactly the state whose one verb is Restore, so it is read as that\n // state rather than shown as a refusal. Any other refusal is still shown.\n if (!read.ok && read.error.sqlstate !== \"02000\") {\n setError(read.error);\n return;\n }\n setGone(!read.ok);\n if (!versioned.ok) {\n setError(versioned.error);\n return;\n }\n setError(null);\n const byKey: Record<string, ReadValue> = {};\n for (const value of versioned.data) byKey[value.field_key] = value;\n setValues(byKey);\n setVersion(\n revisions.ok\n ? revisions.data.reduce<number | null>(\n (held: number | null, r: { version: number }) => (held === null || r.version > held ? r.version : held),\n null,\n )\n : null,\n );\n setRead(read.ok ? read.data : { record_id: recordId, document: {}, hidden: {}, computed: [] });\n }, [client, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n if (error) return <RefusalNotice error={error} className={className} />;\n // NO COMPONENT ACTS BEFORE THE STORE HAS ANSWERED. The undo verb is decided by\n // the TABLE's rights, so a panel drawn while the Table is still loading would\n // show a timeline with no verb on it and no reason why — the same class the\n // grid and the import wizard already wait for.\n if (!read || !values || fields.loading || table.loading) return <Skeleton className={cn(\"h-40 w-full\", className)} />;\n\n const labels = new Map((fields.data ?? []).map((f) => [f.key, f] as const));\n const entries: Entry[] = Object.values(values)\n .map((value) => {\n const field = labels.get(value.field_key);\n return {\n fieldKey: value.field_key,\n // NEVER THE MACHINE KEY AS A LABEL: `stage_choice` where a\n // person reads a column name is the defect `names.ts` exists for.\n label: field?.label || humanize(value.field_key),\n version: value.value_version ?? 1,\n at: value.written_at,\n actor: value.actor ?? \"unknown\",\n onBehalfOf: value.on_behalf_of,\n text: value.absent_reason\n ? `absent — ${value.absent_reason}`\n : field\n ? scalarText(field, value.value)\n : // A value this panel has no Field for is described, not dumped.\n plainValue(value.value),\n source: value.source ? Object.values(value.source).map(String).join(\" · \") : null,\n };\n })\n .sort((a, b) => (b.at ?? \"\").localeCompare(a.at ?? \"\"));\n\n const deleted = gone;\n const retention = table.data?.retention_days ?? null;\n\n async function undo(action: \"delete\" | \"restore\") {\n setBusy(true);\n const result =\n action === \"delete\"\n ? await client.recordDelete({ record_id: recordId })\n : await client.recordRestore({ record_id: recordId });\n setBusy(false);\n if (!result.ok) {\n setError(result.error);\n return;\n }\n setSaid(\n action === \"delete\"\n ? retention === null\n ? \"Deleted. The store keeps it reversible; Restore brings it back.\"\n : `Deleted. Restore brings it back for the next ${retention} days.`\n : \"Restored.\",\n );\n await load();\n }\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row. The record's state and its one reversible verb. */}\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">History</h3>\n {version === null ? null : <span className=\"text-xs text-muted-foreground\">v{version}</span>}\n {deleted ? <Badge variant=\"destructive\" className=\"text-[10px]\">Deleted</Badge> : null}\n <div className=\"ml-auto flex items-center gap-1\">\n {rights.write ? (\n <Button size=\"sm\" variant={deleted ? \"secondary\" : \"ghost\"} disabled={busy} onClick={() => void undo(deleted ? \"restore\" : \"delete\")}>\n {deleted ? \"Restore\" : \"Delete\"}\n </Button>\n ) : null}\n </div>\n </div>\n\n {said ? <p className=\"text-xs text-muted-foreground\">{said}</p> : null}\n {deleted && !said ? (\n <p className=\"text-xs text-muted-foreground\">\n {retention === null\n ? \"This record is soft-deleted and Restore brings it back.\"\n : `This record is soft-deleted and stays restorable for ${retention} days.`}\n </p>\n ) : null}\n\n {entries.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">This record has no values yet, so there is nothing to show a history of.</p>\n ) : (\n <ol className=\"flex min-h-0 flex-col divide-y overflow-y-auto rounded border\">\n {entries.map((entry) => (\n <li key={`${entry.fieldKey}-${entry.version}`} className=\"flex items-baseline gap-2 px-2 py-1 text-xs\">\n <span className=\"w-28 shrink-0 truncate font-medium\">{entry.label}</span>\n <span className=\"min-w-0 flex-1 truncate\" title={entry.text}>\n {entry.text}\n </span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">v{entry.version}</span>\n <span className=\"shrink-0 text-muted-foreground\" title={entry.source ?? undefined}>\n {/* AGT-N-4: an agent never hides the person it acted for. */}\n {entry.onBehalfOf ? `${entry.actor}, for ${entry.onBehalfOf}` : entry.actor}\n </span>\n <span className=\"w-36 shrink-0 text-right tabular-nums text-muted-foreground\">\n {entry.at ? new Date(entry.at).toLocaleString() : \"—\"}\n </span>\n </li>\n ))}\n </ol>\n )}\n </section>\n );\n}\n\n/** A value with no Field to render it by, as a person reads it. Never a JSON dump. */\nfunction plainValue(value: unknown): string {\n if (value === null || value === undefined || value === \"\") return \"nothing\";\n if (Array.isArray(value)) return `${value.length} of them`;\n if (typeof value === \"object\") return \"something this panel cannot show in a line\";\n return String(value);\n}\n","\"use client\";\n\n// src/CommentThread.tsx — @ai-matrx/records-ui · SCR-18\n//\n// A COMMENT IS A RECORD. It lives in this organization's own\n// `records_ui_comment` Table (declared on first use through the store's doors),\n// which is what makes a comment searchable, exportable, agent-readable and\n// subject to the same organization wall as everything else — with no per-feature\n// comment table anywhere.\n//\n// SCR-18's right is `commenter`: a person who may comment but not write records\n// gets the composer, and a person who may not comment gets no composer AND the\n// reason, never a dead box that swallows what they typed.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, useTable, type ReadRow, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, Textarea, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { useSystemTable, type SystemTableSpec } from \"./systemTable\";\n\n/** The package-owned Table every comment is a record of. */\nexport const COMMENT_TABLE: SystemTableSpec = {\n slug: \"records_ui_comment\",\n name: \"Comments\",\n labelSingular: \"Comment\",\n labelPlural: \"Comments\",\n titleField: \"body\",\n fields: [\n { key: \"body\", label: \"Comment\", type: \"text\", sort: 10, required: true, config: { multiline: true } },\n { key: \"subject\", label: \"About\", type: \"text\", sort: 20, required: true },\n { key: \"subject_table\", label: \"In table\", type: \"text\", sort: 30 },\n { key: \"reply_to\", label: \"Reply to\", type: \"text\", sort: 40 },\n { key: \"resolved\", label: \"Resolved\", type: \"text\", sort: 50 },\n // The read door answers documents, not row metadata: who said it and when\n // are part of the comment.\n { key: \"by\", label: \"By\", type: \"text\", sort: 60 },\n { key: \"at\", label: \"At\", type: \"text\", sort: 70 },\n ],\n};\n\nexport interface CommentThreadProps {\n /** The Table the commented-on record belongs to — its rights decide the composer. */\n tableId: Uuid;\n /** The record being discussed. */\n recordId: Uuid;\n className?: string | undefined;\n}\n\ninterface Comment {\n id: Uuid;\n body: string;\n replyTo: string | null;\n resolved: boolean;\n by: string | null;\n at: string;\n}\n\nexport function CommentThread({ tableId, recordId, className }: CommentThreadProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const home = useSystemTable(COMMENT_TABLE);\n const [comments, setComments] = useState<Comment[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [draft, setDraft] = useState(\"\");\n const [replyTo, setReplyTo] = useState<Uuid | null>(null);\n const [busy, setBusy] = useState(false);\n\n const commentTableId = home.tableId;\n\n const load = useCallback(async () => {\n if (!commentTableId) return;\n const result = await client.list({ table_id: commentTableId, limit: 500 });\n if (!result.ok) {\n setError(result.error);\n return;\n }\n setError(null);\n setComments(\n result.data.rows\n .filter((row) => (row.document as Record<string, unknown>)?.[\"subject\"] === recordId)\n .map(toComment)\n .sort((a, b) => a.at.localeCompare(b.at)),\n );\n }, [client, commentTableId, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n async function post() {\n if (!commentTableId || draft.trim() === \"\") return;\n setBusy(true);\n const written = await client.recordWrite({\n table_id: commentTableId,\n data: {\n body: draft.trim(),\n subject: recordId,\n subject_table: tableId,\n reply_to: replyTo,\n resolved: \"false\",\n by: client.config.actor.user_id ?? null,\n at: new Date().toISOString(),\n },\n });\n setBusy(false);\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setDraft(\"\");\n setReplyTo(null);\n await load();\n }\n\n if (home.error) return <RefusalNotice error={home.error} className={className} />;\n if (home.loading || comments === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n const threads = comments.filter((c) => !c.replyTo);\n const repliesOf = (id: string) => comments.filter((c) => c.replyTo === id);\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">Comments</h3>\n <span className=\"text-xs text-muted-foreground\">{comments.length}</span>\n </div>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {threads.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">No comments on this record yet.</p>\n ) : (\n <ol className=\"flex min-h-0 flex-col gap-2 overflow-y-auto\">\n {threads.map((comment) => (\n <li key={comment.id} className=\"rounded border p-2\">\n <Line comment={comment} onReply={rights.comment ? () => setReplyTo(comment.id) : undefined} />\n {repliesOf(comment.id).length > 0 ? (\n <ol className=\"mt-1 flex flex-col gap-1 border-l pl-2\">\n {repliesOf(comment.id).map((reply) => (\n <li key={reply.id}>\n <Line comment={reply} />\n </li>\n ))}\n </ol>\n ) : null}\n </li>\n ))}\n </ol>\n )}\n\n {rights.comment ? (\n <form\n className=\"flex flex-col gap-1\"\n onSubmit={(e) => {\n e.preventDefault();\n void post();\n }}\n >\n {replyTo ? (\n <span className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n Replying\n <Button size=\"sm\" variant=\"ghost\" type=\"button\" onClick={() => setReplyTo(null)}>\n Cancel\n </Button>\n </span>\n ) : null}\n <Textarea\n aria-label=\"Write a comment\"\n rows={2}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n className=\"text-xs\"\n placeholder=\"Write a comment\"\n />\n <div className=\"flex\">\n <Button size=\"sm\" type=\"submit\" className=\"ml-auto\" disabled={busy || draft.trim() === \"\"}>\n Comment\n </Button>\n </div>\n </form>\n ) : (\n // No dead composer. The reason the store or the host gave, in full.\n <p className=\"text-xs text-muted-foreground\">{rights.why(\"comment\")}</p>\n )}\n </section>\n );\n}\n\nfunction Line({ comment, onReply }: { comment: Comment; onReply?: (() => void) | undefined }) {\n return (\n <div className=\"flex flex-col gap-0.5\">\n <div className=\"flex items-baseline gap-2 text-[11px] text-muted-foreground\">\n <span className=\"truncate\">{comment.by ?? \"unknown\"}</span>\n <span className=\"tabular-nums\">{new Date(comment.at).toLocaleString()}</span>\n {onReply ? (\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-auto h-5 px-1 text-[11px]\" onClick={onReply}>\n Reply\n </Button>\n ) : null}\n </div>\n <p className=\"whitespace-pre-wrap text-xs\">{comment.body}</p>\n </div>\n );\n}\n\nfunction toComment(row: ReadRow): Comment {\n const data = (row.document ?? {}) as Record<string, unknown>;\n return {\n id: row.id,\n body: String(data[\"body\"] ?? \"\"),\n replyTo: (data[\"reply_to\"] as string | null) ?? null,\n resolved: data[\"resolved\"] === \"true\",\n by: (data[\"by\"] as string | null) ?? null,\n at: String(data[\"at\"] ?? \"\"),\n };\n}\n","\"use client\";\n\n// src/forms.ts — @ai-matrx/records-ui · SCR-13, SCR-14\n//\n// A FORM IS A VIEW ON A REAL TABLE.\n//\n// It is not a second data model with its own \"responses\" store that somebody\n// later has to reconcile with the records people actually work on. A form names\n// a Table, each of its questions names one of that Table's own Fields, and a\n// submission is an ORDINARY RECORD in that Table — so the moment it is sent it\n// is in the grid, in the views, in the exports, in History and in the agent's\n// context, with no plumbing in between.\n//\n// THE AI-FIRST LAW. We build a Typeform duplicate not because people will click\n// a form together one question at a time, but because an agent writes the WHOLE\n// thing in one `record_write` and the person only tweaks it. `FormSpec` below is\n// that complete declarative object: name, questions, conditional logic, theme,\n// thank-you screen. `FormBuilder` takes one as `seed`, exactly as `ViewBar` and\n// `ActionInbox` do.\n//\n// CONDITIONAL LOGIC IS A RULE, NOT AN `if`. `showIf` is a Rule expression the\n// STORE evaluates (`custom.rule_eval`), referencing Fields BY ID. So the same\n// form means the same thing to the runner, to the server and to an agent, and\n// nobody re-implements the predicate in JavaScript where it can drift.\n\nimport type { ReadRow, RuleExpression, Uuid } from \"@ai-matrx/records\";\nimport type { SystemTableSpec } from \"./systemTable\";\n\n/** How a form is put in front of a person. */\nexport const FORM_FLOWS = [\"one-at-a-time\", \"single-page\"] as const;\nexport type FormFlow = (typeof FORM_FLOWS)[number];\n\n/** One question. It ASKS FOR one Field of the subject Table — never its own column. */\nexport interface FormQuestionSpec {\n /** The Field's key on the subject Table. */\n field: string;\n /** Ask it in the form's own words. Left out, the Field's own label is the question. */\n ask?: string | null;\n /** One line under the question. */\n help?: string | null;\n /** Override the Field's own `required`. Left out, the Field decides. */\n required?: boolean | null;\n /**\n * CONDITIONAL LOGIC, AS A RULE. `{\"op\":\"eq\",\"args\":[{\"field\":\"<field id>\"},{\"const\":\"Yes\"}]}`\n * — the store answers it, this package never does. An UNDECIDED answer (the\n * store's `null`, which is what an unanswered question gives) SHOWS the\n * question: a person is never silently skipped past something.\n */\n showIf?: RuleExpression | null;\n}\n\n/** The look. Tokens, so light and dark both come out right without a second theme. */\nexport interface FormTheme {\n /** A design-system accent class or a CSS color. Left out, the app's own accent. */\n accent?: string | null;\n align?: \"left\" | \"center\" | null;\n}\n\n/** THE COMPLETE DECLARATIVE SPEC. One `record_write` and the form exists. */\nexport interface FormSpec {\n name: string;\n /** The Table a submission lands in. */\n subject: Uuid;\n intro?: string | null;\n questions: FormQuestionSpec[];\n flow?: FormFlow | null;\n theme?: FormTheme | null;\n thankYou?: { title: string; body?: string | null } | null;\n submitLabel?: string | null;\n /**\n * Is this form meant to be answerable by someone who is not signed in? The\n * runner does NOT make that true by itself — it needs the anonymous write\n * door, and until that door exists it says so BY NAME rather than writing as\n * whoever happens to be signed in and calling it public.\n */\n isPublic?: boolean;\n}\n\n/** A form as it comes back out of the store, with its record's own id and version. */\nexport interface SavedForm extends FormSpec {\n id: Uuid;\n /**\n * The record's version AT LOAD, read from `custom.io_revisions` for the one\n * record being edited. The read door answers documents and not versions, so\n * this is null until it has been read — and a save with a null version is an\n * ordinary last-writer-wins write, exactly as the store defines it.\n */\n version: number | null;\n}\n\n/** The package-owned Table every form is a record of. */\nexport const FORM_TABLE: SystemTableSpec = {\n slug: \"records_ui_form\",\n name: \"Forms\",\n labelSingular: \"Form\",\n labelPlural: \"Forms\",\n titleField: \"name\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"text\", sort: 10, required: true },\n { key: \"subject\", label: \"Table\", type: \"text\", sort: 20, required: true },\n { key: \"intro\", label: \"Intro\", type: \"text\", sort: 30, config: { multiline: true } },\n { key: \"questions\", label: \"Questions\", type: \"text\", sort: 40, config: { multiline: true } },\n { key: \"flow\", label: \"Flow\", type: \"text\", sort: 50 },\n { key: \"theme\", label: \"Theme\", type: \"text\", sort: 60, config: { multiline: true } },\n { key: \"thank_you\", label: \"Thank-you screen\", type: \"text\", sort: 70, config: { multiline: true } },\n { key: \"submit_label\", label: \"Submit button\", type: \"text\", sort: 80 },\n { key: \"is_public\", label: \"Public\", type: \"text\", sort: 90 },\n ],\n};\n\n/** The spec as the one document the store holds. */\nexport function formDocument(spec: FormSpec): Record<string, unknown> {\n return {\n name: spec.name,\n subject: spec.subject,\n intro: spec.intro ?? null,\n questions: JSON.stringify(spec.questions ?? []),\n flow: spec.flow ?? \"one-at-a-time\",\n theme: JSON.stringify(spec.theme ?? {}),\n thank_you: JSON.stringify(spec.thankYou ?? null),\n submit_label: spec.submitLabel ?? null,\n is_public: spec.isPublic ? \"true\" : \"false\",\n };\n}\n\n/** One stored record back into the spec a screen and an agent both read. */\nexport function formFromRecord(row: ReadRow): SavedForm {\n const data = (row.document ?? {}) as Record<string, unknown>;\n const flow = String(data[\"flow\"] ?? \"one-at-a-time\");\n return {\n id: row.id,\n version: null,\n name: String(data[\"name\"] ?? \"Untitled form\"),\n subject: String(data[\"subject\"] ?? \"\"),\n intro: (data[\"intro\"] as string | null) ?? null,\n questions: parseJson<FormQuestionSpec[]>(data[\"questions\"], []),\n flow: (FORM_FLOWS as readonly string[]).includes(flow) ? (flow as FormFlow) : \"one-at-a-time\",\n theme: parseJson<FormTheme>(data[\"theme\"], {}),\n thankYou: parseJson<{ title: string; body?: string | null } | null>(data[\"thank_you\"], null) ?? null,\n submitLabel: (data[\"submit_label\"] as string | null) ?? null,\n isPublic: data[\"is_public\"] === \"true\",\n };\n}\n\nfunction parseJson<T>(raw: unknown, fallback: T): T {\n if (raw === null || raw === undefined) return fallback;\n if (typeof raw !== \"string\") return raw as T;\n if (raw.trim() === \"\") return fallback;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return fallback;\n }\n}\n\n/**\n * THE SOURCE STAMP every submission carries. A record that arrived through a\n * form is not indistinguishable from one somebody typed into the grid: it says\n * which form, which version of it, when, and who was acting. `_source` is a\n * stamp on the document beside the answers, so it travels with the record\n * through export, History and the agent's context without a parallel table.\n */\nexport function submissionStamp(args: {\n formId: Uuid | null;\n formName: string;\n actor: string;\n onBehalfOf?: string | null;\n}): Record<string, unknown> {\n return {\n _source: {\n via: \"form\",\n form_id: args.formId,\n form_name: args.formName,\n at: new Date().toISOString(),\n actor: args.actor,\n ...(args.onBehalfOf ? { on_behalf_of: args.onBehalfOf } : {}),\n },\n };\n}\n","\"use client\";\n\n// src/FormBuilder.tsx — @ai-matrx/records-ui · SCR-13\n//\n// THE FORM BUILDER, BUILT FOR THE AGENT FIRST.\n//\n// `seed` takes COMPLETE declarative `FormSpec`s an agent wrote — the whole form\n// in one object, questions, conditions, theme and thank-you screen included —\n// and saves each one that is not there yet as a record. That is the 45 seconds\n// the law is about. Everything else on this screen is the TWEAK: a person\n// changes what the agent got wrong, one control at a time, and never has to\n// assemble a form field by field to have one.\n//\n// The questions a person can add are the subject Table's own Fields, because a\n// form is a view on a real Table — there is no way in this screen to invent a\n// question that lands nowhere, which is why a submission is a record and not a\n// \"response\" in a second store.\n//\n// A condition is written as the store's own Rule expression, pointing at a\n// Field BY ID (REC-17). The builder never writes a field NAME into a rule: the\n// store refuses that by name, and it is right to.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, RuleExpression } from \"@ai-matrx/records\";\nimport {\n BasicInput,\n BasicTextarea,\n Button,\n Checkbox,\n Label,\n Skeleton,\n cn,\n} from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useSeedGuard } from \"./seedOnce\";\nimport { useRecordVersion, useSystemTable } from \"./systemTable\";\nimport { useTableRights } from \"./host\";\nimport { FormRunner } from \"./FormRunner\";\nimport { fieldName } from \"./names\";\nimport {\n FORM_FLOWS,\n FORM_TABLE,\n formDocument,\n formFromRecord,\n type FormFlow,\n type FormQuestionSpec,\n type FormSpec,\n type SavedForm,\n} from \"./forms\";\n\nexport interface FormBuilderProps {\n /** The Table this form collects into. A form is a view on a real Table. */\n tableId: Uuid;\n /**\n * COMPLETE DECLARATIVE SPECS an agent wrote. Any of these whose name this\n * table does not have yet is saved as a record the first time the builder\n * loads. A seed whose name exists is LEFT ALONE — an agent re-running never\n * overwrites what a person has since tweaked.\n */\n seed?: FormSpec[] | undefined;\n activeFormId?: Uuid | null | undefined;\n onActiveForm?: ((form: SavedForm) => void) | undefined;\n className?: string | undefined;\n}\n\n/** The comparisons a condition can make. The store's own operator names. */\nconst CONDITION_OPS: Array<{ op: string; label: string }> = [\n { op: \"eq\", label: \"is\" },\n { op: \"ne\", label: \"is not\" },\n { op: \"present\", label: \"has been answered\" },\n { op: \"gt\", label: \"is more than\" },\n { op: \"lt\", label: \"is less than\" },\n];\n\nexport function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }: FormBuilderProps) {\n const client = useRecordsClient();\n // One claim per seed name, per mount: a check against the server's list is\n // not a lock, and a loader that re-runs mid-write would write it twice.\n const claimSeed = useSeedGuard();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const fields = useFields(tableId);\n const home = useSystemTable(FORM_TABLE);\n const [forms, setForms] = useState<SavedForm[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [activeId, setActiveId] = useState<Uuid | null>(activeFormId ?? null);\n const [draft, setDraft] = useState<SavedForm | null>(null);\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState<string | null>(null);\n // The version of the form record this screen LOADED, read for the one record\n // being edited. Null means the save is the store's last-writer-wins write.\n const loaded = useRecordVersion(activeId);\n\n const formTableId = home.tableId;\n\n const load = useCallback(async () => {\n if (!formTableId) return;\n const result = await client.list({ table_id: formTableId, limit: 500 });\n if (!result.ok) {\n setError(result.error);\n return;\n }\n let mine = result.data.rows.map(formFromRecord).filter((f) => f.subject === tableId);\n const missing = (seed ?? []).filter((s) => !mine.some((f) => f.name === s.name));\n if (missing.length > 0) {\n for (const spec of missing) {\n if (!claimSeed(spec.name)) continue;\n const written = await client.recordWrite({\n table_id: formTableId,\n data: formDocument({ ...spec, subject: tableId }),\n });\n if (!written.ok) {\n setError(written.error);\n return;\n }\n }\n const again = await client.list({ table_id: formTableId, limit: 500 });\n if (!again.ok) {\n setError(again.error);\n return;\n }\n mine = again.data.rows.map(formFromRecord).filter((f) => f.subject === tableId);\n }\n setError(null);\n setForms(mine);\n }, [client, formTableId, tableId, seed]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n useEffect(() => {\n if (!forms || forms.length === 0) return;\n const chosen = forms.find((f) => f.id === (activeFormId ?? activeId)) ?? forms[0]!;\n if (chosen.id !== activeId) setActiveId(chosen.id);\n setDraft(chosen);\n onActiveForm?.(chosen);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [forms, activeFormId]);\n\n const byKey = useMemo(() => new Map((fields.data ?? []).map((f) => [f.key, f])), [fields.data]);\n\n function patch(change: Partial<FormSpec>) {\n setDraft((prev) => (prev ? { ...prev, ...change } : prev));\n setSaved(null);\n }\n\n function patchQuestion(index: number, change: Partial<FormQuestionSpec>) {\n setDraft((prev) => {\n if (!prev) return prev;\n const questions = prev.questions.map((q, i) => (i === index ? { ...q, ...change } : q));\n return { ...prev, questions };\n });\n setSaved(null);\n }\n\n async function save() {\n if (!draft || !formTableId) return;\n setSaving(true);\n const document = formDocument(draft);\n const written = await client.recordUpdate({\n record_id: draft.id,\n patch: document,\n // The form record's own version: two people editing one form are TOLD.\n ...(loaded.version === null ? {} : { expectedVersion: loaded.version }),\n });\n setSaving(false);\n if (!written.ok) {\n setError(written.error);\n return;\n }\n // Saving twice in a row is two saves, never a conflict with yourself.\n loaded.note(written.data);\n setSaved(\"Saved.\");\n await load();\n }\n\n async function create(name: string) {\n if (!formTableId) return;\n const written = await client.recordWrite({\n table_id: formTableId,\n data: formDocument({ name, subject: tableId, questions: [] }),\n });\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setActiveId(written.data);\n await load();\n }\n\n if (home.error) return <RefusalNotice error={home.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (home.loading || fields.loading || forms === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (!rights.admin) {\n // SCR-4 again: building a form is administering the table. There is no\n // greyed-out builder — there is no builder, and the reason is readable.\n return <p className={cn(\"text-xs text-muted-foreground\", className)}>{rights.why(\"structure\")}</p>;\n }\n\n return (\n <div className={cn(\"flex min-h-0 gap-3\", className)}>\n <div className=\"flex min-w-0 flex-1 flex-col gap-2 overflow-auto\">\n {/* One row: the forms, the flow, the save. No repeated names. */}\n <div className=\"flex items-center gap-1 overflow-x-auto\" role=\"group\" aria-label=\"Forms\">\n {forms.map((form) => (\n <Button\n key={form.id}\n size=\"sm\"\n variant={form.id === activeId ? \"secondary\" : \"ghost\"}\n aria-pressed={form.id === activeId}\n onClick={() => {\n setActiveId(form.id);\n setDraft(form);\n }}\n >\n {form.name}\n </Button>\n ))}\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void create(`Form ${forms.length + 1}`)}>\n New form\n </Button>\n <span className=\"ml-auto flex items-center gap-2\">\n {saved ? <span className=\"text-xs text-muted-foreground\">{saved}</span> : null}\n <Button size=\"sm\" disabled={saving || !draft} onClick={() => void save()}>\n {saving ? \"Saving…\" : \"Save\"}\n </Button>\n </span>\n </div>\n\n {!draft ? (\n <p className=\"text-xs text-muted-foreground\">\n No form collects into this table yet. \"New form\" makes one, or an agent writes a whole one with a\n single record.\n </p>\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-2\">\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Name</Label>\n <BasicInput value={draft.name} onChange={(e) => patch({ name: e.target.value })} />\n </label>\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Flow</Label>\n <select\n className=\"h-9 rounded border bg-background px-2 text-sm\"\n value={draft.flow ?? \"one-at-a-time\"}\n onChange={(e) => patch({ flow: e.target.value as FormFlow })}\n >\n {FORM_FLOWS.map((flow) => (\n <option key={flow} value={flow}>\n {flow === \"one-at-a-time\" ? \"One question at a time\" : \"All on one page\"}\n </option>\n ))}\n </select>\n </label>\n <label className=\"col-span-2 flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Intro</Label>\n <BasicTextarea\n rows={2}\n value={draft.intro ?? \"\"}\n onChange={(e) => patch({ intro: e.target.value || null })}\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Submit button</Label>\n <BasicInput\n value={draft.submitLabel ?? \"\"}\n placeholder=\"Submit\"\n onChange={(e) => patch({ submitLabel: e.target.value || null })}\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Thank-you title</Label>\n <BasicInput\n value={draft.thankYou?.title ?? \"\"}\n placeholder=\"Thank you\"\n onChange={(e) =>\n patch({\n thankYou: e.target.value\n ? { title: e.target.value, body: draft.thankYou?.body ?? null }\n : null,\n })\n }\n />\n </label>\n </div>\n\n {/* The questions. Each one asks for a Field this Table actually has. */}\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Questions</span>\n <span>{draft.questions.length} of this table's {fields.data?.length ?? 0} fields</span>\n </div>\n {(fields.data ?? []).map((field) => {\n const index = draft.questions.findIndex((q) => q.field === field.key);\n const asked = index >= 0;\n const question = asked ? draft.questions[index]! : null;\n return (\n <div key={field.id} className=\"rounded border px-2 py-1.5\">\n <div className=\"flex items-center gap-2\">\n <Checkbox\n checked={asked}\n aria-label={`Ask for ${fieldName(field)}`}\n onCheckedChange={(checked) =>\n patch({\n questions: checked\n ? [...draft.questions, { field: field.key }]\n : draft.questions.filter((q) => q.field !== field.key),\n })\n }\n />\n <span className=\"text-xs font-medium\">{fieldName(field)}</span>\n <span className=\"text-xs text-muted-foreground\">{field.key}</span>\n {field.required ? <span className=\"text-xs text-destructive\">required</span> : null}\n </div>\n {asked && question ? (\n <div className=\"mt-1.5 grid grid-cols-2 gap-2 pl-6\">\n <BasicInput\n className=\"h-8 text-xs\"\n placeholder={fieldName(field)}\n aria-label={`How to ask for ${field.key}`}\n value={question.ask ?? \"\"}\n onChange={(e) => patchQuestion(index, { ask: e.target.value || null })}\n />\n <BasicInput\n className=\"h-8 text-xs\"\n placeholder=\"Help text\"\n aria-label={`Help text for ${field.key}`}\n value={question.help ?? \"\"}\n onChange={(e) => patchQuestion(index, { help: e.target.value || null })}\n />\n <Condition\n question={question}\n fieldKeys={fields.data ?? []}\n onChange={(showIf) => patchQuestion(index, { showIf })}\n />\n </div>\n ) : null}\n </div>\n );\n })}\n {draft.questions\n .filter((q) => !byKey.has(q.field))\n .map((q) => (\n <p key={q.field} className=\"text-xs text-destructive\">\n This form asks for \"{q.field}\" and this table has no such Field. It is shown here rather\n than quietly dropped.\n </p>\n ))}\n </div>\n </>\n )}\n </div>\n\n {/* The preview is the RUNNER, not a picture of it: what a person will actually meet. */}\n {draft ? (\n <aside className=\"w-96 shrink-0 overflow-auto rounded border p-2\">\n <FormRunner form={draft} preview />\n </aside>\n ) : null}\n </div>\n );\n}\n\n/** The one condition row. It writes the store's own Rule expression, by Field id. */\nfunction Condition({\n question,\n fieldKeys,\n onChange,\n}: {\n question: FormQuestionSpec;\n fieldKeys: Array<{ id: string; key: string; label: string }>;\n onChange: (showIf: RuleExpression | null) => void;\n}) {\n const expr = question.showIf as { op?: string; args?: Array<{ field?: string; const?: unknown }> } | null;\n const op = expr?.op ?? \"\";\n const onField = expr?.args?.[0]?.field ?? \"\";\n const value = expr?.args?.[1]?.const ?? \"\";\n\n function write(next: { op?: string; field?: string; value?: unknown }) {\n const chosenOp = next.op ?? op;\n const chosenField = next.field ?? onField;\n const chosenValue = next.value ?? value;\n if (!chosenOp || !chosenField) {\n onChange(null);\n return;\n }\n onChange(\n chosenOp === \"present\"\n ? ({ op: \"present\", args: [{ field: chosenField }] } as RuleExpression)\n : ({ op: chosenOp, args: [{ field: chosenField }, { const: chosenValue }] } as RuleExpression),\n );\n }\n\n return (\n <div className=\"col-span-2 flex items-center gap-1 text-xs\">\n <span className=\"text-muted-foreground\">Ask only when</span>\n <select\n aria-label=\"Condition field\"\n className=\"h-8 rounded border bg-background px-1 text-xs\"\n value={onField}\n onChange={(e) => write({ field: e.target.value })}\n >\n <option value=\"\">always</option>\n {fieldKeys.map((f) => (\n <option key={f.id} value={f.id}>\n {f.label || f.key}\n </option>\n ))}\n </select>\n {onField ? (\n <>\n <select\n aria-label=\"Condition comparison\"\n className=\"h-8 rounded border bg-background px-1 text-xs\"\n value={op}\n onChange={(e) => write({ op: e.target.value })}\n >\n {CONDITION_OPS.map((c) => (\n <option key={c.op} value={c.op}>\n {c.label}\n </option>\n ))}\n </select>\n {op !== \"present\" ? (\n <BasicInput\n className=\"h-8 w-28 text-xs\"\n aria-label=\"Condition value\"\n value={String(value ?? \"\")}\n onChange={(e) => write({ value: e.target.value })}\n />\n ) : null}\n </>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/FormRunner.tsx — @ai-matrx/records-ui · SCR-14\n//\n// THE FORM, AS THE PERSON ANSWERING IT SEES IT. One question at a time, a\n// progress line that is honest about how many questions are actually left, the\n// keyboard doing what a keyboard does (Enter goes on, Shift+Enter goes back),\n// and a submission that is an ORDINARY RECORD in a real Table the moment it is\n// sent.\n//\n// TWO ARMS, ONE SCREEN. This file exports ONE component and it runs in two\n// places that could not be more different:\n//\n// · SIGNED IN — mounted inside <RecordsProvider>. It reads the Table's Fields\n// through the read door, asks the store to answer every condition, and\n// writes through `custom.record_write` as the person sitting there.\n// · PUBLIC — served to somebody with NO ACCOUNT, at an unguessable link. There\n// is no session, no organization the caller may name and no read of the\n// table it writes into. The SERVER resolved the form through\n// `custom.form_public` and hands this component `fields` and `onSubmit`, so\n// the identical screen runs with the store nowhere near the browser.\n//\n// The public arm is why `useOptionalRecordsClient` exists in @ai-matrx/records\n// and why the connected half lives in its own component below: React hooks are\n// unconditional, so \"call the store's hooks only sometimes\" has to be a\n// different component, never an `if` around a hook.\n//\n// FIVE THINGS THIS COMPONENT REFUSES TO DO:\n//\n// 1. It never evaluates a condition itself. `showIf` is a Rule and the STORE\n// answers it (`custom.rule_eval`), so the form branches the same way for a\n// person, for the server and for an agent. An UNDECIDED answer — which is\n// what the store returns for a question nobody has answered yet — SHOWS the\n// question. Undecided is not false, and silently skipping a person past\n// something is the exact failure the store's own null-handling avoids. On\n// the public arm there is no evaluator at all, so every conditional question\n// is shown AND the form says so, rather than branching on a guess.\n// 2. It never draws a file chooser with nowhere to put the file. With no\n// `upload` port bound the attachment question says so in one sentence.\n// 3. It never calls itself public on the strength of a flag. `isPublic` needs\n// the anonymous write door; a signed-in mount of a public form says who the\n// record will be stamped as, by name.\n// 4. It never invents its own editors. Every answer is taken with the same\n// `FieldControl` the record form uses, so a currency in a form and a\n// currency in the grid are the same control with the same unit.\n// 5. It never sends the decoy. `honeypotKey` renders an input that no person\n// can see, reach by keyboard or autofill into; its value travels beside the\n// answers and the door decides what to do about it.\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useFields, useOptionalRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { Field, RecordsError } from \"@ai-matrx/records\";\nimport { Button, Progress, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { FieldControl, FieldLabel } from \"./editors\";\nimport { editorKindFor } from \"./parity\";\nimport { NO_UPLOAD_REASON, useRecordsUi } from \"./host\";\nimport { submissionStamp, type FormSpec, type SavedForm } from \"./forms\";\n\n/** What the public arm's `onSubmit` answers. A refusal carries the door's words. */\nexport type FormSubmitOutcome =\n | { ok: true; message?: string | null; recordId?: Uuid | null }\n | { ok: false; message: string };\n\nexport interface FormRunnerProps {\n /** The complete spec. An agent wrote it; `FormBuilder` saved it; this runs it. */\n form: FormSpec | SavedForm;\n /**\n * PUBLIC ARM — the subject Table's Fields, already resolved by the server\n * through `custom.form_public`. Given together with `onSubmit`, this component\n * mounts no store client at all and the browser never touches the store.\n */\n fields?: readonly Field[] | undefined;\n /** PUBLIC ARM — where an answer goes. Server action or route handler. */\n onSubmit?: ((values: Record<string, unknown>) => Promise<FormSubmitOutcome>) | undefined;\n /**\n * PUBLIC ARM — the name of a decoy input. A person never fills it; a script\n * fills everything. The door decides what a filled one means, not this screen.\n */\n honeypotKey?: string | null | undefined;\n /** Preview mode answers the questions but writes nothing, and says so. */\n preview?: boolean | undefined;\n onSubmitted?: ((recordId: Uuid | null) => void) | undefined;\n className?: string | undefined;\n}\n\ntype Answers = Record<string, unknown>;\n\n/** One question resolved against the subject Table's own Fields. */\ninterface ResolvedQuestion {\n key: string;\n ask: string;\n help: string | null;\n required: boolean;\n /** Null when the Table has no such Field — named on screen, never dropped. */\n field: Field | null;\n showIf: unknown;\n}\n\n/**\n * THE ONE ENTRY POINT. It picks the arm and nothing else: a caller that brought\n * the Fields and a place to send the answers gets the stage on its own, and\n * everybody else gets the connected half, which reads both from the store.\n */\nexport function FormRunner(props: FormRunnerProps) {\n if (props.fields && props.onSubmit) {\n return <FormStage {...props} fields={props.fields} onSubmit={props.onSubmit} />;\n }\n return <ConnectedFormRunner {...props} />;\n}\n\n/** The signed-in arm: the Fields from the read door, the answers through the write door. */\nfunction ConnectedFormRunner(props: FormRunnerProps) {\n const client = useOptionalRecordsClient();\n const fields = useFields(props.form.subject);\n const { form, className } = props;\n\n const submit = useCallback(\n async (values: Record<string, unknown>): Promise<FormSubmitOutcome> => {\n if (!client) {\n return {\n ok: false,\n message:\n \"This form has nowhere to send an answer: it is running outside the record store \" +\n \"and nobody gave it a submit port. A public form is served with its questions and \" +\n \"its submit port by the server; a signed-in one needs <RecordsProvider> above it.\",\n };\n }\n const document = {\n ...values,\n ...submissionStamp({\n formId: (form as SavedForm).id ?? null,\n formName: form.name,\n actor: client.config.actor.actor,\n onBehalfOf: client.config.actor.on_behalf_of ?? null,\n }),\n };\n const written = await client.recordWrite({ table_id: form.subject, data: document });\n if (!written.ok) return { ok: false, message: written.error.message };\n return { ok: true, recordId: written.data };\n },\n [client, form],\n );\n\n const evaluate = useCallback(\n async (expr: unknown, values: Answers): Promise<boolean | null> => {\n if (!client) return null;\n const answered = await client.ruleEval({ expr, values });\n if (!answered.ok) throw answered.error;\n // `null` is UNDECIDED. Undecided shows the question.\n return answered.data as boolean | null;\n },\n [client],\n );\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (fields.loading) return <Skeleton className={cn(\"h-40 w-full\", className)} />;\n return (\n <FormStage\n {...props}\n fields={fields.data ?? []}\n onSubmit={props.onSubmit ?? submit}\n evaluate={evaluate}\n connected\n />\n );\n}\n\n/**\n * THE SCREEN. It knows about questions, a keyboard and a thank-you, and nothing\n * whatsoever about a database. Both arms render exactly this.\n */\nfunction FormStage({\n form,\n fields,\n onSubmit,\n evaluate,\n honeypotKey,\n preview = false,\n onSubmitted,\n className,\n connected = false,\n}: FormRunnerProps & {\n fields: readonly Field[];\n onSubmit: (values: Record<string, unknown>) => Promise<FormSubmitOutcome>;\n evaluate?: ((expr: unknown, values: Answers) => Promise<boolean | null>) | undefined;\n connected?: boolean;\n}) {\n const host = useRecordsUi();\n const [answers, setAnswers] = useState<Answers>({});\n const [at, setAt] = useState(0);\n const [error, setError] = useState<RecordsError | null>(null);\n const [refusal, setRefusal] = useState<string | null>(null);\n const [writing, setWriting] = useState(false);\n const [done, setDone] = useState<string | null>(null);\n /** Which conditional questions the STORE said to hide. Keyed by field key. */\n const [hidden, setHidden] = useState<Record<string, boolean>>({});\n const decoy = useRef(\"\");\n const stage = useRef<HTMLDivElement>(null);\n\n const questions: ResolvedQuestion[] = useMemo(() => {\n const byKey = new Map((fields ?? []).map((f) => [f.key, f]));\n return (form.questions ?? []).map((q) => {\n const field = byKey.get(q.field) ?? null;\n return {\n key: q.field,\n ask: q.ask ?? field?.label ?? q.field,\n help: q.help ?? null,\n required: q.required ?? field?.required ?? false,\n field,\n showIf: q.showIf ?? null,\n };\n });\n }, [fields, form.questions]);\n\n // ── the conditions, answered by the STORE ────────────────────────────────\n // Re-asked whenever an answer changes, because that is what a condition is\n // about. One call per conditional question; a form with no conditions makes\n // no calls at all, and a public form makes none because it has no evaluator —\n // see `unanswerable` below, which SAYS that rather than branching on a guess.\n useEffect(() => {\n let cancelled = false;\n const conditional = questions.filter((q) => q.showIf);\n if (conditional.length === 0 || !evaluate) return;\n void (async () => {\n const next: Record<string, boolean> = {};\n for (const q of conditional) {\n try {\n const answered = await evaluate(q.showIf, answers);\n // `null` is UNDECIDED. Undecided shows the question.\n next[q.key] = answered === false;\n } catch (thrown) {\n // A condition the store could not work out is NOT a silent hide: the\n // question stays, and the store's sentence is shown above the form.\n if (!cancelled) setError(thrown as RecordsError);\n next[q.key] = false;\n }\n }\n if (!cancelled) setHidden(next);\n })();\n return () => {\n cancelled = true;\n };\n }, [evaluate, questions, answers]);\n\n const live = questions.filter((q) => !hidden[q.key]);\n const oneAtATime = (form.flow ?? \"one-at-a-time\") === \"one-at-a-time\";\n const index = Math.min(at, Math.max(live.length - 1, 0));\n const current = live[index];\n const centred = (form.theme?.align ?? \"center\") === \"center\";\n\n const answered = live.filter((q) => {\n const v = answers[q.key];\n return v !== undefined && v !== null && v !== \"\";\n }).length;\n\n const missing = live.filter((q) => {\n const v = answers[q.key];\n return q.required && (v === undefined || v === null || v === \"\");\n });\n\n const submit = useCallback(async () => {\n if (preview) {\n setDone(\"preview\");\n return;\n }\n setWriting(true);\n setError(null);\n setRefusal(null);\n const values: Record<string, unknown> = Object.fromEntries(\n live.map((q) => [q.key, answers[q.key] ?? null]),\n );\n if (honeypotKey) values[honeypotKey] = decoy.current;\n const outcome = await onSubmit(values);\n setWriting(false);\n if (!outcome.ok) {\n setRefusal(outcome.message);\n return;\n }\n setDone(outcome.message ?? \"sent\");\n onSubmitted?.(outcome.recordId ?? null);\n }, [answers, form, honeypotKey, live, onSubmit, onSubmitted, preview]);\n\n function advance() {\n if (!oneAtATime) return;\n if (index < live.length - 1) setAt(index + 1);\n else if (missing.length === 0) void submit();\n }\n\n function retreat() {\n if (oneAtATime && index > 0) setAt(index - 1);\n }\n\n // The keyboard flow. Enter goes on, Shift+Enter goes back — except inside a\n // long-text answer, where Enter is a new line and always has been.\n function onKeyDown(event: React.KeyboardEvent) {\n if (event.key !== \"Enter\") return;\n const target = event.target as HTMLElement;\n if (target.tagName === \"TEXTAREA\" && !event.metaKey && !event.ctrlKey) return;\n event.preventDefault();\n if (event.shiftKey) retreat();\n else advance();\n }\n\n useEffect(() => {\n // Moving to a question puts the caret in it: a person who is typing never\n // has to reach for the mouse to answer the next one.\n const input = stage.current?.querySelector<HTMLElement>(\n \"input:not([tabindex='-1']), textarea, select, [role='combobox']\",\n );\n input?.focus();\n }, [index, done]);\n\n // ── the thank-you screen ─────────────────────────────────────────────────\n if (done) {\n return (\n <section className={cn(\"mx-auto max-w-xl py-10\", centred && \"text-center\", className)}>\n <h2 className=\"text-lg font-medium\">{form.thankYou?.title ?? \"Thank you\"}</h2>\n {form.thankYou?.body ? (\n <p className=\"mt-1 text-sm text-muted-foreground\">{form.thankYou.body}</p>\n ) : null}\n <p className=\"mt-3 text-xs text-muted-foreground\">\n {done === \"preview\"\n ? \"This was a preview, so nothing was written.\"\n : done === \"sent\"\n ? `Saved to ${form.name}, with this form stamped on it.`\n : done}\n </p>\n </section>\n );\n }\n\n const unresolved = questions.filter((q) => !q.field);\n // A conditional question with nobody to answer its condition is SHOWN, and\n // that is said out loud. Hiding it would be branching on a guess; showing it\n // silently would leave the form's author believing a condition applied.\n const unanswerable = !evaluate && questions.some((q) => q.showIf);\n // A signed-in mount of a form meant for strangers writes as the person\n // sitting there, and says whose name the record will carry. The public arm\n // has no client at all, so this is only ever about the owner's own preview.\n const signedInPublic = connected && form.isPublic === true;\n\n return (\n <section\n className={cn(\"mx-auto flex max-w-xl flex-col gap-3 py-4\", centred && \"text-center\", className)}\n onKeyDown={onKeyDown}\n >\n {/* One row. The name, the progress, the count — no subtitle restating the name. */}\n <header className=\"flex items-center gap-3 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{form.name}</span>\n <Progress value={live.length === 0 ? 0 : (answered / live.length) * 100} className=\"h-1 flex-1\" />\n <span className=\"tabular-nums\">\n {oneAtATime ? `${index + 1} of ${live.length}` : `${answered} of ${live.length}`}\n </span>\n </header>\n\n {signedInPublic ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-left text-xs text-muted-foreground\">\n You are answering this signed in, so the record will carry your name. A stranger answers the\n same form at its public link, where the answer arrives through the anonymous door instead.\n </p>\n ) : null}\n\n {unanswerable ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-left text-xs text-muted-foreground\">\n This form has questions that only appear in certain cases. Nothing here can work out which\n ones, so all of them are being shown rather than any being skipped.\n </p>\n ) : null}\n\n {unresolved.length > 0 ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-left text-xs text-destructive\">\n {unresolved.map((q) => q.key).join(\", \")} {unresolved.length === 1 ? \"is a question\" : \"are questions\"} this\n form asks for and this table has no such Field. Add the Field, or take the question out — it is\n shown here rather than quietly dropped, because a dropped question is an answer nobody gave.\n </p>\n ) : null}\n\n {form.intro && index === 0 ? <p className=\"text-sm text-muted-foreground\">{form.intro}</p> : null}\n\n {error ? <RefusalNotice error={error} className=\"text-left\" /> : null}\n {refusal ? (\n <p role=\"alert\" className=\"rounded border border-destructive/40 px-2 py-1 text-left text-xs text-destructive\">\n {refusal}\n </p>\n ) : null}\n\n <div ref={stage} className=\"flex flex-col gap-4 text-left\">\n {(oneAtATime ? (current ? [current] : []) : live).map((q) => (\n <Question\n key={q.key}\n question={q}\n value={answers[q.key]}\n onChange={(v) => setAnswers((prev) => ({ ...prev, [q.key]: v }))}\n upload={host.upload}\n />\n ))}\n {live.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n Every question in this form is hidden by its own condition right now, so there is nothing to\n answer yet.\n </p>\n ) : null}\n </div>\n\n {/* THE DECOY. Off-screen, out of the tab order, and told not to be\n autofilled — so no person and no password manager ever touches it. */}\n {honeypotKey ? (\n <div aria-hidden className=\"pointer-events-none absolute left-[-9999px] h-px w-px overflow-hidden\">\n <label htmlFor={`hp-${honeypotKey}`}>Leave this field empty</label>\n <input\n id={`hp-${honeypotKey}`}\n name={honeypotKey}\n type=\"text\"\n tabIndex={-1}\n autoComplete=\"off\"\n defaultValue=\"\"\n onChange={(e) => {\n decoy.current = e.target.value;\n }}\n />\n </div>\n ) : null}\n\n <footer className={cn(\"flex flex-wrap items-center gap-2\", centred && \"justify-center\")}>\n {oneAtATime && index > 0 ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={retreat}>\n Back\n </Button>\n ) : null}\n {oneAtATime && index < live.length - 1 ? (\n <Button size=\"sm\" onClick={advance}>\n Next\n </Button>\n ) : (\n <Button size=\"sm\" disabled={writing || missing.length > 0} onClick={() => void submit()}>\n {writing ? \"Sending…\" : (form.submitLabel ?? \"Submit\")}\n </Button>\n )}\n {missing.length > 0 && (!oneAtATime || index === live.length - 1) ? (\n <span className=\"text-xs text-muted-foreground\">\n {missing.map((q) => q.ask).join(\", \")} still {missing.length === 1 ? \"needs\" : \"need\"} an answer.\n </span>\n ) : null}\n {preview ? <span className=\"text-xs text-muted-foreground\">Preview — nothing is written.</span> : null}\n </footer>\n </section>\n );\n}\n\n/** One question: the Field's own editor, or the honest sentence when it cannot be drawn. */\nfunction Question({\n question,\n value,\n onChange,\n upload,\n}: {\n question: ResolvedQuestion;\n value: unknown;\n onChange: (value: unknown) => void;\n upload: ReturnType<typeof useRecordsUi>[\"upload\"];\n}) {\n const [uploadError, setUploadError] = useState<string | null>(null);\n const field = question.field;\n if (!field) return null;\n\n const id = `form-${field.key}`;\n const isAttachment = editorKindFor(field) === \"attachment\";\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel field={{ ...field, label: question.ask, required: question.required }} htmlFor={id} />\n {question.help ? <p className=\"text-xs text-muted-foreground\">{question.help}</p> : null}\n {isAttachment && !upload ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{NO_UPLOAD_REASON}</p>\n ) : isAttachment ? (\n <>\n <input\n id={id}\n type=\"file\"\n className=\"text-xs\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (!file) return;\n setUploadError(null);\n void upload?.(file).then((result) => {\n if (!result) return;\n if (result.ok) onChange(result.fileId);\n else setUploadError(result.reason);\n });\n }}\n />\n {uploadError ? <p className=\"text-xs text-destructive\">{uploadError}</p> : null}\n </>\n ) : (\n <FieldControl field={field} value={value} onChange={onChange} id={id} />\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/charts.ts — @ai-matrx/records-ui · SCR-15, SCR-16\n//\n// A CHART IS A QUESTION THE STORE ANSWERS, NOT A PILE OF ROWS A BROWSER SUMS.\n//\n// Every block here is drawn from ONE call to `custom.record_aggregate` — the\n// eighth verb (AGT-N-8) — whose aggregate node sits ABOVE the join to the read\n// door's visibility set. Two consequences, and both of them are the reason this\n// file exists at all:\n//\n// · A chart shows exactly the records this person may see. Rows they may not\n// see are never fetched, so they cannot be summed and then hidden — and a\n// total that quietly included them would be a screen lying in the one place\n// nobody would ever check.\n// · A dashboard over a hundred thousand records is one round trip per block,\n// not a hundred thousand rows over the wire.\n//\n// AND A DASHBOARD IS ONE RECORD. `DashboardSpec` is the whole thing — every\n// block, its question and its shape — so an agent writes a finished dashboard\n// with ONE `record_write` and the person only tweaks it.\n\nimport type { AggregateBucket, AggregateMeasure, ReadRow, Uuid } from \"@ai-matrx/records\";\nimport type { SystemTableSpec } from \"./systemTable\";\n\n/** The shapes a block can take. Closed: a shape nobody drew is not offered. */\nexport const CHART_KINDS = [\"bar\", \"column\", \"line\", \"donut\", \"number\", \"table\"] as const;\nexport type ChartKind = (typeof CHART_KINDS)[number];\n\nexport const CHART_KIND_LABEL: Record<ChartKind, string> = {\n bar: \"Bars\",\n column: \"Columns\",\n line: \"Line\",\n donut: \"Donut\",\n number: \"Number\",\n table: \"Table\",\n};\n\n/** What each shape needs before it can draw, in one sentence a block prints. */\nexport const CHART_NEEDS: Record<ChartKind, string | null> = {\n bar: \"A bar chart needs something to group by — pick a Field and the bars appear.\",\n column: \"A column chart needs something to group by — pick a Field and the columns appear.\",\n line: \"A line needs a date Field to run along — pick one and the line appears.\",\n donut: \"A donut needs something to group by — pick a Field and the slices appear.\",\n number: null,\n table: null,\n};\n\n/** ONE BLOCK: the question and the shape, in one declarative object. */\nexport interface ChartSpec {\n title: string;\n /** The Table this block asks about. */\n subject: Uuid;\n kind: ChartKind;\n /** Field keys whose values become the groups. */\n groupBy?: string[];\n /** A date Field truncated to a period — what a line runs along. */\n bucket?: { key: string; by: AggregateBucket } | null;\n /** `count` needs no key; every other measure reads one Field. */\n measures?: AggregateMeasure[];\n /** Equality only, and the store puts it in the SAME WHERE as visibility. */\n filter?: Record<string, string>;\n limit?: number;\n /** How wide this block sits on the canvas, in twelfths. */\n span?: number;\n}\n\n/** THE WHOLE DASHBOARD, as one object an agent writes in one call. */\nexport interface DashboardSpec {\n name: string;\n /** The Table most of its blocks are about. A block may name another. */\n subject: Uuid;\n blocks: ChartSpec[];\n}\n\nexport interface SavedDashboard extends DashboardSpec {\n id: Uuid;\n /**\n * The record's version AT LOAD, read from `custom.io_revisions` for the one\n * record being edited. The read door answers documents and not versions, so\n * this is null until it has been read — and a save with a null version is an\n * ordinary last-writer-wins write, exactly as the store defines it.\n */\n version: number | null;\n}\n\n/** The package-owned Table every dashboard is a record of. */\nexport const DASHBOARD_TABLE: SystemTableSpec = {\n slug: \"records_ui_dashboard\",\n name: \"Dashboards\",\n labelSingular: \"Dashboard\",\n labelPlural: \"Dashboards\",\n titleField: \"name\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"text\", sort: 10, required: true },\n { key: \"subject\", label: \"Table\", type: \"text\", sort: 20, required: true },\n { key: \"blocks\", label: \"Blocks\", type: \"text\", sort: 30, config: { multiline: true } },\n ],\n};\n\nexport function dashboardDocument(spec: DashboardSpec): Record<string, unknown> {\n return {\n name: spec.name,\n subject: spec.subject,\n blocks: JSON.stringify(spec.blocks ?? []),\n };\n}\n\nexport function dashboardFromRecord(row: ReadRow): SavedDashboard {\n const data = (row.document ?? {}) as Record<string, unknown>;\n let blocks: ChartSpec[] = [];\n const raw = data[\"blocks\"];\n if (Array.isArray(raw)) blocks = raw as ChartSpec[];\n else if (typeof raw === \"string\" && raw.trim() !== \"\") {\n try {\n const parsed: unknown = JSON.parse(raw);\n if (Array.isArray(parsed)) blocks = parsed as ChartSpec[];\n } catch {\n blocks = [];\n }\n }\n return {\n id: row.id,\n version: null,\n name: String(data[\"name\"] ?? \"Untitled dashboard\"),\n subject: String(data[\"subject\"] ?? \"\"),\n blocks,\n };\n}\n\n/**\n * The series palette. Six SEMANTIC tokens the design system already flips for\n * dark mode, so a chart is correct in both themes without a second palette and\n * without a hex code anywhere in this package.\n */\nexport const SERIES_COLORS = [\n \"hsl(var(--primary))\",\n \"hsl(var(--info))\",\n \"hsl(var(--success))\",\n \"hsl(var(--warning))\",\n \"hsl(var(--destructive))\",\n \"hsl(var(--accent-foreground))\",\n] as const;\n\n/** The label one aggregate row carries — its groups, joined the way a person reads them. */\nexport function groupLabel(groups: Record<string, string | null>): string {\n const parts = Object.values(groups).map((v) => (v === null || v === \"\" ? \"—\" : v));\n return parts.length === 0 ? \"All records\" : parts.join(\" · \");\n}\n","\"use client\";\n\n// src/docs.ts — @ai-matrx/records-ui · SCR-20, SCR-21, SCR-22\n//\n// DOCUMENTS OVER RECORDS. A template is a body whose tokens point at Fields BY\n// ID; a render is written ONCE and frozen with the SHA-256 of its own text; a\n// signature seals that exact version and is immutable once made.\n//\n// Three things this package refuses to re-implement, because the store already\n// does them and doing them twice is how two answers appear:\n// · which tokens a body contains — `custom.doc_tokens`;\n// · which of them this Table cannot answer, and why — `custom.doc_unresolved_tokens`;\n// · whether a signature still holds — `custom.doc_signature_intact`.\n//\n// The token syntax is the store's own: `{{field:<the field's id>}}`. A name\n// would be a token that silently stops resolving the day somebody renames a\n// Field, which is the exact failure REC-17 exists to prevent.\n\nimport type { Field, Uuid } from \"@ai-matrx/records\";\n\n/** The one token form, written the way the store's own pattern reads it. */\nexport function fieldToken(fieldId: Uuid): string {\n return `{{field:${fieldId}}}`;\n}\n\n/** THE DECLARATIVE SPEC an agent writes. One template, whole, in one object. */\nexport interface DocTemplateSpec {\n name: string;\n /** The body, tokens and all. */\n body: string;\n}\n\n/**\n * A template written in terms of Field KEYS — which is how an agent thinks and\n * how a person reads — turned into the store's id-based tokens. The agent writes\n * `{{title}}`; what is stored points at the Field's id, so a rename never\n * silently empties the document.\n *\n * A key this Table does not have is LEFT EXACTLY AS IT IS, so\n * `custom.doc_unresolved_tokens` names it and the screen shows the store's own\n * reason — it is never quietly deleted from the body.\n */\nexport function bodyFromKeys(body: string, fields: Field[]): string {\n const byKey = new Map(fields.map((f) => [f.key, f.id]));\n return body.replace(/\\{\\{\\s*([a-zA-Z0-9_]+)\\s*\\}\\}/g, (whole, key: string) => {\n const id = byKey.get(key);\n return id ? fieldToken(id) : whole;\n });\n}\n\n/** The reverse, for a person reading a stored body: ids shown as the Field's label. */\nexport function bodyForReading(body: string, fields: Field[]): string {\n const byId = new Map(fields.map((f) => [f.id, f.label || f.key]));\n return body.replace(/\\{\\{\\s*field:([0-9a-fA-F-]{36})\\s*\\}\\}/g, (whole, id: string) => {\n const label = byId.get(id);\n return label ? `{{${label}}}` : whole;\n });\n}\n\n/** VAL-10: a signature is a Value on a text Field whose format is `signature`. */\nexport function isSignatureField(field: Field): boolean {\n return field.type === \"text\" && (field.format ?? \"\").toLowerCase() === \"signature\";\n}\n","\"use client\";\n\n// src/DocTemplate.tsx — @ai-matrx/records-ui · SCR-20\n//\n// THE TEMPLATE EDITOR. A body, a palette of this Table's own Fields, and the\n// STORE's verdict on which tokens it cannot answer — never this package's.\n//\n// `custom.doc_unresolved_tokens` is asked on every change and its sentence is\n// shown verbatim beside the token it is about. A template is still saveable\n// with an unresolved token, because half-written is a normal state; what is not\n// allowed is publishing one and letting a token reach a person's document\n// looking like text somebody typed.\n//\n// `seed` is the agent's half, as everywhere: complete templates written in\n// Field KEYS (`{{title}}`), converted to the store's id-based tokens on the way\n// in, so a rename never silently empties a contract.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { DocTemplateRow, DocUnresolvedToken, RecordsError } from \"@ai-matrx/records\";\nimport { BasicInput, BasicTextarea, Button, Label, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useSeedGuard } from \"./seedOnce\";\nimport { useTableRights } from \"./host\";\nimport { bodyFromKeys, fieldToken, type DocTemplateSpec } from \"./docs\";\nimport { fieldName } from \"./names\";\n\nexport interface DocTemplateProps {\n /** The Table these templates render. */\n tableId: Uuid;\n /** COMPLETE templates an agent wrote, in Field keys. Saved once, never overwritten. */\n seed?: DocTemplateSpec[] | undefined;\n activeTemplateId?: Uuid | null | undefined;\n onActiveTemplate?: ((template: DocTemplateRow) => void) | undefined;\n className?: string | undefined;\n}\n\nexport function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, className }: DocTemplateProps) {\n const client = useRecordsClient();\n // One claim per seed name, per mount: a check against the server's list is\n // not a lock, and a loader that re-runs mid-write would write it twice.\n const claimSeed = useSeedGuard();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const fields = useFields(tableId);\n const [templates, setTemplates] = useState<DocTemplateRow[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [activeId, setActiveId] = useState<Uuid | null>(activeTemplateId ?? null);\n const [draftName, setDraftName] = useState(\"\");\n const [draftBody, setDraftBody] = useState(\"\");\n const [unresolved, setUnresolved] = useState<DocUnresolvedToken[]>([]);\n const [saving, setSaving] = useState(false);\n\n const load = useCallback(async () => {\n const held = await client.docTemplates({ table_id: tableId });\n if (!held.ok) {\n setError(held.error);\n return;\n }\n let rows = held.data;\n const missing = (seed ?? []).filter((s) => !rows.some((t) => t.name === s.name));\n if (missing.length > 0 && (fields.data ?? []).length > 0) {\n for (const spec of missing) {\n if (!claimSeed(spec.name)) continue;\n const saved = await client.docTemplateSave({\n table_id: tableId,\n name: spec.name,\n body: bodyFromKeys(spec.body, fields.data ?? []),\n });\n if (!saved.ok) {\n setError(saved.error);\n return;\n }\n }\n const again = await client.docTemplates({ table_id: tableId });\n if (!again.ok) {\n setError(again.error);\n return;\n }\n rows = again.data;\n }\n setError(null);\n setTemplates(rows);\n }, [client, tableId, seed, fields.data]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n useEffect(() => {\n if (!templates || templates.length === 0) return;\n const chosen = templates.find((t) => t.id === (activeTemplateId ?? activeId)) ?? templates[0]!;\n if (chosen.id !== activeId) setActiveId(chosen.id);\n setDraftName(chosen.name);\n setDraftBody(chosen.body);\n onActiveTemplate?.(chosen);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [templates, activeTemplateId]);\n\n // The STORE's verdict on the body, re-asked as it is typed. Never this\n // package's own idea of which token resolves.\n useEffect(() => {\n let cancelled = false;\n if (draftBody.trim() === \"\") {\n setUnresolved([]);\n return;\n }\n void client.docUnresolvedTokens({ table_id: tableId, body: draftBody }).then((answered) => {\n if (cancelled) return;\n if (answered.ok) setUnresolved(answered.data);\n });\n return () => {\n cancelled = true;\n };\n }, [client, tableId, draftBody]);\n\n async function save() {\n setSaving(true);\n const saved = await client.docTemplateSave({\n table_id: tableId,\n name: draftName.trim() || \"Untitled template\",\n body: draftBody,\n template_id: activeId,\n });\n setSaving(false);\n if (!saved.ok) {\n setError(saved.error);\n return;\n }\n setActiveId(saved.data);\n await load();\n }\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (templates === null || fields.loading) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (!rights.admin) {\n return <p className={cn(\"text-xs text-muted-foreground\", className)}>{rights.why(\"structure\")}</p>;\n }\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {/* One row: the templates, the version, the save. */}\n <div className=\"flex items-center gap-1 overflow-x-auto\" role=\"group\" aria-label=\"Templates\">\n {templates.map((t) => (\n <Button\n key={t.id}\n size=\"sm\"\n variant={t.id === activeId ? \"secondary\" : \"ghost\"}\n aria-pressed={t.id === activeId}\n onClick={() => {\n setActiveId(t.id);\n setDraftName(t.name);\n setDraftBody(t.body);\n }}\n >\n {t.name}\n <span className=\"ml-1 text-[10px] text-muted-foreground\">v{t.template_version}</span>\n </Button>\n ))}\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n setActiveId(null);\n setDraftName(\"\");\n setDraftBody(\"\");\n }}\n >\n New template\n </Button>\n <Button size=\"sm\" className=\"ml-auto\" disabled={saving} onClick={() => void save()}>\n {saving ? \"Saving…\" : \"Save\"}\n </Button>\n </div>\n\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Name</Label>\n <BasicInput value={draftName} onChange={(e) => setDraftName(e.target.value)} placeholder=\"Agreement\" />\n </label>\n\n {/* The palette: this Table's own Fields, inserted as the store's own token. */}\n <div className=\"flex flex-wrap items-center gap-1\">\n <span className=\"text-xs text-muted-foreground\">Insert</span>\n {(fields.data ?? []).map((field) => (\n <Button\n key={field.id}\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-6 px-1.5 text-xs\"\n onClick={() => setDraftBody((body) => `${body}${fieldToken(field.id)}`)}\n >\n {fieldName(field)}\n </Button>\n ))}\n </div>\n\n <BasicTextarea\n rows={10}\n aria-label=\"Template body\"\n className=\"font-mono text-xs\"\n value={draftBody}\n onChange={(e) => setDraftBody(e.target.value)}\n />\n\n {/* The store's own sentence per token it cannot answer — verbatim. */}\n {unresolved.length > 0 ? (\n <ul className=\"flex flex-col gap-0.5 rounded border border-dashed px-2 py-1 text-xs\">\n {unresolved.map((token) => (\n <li key={token.raw} className=\"text-destructive\">\n <code>{token.raw}</code> — {token.why}\n </li>\n ))}\n </ul>\n ) : draftBody.trim() !== \"\" ? (\n <p className=\"text-xs text-muted-foreground\">\n Every token in this body points at a Field this table can answer.\n </p>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/DocRender.tsx — @ai-matrx/records-ui · SCR-21\n//\n// ONE TEMPLATE, ONE RECORD, ONE DOCUMENT — and the preview and the frozen\n// version are the SAME bytes, because both come from the store.\n//\n// `custom.doc_render_body` resolves the tokens without writing anything, which\n// is the preview. `custom.doc_render_document` writes the render: the text and\n// the SHA-256 of that text, frozen. Everything downstream — a signature, a PDF,\n// a link somebody sends — is about a VERSION, never about \"the document as it\n// happens to read today\". That is the whole reason a render is a row and not a\n// function call a screen repeats.\n//\n// The PDF is `@ai-matrx/print`'s, not a second renderer: the platform has one\n// answer to \"make this a PDF\" and this screen uses it.\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { DocRenderRow, RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\n\nexport interface DocRenderProps {\n templateId: Uuid;\n recordId: Uuid;\n /** A name for the file when somebody takes the PDF. */\n filename?: string | undefined;\n onRendered?: ((render: DocRenderRow) => void) | undefined;\n className?: string | undefined;\n}\n\nexport function DocRender({ templateId, recordId, filename, onRendered, className }: DocRenderProps) {\n const client = useRecordsClient();\n const [preview, setPreview] = useState<string | null>(null);\n const [renders, setRenders] = useState<DocRenderRow[] | null>(null);\n const [showing, setShowing] = useState<Uuid | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const paper = useRef<HTMLDivElement>(null);\n\n const load = useCallback(async () => {\n const [body, held] = await Promise.all([\n client.docRenderBody({ template_id: templateId, record_id: recordId }),\n client.docRenders({ record_id: recordId }),\n ]);\n if (!body.ok) {\n setError(body.error);\n return;\n }\n if (!held.ok) {\n setError(held.error);\n return;\n }\n setError(null);\n setPreview(body.data);\n setRenders(held.data.filter((r) => r.template_id === templateId));\n }, [client, templateId, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n async function freeze() {\n setBusy(\"freeze\");\n const written = await client.docRenderDocument({ template_id: templateId, record_id: recordId });\n setBusy(null);\n if (!written.ok) {\n setError(written.error);\n return;\n }\n await load();\n setShowing(written.data);\n const made = (await client.docRenders({ record_id: recordId }));\n if (made.ok) {\n const row = made.data.find((r) => r.id === written.data);\n if (row) onRendered?.(row);\n }\n }\n\n async function toPdf() {\n const element = paper.current;\n if (!element) return;\n setBusy(\"pdf\");\n try {\n // The platform's ONE answer to \"make this a PDF\". A second renderer here\n // would produce a document that does not match the printed one.\n const { captureToPDF } = await import(\"@ai-matrx/print/pdf\");\n await captureToPDF(element, { filename: filename ?? \"document\" });\n } catch (thrown) {\n setError({\n code: \"internal\",\n message: \"The PDF could not be made on this screen.\",\n hint: thrown instanceof Error ? thrown.message : String(thrown),\n });\n } finally {\n setBusy(null);\n }\n }\n\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (preview === null || renders === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n const frozen = showing ? (renders.find((r) => r.id === showing) ?? null) : null;\n const text = frozen ? frozen.body : preview;\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {/* One row: which version is on screen, and the two verbs. */}\n <div className=\"flex items-center gap-1 text-xs\">\n <Button\n size=\"sm\"\n variant={frozen ? \"ghost\" : \"secondary\"}\n aria-pressed={!frozen}\n onClick={() => setShowing(null)}\n >\n As it reads now\n </Button>\n {renders.map((render) => (\n <Button\n key={render.id}\n size=\"sm\"\n variant={render.id === showing ? \"secondary\" : \"ghost\"}\n aria-pressed={render.id === showing}\n onClick={() => setShowing(render.id)}\n title={`Template v${render.template_version} · ${render.content_hash.slice(0, 12)}`}\n >\n {new Date(render.rendered_at).toLocaleString()}\n </Button>\n ))}\n <span className=\"ml-auto flex items-center gap-1\">\n <Button size=\"sm\" disabled={busy !== null} onClick={() => void freeze()}>\n {busy === \"freeze\" ? \"Freezing…\" : \"Freeze this version\"}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" disabled={busy !== null} onClick={() => void toPdf()}>\n {busy === \"pdf\" ? \"Making the PDF…\" : \"PDF\"}\n </Button>\n </span>\n </div>\n\n {/* The document. Frozen bytes when a version is chosen, the live resolution\n otherwise — and the screen says which, because they are not the same thing. */}\n <div ref={paper} className=\"whitespace-pre-wrap rounded border bg-background p-4 text-sm text-foreground\">\n {text}\n </div>\n\n <p className=\"text-xs text-muted-foreground\">\n {frozen\n ? `Frozen ${new Date(frozen.rendered_at).toLocaleString()} from template v${frozen.template_version}. Its text and its SHA-256 (${frozen.content_hash.slice(0, 12)}…) are what any signature seals.`\n : \"This is how the template reads against this record right now. Nothing has been frozen, so there is no version for anyone to sign yet.\"}\n </p>\n </div>\n );\n}\n","\"use client\";\n\n// src/SignBlock.tsx — @ai-matrx/records-ui · SCR-22\n//\n// A SIGNATURE IS A VALUE, AND THE STORE DECIDES WHETHER IT STILL HOLDS.\n//\n// VAL-10: a signature is written on a text Field whose format is `signature`,\n// on the record's own Table, through `custom.doc_sign` — which writes it as an\n// ordinary Value with the envelope law's stamp plus the document version and\n// hash it sealed. So a signature is in History, in the export and in the agent's\n// context like any other Value, and there is no signatures feature bolted on.\n//\n// THREE THINGS THIS SCREEN NEVER DOES:\n// · It never checks a seal itself. `custom.doc_signature_intact` answers, and\n// its verdict is shown as the store said it.\n// · It never offers to re-sign. The door refuses a second signature on a Field\n// already signed, and the screen says the same sentence rather than showing a\n// button that will be refused.\n// · It never signs anything unfrozen. A seal is over a document VERSION, so\n// with no render there is no Sign — and the reason is on screen.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useFields, useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { DocRenderRow, DocSignatureRow, Field, RecordsError } from \"@ai-matrx/records\";\nimport { BasicInput, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { useTable } from \"@ai-matrx/records/react\";\nimport { isSignatureField } from \"./docs\";\nimport { fieldName } from \"./names\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface SignBlockProps {\n tableId: Uuid;\n recordId: Uuid;\n /** The frozen version being signed. Without one there is nothing to seal. */\n render: DocRenderRow | null;\n className?: string | undefined;\n}\n\nexport function SignBlock({ tableId, recordId, render, className }: SignBlockProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const fields = useFields(tableId);\n const [signatures, setSignatures] = useState<DocSignatureRow[] | null>(null);\n const [verdicts, setVerdicts] = useState<Record<string, unknown>>({});\n const [error, setError] = useState<RecordsError | null>(null);\n const [name, setName] = useState(\"\");\n const [busy, setBusy] = useState(false);\n\n const load = useCallback(async () => {\n const held = await client.docSignatures({ record_id: recordId });\n if (!held.ok) {\n setError(held.error);\n return;\n }\n setError(null);\n setSignatures(held.data);\n // Whether each seal still holds is the STORE's answer, asked for each one.\n const answers: Record<string, unknown> = {};\n for (const signature of held.data) {\n const intact = await client.docSignatureIntact({ signature_id: signature.id });\n answers[signature.id] = intact.ok ? intact.data : refusalLineForAPerson(intact.error);\n }\n setVerdicts(answers);\n }, [client, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n async function sign(field: Field) {\n if (!render) return;\n setBusy(true);\n const signed = await client.docSign({\n render_id: render.id,\n field_key: field.key,\n signer_name: name.trim(),\n signer_user_id: client.config.actor.user_id ?? null,\n });\n setBusy(false);\n if (!signed.ok) {\n setError(signed.error);\n return;\n }\n setName(\"\");\n await load();\n }\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (fields.loading || signatures === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n const signable = (fields.data ?? []).filter(isSignatureField);\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Signatures</span>\n <span>{signatures.length} on this record</span>\n </div>\n\n {signatures.length > 0 ? (\n <ul className=\"flex flex-col gap-1\">\n {signatures.map((signature) => {\n const verdict = verdicts[signature.id];\n const intact = typeof verdict === \"object\" && verdict !== null ? (verdict as { intact?: boolean }).intact : undefined;\n return (\n <li key={signature.id} className=\"rounded border px-2 py-1.5 text-xs\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{signature.signer_name}</span>\n <span className=\"text-muted-foreground\">{signature.field_key}</span>\n <span className=\"text-muted-foreground\">{new Date(signature.signed_at).toLocaleString()}</span>\n <span className=\"ml-auto font-mono text-[10px] text-muted-foreground\">\n v{signature.document_version} · {signature.document_hash.slice(0, 12)}\n </span>\n </div>\n {/* The store's verdict, not a check this screen invented. */}\n <p className={cn(\"mt-0.5\", intact === false ? \"text-destructive\" : \"text-muted-foreground\")}>\n {intact === true\n ? \"The store says what was signed is still exactly what is there.\"\n : intact === false\n ? typeof verdict === \"object\" && verdict !== null && \"reason\" in verdict\n ? String((verdict as { reason?: unknown }).reason)\n : \"The store says what is there no longer matches what was signed.\"\n : String(verdict ?? \"\")}\n </p>\n </li>\n );\n })}\n </ul>\n ) : null}\n\n {/* A seal is over a VERSION, so with nothing frozen there is no Sign at\n all — and the reason is on screen rather than a dead button. */}\n {!render ? (\n <p className=\"text-xs text-muted-foreground\">\n Nothing has been frozen yet, so there is no version to sign. A signature seals one exact document\n version and its hash — \"the document as it reads today\" is not something anyone can agree to.\n </p>\n ) : signable.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n This table has no signature Field, so there is nowhere to write a signature. A signature is a Value\n on a text Field whose format is <code>signature</code> — add one and the signing appears.\n </p>\n ) : !rights.write ? (\n <p className=\"text-xs text-muted-foreground\">{rights.why(\"write\")}</p>\n ) : (\n <div className=\"flex flex-col gap-1\">\n {signable.map((field) => {\n const already = signatures.find((s) => s.field_key === field.key);\n if (already) {\n return (\n <p key={field.id} className=\"text-xs text-muted-foreground\">\n {fieldName(field)} is signed, and a signature is immutable once made. A further\n agreement is a further Field with its own signature, or a further version with its own seal.\n </p>\n );\n }\n return (\n <form\n key={field.id}\n className=\"flex items-center gap-1\"\n onSubmit={(event) => {\n event.preventDefault();\n if (name.trim() !== \"\") void sign(field);\n }}\n >\n <BasicInput\n className=\"h-8 w-56 text-xs\"\n aria-label={`Sign ${fieldName(field)}`}\n placeholder=\"Type your full name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n <Button size=\"sm\" type=\"submit\" disabled={busy || name.trim() === \"\"}>\n Sign\n </Button>\n <span className=\"text-xs text-muted-foreground\">\n seals version {render.template_version} · {render.content_hash.slice(0, 12)}…\n </span>\n </form>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/NotifyRuleEditor.tsx — @ai-matrx/records-ui · SCR-19\n//\n// \"TELL ME WHEN SOMETHING IN THIS VIEW CHANGES\" — and that sentence is a RULE\n// RECORD, not a notifications table.\n//\n// DOOR-18: a subscription is an ordinary Rule carrying a `subscription` block\n// that names a saved view, a cadence, a channel and the person to tell. The\n// store answers `custom.agg_subscriptions`, fires `custom.agg_subscription_fire`\n// and delivers through `communication.notification`. So there is one notifier in\n// this platform, and a subscription is readable, historied, exportable and\n// agent-writable exactly like everything else this package touches.\n//\n// THE PART THAT MATTERS MOST IS NOT ON THIS SCREEN. `custom.agg_view_admits`\n// runs the admission test as the SUBSCRIBER, not as the writer: a change to a\n// record the subscriber may not see is not a notification they are entitled to,\n// because the notification's existence would leak the record. This editor never\n// re-implements that test and never offers to turn it off.\n//\n// `seed` is the agent's half, as everywhere else: complete declarative\n// subscriptions, written once, never overwriting one a person has since changed.\n//\n// WHAT DOES NOT WORK YET, AND WHY IT SAYS SO INSTEAD OF PRETENDING. A\n// subscription is a RULE record, and `custom.record_write` — the one write door\n// — inserts `data_class = 'record'`. A document written that way is not a Rule:\n// `custom.agg_subscriptions` never sees it, so a screen that wrote one and said\n// \"subscribed\" would have subscribed nobody to anything and left a stray record\n// behind. Declaring a Rule needs a door of its own (`custom.rule_declare`,\n// W1-RULE's), so this editor asks for that door BY NAME and shows the store's\n// refusal. Reading, listing and stopping a subscription all work today; the day\n// the door lands, so does subscribing, with no change on this screen.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, Subscription } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { NO_SAVED_VIEWS_REASON, useRecordsUi, useTableRights } from \"./host\";\n\n/** THE DECLARATIVE SPEC an agent writes. One declaration and a person is told. */\nexport interface NotifyRuleSpec {\n name: string;\n savedViewId: Uuid;\n /** `immediate` fires on the change; `digest` is collected and sent on a schedule. */\n cadence?: string;\n /** The digest's schedule, in the store's own words. Meaningless for `immediate`. */\n schedule?: string | null;\n channel?: string;\n /** Who is told. Left out, the person setting it up — \"tell ME\". */\n recipientUserId?: Uuid | null;\n eventKey?: string;\n}\n\nexport interface NotifyRuleEditorProps {\n /** The Table these subscriptions are about — the Rule's scope. */\n tableId: Uuid;\n /** COMPLETE declarative subscriptions an agent wrote. Saved once, never overwritten. */\n seed?: NotifyRuleSpec[] | undefined;\n className?: string | undefined;\n}\n\nexport function NotifyRuleEditor({ tableId, seed, className }: NotifyRuleEditorProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const [subscriptions, setSubscriptions] = useState<Subscription[] | null>(null);\n const [cadences, setCadences] = useState<string[]>([]);\n const [views, setViews] = useState<Array<{ id: Uuid; name: string }> | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n\n const load = useCallback(async () => {\n const [held, offered] = await Promise.all([\n client.aggSubscriptions(),\n // The cadences are ASKED of the store, never a list typed into a picker\n // here that could drift from what the digest runner understands.\n client.aggSubscriptionCadences(),\n ]);\n if (!held.ok) {\n setError(held.error);\n return;\n }\n setError(null);\n setSubscriptions(held.data);\n if (offered.ok) setCadences(offered.data);\n if (host.savedViews) setViews(await host.savedViews());\n else setViews(null);\n }, [client, host]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const write = useCallback(\n async (spec: NotifyRuleSpec) => {\n const declared = await client.ruleDeclare({\n spec: {\n name: spec.name,\n // REC-15: a subscription answers yes-or-no about a record, so it is a\n // predicate, and what it decides is membership of the view.\n kind: \"predicate\",\n uses: [\"membership\"],\n scope_table_id: tableId,\n applies_to_types: [],\n expr: { const: true },\n subscription: {\n saved_view_id: spec.savedViewId,\n cadence: spec.cadence ?? \"immediate\",\n schedule: spec.schedule ?? null,\n channel: spec.channel ?? \"in_app\",\n // \"Tell me\" is the default, and the store fires at nobody when this\n // is null — which it says out loud rather than dropping quietly.\n recipient_user_id: spec.recipientUserId ?? client.config.actor.user_id ?? null,\n event_key: spec.eventKey ?? \"records.changed\",\n },\n },\n });\n if (!declared.ok) {\n setError(declared.error);\n return false;\n }\n return true;\n },\n [client, tableId],\n );\n\n // The agent's specs, saved once. A seed whose name is already subscribed is\n // left alone — an agent re-running never overwrites a person's tweak.\n useEffect(() => {\n if (!subscriptions || !seed || seed.length === 0) return;\n const missing = seed.filter((s) => !subscriptions.some((held) => held.name === s.name));\n if (missing.length === 0) return;\n void (async () => {\n for (const spec of missing) {\n if (!(await write(spec))) return;\n }\n await load();\n })();\n }, [subscriptions, seed, write, load]);\n\n async function subscribe(viewId: Uuid, viewName: string, cadence: string) {\n setBusy(true);\n const ok = await write({ name: `${viewName} — ${cadence}`, savedViewId: viewId, cadence });\n setBusy(false);\n if (ok) await load();\n }\n\n async function unsubscribe(ruleId: Uuid) {\n setBusy(true);\n const deleted = await client.recordDelete({ record_id: ruleId });\n setBusy(false);\n if (!deleted.ok) {\n setError(deleted.error);\n return;\n }\n await load();\n }\n\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (subscriptions === null) return <Skeleton className={cn(\"h-40 w-full\", className)} />;\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {/* One row. What this is, and how many there are — no subtitle repeating it. */}\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Tell me when</span>\n <span>{subscriptions.length} subscription{subscriptions.length === 1 ? \"\" : \"s\"}</span>\n </div>\n\n {subscriptions.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n Nothing is telling anyone about this yet. A subscription is a Rule over a saved view, so what\n you are told about is exactly what that view holds.\n </p>\n ) : (\n <ul className=\"flex flex-col gap-1\">\n {subscriptions.map((held) => (\n <li key={held.rule_id} className=\"flex items-center gap-2 rounded border px-2 py-1.5 text-xs\">\n <span className=\"truncate font-medium\">{held.name}</span>\n <span className=\"text-muted-foreground\">{held.cadence}</span>\n <span className=\"text-muted-foreground\">{held.channel}</span>\n {held.cadence === \"digest\" && held.schedule ? (\n <span className=\"text-muted-foreground\">{held.schedule}</span>\n ) : null}\n {/* Nothing fails silently: a subscription that fires at nobody\n says so, rather than looking like it is working. */}\n {held.recipient_user_id === null ? (\n <span className=\"text-destructive\">\n This one has nobody to tell, so it fires at nobody.\n </span>\n ) : null}\n {held.saved_view_id === null ? (\n <span className=\"text-destructive\">\n This one names no view, so the store never admits a record to it.\n </span>\n ) : null}\n {rights.write ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"ml-auto\"\n disabled={busy}\n onClick={() => void unsubscribe(held.rule_id)}\n >\n Stop telling me\n </Button>\n ) : null}\n </li>\n ))}\n </ul>\n )}\n\n {/* Subscribing to a view needs the views, and the store has no door onto\n them — so with no port bound this says that, rather than showing an\n empty picker that reads like \"you have no views\". */}\n {views === null ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n {NO_SAVED_VIEWS_REASON}\n </p>\n ) : views.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n This organization has no saved views yet, so there is nothing to subscribe to. Save a view first.\n </p>\n ) : rights.write ? (\n <form\n className=\"flex items-center gap-1\"\n onSubmit={(event) => {\n event.preventDefault();\n const form = event.currentTarget;\n const view = (form.elements.namedItem(\"view\") as HTMLSelectElement).value;\n const cadence = (form.elements.namedItem(\"cadence\") as HTMLSelectElement).value;\n const name = views.find((v) => v.id === view)?.name ?? \"View\";\n if (view) void subscribe(view, name, cadence);\n }}\n >\n <select name=\"view\" aria-label=\"View to be told about\" className=\"h-7 rounded border bg-background px-1 text-xs\">\n {views.map((view) => (\n <option key={view.id} value={view.id}>\n {view.name}\n </option>\n ))}\n </select>\n <select name=\"cadence\" aria-label=\"How often\" className=\"h-7 rounded border bg-background px-1 text-xs\">\n {(cadences.length > 0 ? cadences : [\"immediate\"]).map((cadence) => (\n <option key={cadence} value={cadence}>\n {cadence === \"immediate\" ? \"as it happens\" : cadence}\n </option>\n ))}\n </select>\n <Button size=\"sm\" type=\"submit\" disabled={busy}>\n Tell me\n </Button>\n </form>\n ) : (\n <p className=\"text-xs text-muted-foreground\">{rights.why(\"write\")}</p>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/ChartBlock.tsx — @ai-matrx/records-ui · SCR-15\n//\n// ONE BLOCK, ONE CALL TO THE STORE. The grouping, the bucketing, the filter and\n// the measure are all `custom.record_aggregate`'s work, computed inside the\n// read door's own query — this file draws the answer and does not do any\n// arithmetic of its own beyond turning numbers into pixels.\n//\n// WHY NOT SUM IN THE BROWSER: the aggregate node sits above the visibility\n// join, so the total is over exactly the records this person may see. A browser\n// that fetched rows and summed them would either read rows it may not have or\n// under-count them silently, and a wrong total is the hardest lie to notice.\n//\n// A SHAPE THAT CANNOT BE DRAWN SAYS THE SENTENCE THAT FIXES IT. A donut with\n// nothing to group by and a line with no date Field print what they need; they\n// never draw an empty frame that reads like \"there is no data\".\n\nimport { useEffect, useState } from \"react\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport { measureKey, type AggregateRow, type RecordsError } from \"@ai-matrx/records\";\nimport { Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { CHART_NEEDS, SERIES_COLORS, groupLabel, type ChartSpec } from \"./charts\";\n\nexport interface ChartBlockProps {\n spec: ChartSpec;\n className?: string | undefined;\n}\n\nexport function ChartBlock({ spec, className }: ChartBlockProps) {\n const client = useRecordsClient();\n const [rows, setRows] = useState<AggregateRow[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n\n const measures = spec.measures && spec.measures.length > 0 ? spec.measures : [{ op: \"count\" as const }];\n const primary = measureKey(measures[0]!);\n const grouped = (spec.groupBy ?? []).length > 0 || !!spec.bucket;\n const needs = grouped ? null : CHART_NEEDS[spec.kind];\n\n const question = JSON.stringify({\n t: spec.subject,\n g: spec.groupBy ?? [],\n m: measures,\n b: spec.bucket ?? null,\n f: spec.filter ?? {},\n l: spec.limit ?? 50,\n });\n\n useEffect(() => {\n if (needs) return;\n let cancelled = false;\n setRows(null);\n setError(null);\n void client\n .recordAggregate({\n table_id: spec.subject,\n groupBy: spec.groupBy ?? [],\n measures,\n bucket: spec.bucket ?? null,\n filter: spec.filter ?? {},\n limit: spec.limit ?? 50,\n })\n .then((result) => {\n if (cancelled) return;\n if (result.ok) setRows(result.data);\n else setError(result.error);\n });\n return () => {\n cancelled = true;\n };\n // The QUESTION is the dependency, not the object identity: a parent that\n // rebuilds the same spec every render must not re-ask the store forever.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, question, needs]);\n\n return (\n <figure className={cn(\"flex min-w-0 flex-col gap-1.5 rounded border p-2\", className)}>\n {/* One row. The title and what is being measured — no subtitle repeating the title. */}\n <figcaption className=\"flex items-baseline gap-2 text-xs\">\n <span className=\"truncate font-medium\">{spec.title}</span>\n <span className=\"ml-auto shrink-0 text-muted-foreground\">{primary.replace(\"_\", \" of \")}</span>\n </figcaption>\n\n {needs ? (\n <p className=\"px-1 py-3 text-xs text-muted-foreground\">{needs}</p>\n ) : error ? (\n <RefusalNotice error={error} />\n ) : rows === null ? (\n <Skeleton className=\"h-28 w-full\" />\n ) : rows.length === 0 ? (\n <p className=\"px-1 py-3 text-xs text-muted-foreground\">\n The store answered this question with no groups at all, so there is nothing to draw yet.\n </p>\n ) : (\n <Drawing kind={spec.kind} rows={rows} measure={primary} />\n )}\n </figure>\n );\n}\n\nfunction value(row: AggregateRow, measure: string): number {\n const held = row.measures?.[measure];\n return typeof held === \"number\" ? held : Number(held ?? 0);\n}\n\nfunction pretty(n: number): string {\n return Number.isInteger(n) ? n.toLocaleString() : n.toLocaleString(undefined, { maximumFractionDigits: 2 });\n}\n\nfunction Drawing({ kind, rows, measure }: { kind: ChartSpec[\"kind\"]; rows: AggregateRow[]; measure: string }) {\n const points = rows.map((row) => ({ label: groupLabel(row.groups ?? {}), value: value(row, measure), n: row.row_count }));\n const top = Math.max(...points.map((p) => p.value), 0) || 1;\n\n if (kind === \"number\") {\n const total = points.reduce((sum, p) => sum + p.value, 0);\n return (\n <div className=\"flex items-baseline gap-2 px-1 py-2\">\n <span className=\"text-2xl font-semibold tabular-nums\">{pretty(total)}</span>\n <span className=\"text-xs text-muted-foreground\">\n from {points.reduce((sum, p) => sum + p.n, 0).toLocaleString()} records\n </span>\n </div>\n );\n }\n\n if (kind === \"table\") {\n return (\n <table className=\"w-full text-xs\">\n <tbody>\n {points.map((p) => (\n <tr key={p.label} className=\"border-t first:border-t-0\">\n <td className=\"py-0.5 pr-2 truncate\">{p.label}</td>\n <td className=\"py-0.5 text-right tabular-nums\">{pretty(p.value)}</td>\n <td className=\"py-0.5 pl-2 text-right tabular-nums text-muted-foreground\">{p.n}</td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n }\n\n if (kind === \"bar\") {\n // Horizontal bars, because a category label is words and words read across.\n return (\n <ul className=\"flex flex-col gap-1 px-1 py-1\">\n {points.map((p, i) => (\n <li key={p.label} className=\"flex items-center gap-2 text-xs\">\n <span className=\"w-28 shrink-0 truncate\" title={p.label}>\n {p.label}\n </span>\n <span className=\"h-3 min-w-0 flex-1 rounded-sm bg-muted\">\n <span\n className=\"block h-3 rounded-sm\"\n style={{ width: `${Math.max((p.value / top) * 100, 1)}%`, background: SERIES_COLORS[i % SERIES_COLORS.length] }}\n />\n </span>\n <span className=\"w-16 shrink-0 text-right tabular-nums\">{pretty(p.value)}</span>\n </li>\n ))}\n </ul>\n );\n }\n\n if (kind === \"column\" || kind === \"line\") {\n const width = 320;\n const height = 96;\n const step = points.length > 1 ? width / (points.length - 1) : width;\n const y = (v: number) => height - (v / top) * (height - 8) - 4;\n return (\n <div className=\"px-1 py-1\">\n <svg viewBox={`0 0 ${width} ${height}`} className=\"h-24 w-full\" role=\"img\" aria-label={`${measure} by group`}>\n {kind === \"line\" ? (\n <polyline\n fill=\"none\"\n stroke={SERIES_COLORS[0]}\n strokeWidth=\"2\"\n points={points.map((p, i) => `${i * step},${y(p.value)}`).join(\" \")}\n />\n ) : (\n points.map((p, i) => {\n const barWidth = Math.max(width / points.length - 4, 2);\n return (\n <rect\n key={p.label}\n x={(width / points.length) * i + 2}\n y={y(p.value)}\n width={barWidth}\n height={height - 4 - y(p.value)}\n rx=\"2\"\n fill={SERIES_COLORS[i % SERIES_COLORS.length]}\n />\n );\n })\n )}\n </svg>\n <ul className=\"mt-1 flex flex-wrap gap-x-3 gap-y-0.5 text-xs text-muted-foreground\">\n {points.map((p) => (\n <li key={p.label} className=\"tabular-nums\">\n {p.label} {pretty(p.value)}\n </li>\n ))}\n </ul>\n </div>\n );\n }\n\n // donut\n const total = points.reduce((sum, p) => sum + p.value, 0) || 1;\n let offset = 0;\n const radius = 34;\n const circumference = 2 * Math.PI * radius;\n return (\n <div className=\"flex items-center gap-3 px-1 py-1\">\n <svg viewBox=\"0 0 88 88\" className=\"h-24 w-24 shrink-0\" role=\"img\" aria-label={`${measure} by group`}>\n {points.map((p, i) => {\n const length = (p.value / total) * circumference;\n const dash = `${length} ${circumference - length}`;\n const node = (\n <circle\n key={p.label}\n cx=\"44\"\n cy=\"44\"\n r={radius}\n fill=\"none\"\n stroke={SERIES_COLORS[i % SERIES_COLORS.length]}\n strokeWidth=\"14\"\n strokeDasharray={dash}\n strokeDashoffset={-offset}\n transform=\"rotate(-90 44 44)\"\n />\n );\n offset += length;\n return node;\n })}\n </svg>\n <ul className=\"flex min-w-0 flex-col gap-0.5 text-xs\">\n {points.map((p, i) => (\n <li key={p.label} className=\"flex items-center gap-1.5\">\n <span\n className=\"h-2 w-2 shrink-0 rounded-sm\"\n style={{ background: SERIES_COLORS[i % SERIES_COLORS.length] }}\n />\n <span className=\"truncate\">{p.label}</span>\n <span className=\"ml-auto shrink-0 tabular-nums\">{pretty(p.value)}</span>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n","\"use client\";\n\n// src/DashboardCanvas.tsx — @ai-matrx/records-ui · SCR-16\n//\n// A DASHBOARD IS ONE RECORD, and its blocks are that record's own document. So\n// a dashboard is shareable, exportable, historied, commentable and\n// agent-writable for free — every one of those is something this package\n// already does to records, and none of it is written twice.\n//\n// `seed` is the agent's half: COMPLETE `DashboardSpec`s, each saved as a record\n// the first time the canvas loads and never overwritten afterwards. A person\n// adding a block, renaming one or changing its shape is the tweak.\n//\n// Every block is its own single call to `custom.record_aggregate`, so a canvas\n// of eight blocks is eight round trips over eight aggregates, never eight\n// downloads of the table.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useSeedGuard } from \"./seedOnce\";\nimport { useRecordVersion, useSystemTable } from \"./systemTable\";\nimport { useTableRights } from \"./host\";\nimport { ChartBlock } from \"./ChartBlock\";\nimport {\n CHART_KINDS,\n CHART_KIND_LABEL,\n DASHBOARD_TABLE,\n dashboardDocument,\n dashboardFromRecord,\n type ChartKind,\n type ChartSpec,\n type DashboardSpec,\n type SavedDashboard,\n} from \"./charts\";\n\nexport interface DashboardCanvasProps {\n /** The Table these blocks are about. */\n tableId: Uuid;\n /** COMPLETE declarative dashboards an agent wrote. Saved once, never overwritten. */\n seed?: DashboardSpec[] | undefined;\n activeDashboardId?: Uuid | null | undefined;\n className?: string | undefined;\n}\n\nexport function DashboardCanvas({ tableId, seed, activeDashboardId, className }: DashboardCanvasProps) {\n const client = useRecordsClient();\n // One claim per seed name, per mount: a check against the server's list is\n // not a lock, and a loader that re-runs mid-write would write it twice.\n const claimSeed = useSeedGuard();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const fields = useFields(tableId);\n const home = useSystemTable(DASHBOARD_TABLE);\n const [boards, setBoards] = useState<SavedDashboard[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [activeId, setActiveId] = useState<Uuid | null>(activeDashboardId ?? null);\n // The version of the board this canvas LOADED, for the one record being edited.\n const loaded = useRecordVersion(activeId);\n\n const boardTableId = home.tableId;\n\n const load = useCallback(async () => {\n if (!boardTableId) return;\n const result = await client.list({ table_id: boardTableId, limit: 500 });\n if (!result.ok) {\n setError(result.error);\n return;\n }\n let mine = result.data.rows.map(dashboardFromRecord).filter((d) => d.subject === tableId);\n const missing = (seed ?? []).filter((s) => !mine.some((d) => d.name === s.name));\n if (missing.length > 0) {\n for (const spec of missing) {\n if (!claimSeed(spec.name)) continue;\n const written = await client.recordWrite({\n table_id: boardTableId,\n data: dashboardDocument({ ...spec, subject: tableId }),\n });\n if (!written.ok) {\n setError(written.error);\n return;\n }\n }\n const again = await client.list({ table_id: boardTableId, limit: 500 });\n if (!again.ok) {\n setError(again.error);\n return;\n }\n mine = again.data.rows.map(dashboardFromRecord).filter((d) => d.subject === tableId);\n }\n setError(null);\n setBoards(mine);\n }, [client, boardTableId, tableId, seed]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n useEffect(() => {\n if (!boards || boards.length === 0) return;\n const chosen = boards.find((d) => d.id === (activeDashboardId ?? activeId)) ?? boards[0]!;\n if (chosen.id !== activeId) setActiveId(chosen.id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [boards, activeDashboardId]);\n\n async function writeBlocks(board: SavedDashboard, blocks: ChartSpec[]) {\n const updated = await client.recordUpdate({\n record_id: board.id,\n patch: dashboardDocument({ ...board, blocks }),\n // The dashboard record's own version: two tabs editing one board are TOLD.\n ...(loaded.version === null ? {} : { expectedVersion: loaded.version }),\n });\n if (!updated.ok) {\n setError(updated.error);\n return;\n }\n // The store's own new version, so the NEXT change to this board is a change\n // and not a conflict with the person who just made the last one.\n loaded.note(updated.data);\n await load();\n }\n\n async function create() {\n if (!boardTableId) return;\n const written = await client.recordWrite({\n table_id: boardTableId,\n data: dashboardDocument({ name: `Dashboard ${(boards?.length ?? 0) + 1}`, subject: tableId, blocks: [] }),\n });\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setActiveId(written.data);\n await load();\n }\n\n if (home.error) return <RefusalNotice error={home.error} className={className} />;\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (home.loading || boards === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n const board = boards.find((d) => d.id === activeId) ?? null;\n const groupable = (fields.data ?? []).filter((f) => f.type === \"text\" || f.type === \"list\");\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: the boards, and the two verbs that change this one. */}\n <div className=\"flex items-center gap-1 overflow-x-auto\" role=\"group\" aria-label=\"Dashboards\">\n {boards.map((d) => (\n <Button\n key={d.id}\n size=\"sm\"\n variant={d.id === activeId ? \"secondary\" : \"ghost\"}\n aria-pressed={d.id === activeId}\n onClick={() => setActiveId(d.id)}\n >\n {d.name}\n </Button>\n ))}\n {/* SCR-4: making a dashboard is administering the table, so a member\n gets no dead button — there is no button. */}\n {rights.admin ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void create()}>\n New dashboard\n </Button>\n ) : null}\n {board && rights.admin ? (\n <span className=\"ml-auto flex items-center gap-1\">\n <select\n aria-label=\"Add a block\"\n className=\"h-7 rounded border bg-background px-1 text-xs\"\n value=\"\"\n onChange={(e) => {\n const kind = e.target.value as ChartKind;\n if (!kind) return;\n const by = groupable[0]?.key;\n void writeBlocks(board, [\n ...board.blocks,\n {\n title: CHART_KIND_LABEL[kind],\n subject: tableId,\n kind,\n ...(by && kind !== \"number\" ? { groupBy: [by] } : {}),\n measures: [{ op: \"count\" }],\n },\n ]);\n }}\n >\n <option value=\"\">Add a block</option>\n {CHART_KINDS.map((kind) => (\n <option key={kind} value={kind}>\n {CHART_KIND_LABEL[kind]}\n </option>\n ))}\n </select>\n </span>\n ) : null}\n </div>\n\n {!board ? (\n <p className=\"text-xs text-muted-foreground\">\n {rights.admin\n ? \"No dashboard looks at this table yet. \\\"New dashboard\\\" makes one, or an agent writes a whole one with a single record.\"\n : rights.why(\"structure\")}\n </p>\n ) : board.blocks.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n This dashboard has no blocks yet. Each one is a single question the store answers — grouped,\n bucketed and measured inside the read door.\n </p>\n ) : (\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3\">\n {board.blocks.map((block, index) => (\n <div key={`${block.title}-${index}`} className=\"flex min-w-0 flex-col gap-1\">\n <ChartBlock spec={{ ...block, subject: block.subject || tableId }} />\n {rights.admin ? (\n <div className=\"flex items-center gap-1 text-xs\">\n <select\n aria-label={`Shape of ${block.title}`}\n className=\"h-7 rounded border bg-background px-1 text-xs\"\n value={block.kind}\n onChange={(e) =>\n void writeBlocks(\n board,\n board.blocks.map((b, i) => (i === index ? { ...b, kind: e.target.value as ChartKind } : b)),\n )\n }\n >\n {CHART_KINDS.map((kind) => (\n <option key={kind} value={kind}>\n {CHART_KIND_LABEL[kind]}\n </option>\n ))}\n </select>\n <select\n aria-label={`Group ${block.title} by`}\n className=\"h-7 rounded border bg-background px-1 text-xs\"\n value={block.groupBy?.[0] ?? \"\"}\n onChange={(e) =>\n void writeBlocks(\n board,\n board.blocks.map((b, i) =>\n i === index ? { ...b, groupBy: e.target.value ? [e.target.value] : [] } : b,\n ),\n )\n }\n >\n <option value=\"\">no grouping</option>\n {groupable.map((f) => (\n <option key={f.id} value={f.key}>\n {f.label || f.key}\n </option>\n ))}\n </select>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => void writeBlocks(board, board.blocks.filter((_, i) => i !== index))}\n >\n Remove\n </Button>\n </div>\n ) : null}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/FormsPanel.tsx — @ai-matrx/records-ui · PRODUCTS row 1, the owner's side\n//\n// THE FORMS OF ONE TABLE, on the table's own screen, in the table's own rail.\n//\n// It is deliberately NOT a tab bar, a second page or a \"Forms\" area of the app:\n// a form is a VIEW ON THIS TABLE, so it belongs beside this table's settings,\n// its inbox and its import — reached the same way, drawn by the same primitive,\n// closing the same way. A separate Forms section would be the parallel layer the\n// canvas ruling forbade: one more place to look for something that is already\n// somewhere.\n//\n// WHAT AN OWNER ACTUALLY NEEDS HERE, and nothing else:\n// · the link, copied in one click, because that is the whole product;\n// · how many answers arrived, how many are IN THE TABLE, and how many are\n// waiting for a person — three different numbers, and conflating them is how\n// somebody believes they have twelve patients when four are still held;\n// · open and close, which is one act (`custom.anon_publish`) and needs `admin`\n// on this table, because it decides whether strangers may add rows to it.\n//\n// ABSENT, NEVER DEAD. Someone without `admin` sees the forms and their links and\n// no open/close control at all — not a greyed one. The store answers the level\n// (`custom.my_levels`, through `useTableRights`); this screen never guesses it.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport { publicFormPath, type FormSummary, type RecordsError } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\n\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi, useTableRights } from \"./host\";\n\nexport interface FormsPanelProps {\n tableId: Uuid;\n className?: string | undefined;\n}\n\n/**\n * THERE IS NO \"NEW FORM\" BUTTON HERE, AND THAT IS THE PRODUCT.\n *\n * PRODUCTS row 1 is written under one law: *\"we do not ship a builder people\n * click together.\"* A person says \"make me an intake form for new patients that\n * tells me when one arrives\" and the agent writes the table, the fields, the\n * validation and the notify rule in one call (`form_propose`) and hands back the\n * link. Putting a builder button here would make the slow path the obvious one.\n *\n * What this panel is for is everything AFTER that sentence: the link, the three\n * numbers, and opening or closing it.\n *\n * (`FormBuilder` in this package is a different thing and stays a different\n * thing: it edits form RECORDS in the package's own `records_ui_form` table,\n * which is not `custom.anon_form` and carries no publish binding. Converging the\n * two is real work and it is named in this lane's progress notes rather than\n * half-done here.)\n */\nconst NO_BUILDER =\n \"A form asks for this table's own fields, and its answers land here as ordinary records stamped \" +\n \"with the form they came through. Ask an agent for one in a sentence — what it should ask for, and \" +\n \"who to tell when somebody answers.\";\n\n/** The words for each state, said once. A state a screen invents is a state that drifts. */\nconst STATE_WORDS: Record<FormSummary[\"state\"], string> = {\n draft: \"Not published — the link does not answer yet.\",\n open: \"Open — anyone with the link can answer it.\",\n closed: \"Closed — it keeps its answers and takes no more.\",\n full: \"Full — it has all the answers it was set up to take.\",\n};\n\nexport function FormsPanel({ tableId, className }: FormsPanelProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const [forms, setForms] = useState<FormSummary[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState<Uuid | null>(null);\n const [copied, setCopied] = useState<Uuid | null>(null);\n\n const load = useCallback(async () => {\n const answered = await client.forms({ table_id: tableId });\n if (!answered.ok) {\n setError(answered.error);\n setForms([]);\n return;\n }\n setError(null);\n setForms(answered.data);\n }, [client, tableId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const toggle = useCallback(\n async (form: FormSummary) => {\n setBusy(form.form_id as Uuid);\n const wanted = form.published_at === null || form.closed_at !== null;\n const answered = await client.anonPublish({ form_id: form.form_id as Uuid, published: wanted });\n setBusy(null);\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n await load();\n },\n [client, load],\n );\n\n // THE LINK IS THE PRODUCT, so copying it is one click and it SAYS it worked.\n // A clipboard that is unavailable (an insecure origin, a locked-down browser)\n // shows the address instead of failing silently.\n const [shown, setShown] = useState<string | null>(null);\n const copy = useCallback(async (url: string, formId: Uuid) => {\n try {\n await navigator.clipboard.writeText(url);\n setCopied(formId);\n setShown(null);\n window.setTimeout(() => setCopied(null), 1600);\n } catch {\n setShown(url);\n }\n }, []);\n\n if (forms === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n const origin = host.publicOrigin ?? (typeof window === \"undefined\" ? \"\" : window.location.origin);\n\n return (\n <section className={cn(\"flex flex-col gap-3\", className)}>\n <header className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">Forms</h3>\n <span className=\"text-xs text-muted-foreground\">\n {forms.length === 0 ? \"none yet\" : `${forms.length}`}\n </span>\n <div className=\"flex-1\" />\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {forms.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {rights.structure\n ? NO_BUILDER\n : \"This table has no forms. Making one needs the admin level on it, because a form decides what people with no account may add here.\"}\n </p>\n ) : null}\n\n <ul className=\"flex flex-col gap-2\">\n {forms.map((form) => {\n const url = `${origin}${publicFormPath(form.form_id)}`;\n return (\n <li key={form.form_id} className=\"rounded-md border p-2.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">\n {form.title ?? form.slug}\n </span>\n <Badge variant={form.state === \"open\" ? \"default\" : \"secondary\"}>{form.state}</Badge>\n </div>\n\n <p className=\"mt-0.5 text-xs text-muted-foreground\">{STATE_WORDS[form.state]}</p>\n\n {/* THREE NUMBERS, NEVER ONE. \"12 responses\" while four are held is\n how somebody comes to believe they have twelve patients. */}\n <p className=\"mt-1.5 text-xs\">\n <span className=\"font-medium\">{form.in_table}</span> in the table\n {form.held > 0 ? (\n <>\n {\" · \"}\n <span className=\"font-medium\">{form.held}</span> waiting for someone\n </>\n ) : null}\n {form.rejected > 0 ? (\n <>\n {\" · \"}\n <span className=\"font-medium\">{form.rejected}</span> turned away\n </>\n ) : null}\n {form.submission_cap !== null ? (\n <span className=\"text-muted-foreground\"> · stops at {form.submission_cap}</span>\n ) : null}\n </p>\n\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5\">\n {form.published_at ? (\n <Button size=\"sm\" variant=\"outline\" onClick={() => void copy(url, form.form_id as Uuid)}>\n {copied === form.form_id ? \"Copied\" : \"Copy link\"}\n </Button>\n ) : null}\n {rights.structure ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={busy === form.form_id}\n onClick={() => void toggle(form)}\n >\n {busy === form.form_id\n ? \"…\"\n : form.published_at && !form.closed_at\n ? \"Close\"\n : \"Open it\"}\n </Button>\n ) : null}\n </div>\n\n {shown && shown === url ? (\n <p className=\"mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs\">\n This browser would not let the page copy for you, so here it is to copy by hand:{\" \"}\n {url}\n </p>\n ) : null}\n </li>\n );\n })}\n </ul>\n\n {!rights.known ? (\n <p className=\"text-xs text-muted-foreground\">\n Still asking what you may do with this table — nothing is offered until it answers.\n </p>\n ) : null}\n </section>\n );\n}\n","\"use client\";\n\n// src/RecordChat.tsx — @ai-matrx/records-ui · SCR-26\n//\n// \"TALK TO THIS RECORD\" — AND THERE IS EXACTLY ONE CHAT SURFACE IN THIS\n// PLATFORM, WHICH IS NOT THIS ONE.\n//\n// The temptation here is to build a message list and a composer. Doing that\n// would give AI Matrx a second chat UI that streams differently, handles tool\n// asks differently, pages history differently and drifts from the real one\n// within a month — for the sake of a panel beside a record. So this component\n// builds NO chat UI at all.\n//\n// What it builds is the thing only the record store can build: the CONTEXT.\n// It reads the one record THROUGH THE READ DOOR (`custom.read_record`), turns\n// the Fields the store agreed this person may see into named context entries,\n// names the ones the store MASKED rather than pretending the record has fewer\n// fields than it has, and hands that to the host's chat port.\n//\n// WHAT matrx-frontend MUST PASS (the port, in its own words):\n//\n// <RecordsUiProvider value={{\n// chat: (ctx) => {\n// const { conversationId } = useAgentLauncher(agentId, {\n// surfaceKey: ctx.surfaceKey,\n// runtime: { context: Object.fromEntries(ctx.entries.map(e => [e.key, e.value])) },\n// });\n// return <AgentConversationColumn conversationId={conversationId} surfaceKey={ctx.surfaceKey} />;\n// },\n// }}>\n//\n// `AgentConversationColumn`\n// (matrx-frontend `features/agents/components/shared/AgentConversationColumn.tsx`)\n// is that one surface, and it cannot live in this package: it reads the app's\n// Redux store — conversations, messages, instance-context, surfaces — and a\n// package that imported those would stop being a package. The agent itself is\n// resolved through a Mandate on the host's side, never a UUID pinned here.\n//\n// UNBOUND, THIS COMPONENT IS ABSENT WITH ITS REASON. It never draws a dead\n// composer, and it never quietly renders a transcript that goes nowhere.\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { Field, HiddenFieldNotice, RecordsError } from \"@ai-matrx/records\";\nimport { Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi } from \"./host\";\nimport { scalarText } from \"./values\";\n\n/** One named piece of grounding, shaped the way the platform's context slice takes them. */\nexport interface RecordChatEntry {\n key: string;\n value: unknown;\n label: string;\n /** `text` for a scalar, `json` for a structure. The host maps this to its own vocabulary. */\n type: \"text\" | \"json\";\n}\n\n/** A Field the STORE masked for this reader, named rather than silently dropped. */\nexport interface RecordChatWithheld {\n key: string;\n label: string;\n /** The store's own reason. */\n reason: string;\n}\n\n/** Everything the host's chat surface needs, and nothing about how it should look. */\nexport interface RecordChatContext {\n /**\n * A unique key per mounted conversation. Two record panels open at once must\n * not fight over focus, so this is derived from the record and never a\n * constant.\n */\n surfaceKey: string;\n tableId: Uuid;\n recordId: Uuid;\n tableName: string;\n /** The record's own title, for the panel's one-row header and the chip. */\n title: string;\n /** The grounding, already read through the read door. */\n entries: RecordChatEntry[];\n /** What this reader is NOT being given, with the store's reason for each. */\n withheld: RecordChatWithheld[];\n}\n\nexport const NO_CHAT_REASON =\n \"No chat port is bound, so this panel is absent rather than showing a composer that goes nowhere. \" +\n \"Bind `chat` on <RecordsUiProvider> with your host's own chat surface — in AI Matrx that is \" +\n \"`AgentConversationColumn`, launched through a Mandate — and this panel becomes that surface with \" +\n \"this record as its context. This package deliberately ships no second chat UI.\";\n\nexport interface RecordChatProps {\n tableId: Uuid;\n recordId: Uuid;\n className?: string | undefined;\n}\n\nexport function RecordChat({ tableId, recordId, className }: RecordChatProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const [read, setRead] = useState<{\n document: Record<string, unknown>;\n hidden: Record<string, HiddenFieldNotice>;\n } | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setRead(null);\n setError(null);\n void client.recordRead({ record_id: recordId }).then((answered) => {\n if (cancelled) return;\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setRead({\n document: answered.data.document as Record<string, unknown>,\n hidden: answered.data.hidden ?? {},\n });\n });\n return () => {\n cancelled = true;\n };\n }, [client, recordId]);\n\n const context: RecordChatContext | null = useMemo(() => {\n if (!read || !table.data || !fields.data) return null;\n const titleKey = table.data.title_field ?? fields.data[0]?.key ?? \"\";\n const title = String(read.document[titleKey] ?? \"this record\");\n const withheld: RecordChatWithheld[] = Object.entries(read.hidden).map(([key, notice]) => ({\n key,\n label: fields.data?.find((f) => f.key === key)?.label ?? key,\n reason: noticeText(notice),\n }));\n return {\n surfaceKey: `records-ui:record-chat:${recordId}`,\n tableId,\n recordId,\n tableName: table.data.name,\n title,\n entries: entriesFor(fields.data, read.document, table.data.name, title, withheld),\n // Two different absences, both named: what the STORE masked for this\n // reader, and what the organization's own policy keeps out of a\n // conversation. Neither one silently shrinks the record.\n withheld,\n };\n }, [read, table.data, fields.data, recordId, tableId]);\n\n if (error) return <RefusalNotice error={error} className={className} />;\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (!context) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (!host.chat) {\n // ABSENT, WITH THE REASON — and with what was going to be sent, because a\n // person reading \"no chat port is bound\" should be able to see that the\n // record half of this actually works.\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{context.title}</span>\n <span>{context.entries.length} facts ready</span>\n </header>\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{NO_CHAT_REASON}</p>\n <Withheld withheld={context.withheld} />\n </section>\n );\n }\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: the record, and what the agent is holding. No repeated names. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{context.title}</span>\n <span>{context.entries.length} facts in context</span>\n </header>\n <Withheld withheld={context.withheld} />\n <div className=\"flex min-h-0 flex-1 flex-col\">{host.chat(context)}</div>\n </section>\n );\n}\n\n/**\n * The store masked something, and the person is TOLD.\n *\n * An agent answering out of a record it was given nine of eleven fields from\n * will answer confidently and wrongly about the other two. A screen that hid\n * that would be the record store lying about what it handed over.\n */\nfunction Withheld({ withheld }: { withheld: RecordChatWithheld[] }) {\n if (withheld.length === 0) return null;\n return (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n Not in this conversation: {withheld.map((w) => w.label).join(\", \")}.{\" \"}\n {withheld[0]?.reason ? withheld[0].reason : \"The store masked it for this reader.\"} An answer here is\n an answer without {withheld.length === 1 ? \"that field\" : \"those fields\"}.\n </p>\n );\n}\n\n/**\n * THE GROUNDING, AND IT CARRIES THE FIELD'S MEANING.\n *\n * FLD-N-1: a unit and a format are on the Field because they change what the\n * value MEANS, so `48000` reaches the agent as `$48,000` exactly as it reaches\n * the screen. An agent given the bare number is an agent one currency away from\n * a confident mistake.\n */\nfunction entriesFor(\n fields: Field[],\n document: Record<string, unknown>,\n tableName: string,\n title: string,\n held: RecordChatWithheld[],\n): RecordChatEntry[] {\n const entries: RecordChatEntry[] = [\n {\n key: \"record_subject\",\n label: \"Record\",\n type: \"text\",\n value: `${title} — a ${tableName} record.`,\n },\n ];\n for (const field of fields) {\n // AGT-7 / VAL-6: a Field's sensitivity is a CEILING. The store's four words\n // are public · internal · confidential · restricted, and the top two are\n // ceilings no conversation rises through. Both these and FLD-12's `exclude`\n // and `on_request` are left out HERE and named in `held` below: a field\n // that quietly vanished would be a field the agent answers around.\n // FLD-12 is the FIELD'S OWN ANSWER to \"may an agent see this?\", in the\n // store's four words, and `exclude` means exactly that. AGT-7 adds a\n // ceiling on top: `confidential` and `restricted` values are not handed to\n // a conversation whatever the policy says.\n const guarded = field.sensitivity === \"confidential\" || field.sensitivity === \"restricted\";\n if (guarded || field.context_policy === \"exclude\" || field.context_policy === \"on_request\") {\n held.push({\n key: field.key,\n label: field.label,\n reason: guarded\n ? `This field is marked ${field.sensitivity}, so it is not handed to a conversation.`\n : field.context_policy === \"exclude\"\n ? \"This field says an agent may not see its values.\"\n : \"This field is given on request, so the agent asks for it rather than being handed it.\",\n });\n continue;\n }\n const raw = document[field.key];\n if (raw === undefined || raw === null || raw === \"\") continue;\n const structured = typeof raw === \"object\";\n entries.push({\n key: field.key,\n label: field.label,\n type: structured ? \"json\" : \"text\",\n value: structured ? raw : scalarText(field, raw),\n });\n }\n return entries;\n}\n\nfunction noticeText(notice: HiddenFieldNotice): string {\n const bag = notice as unknown as Record<string, unknown>;\n const said = bag[\"reason\"] ?? bag[\"message\"] ?? bag[\"why\"];\n return typeof said === \"string\" && said.length > 0 ? said : \"The store masked this field for this reader.\";\n}\n","\"use client\";\n\n// src/EnrichPanel.tsx — @ai-matrx/records-ui · SCR-27\n//\n// PER-FIELD AI FILL, AND THE THREE FACTS IT REFUSES TO FAKE.\n//\n// A Field whose `source` is `agent` is a Field the organization said an agent\n// keeps filled (FLD-7). `review_interval_days` is how often (AGT-6). Those two\n// live on the Field record, so this panel does not decide which fields are\n// agent-filled and it does not decide when they are stale — it READS both, and\n// a Table with no agent Fields says so instead of offering a Fill button over\n// nothing.\n//\n// 1. FRESHNESS IS THE VALUE'S OWN. `_values.<key>.at` is when it was written\n// and `.actor` is who wrote it; `review_interval_days` turns those into\n// \"due\" or \"fresh\". A screen that timed this off `updated_at` on the row\n// would call every field stale because one of them changed.\n//\n// 2. THE PROVENANCE BADGE IS NOT DECORATION. VAL-8: a value knows whether a\n// person or an agent wrote it, and which person the agent was acting for.\n// That is shown on every agent-filled value, always, because a number a\n// machine guessed and a number a person typed are different facts and the\n// difference must survive into the screen.\n//\n// 3. THE FILL GOES THROUGH THE SERVER, NEVER THROUGH THIS CLIENT. The write\n// has to be stamped actor `agent` on behalf of the person, and a browser\n// that stamped itself `agent` would be a browser claiming to be an agent.\n// The server's own `records` tool does it properly\n// (aidream `packages/matrx-records/matrx_records/agent/tool.py`:\n// `Actor.agent(principal)` → the reserved document keys `_actor` and\n// `_on_behalf_of`), so this panel asks the HOST to make that call.\n//\n// WHAT matrx-frontend MUST PASS:\n//\n// <RecordsUiProvider value={{\n// enrich: async (ask) =>\n// fetch(\"/api/ai/tools/execute\", { method: \"POST\", body: JSON.stringify({\n// tool_name: \"records\", surface: \"records-ui:enrich\",\n// arguments: { action: \"record_write\", record_id: ask.recordId,\n// values: Object.fromEntries(ask.fields.map(f => [f.key, null])) },\n// })}).then(...)\n//\n// TWO LIVE GATES SIT IN FRONT OF THAT CALL TODAY, and this panel names them\n// rather than spinning: the knob `custom/code_paths_enabled` resolves false\n// (the tool refuses every action while it does), and the `records` row in\n// `tool.binding` is `is_active = false`. Both are switches somebody flips on\n// purpose; neither is something a screen may work around.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { Field, RecordDocument, RecordsError, ValueEnvelope } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi, useTableRights } from \"./host\";\nimport { envelopeFor, RecordValue } from \"./values\";\n\n/** What the host is asked to have the server's `records` tool do. */\nexport interface EnrichAsk {\n tableId: Uuid;\n recordId: Uuid;\n /** The agent Fields to refill, each with why this panel thinks it is due. */\n fields: Array<{ key: string; label: string; because: string }>;\n}\n\nexport interface EnrichOutcome {\n ok: boolean;\n /** What happened, in a sentence — the server's own words when it has some. */\n message: string;\n}\n\nexport const NO_ENRICH_REASON =\n \"No enrich port is bound, so nothing here offers to fill a field it cannot fill. An AI fill is \" +\n \"written by the SERVER with actor `agent` on behalf of you — a browser that stamped itself `agent` \" +\n \"would be a browser claiming to be one — so bind `enrich` on <RecordsUiProvider> with a call to the \" +\n \"server's own `records` tool (action `record_write`). Two switches also sit in front of it today: \" +\n \"the knob `custom/code_paths_enabled` resolves false, and the `records` row in `tool.binding` is \" +\n \"`is_active = false`.\";\n\nexport interface EnrichPanelProps {\n tableId: Uuid;\n recordId: Uuid;\n className?: string | undefined;\n}\n\ninterface AgentField {\n field: Field;\n envelope: ValueEnvelope | undefined;\n value: unknown;\n /** Days since it was written, or null when it has never been written. */\n ageDays: number | null;\n /** The Field's own interval, null when the organization set none. */\n everyDays: number | null;\n due: boolean;\n /** Why it is due, or why it is not — said in words, never left to a colour. */\n because: string;\n}\n\nexport function EnrichPanel({ tableId, recordId, className }: EnrichPanelProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const [document, setDocument] = useState<RecordDocument | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [outcome, setOutcome] = useState<EnrichOutcome | null>(null);\n\n const load = useCallback(async () => {\n const answered = await client.recordRead({ record_id: recordId });\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setError(null);\n setDocument(answered.data.document);\n }, [client, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const agentFields: AgentField[] | null = useMemo(() => {\n if (!fields.data || !document) return null;\n // FLD-7: the STORE says which fields an agent keeps filled. This panel has\n // no list of its own and no heuristic — a Field is here because its own\n // record says `source = 'agent'`.\n return fields.data.filter((f) => f.source === \"agent\").map((field) => describe(field, document));\n }, [fields.data, document]);\n\n const runFill = useCallback(\n async (targets: AgentField[]) => {\n if (!host.enrich || targets.length === 0) return;\n setBusy(targets.length === 1 ? (targets[0] as AgentField).field.key : \"*\");\n setOutcome(null);\n const answered = await host.enrich({\n tableId,\n recordId,\n fields: targets.map((t) => ({ key: t.field.key, label: t.field.label, because: t.because })),\n });\n setBusy(null);\n setOutcome(answered);\n // Re-read either way: a refused fill leaves the record exactly as it was,\n // and a screen that assumed so without looking would be guessing.\n await load();\n },\n [host, load, recordId, tableId],\n );\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (error) return <RefusalNotice error={error} className={className} />;\n if (!agentFields) return <Skeleton className={cn(\"h-40 w-full\", className)} />;\n\n if (agentFields.length === 0) {\n return (\n <p className={cn(\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\", className)}>\n No Field on {table.data?.name ?? \"this table\"} says an agent keeps it filled, so there is nothing\n here to enrich. A Field becomes agent-filled by carrying <code>source = agent</code> on its own\n record — set it in the field editor and it appears here with its review interval.\n </p>\n );\n }\n\n const due = agentFields.filter((f) => f.due);\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: the count, what is due, and the one verb. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">AI fill</span>\n <span>\n {agentFields.length} agent {agentFields.length === 1 ? \"field\" : \"fields\"}\n {due.length > 0 ? `, ${due.length} due` : \", all fresh\"}\n </span>\n {host.enrich && rights.write && due.length > 0 ? (\n <Button size=\"sm\" className=\"ml-auto\" disabled={busy !== null} onClick={() => void runFill(due)}>\n {busy === \"*\" ? \"Asking…\" : `Refill ${due.length}`}\n </Button>\n ) : null}\n </header>\n\n {/* The port is not bound: absent verb, stated reason. Never a dead button. */}\n {!host.enrich ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{NO_ENRICH_REASON}</p>\n ) : null}\n {host.enrich && !rights.write ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{rights.why(\"write\")}</p>\n ) : null}\n\n {outcome ? (\n <p\n className={cn(\n \"rounded border px-2 py-1 text-xs\",\n outcome.ok ? \"text-muted-foreground\" : \"border-destructive text-destructive\",\n )}\n >\n {outcome.message}\n </p>\n ) : null}\n\n <ul className=\"flex min-h-0 flex-col gap-1 overflow-y-auto\">\n {agentFields.map((entry) => (\n <li key={entry.field.key} className=\"rounded border p-2\">\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-xs font-medium\">{entry.field.label}</span>\n <ProvenanceBadge envelope={entry.envelope} />\n <span className={cn(\"text-[11px]\", entry.due ? \"text-destructive\" : \"text-muted-foreground\")}>\n {entry.because}\n </span>\n {host.enrich && rights.write ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"ml-auto h-6 px-2 text-[11px]\"\n disabled={busy !== null}\n onClick={() => void runFill([entry])}\n >\n {busy === entry.field.key ? \"Asking…\" : \"Fill\"}\n </Button>\n ) : null}\n </div>\n <div className=\"mt-1 text-xs\"><RecordValue field={entry.field} value={entry.value} document={document ?? undefined} /></div>\n </li>\n ))}\n </ul>\n </section>\n );\n}\n\n/**\n * VAL-8 ON SCREEN. Who wrote this value, and — when it was an agent — which\n * person they were acting for. AGT-N-4 is the whole reason the second half is\n * shown: an agent carries the exact authority of the person operating it, so\n * \"an agent, for Dana\" is the true sentence and \"an agent\" is not.\n */\nfunction ProvenanceBadge({ envelope }: { envelope: ValueEnvelope | undefined }) {\n if (!envelope) return null;\n if (envelope.actor !== \"agent\") {\n return (\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {envelope.actor === \"system\" ? \"written by the system\" : \"written by a person\"}\n </Badge>\n );\n }\n return (\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {envelope.on_behalf_of ? `filled by an agent, for ${envelope.on_behalf_of}` : \"filled by an agent\"}\n </Badge>\n );\n}\n\n/**\n * IS THIS VALUE DUE? Read off the value's own envelope and the Field's own\n * interval, and said in a sentence.\n *\n * An interval nobody set is NOT silently \"never due\" and not silently \"always\n * due\": the Field has no review interval, that is stated, and the value is left\n * alone. A knob nobody turned is not a decision somebody made.\n */\nfunction describe(field: Field, document: RecordDocument): AgentField {\n const envelope = envelopeFor(document, field.key);\n const value = (document as Record<string, unknown>)[field.key];\n const everyDays = field.review_interval_days ?? null;\n const writtenAt = envelope?.at ? Date.parse(envelope.at) : Number.NaN;\n const ageDays = Number.isNaN(writtenAt) ? null : Math.floor((Date.now() - writtenAt) / 86_400_000);\n\n if (value === undefined || value === null || value === \"\") {\n return {\n field,\n envelope,\n value,\n ageDays,\n everyDays,\n due: true,\n because: \"never filled\",\n };\n }\n if (everyDays === null) {\n return {\n field,\n envelope,\n value,\n ageDays,\n everyDays,\n due: false,\n because:\n ageDays === null ? \"no review interval set\" : `filled ${ageDays}d ago, no review interval set`,\n };\n }\n if (ageDays === null) {\n return {\n field,\n envelope,\n value,\n ageDays,\n everyDays,\n due: true,\n because: `every ${everyDays}d, and this value carries no date`,\n };\n }\n return {\n field,\n envelope,\n value,\n ageDays,\n everyDays,\n due: ageDays >= everyDays,\n because: ageDays >= everyDays ? `${ageDays}d old, due every ${everyDays}d` : `${ageDays}d old of ${everyDays}d`,\n };\n}\n","\"use client\";\n\n// src/ChecklistRunner.tsx — @ai-matrx/records-ui · SCR-28\n//\n// A CHECKLIST IS NOT A LIST OF STRINGS. Every step is a REAL RECORD in a real\n// Table, related to the others, so a step can be assigned, commented on,\n// exported, historied and read by an agent exactly like anything else in this\n// store — and \"step 3 of the onboarding\" is a row somebody can find six months\n// later rather than a line in a JSON blob.\n//\n// THE TEMPLATE IS INSTANTIATED IN ONE ACT (REC-70). `custom.work_template_instantiate`\n// judges the whole graph before writing any of it, so a half-made checklist is\n// not a state this store can be in — and this component does not loop writing\n// steps one at a time, which is exactly how half-made checklists happen.\n//\n// THE STORE OWNS THE ORDER, THE TURN AND THE STATES:\n// · `custom.work_states()` is the five states and what each may become. This\n// screen hardcodes none of them; a picker built from a hardcoded list is a\n// second source of truth waiting to disagree.\n// · `custom.work_whose_turn` says whose turn each step is and whether its\n// state is terminal.\n// · `custom.work_transition_refusal` says why a move is refused, ASKED FIRST,\n// so a person is told before they try rather than after.\n//\n// `seed` is the agent's half: a complete declarative template, saved the first\n// time it is seen, exactly as `ViewBar`, `FormBuilder` and `DashboardCanvas`\n// take theirs. An agent writes a twelve-step checklist in one object.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useRecordsClient, useTable, type ReadRow, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, WorkGraph, WorkState, WorkTurn } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { useSystemTable, type SystemTableSpec } from \"./systemTable\";\n\n/** THE COMPLETE DECLARATIVE SPEC — one object, one `record_write`, a whole checklist. */\nexport interface ChecklistSpec {\n name: string;\n /** The Table the steps become records in. */\n subject: Uuid;\n steps: ChecklistStepSpec[];\n}\n\nexport interface ChecklistStepSpec {\n /** The document this step's record starts life with. `title` is what a person reads. */\n title: string;\n /** Anything else the subject Table's Fields take. */\n data?: Record<string, unknown>;\n}\n\n/**\n * The package-owned Table a checklist RUN is recorded in. The steps are records\n * in the subject Table — this holds only which template was instantiated and\n * when, so re-opening a checklist finds the same steps rather than making new\n * ones. (Running the same checklist twice on purpose is two rows here, which is\n * the correct answer: they are two runs.)\n */\nexport const CHECKLIST_TABLE: SystemTableSpec = {\n slug: \"records_ui_checklist_run\",\n name: \"Checklist runs\",\n labelSingular: \"Checklist run\",\n labelPlural: \"Checklist runs\",\n titleField: \"name\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"text\", sort: 10, required: true },\n { key: \"subject\", label: \"Table\", type: \"text\", sort: 20, required: true },\n { key: \"template_id\", label: \"Template\", type: \"text\", sort: 30 },\n { key: \"instantiation_id\", label: \"Instantiation\", type: \"text\", sort: 40 },\n { key: \"step_ids\", label: \"Steps\", type: \"text\", sort: 50, config: { multiline: true } },\n { key: \"started_at\", label: \"Started\", type: \"text\", sort: 60 },\n ],\n};\n\nexport interface ChecklistRunnerProps {\n /** The Table the steps live in — normally the same Table the checklist is about. */\n tableId: Uuid;\n /** The agent's half. Each spec not already run is instantiated once. */\n seed?: ChecklistSpec[] | undefined;\n className?: string | undefined;\n}\n\ninterface Run {\n id: Uuid;\n name: string;\n subject: Uuid;\n templateId: Uuid | null;\n stepIds: Uuid[];\n startedAt: string;\n}\n\nexport function ChecklistRunner({ tableId, seed, className }: ChecklistRunnerProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const home = useSystemTable(CHECKLIST_TABLE);\n const [runs, setRuns] = useState<Run[] | null>(null);\n const [activeId, setActiveId] = useState<Uuid | null>(null);\n const [turns, setTurns] = useState<WorkTurn[] | null>(null);\n const [states, setStates] = useState<WorkState[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n const [note, setNote] = useState<string | null>(null);\n\n const runTableId = home.tableId;\n\n // The five states, from the store. Asked once, never typed out here.\n useEffect(() => {\n let cancelled = false;\n void client.workStates().then((answered) => {\n if (cancelled || !answered.ok) return;\n setStates([...answered.data].sort((a, b) => a.sort - b.sort));\n });\n return () => {\n cancelled = true;\n };\n }, [client]);\n\n const loadRuns = useCallback(async (): Promise<Run[] | null> => {\n if (!runTableId) return null;\n const listed = await client.list({ table_id: runTableId, limit: 200 });\n if (!listed.ok) {\n setError(listed.error);\n return null;\n }\n setError(null);\n const held = listed.data.rows.map(toRun).filter((r) => r.subject === tableId);\n setRuns(held);\n return held;\n }, [client, runTableId, tableId]);\n\n useEffect(() => {\n void loadRuns();\n }, [loadRuns]);\n\n // ── the seed: instantiated ONCE, never on top of a run that exists ────────\n useEffect(() => {\n let cancelled = false;\n if (!runTableId || !seed || seed.length === 0 || runs === null) return;\n const missing = seed.filter((spec) => !runs.some((run) => run.name === spec.name));\n if (missing.length === 0) return;\n void (async () => {\n for (const spec of missing) {\n if (cancelled) return;\n const started = await start(client, runTableId, spec);\n if (!started.ok) {\n setError(started.error);\n return;\n }\n }\n if (!cancelled) await loadRuns();\n })();\n return () => {\n cancelled = true;\n };\n }, [client, loadRuns, runTableId, runs, seed]);\n\n const active = useMemo(\n () => runs?.find((r) => r.id === activeId) ?? runs?.[0] ?? null,\n [runs, activeId],\n );\n\n // Whose turn each step is — the STORE's answer, over the whole subject Table,\n // narrowed here to this run's own steps.\n const loadTurns = useCallback(async () => {\n const answered = await client.workWhoseTurn({ table_id: tableId, includeFinished: true });\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setTurns(answered.data);\n }, [client, tableId]);\n\n // Re-asked whenever the RUN changes, not only on mount: the seed instantiates\n // its steps AFTER the first read, so a screen that asked once would draw a\n // checklist whose every step said \"you cannot see this\" — records that had\n // been written a second earlier.\n useEffect(() => {\n void loadTurns();\n }, [loadTurns, active?.id, active?.stepIds.length]);\n\n async function move(step: Uuid, to: string) {\n setBusy(true);\n setNote(null);\n const written = await client.recordUpdate({ record_id: step, patch: { status: to } });\n setBusy(false);\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setError(null);\n setNote(`Moved to ${to}.`);\n await loadTurns();\n }\n\n if (home.error) return <RefusalNotice error={home.error} className={className} />;\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (home.loading || runs === null) return <Skeleton className={cn(\"h-48 w-full\", className)} />;\n\n if (!active) {\n return (\n <p className={cn(\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\", className)}>\n No checklist has been run against {table.data?.name ?? \"this table\"} yet. Pass a complete template as{\" \"}\n <code>seed</code> — a name and its ordered steps — and it is instantiated once, as real records.\n </p>\n );\n }\n\n const steps = active.stepIds\n .map((id) => turns?.find((t) => t.record_id === id) ?? null)\n .map((turn, index) => ({ turn, index, id: active.stepIds[index] as Uuid }));\n const done = steps.filter((s) => s.turn?.terminal === true).length;\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: which run, and how far through. No subtitle restating the name. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{active.name}</span>\n <span className=\"tabular-nums\">\n {done} of {steps.length} done\n </span>\n {runs.length > 1 ? (\n <select\n aria-label=\"Checklist run\"\n className=\"ml-auto h-7 rounded border bg-background px-1 text-xs\"\n value={active.id}\n onChange={(e) => setActiveId(e.target.value as Uuid)}\n >\n {runs.map((r) => (\n <option key={r.id} value={r.id}>\n {r.name}\n </option>\n ))}\n </select>\n ) : null}\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n {note ? <p className=\"text-xs text-muted-foreground\">{note}</p> : null}\n\n {turns === null ? (\n <Skeleton className=\"h-24 w-full\" />\n ) : (\n <ol className=\"flex min-h-0 flex-col gap-1 overflow-y-auto\">\n {steps.map(({ turn, index, id }) => (\n <li key={id} className=\"flex items-center gap-2 rounded border p-2\">\n <span className=\"w-5 shrink-0 text-right text-[11px] tabular-nums text-muted-foreground\">\n {index + 1}\n </span>\n <span className={cn(\"min-w-0 flex-1 truncate text-xs\", turn?.terminal && \"text-muted-foreground line-through\")}>\n {turn?.title ??\n // The step is a record the read door did not return. That is a\n // fact about visibility, not an empty row, so it says so.\n \"This step is a record you cannot see — it is in the run, and the store did not return it to you.\"}\n </span>\n {turn?.assignee_id ? (\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {turn.turn ?? \"assigned\"}\n </Badge>\n ) : null}\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {turn?.status ?? turn?.state ?? \"Not started\"}\n </Badge>\n {/* The next states are the STORE's `next` for the state this step\n is actually in. A move nobody may make is never offered. */}\n {rights.write && turn && states ? (\n <NextMove\n states={states}\n current={turn.status ?? turn.state ?? null}\n disabled={busy}\n onMove={(to) => void move(id, to)}\n />\n ) : null}\n </li>\n ))}\n </ol>\n )}\n\n {!rights.write ? <p className=\"text-xs text-muted-foreground\">{rights.why(\"write\")}</p> : null}\n </section>\n );\n}\n\n/**\n * The moves this step may actually make, from `custom.work_states()`.\n *\n * A state the store does not list as `next` is not shown greyed out — it is not\n * there. Offering a move that will be refused, and only saying so afterwards,\n * is the screen making a person find out by failing.\n */\nfunction NextMove({\n states,\n current,\n disabled,\n onMove,\n}: {\n states: WorkState[];\n current: string | null;\n disabled: boolean;\n onMove: (to: string) => void;\n}) {\n const here = states.find((s) => s.name === current) ?? states[0];\n const next = here?.next ?? [];\n if (next.length === 0) {\n return <span className=\"text-[11px] text-muted-foreground\">finished</span>;\n }\n return (\n <span className=\"flex shrink-0 gap-1\">\n {next.map((to) => (\n <Button key={to} size=\"sm\" variant=\"ghost\" className=\"h-6 px-2 text-[11px]\" disabled={disabled} onClick={() => onMove(to)}>\n {to}\n </Button>\n ))}\n </span>\n );\n}\n\n/**\n * ONE ACT. The template is declared, judged and instantiated, and only then is\n * the run recorded — so a refused graph leaves nothing behind at all.\n */\nasync function start(\n client: ReturnType<typeof useRecordsClient>,\n runTableId: Uuid,\n spec: ChecklistSpec,\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const graph: WorkGraph = {\n // A ref is lower-case letters, digits and underscores — the store refuses\n // `step-1` by name (\"every record in a template needs a name made of\n // lower-case letters, digits and underscores\"). Refs are built here rather\n // than taken from a person's step title for exactly that reason.\n nodes: spec.steps.map((step, index) => ({\n ref: `step_${index + 1}`,\n table: spec.subject,\n data: { title: step.title, ...(step.data ?? {}) },\n })),\n // Each step owns the next, so the order is a fact in the store rather than\n // an array index a screen remembered.\n relations: spec.steps.slice(1).map((_, index) => ({ from: `step_${index + 1}`, to: `step_${index + 2}` })),\n };\n\n // ASKED BEFORE IT IS WRITTEN. The store says why a graph would be refused,\n // and a refusal here costs nothing rather than leaving a declared template\n // nobody can instantiate.\n const refusal = await client.workTemplateRefusal({ graph });\n if (!refusal.ok) return refusal;\n if (refusal.data) {\n return {\n ok: false,\n error: {\n code: \"refused_by_rule\",\n message: refusal.data,\n hint: \"The store judged the whole graph before anything was written, so nothing was — fix the template and run it again.\",\n },\n };\n }\n\n const declared = await client.workTemplateDeclare({ name: spec.name, graph });\n if (!declared.ok) return declared;\n const made = await client.workTemplateInstantiate({ template_id: declared.data });\n if (!made.ok) return made;\n\n return client.recordWrite({\n table_id: runTableId,\n data: {\n name: spec.name,\n subject: spec.subject,\n template_id: declared.data,\n instantiation_id: made.data.instantiation_id,\n step_ids: JSON.stringify(made.data.records),\n started_at: new Date().toISOString(),\n },\n });\n}\n\nfunction toRun(row: ReadRow): Run {\n const data = (row.document ?? {}) as Record<string, unknown>;\n let stepIds: Uuid[] = [];\n try {\n const raw = data[\"step_ids\"];\n stepIds = typeof raw === \"string\" ? (JSON.parse(raw) as Uuid[]) : Array.isArray(raw) ? (raw as Uuid[]) : [];\n } catch {\n stepIds = [];\n }\n return {\n id: row.id,\n name: String(data[\"name\"] ?? \"Checklist\"),\n subject: String(data[\"subject\"] ?? \"\"),\n templateId: (data[\"template_id\"] as Uuid | null) ?? null,\n stepIds,\n startedAt: String(data[\"started_at\"] ?? \"\"),\n };\n}\n","\"use client\";\n\n// src/BookingSlots.tsx — @ai-matrx/records-ui · SCR-29\n//\n// AVAILABILITY, A SLOT PICKER, AND THE ONE THING THAT MAKES BOOKING HARD:\n// TWO PEOPLE PICKING THE SAME SLOT AT THE SAME MOMENT.\n//\n// This screen does not decide that. `custom.work_slot_hold` does, under a\n// unique index, and the loser is TOLD — not shown a spinner, not silently given\n// the next slot, not left believing they have a booking that somebody else has.\n// A picker that filtered out taken slots client-side would be correct roughly\n// until two people used it.\n//\n// WHERE A HOLD LIVES, AND WHY IT IS NOT THE BOOKING TABLE. Measured against the\n// live store: `custom.work_slot_hold` WRITES a record for the hold, so pointing\n// it at the bookings Table is refused by that Table's own Rules (\"Title is\n// required\"), and `custom.work_slot_holds` then reads every booking back as a\n// hold with no slot key. A slot has to live in a Table declared for it, by\n// `custom.work_slots_declare`, which builds the UNIQUE INDEX that makes one\n// hold per slot true in the database rather than true in an application. So\n// this component declares that Table once, through the same doors everything\n// else uses, and holds against it.\n//\n// THE THREE PARTS, AND WHO OWNS EACH:\n// · AVAILABILITY is the organization's own: a start hour, an end hour, a slot\n// length, over N days. Those are knobs on this component with sensible\n// defaults, because they are an opinion and opinions are settings.\n// · WHAT IS TAKEN is the store's: `custom.work_slot_holds` lists every hold\n// with whether it has LAPSED, so a slot that came back says why rather than\n// reappearing mysteriously.\n// · WHAT A BOOKING *IS* is `FormRunner`'s: the person answers the form's own\n// questions and the submission is an ORDINARY RECORD in a real Table. There\n// is no bookings table, no second data model, and no reconciliation later.\n//\n// THE ORDER MATTERS AND IT IS THE STRICT ONE: hold the slot FIRST, then take\n// the details, then release the hold only if they abandon it. Taking details\n// first and holding after is how two people fill in a form and one of them\n// finds out at the end.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, WorkSlotHold } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { FormRunner } from \"./FormRunner\";\nimport type { FormSpec } from \"./forms\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface BookingSlotsProps {\n /** The Table holds are taken against, and the Table a booking lands in. */\n tableId: Uuid;\n /** The form a person fills in once they hold a slot. Its `subject` is the Table. */\n form: FormSpec;\n /** Availability — the organization's opinion, with a default rather than a question. */\n availability?: {\n /** First hour offered, 24h. Default 9. */\n fromHour?: number;\n /** Last hour offered, exclusive. Default 17. */\n toHour?: number;\n /** Minutes per slot. Default 60. */\n everyMinutes?: number;\n /** How many days ahead to offer. Default 5. */\n days?: number;\n };\n /** How long a hold lasts before the store lets the slot go. Default 15 minutes. */\n holdFor?: string;\n /** `null` when the answer was HELD rather than written — see the runner's own note. */\n onBooked?: ((recordId: Uuid | null) => void) | undefined;\n className?: string | undefined;\n}\n\ninterface Slot {\n /** The key the STORE holds. Stable, sortable, and the same string for everyone. */\n key: string;\n at: Date;\n taken: boolean;\n /** Set when the slot is taken: who by, so a person can see it is their own. */\n holder: string | null;\n}\n\nexport function BookingSlots({\n tableId,\n form,\n availability,\n holdFor = \"15 minutes\",\n onBooked,\n className,\n}: BookingSlotsProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const [slotTableId, setSlotTableId] = useState<Uuid | null>(null);\n const [holds, setHolds] = useState<WorkSlotHold[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [held, setHeld] = useState<{ slot: Slot; holdId: Uuid | null } | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [refused, setRefused] = useState<string | null>(null);\n\n const me = client.config.actor.user_id ?? \"anonymous\";\n const slug = `records_ui_slots_${tableId.replace(/-/g, \"\").slice(0, 16)}`;\n\n // ── the slots Table, declared once, through the store's own doors ─────────\n // A Home first (REC-1: a Table has to live somewhere), then the declaration\n // — the same sequence `ensureSystemTable` obeys, and for the same reason.\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n // FOUND BEFORE IT IS MADE. Two screens open on the same bookings Table\n // must hold against the SAME slots Table, or each one has its own\n // private idea of what is free and the unique index protects nothing.\n const tables = await client.tableList();\n if (!tables.ok) {\n if (!cancelled) setError(tables.error);\n return;\n }\n const already = tables.data.find((t) => t.slug === slug);\n if (already) {\n if (!cancelled) setSlotTableId(already.id);\n return;\n }\n const kernel = await client.personKernelId();\n if (!kernel.ok) {\n if (!cancelled) setError(kernel.error);\n return;\n }\n const home = await client.recordWrite({\n table_id: kernel.data,\n data: { name: `Slots for ${tableId}` },\n });\n if (!home.ok) {\n if (!cancelled) setError(home.error);\n return;\n }\n const declared = await client.workSlotsDeclare({\n name: `Slots for ${table.data?.name ?? \"bookings\"}`,\n slug,\n homeId: home.data,\n });\n if (cancelled) return;\n if (!declared.ok) {\n // THE STORE REFUSED TO MAKE SLOTS AT ALL — most often because it\n // cannot build the unique index that keeps one hold per slot. That is\n // shown verbatim and NO PICKER IS DRAWN: a booking screen over a store\n // that cannot decide a double-booking is a screen that will sell the\n // same hour twice and look fine doing it.\n setError(declared.error);\n return;\n }\n const made = (declared.data ?? {}) as Record<string, unknown>;\n setSlotTableId((made[\"table_id\"] as Uuid | undefined) ?? null);\n })();\n return () => {\n cancelled = true;\n };\n }, [client, slug, table.data, tableId]);\n\n const loadHolds = useCallback(async () => {\n if (!slotTableId) return;\n const answered = await client.workSlotHolds({ table_id: slotTableId });\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setError(null);\n setHolds(answered.data);\n }, [client, slotTableId]);\n\n useEffect(() => {\n void loadHolds();\n }, [loadHolds]);\n\n const slots: Slot[] = useMemo(() => {\n const fromHour = availability?.fromHour ?? 9;\n const toHour = availability?.toHour ?? 17;\n const everyMinutes = availability?.everyMinutes ?? 60;\n const days = availability?.days ?? 5;\n // A LAPSED hold is not a taken slot. The store says which is which, so the\n // slot comes back on its own and nobody has to guess from a clock.\n const taken = new Map(\n (holds ?? []).filter((h) => !h.expired).map((h) => [h.slot_key, h.holder] as const),\n );\n const out: Slot[] = [];\n const first = new Date();\n first.setHours(0, 0, 0, 0);\n for (let day = 0; day < days; day += 1) {\n for (let minute = fromHour * 60; minute < toHour * 60; minute += everyMinutes) {\n const at = new Date(first);\n at.setDate(at.getDate() + day);\n at.setMinutes(minute);\n if (at.getTime() < Date.now()) continue;\n const key = at.toISOString();\n out.push({ key, at, taken: taken.has(key), holder: taken.get(key) ?? null });\n }\n }\n return out;\n }, [availability, holds]);\n\n async function take(slot: Slot) {\n if (!slotTableId) return;\n setBusy(slot.key);\n setRefused(null);\n setError(null);\n const answered = await client.workSlotHold({\n table_id: slotTableId,\n slotKey: slot.key,\n holder: me,\n ttl: holdFor,\n });\n setBusy(null);\n if (!answered.ok) {\n // THE LOSING HALF OF A RACE, AND IT IS THE DATABASE'S ANSWER.\n // `already_exists` is the unique index refusing a second hold on one\n // slot; the store's own sentence names the index that did it. Shown\n // verbatim, because \"the slot is already held\" is a fact a person can act\n // on and a spinner is not.\n if (answered.error.code === \"already_exists\") {\n setRefused(refusalLineForAPerson(answered.error));\n } else {\n setError(answered.error);\n }\n await loadHolds();\n return;\n }\n const outcome = (answered.data ?? {}) as Record<string, unknown>;\n const holdId = (outcome[\"hold_id\"] as Uuid | undefined) ?? null;\n if (!holdId) {\n setRefused(\n \"The store did not hold that slot and did not say why, so nothing was booked. Pick another, and \" +\n \"report this — a hold that neither succeeds nor refuses is a defect, not a busy moment.\",\n );\n await loadHolds();\n return;\n }\n setHeld({ slot, holdId });\n }\n\n async function letGo() {\n if (held?.holdId) await client.workSlotRelease({ hold_id: held.holdId });\n setHeld(null);\n await loadHolds();\n }\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n // A refusal from the declaration is the END of this screen, not a banner over\n // a working picker.\n if (error && !slotTableId) return <RefusalNotice error={error} className={className} />;\n if (holds === null || !slotTableId) return <Skeleton className={cn(\"h-48 w-full\", className)} />;\n\n // ── the slot is held: now, and only now, the details ──────────────────────\n if (held) {\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{whenText(held.slot.at)}</span>\n <span>held for you for {holdFor}</span>\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-auto h-6 px-2 text-[11px]\" onClick={() => void letGo()}>\n Pick another\n </Button>\n </header>\n <FormRunner\n // The booking IS the submission: an ordinary record in a real Table,\n // carrying the slot it was made for, so it is in the grid and the\n // exports the moment it is sent.\n form={{\n ...form,\n questions: form.questions,\n }}\n onSubmitted={(recordId) => {\n // A SUBMISSION DOES NOT ALWAYS BECOME A RECORD. `FormRunner` now\n // answers `null` when the form's own accept Rule held the answer for\n // a person instead of clearing it (DOOR-17's quarantine), and there\n // is nothing to stamp the slot onto until somebody does. Silently\n // patching `null` would have been a booking that lost its slot.\n if (recordId === null) {\n setRefused(\n \"Your details were sent and are waiting for someone to confirm them, so this slot is \" +\n \"not held for you yet. Whoever owns this form will be in touch.\",\n );\n void loadHolds();\n onBooked?.(null);\n return;\n }\n void client\n .recordUpdate({ record_id: recordId, patch: { slot: held.slot.key } })\n .then(() => loadHolds());\n onBooked?.(recordId);\n }}\n />\n </section>\n );\n }\n\n const free = slots.filter((s) => !s.taken).length;\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: what is on offer. No subtitle restating it. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Pick a time</span>\n <span className=\"tabular-nums\">\n {free} free of {slots.length}\n </span>\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n {refused ? <p className=\"rounded border border-destructive px-2 py-1 text-xs text-destructive\">{refused}</p> : null}\n\n {slots.length === 0 ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n There is no time left today inside the hours this is offered in. Tomorrow's slots appear here\n from midnight — this is empty because the day is over, not because something failed.\n </p>\n ) : (\n <ol className=\"flex flex-wrap gap-1\">\n {slots.map((slot) => (\n <li key={slot.key}>\n {/* A taken slot is not a dead button: it is not a button. */}\n {slot.taken ? (\n <span\n className=\"inline-flex h-8 items-center rounded border border-dashed px-2 text-[11px] text-muted-foreground\"\n title={slot.holder === me ? \"You are holding this one.\" : \"Somebody is holding this one.\"}\n >\n {whenText(slot.at)} · {slot.holder === me ? \"yours\" : \"taken\"}\n </span>\n ) : (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-8 px-2 text-[11px]\"\n disabled={busy !== null}\n onClick={() => void take(slot)}\n >\n {busy === slot.key ? \"Holding…\" : whenText(slot.at)}\n </Button>\n )}\n </li>\n ))}\n </ol>\n )}\n </section>\n );\n}\n\nfunction whenText(at: Date): string {\n return at.toLocaleString(undefined, { weekday: \"short\", hour: \"numeric\", minute: \"2-digit\" });\n}\n","\"use client\";\n\n// src/CaptureSheet.tsx — @ai-matrx/records-ui · SCR-30\n//\n// A PHONE, IN A BASEMENT, WITH NO SIGNAL — AND THE CAPTURE STILL COUNTS.\n//\n// Everything hard about offline capture is one question: when the phone comes\n// back and fires the same capture for the thirtieth time, does the store write\n// thirty records? The answer is the OFFLINE CAPTURE CONTRACT, and both halves\n// of it are load-bearing:\n//\n// 1. THE CLIENT MINTS THE ID, BEFORE THE FIRST ATTEMPT, OFFLINE. `clientKey`\n// is decided the moment a person hits Capture — not when the write lands,\n// because a key minted by the server is a key that does not exist while\n// there is no server. It is never re-minted on retry: re-minting is exactly\n// how a retry becomes a second capture.\n// 2. THE STORE DEDUPES ON IT. `custom.anon_capture` writes a replay-ledger row\n// `on conflict do nothing` under a unique index and returns the record id\n// the FIRST attempt produced. So the second, third and thirtieth replay all\n// take the same branch whatever this client believes, and a phone that\n// crashed mid-send loses nothing.\n//\n// THREE MORE THINGS THIS SHEET REFUSES TO FAKE:\n// · It never claims a capture is saved while it is queued. The queue is\n// visible, counted, and each waiting item says what the store last said.\n// · With no `captureQueue` port bound the queue is IN MEMORY for the life of\n// the page and SAYS SO — a queue that silently died with the tab is the\n// precise failure this component exists to prevent.\n// · A camera or a microphone this browser will not give it is named, not\n// rendered as a button that does nothing. Bytes go through the host's\n// `upload` port; with none bound, the photo and voice capture say so and\n// the reading capture — which is just a number and a note — still works.\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Input, Skeleton, Textarea, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { NO_UPLOAD_REASON, useRecordsUi, type PendingCapture } from \"./host\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\n/** The three things a phone captures. Each one writes the SAME kind of record. */\nexport const CAPTURE_MODES = [\"reading\", \"photo\", \"voice\"] as const;\nexport type CaptureMode = (typeof CAPTURE_MODES)[number];\n\nexport const IN_MEMORY_QUEUE_REASON =\n \"No capture queue is bound, so anything that cannot be sent right now is held in this page's memory \" +\n \"and is lost if the page closes. Bind `captureQueue` on <RecordsUiProvider> with your host's own \" +\n \"durable store (IndexedDB in a browser) and a queued capture survives the tab, the reload and the \" +\n \"flight. It is said here rather than discovered later.\";\n\nexport interface CaptureSheetProps {\n /** The Table a capture becomes a record in. */\n tableId: Uuid;\n /** Which Field a reading's number goes in. Defaults to the first range Field. */\n readingField?: string | undefined;\n /** Which Field the note goes in. Defaults to the Table's title field. */\n noteField?: string | undefined;\n /** Which Field an attachment's file id goes in. */\n attachmentField?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * THE CLIENT-MINTED ID. `crypto.randomUUID` where there is one; a time-and-\n * randomness key where there is not. Either way it is decided HERE, offline,\n * before anything is attempted.\n */\nfunction mintClientKey(): string {\n const c = globalThis.crypto as { randomUUID?: () => string } | undefined;\n if (typeof c?.randomUUID === \"function\") return `capture:${c.randomUUID()}`;\n return `capture:${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;\n}\n\nfunction deviceName(): string {\n const nav = globalThis.navigator as { userAgent?: string } | undefined;\n return nav?.userAgent ? nav.userAgent.slice(0, 120) : \"unknown device\";\n}\n\nexport function CaptureSheet({\n tableId,\n readingField,\n noteField,\n attachmentField,\n className,\n}: CaptureSheetProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const [mode, setMode] = useState<CaptureMode>(\"reading\");\n const [reading, setReading] = useState(\"\");\n const [note, setNote] = useState(\"\");\n const [fileId, setFileId] = useState<Uuid | null>(null);\n const [pending, setPending] = useState<PendingCapture[] | null>(null);\n const [saved, setSaved] = useState<Uuid[]>([]);\n const [error, setError] = useState<RecordsError | null>(null);\n const [uploadError, setUploadError] = useState<string | null>(null);\n const [flushing, setFlushing] = useState(false);\n /** Kept in a ref as well so a flush never races the render that queued an item. */\n const queue = useRef<PendingCapture[]>([]);\n\n const keep = useCallback(\n async (next: PendingCapture[]) => {\n queue.current = next;\n setPending(next);\n if (host.captureQueue) await host.captureQueue.save(next);\n },\n [host],\n );\n\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n const held = host.captureQueue ? await host.captureQueue.load() : [];\n if (cancelled) return;\n queue.current = held;\n setPending(held);\n })();\n return () => {\n cancelled = true;\n };\n }, [host]);\n\n const resolved = useCallback(() => {\n const all = fields.data ?? [];\n return {\n reading: readingField ?? all.find((f) => f.type === \"range\")?.key ?? null,\n note: noteField ?? table.data?.title_field ?? all[0]?.key ?? null,\n attachment: attachmentField ?? all.find((f) => f.format === \"file\" || f.format === \"image\")?.key ?? null,\n };\n }, [attachmentField, fields.data, noteField, readingField, table.data]);\n\n /**\n * SEND EVERYTHING WAITING. Each item goes through `custom.anon_capture` with\n * the key it was minted with — so an item that actually landed last time\n * comes back with the same record id and leaves the queue, and an item that\n * did not is tried again. Nothing here decides \"this probably worked\".\n */\n const flush = useCallback(async () => {\n if (flushing || queue.current.length === 0) return;\n setFlushing(true);\n const left: PendingCapture[] = [];\n const landed: Uuid[] = [];\n for (const item of queue.current) {\n const answered = await client.anonCapture({\n table_id: item.tableId,\n clientKey: item.clientKey,\n payload: item.payload,\n device: item.device,\n capturedAt: item.capturedAt,\n });\n if (answered.ok) {\n landed.push(answered.data);\n continue;\n }\n left.push({ ...item, attempts: item.attempts + 1, lastRefusal: refusalLineForAPerson(answered.error) });\n setError(answered.error);\n }\n if (landed.length > 0) {\n setSaved((held) => [...held, ...landed]);\n setError(null);\n }\n await keep(left);\n setFlushing(false);\n }, [client, flushing, keep]);\n\n // A capture is queued first and sent immediately after, which is the same\n // path a reconnect takes. There is no \"online\" branch that skips the queue:\n // one path means the offline path is the one that is actually exercised.\n async function capture() {\n const keys = resolved();\n const payload: Record<string, unknown> = {};\n if (keys.note && note.trim() !== \"\") payload[keys.note] = note.trim();\n if (mode === \"reading\" && keys.reading && reading.trim() !== \"\") {\n payload[keys.reading] = Number(reading);\n }\n if (mode !== \"reading\" && keys.attachment && fileId) payload[keys.attachment] = fileId;\n if (Object.keys(payload).length === 0) return;\n\n const item: PendingCapture = {\n // MINTED HERE. Before the attempt, not after it.\n clientKey: mintClientKey(),\n tableId,\n payload,\n capturedAt: new Date().toISOString(),\n device: deviceName(),\n attempts: 0,\n lastRefusal: null,\n };\n setReading(\"\");\n setNote(\"\");\n setFileId(null);\n await keep([...queue.current, item]);\n await flush();\n }\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (fields.loading || pending === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n const keys = resolved();\n\n return (\n <section className={cn(\"mx-auto flex w-full max-w-sm flex-col gap-2\", className)}>\n {/* One row, phone-first: the three modes and the queue count. */}\n <header className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n {CAPTURE_MODES.map((m) => (\n <Button\n key={m}\n size=\"sm\"\n variant={m === mode ? \"default\" : \"ghost\"}\n className=\"h-8 px-3 text-[11px] capitalize\"\n onClick={() => setMode(m)}\n >\n {m}\n </Button>\n ))}\n <span className=\"ml-auto tabular-nums\">\n {pending.length > 0 ? `${pending.length} waiting` : `${saved.length} saved`}\n </span>\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {mode === \"reading\" ? (\n keys.reading ? (\n <Input\n aria-label=\"Reading\"\n inputMode=\"decimal\"\n // A phone keyboard, and a touch target a thumb can hit.\n className=\"h-12 text-lg\"\n placeholder=\"0\"\n value={reading}\n onChange={(e) => setReading(e.target.value)}\n />\n ) : (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n {table.data?.name ?? \"This table\"} has no number Field for a reading to go in, so this mode\n would have nowhere to put what you typed. Add one, or name it with <code>readingField</code>.\n </p>\n )\n ) : null}\n\n {mode !== \"reading\" ? (\n !host.upload ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{NO_UPLOAD_REASON}</p>\n ) : !keys.attachment ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n {table.data?.name ?? \"This table\"} has no Field a file id can go in, so a {mode} capture would\n upload the bytes and then have nowhere to record them. Add one, or name it with{\" \"}\n <code>attachmentField</code>.\n </p>\n ) : (\n <>\n <input\n aria-label={mode === \"photo\" ? \"Take a photo\" : \"Record a voice note\"}\n type=\"file\"\n className=\"text-xs\"\n // Phone-first: this is what opens the camera and the microphone\n // rather than a file browser.\n accept={mode === \"photo\" ? \"image/*\" : \"audio/*\"}\n capture={mode === \"photo\" ? \"environment\" : undefined}\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (!file) return;\n setUploadError(null);\n void host.upload?.(file).then((result) => {\n if (result.ok) setFileId(result.fileId);\n else setUploadError(result.reason);\n });\n }}\n />\n {fileId ? <p className=\"text-[11px] text-muted-foreground\">Attached.</p> : null}\n {uploadError ? <p className=\"text-xs text-destructive\">{uploadError}</p> : null}\n </>\n )\n ) : null}\n\n <Textarea\n aria-label=\"Note\"\n rows={2}\n className=\"text-sm\"\n placeholder=\"Note\"\n value={note}\n onChange={(e) => setNote(e.target.value)}\n />\n\n <Button className=\"h-12\" onClick={() => void capture()}>\n Capture\n </Button>\n\n {/* The queue, visible and honest. Never a capture that claims to be saved. */}\n {pending.length > 0 ? (\n <div className=\"flex flex-col gap-1 rounded border p-2\">\n <div className=\"flex items-center gap-2 text-xs\">\n <span className=\"font-medium\">Waiting to send</span>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"ml-auto h-6 px-2 text-[11px]\"\n disabled={flushing}\n onClick={() => void flush()}\n >\n {flushing ? \"Sending…\" : \"Try now\"}\n </Button>\n </div>\n <ul className=\"flex flex-col gap-0.5\">\n {pending.map((item) => (\n <li key={item.clientKey} className=\"text-[11px] text-muted-foreground\">\n {new Date(item.capturedAt).toLocaleTimeString()} · {item.attempts} tried\n {item.lastRefusal ? ` · ${item.lastRefusal}` : \"\"}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n\n {!host.captureQueue ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-[11px] text-muted-foreground\">\n {IN_MEMORY_QUEUE_REASON}\n </p>\n ) : null}\n </section>\n );\n}\n","\"use client\";\n\n// src/PortalShell.tsx — @ai-matrx/records-ui · SCR-23\n//\n// AN OUTSIDER'S WHOLE WORLD: their list, their record, their form — and NOTHING\n// ELSE, because they are not in the organization.\n//\n// VIS-31 is the fact this shell is built on, and it is subtle enough that the\n// store says it in one place so no screen can invent a second answer: \"no\n// organization\" cannot mean \"no row in the membership table\", because signup\n// mints every account a PERSONAL organization — under that reading nobody would\n// ever be external. `iam.is_external_principal` means no membership of a\n// NON-personal organization, and `iam.external_principal_card` says WHY in\n// plain English, which is what this shell shows instead of an empty page.\n//\n// WHAT AN OUTSIDER REACHES IS NOT \"THEIR ORGANIZATION'S RECORDS\". It is\n// `iam.external_principal_reach` — exactly the resource ids Visibility handed\n// them, one by one. A portal that listed a Table and relied on the read door to\n// filter would be a portal whose correctness depended on a filter running; this\n// one asks for the list of ids first and reads only those.\n//\n// AND THE SHELL IS HONEST ABOUT THE LANE. While `custom/external_principal_enabled`\n// is false the doors refuse BY NAME, which is the answer the platform gave\n// before this campaign, and this screen shows that sentence rather than an\n// empty list that reads like \"you have nothing\".\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { ExternalPrincipalCard, RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { Peek } from \"./Peek\";\nimport { FormRunner } from \"./FormRunner\";\nimport type { FormSpec } from \"./forms\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface PortalShellProps {\n /** The Table the outsider's records belong to. */\n tableId: Uuid;\n /** OPTIONAL. A form the outsider may send — their one way to put something in. */\n form?: FormSpec | undefined;\n /** What the resources are called in `iam`'s own vocabulary. Default `record`. */\n resourceType?: string;\n className?: string | undefined;\n}\n\nexport function PortalShell({ tableId, form, resourceType = \"record\", className }: PortalShellProps) {\n const client = useRecordsClient();\n const [card, setCard] = useState<ExternalPrincipalCard | null>(null);\n const [reach, setReach] = useState<Uuid[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [open, setOpen] = useState<Uuid | null>(null);\n const [sending, setSending] = useState(false);\n\n const load = useCallback(async () => {\n // WHO THEY ARE, FIRST. A portal that read records before it knew whose\n // portal it was would be a portal deciding that for itself.\n const who = await client.externalPrincipalCard();\n if (!who.ok) {\n setError(who.error);\n return;\n }\n setError(null);\n setCard(who.data);\n const reached = await client.externalPrincipalReach({ resourceType });\n if (!reached.ok) {\n setError(reached.error);\n return;\n }\n setReach(reached.data.map((row) => row.resource_id));\n }, [client, resourceType]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n if (error) {\n // The lane is closed, or the outsider is not one. Either way the sentence\n // is `iam`'s own, verbatim — never softened into \"nothing to show\".\n return <RefusalNotice error={error} className={className} />;\n }\n if (!card || reach === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (!card.external) {\n return (\n <p className={cn(\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\", className)}>\n {card.explanation ||\n \"You are a member of an organization here, so this portal is not yours — a portal is the scoped \" +\n \"view an OUTSIDER gets. You have the full application instead.\"}\n </p>\n );\n }\n\n if (sending && form) {\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{form.name}</span>\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-auto h-6 px-2 text-[11px]\" onClick={() => setSending(false)}>\n Back\n </Button>\n </header>\n <FormRunner\n form={form}\n onSubmitted={() => {\n setSending(false);\n void load();\n }}\n />\n </section>\n );\n }\n\n if (open) {\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <Peek tableId={tableId} recordId={open} onClose={() => setOpen(null)} />\n </section>\n );\n }\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: how many things are theirs, and the one thing they may do. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Shared with you</span>\n <span className=\"tabular-nums\">{reach.length}</span>\n {form ? (\n <Button size=\"sm\" className=\"ml-auto h-7 px-2 text-[11px]\" onClick={() => setSending(true)}>\n {form.submitLabel ?? form.name}\n </Button>\n ) : null}\n </header>\n\n {reach.length === 0 ? (\n // EMPTY, AND IT SAYS WHICH EMPTY. \"Nobody has shared anything with you\"\n // and \"the store would not tell us\" are different sentences, and a\n // person acts on them differently.\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n Nothing has been shared with you yet. {card.explanation} When somebody shares a record with you it\n appears here — this list is exactly what Visibility gave you, one record at a time, never an\n organization's list.\n </p>\n ) : (\n <ul className=\"flex min-h-0 flex-col gap-1 overflow-y-auto\">\n {reach.map((id) => (\n <li key={id}>\n <button\n type=\"button\"\n className=\"w-full truncate rounded border px-2 py-1.5 text-left text-xs hover:bg-muted\"\n onClick={() => setOpen(id)}\n >\n <PortalRow tableId={tableId} recordId={id} />\n </button>\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n}\n\n/**\n * One line for one record the outsider may see. It reads through the SAME read\n * door as everything else — there is no portal read path, because a second read\n * path is a second place for a visibility bug to live.\n */\nfunction PortalRow({ tableId, recordId }: { tableId: Uuid; recordId: Uuid }) {\n const client = useRecordsClient();\n const [title, setTitle] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void client.recordRead({ record_id: recordId }).then((answered) => {\n if (cancelled) return;\n if (!answered.ok) {\n setTitle(refusalLineForAPerson(answered.error));\n return;\n }\n const document = answered.data.document as Record<string, unknown>;\n const first = Object.values(document).find((v) => typeof v === \"string\" && v !== \"\");\n setTitle(typeof first === \"string\" ? first : recordId);\n });\n return () => {\n cancelled = true;\n };\n }, [client, recordId, tableId]);\n\n return <span>{title ?? \"…\"}</span>;\n}\n","\"use client\";\n\n// src/PublicViewPage.tsx — @ai-matrx/records-ui · SCR-24\n//\n// THE PUBLIC PAGE A SIGNED-OUT VISITOR LANDS ON, AND THE NOTE IT REFUSES TO\n// LEAVE OFF.\n//\n// VIS-32: a share, however generous, produces NO public address. A public\n// address exists only because somebody made a publish binding on purpose, and\n// the binding carries its own RENDER MODE — this page does not choose between\n// a list and a detail, it is TOLD.\n//\n// `iam.resolve_publish_binding` is the whole of the resolution, and three\n// different-looking situations deliberately resolve identically to NOTHING: an\n// address nobody ever made, an address that was revoked, and an address whose\n// lane was closed again. They are one 404, because an address that answered\n// differently for a revoked binding would be an existence oracle — \"this used\n// to be something\" is information a stranger should not get for free.\n//\n// D-15, AND IT IS NOT DECORATION. Nothing was scanned before this was listed:\n// there is no pre-listing scan, no quarantine, no report-and-takedown ranking.\n// `iam.world_publish_gap_notice()` is ONE function so the screen, the API, the\n// admission row and this page cannot drift into four different admissions of\n// the same gap — or into none. The note is carried on EVERY read and is shown\n// here every time, including when everything worked.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type ReadRow, type Uuid } from \"@ai-matrx/records/react\";\nimport type { Field, RecordsError, ResolvedPublishBinding } from \"@ai-matrx/records\";\nimport { Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { RecordValue } from \"./values\";\n\nexport interface PublicViewPageProps {\n /** The public address, exactly as it appears in the URL. */\n slug: string;\n className?: string | undefined;\n}\n\nexport function PublicViewPage({ slug, className }: PublicViewPageProps) {\n const client = useRecordsClient();\n const [binding, setBinding] = useState<ResolvedPublishBinding | null | \"none\">(null);\n const [rows, setRows] = useState<ReadRow[] | null>(null);\n const [fields, setFields] = useState<Field[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n /** D-15's sentence, read from the store even when a binding did not resolve. */\n const [gap, setGap] = useState<string | null>(null);\n\n const load = useCallback(async () => {\n // The gap notice is read FIRST and unconditionally: a page that only\n // admitted the gap on the happy path would be a page that stops admitting\n // it exactly when something is wrong.\n const notice = await client.worldPublishGapNotice();\n if (notice.ok) setGap(notice.data);\n\n const resolved = await client.resolvePublishBinding({ slug });\n if (!resolved.ok) {\n setError(resolved.error);\n return;\n }\n setError(null);\n const found = resolved.data[0];\n if (!found) {\n setBinding(\"none\");\n return;\n }\n setBinding(found);\n\n // The render mode says which read to do. It is the BINDING's decision, made\n // when it was published, not a guess this page makes from the shape of the\n // answer.\n if (found.render_mode === \"list\") {\n const listed = await client.list({ table_id: found.resource_id, limit: 100 });\n if (!listed.ok) {\n setError(listed.error);\n return;\n }\n setRows(listed.data.rows);\n const held = await client.fields({ table_id: found.resource_id });\n if (held.ok) setFields(held.data);\n return;\n }\n const read = await client.recordRead({ record_id: found.resource_id });\n if (!read.ok) {\n setError(read.error);\n return;\n }\n setRows([{ id: found.resource_id, document: read.data.document, level: \"viewer\", hidden: read.data.hidden } as ReadRow]);\n }, [client, slug]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n if (error) return <RefusalNotice error={error} className={className} />;\n if (binding === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (binding === \"none\") {\n // THE 404, AND IT IS THE SAME 404 FOR ALL THREE CAUSES. Nothing here hints\n // that this address ever existed.\n return (\n <main className={cn(\"mx-auto max-w-2xl py-16 text-center\", className)}>\n <h1 className=\"text-lg font-medium\">Nothing here</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n There is no public page at this address.\n </p>\n {gap ? <p className=\"mt-6 text-xs text-muted-foreground\">{gap}</p> : null}\n </main>\n );\n }\n\n return (\n <main className={cn(\"mx-auto flex max-w-2xl flex-col gap-3 py-8\", className)}>\n {/* One row. The namespace it was published under, and nothing restating it. */}\n <header className=\"flex items-baseline gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{binding.namespace ?? \"Published\"}</span>\n <span>{binding.render_mode === \"list\" ? `${rows?.length ?? 0} items` : \"Shared publicly\"}</span>\n </header>\n\n {rows === null ? (\n <Skeleton className=\"h-40 w-full\" />\n ) : rows.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">This page has nothing on it yet.</p>\n ) : (\n <ol className=\"flex flex-col gap-2\">\n {rows.map((row) => (\n <li key={row.id} className=\"rounded border p-3\">\n <PublicRow row={row} fields={fields} />\n </li>\n ))}\n </ol>\n )}\n\n {/* D-15, ON EVERY READ, INCLUDING THE HAPPY ONE. */}\n <footer className=\"mt-4 border-t pt-3 text-xs text-muted-foreground\">\n {binding.notice || gap || \"Nothing was scanned before this was listed.\"}\n </footer>\n </main>\n );\n}\n\n/**\n * One public row. It draws through the same `renderValue` as every other screen\n * in this package, so a unit and a format mean the same thing to a stranger as\n * they do to the person who typed the value.\n */\nfunction PublicRow({ row, fields }: { row: ReadRow; fields: Field[] | null }) {\n const document = (row.document ?? {}) as Record<string, unknown>;\n if (!fields) {\n const first = Object.entries(document).filter(([key]) => !key.startsWith(\"_\"));\n return (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-sm\">\n {first.map(([key, value]) => (\n <div key={key} className=\"contents\">\n <dt className=\"text-xs text-muted-foreground\">{key}</dt>\n <dd className=\"text-sm\">{String(value ?? \"\")}</dd>\n </div>\n ))}\n </dl>\n );\n }\n return (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1\">\n {fields.map((field) => (\n <div key={field.key} className=\"contents\">\n <dt className=\"text-xs text-muted-foreground\">{field.label}</dt>\n <dd className=\"text-sm\"><RecordValue field={field} value={document[field.key]} document={row.document} /></dd>\n </div>\n ))}\n </dl>\n );\n}\n","\"use client\";\n\n// src/EmbedFrame.tsx — @ai-matrx/records-ui · SCR-25\n//\n// PUTTING ONE OF OUR FORMS OR VIEWS ON SOMEBODY ELSE'S WEBSITE, WITHOUT HANDING\n// THEM A WAY INTO EVERYTHING ELSE.\n//\n// This component is two halves that must not be confused:\n//\n// · THE ISSUING HALF (`EmbedFrame`) runs on OUR side, signed in, for the\n// person who owns the form. It mints a token through\n// `custom.anon_token_issue` and shows the snippet to paste. The secret comes\n// back ONCE — only its digest is stored, so a database read, a backup or a\n// leaked dump cannot produce a working token — which is why this screen says\n// so out loud and offers to mint a new one rather than pretending it can\n// show the old one again.\n//\n// · THE HANDSHAKE (`useEmbedHandshake`) runs on THEIR page, inside the iframe.\n// It calls `custom.anon_token_verify` with the secret and the ORIGIN, and\n// the store decides. It is the store that decides, and the check is EXACT —\n// `https://example.com.evil.test` passes a suffix match and fails this one.\n//\n// THE THREE THINGS THE STORE REFUSES, AND THIS SCREEN NAMES BEFORE IT ASKS:\n// 1. A token with no origin list. An empty list does not mean \"everywhere\" —\n// it is refused at issue, because a token that works from any page on the\n// internet includes an attacker's.\n// 2. A token carrying both read and write. One credential, one decision; the\n// second is always the one nobody meant to grant.\n// 3. A write token for a form nobody published. Closed by default.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { AnonTokenBinding, RecordsError } from \"@ai-matrx/records\";\nimport { Button, Input, Skeleton, Textarea, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi, useTableRights } from \"./host\";\nimport { useTable } from \"@ai-matrx/records/react\";\n\nexport interface EmbedFrameProps {\n /** The Table whose rights decide whether an embed may be issued at all. */\n tableId: Uuid;\n /** A write embed names the form it writes into. */\n formId?: Uuid | null | undefined;\n /** A read embed names the saved view or the record it shows. */\n savedViewId?: Uuid | null | undefined;\n recordId?: Uuid | null | undefined;\n /** Where the embedded page is served from — the `src` of the iframe. */\n embedUrl: string;\n className?: string | undefined;\n}\n\nexport function EmbedFrame({\n tableId,\n formId,\n savedViewId,\n recordId,\n embedUrl,\n className,\n}: EmbedFrameProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const [origins, setOrigins] = useState(\"\");\n const [secret, setSecret] = useState<string | null>(null);\n const [tokenId, setTokenId] = useState<Uuid | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n\n // A write embed needs a form; a read embed needs a view or a record. The mode\n // is therefore a FACT about what was passed, never a toggle somebody can set\n // to a value the store will refuse.\n const mode: \"read\" | \"write\" = formId ? \"write\" : \"read\";\n\n const parsed = origins\n .split(/[\\s,]+/)\n .map((o) => o.trim())\n .filter((o) => o.length > 0);\n\n const issue = useCallback(async () => {\n setBusy(true);\n setError(null);\n const minted = await client.anonTokenIssue({\n mode,\n allowedOrigins: parsed,\n formId: formId ?? null,\n savedViewId: savedViewId ?? null,\n recordId: recordId ?? null,\n });\n setBusy(false);\n if (!minted.ok) {\n setError(minted.error);\n return;\n }\n setSecret(minted.data.secret);\n setTokenId(minted.data.token_id);\n host.notify?.success(\"Embed token issued. Copy it now — it is never shown again.\");\n }, [client, formId, host, mode, parsed, recordId, savedViewId]);\n\n const revoke = useCallback(async () => {\n if (!tokenId) return;\n setBusy(true);\n const done = await client.anonTokenRevoke({ token_id: tokenId });\n setBusy(false);\n if (!done.ok) {\n setError(done.error);\n return;\n }\n setSecret(null);\n setTokenId(null);\n }, [client, tokenId]);\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (table.loading) return <Skeleton className={cn(\"h-48 w-full\", className)} />;\n\n // Issuing an embed hands a stranger a way in, so the store asks for `admin`\n // on the Table. Without it there is no control here at all — not a greyed\n // one — and the reason is shown.\n if (!rights.admin) {\n return (\n <p className={cn(\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\", className)}>\n {rights.why(\"structure\")} Issuing an embed opens a way in from somebody else's website, so the store asks for\n the admin level on this table before it will mint one.\n </p>\n );\n }\n\n const snippet = secret\n ? `<iframe src=\"${embedUrl}#t=${secret}\" style=\"width:100%;height:640px;border:0\" loading=\"lazy\"></iframe>`\n : null;\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: what kind of embed this is, and where it may run. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Embed</span>\n <span>{mode === \"write\" ? \"a form people can send\" : \"a read-only view\"}</span>\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n <label className=\"flex flex-col gap-1 text-xs\">\n <span className=\"text-muted-foreground\">Sites this embed works on</span>\n <Input\n aria-label=\"Allowed origins\"\n className=\"h-8 text-xs\"\n placeholder=\"https://example.com\"\n value={origins}\n onChange={(e) => setOrigins(e.target.value)}\n />\n {/* Said BEFORE the refusal, because a person should not have to be\n refused to learn the rule. */}\n <span className=\"text-[11px] text-muted-foreground\">\n Name every site, scheme and host and port. An empty list is refused rather than quietly meaning\n \"anywhere\": a token that works from any page on the internet includes an attacker's. The match is\n exact, so <code>example.com.evil.test</code> will not pass.\n </span>\n </label>\n\n {!secret ? (\n <Button size=\"sm\" className=\"self-start\" disabled={busy || parsed.length === 0} onClick={() => void issue()}>\n {busy ? \"Issuing…\" : \"Issue embed\"}\n </Button>\n ) : (\n <>\n <p className=\"rounded border px-2 py-1 text-xs text-muted-foreground\">\n Copy this now. Only its digest is stored, so nobody — including us — can show it to you again;\n if it is lost, issue a new one and replace the old.\n </p>\n <Textarea aria-label=\"Embed snippet\" readOnly rows={3} className=\"font-mono text-[11px]\" value={snippet ?? \"\"} />\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => void navigator.clipboard?.writeText(snippet ?? \"\")}\n >\n Copy\n </Button>\n <Button size=\"sm\" variant=\"ghost\" disabled={busy} onClick={() => void revoke()}>\n Revoke\n </Button>\n </div>\n </>\n )}\n </section>\n );\n}\n\n/**\n * THE OTHER HALF, RUNNING INSIDE THE IFRAME ON SOMEBODY ELSE'S PAGE.\n *\n * It hands the secret and this page's own origin to the store and uses whatever\n * comes back. It decides nothing itself: a handshake that checked the origin in\n * JavaScript would be a handshake an attacker can edit.\n *\n * `origin` is taken from `window.location.origin` by default rather than from a\n * prop, because a prop is a value the embedding page controls and the origin\n * must not be.\n */\nexport function useEmbedHandshake(args: { secret: string; requiredMode?: \"read\" | \"write\"; origin?: string }): {\n binding: AnonTokenBinding | null;\n error: RecordsError | null;\n loading: boolean;\n} {\n const client = useRecordsClient();\n const [binding, setBinding] = useState<AnonTokenBinding | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [loading, setLoading] = useState(true);\n const origin = args.origin ?? (typeof location === \"undefined\" ? \"\" : location.origin);\n const { secret, requiredMode } = args;\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n setError(null);\n void client\n .anonTokenVerify({ secret, origin, requiredMode: requiredMode ?? null })\n .then((answered) => {\n if (cancelled) return;\n setLoading(false);\n if (!answered.ok) {\n setError(answered.error);\n setBinding(null);\n return;\n }\n setBinding(answered.data);\n });\n return () => {\n cancelled = true;\n };\n }, [client, origin, requiredMode, secret]);\n\n return { binding, error, loading };\n}\n","\"use client\";\n\n// src/RecordsMount.tsx — @ai-matrx/records-ui\n//\n// THE ONE LINE A HOST ROUTE WRITES. `<RecordsProvider>` from @ai-matrx/records\n// and `<RecordsUiProvider>` from this package are two providers that must be\n// nested in one order, every time — so a route that got the order wrong would\n// fail with \"useRecordsClient was called outside <RecordsProvider>\" at the\n// bottom of a screen nobody was looking at. This mounts both, in the one order\n// that is correct, so a route file stays a mount and nothing more.\n//\n// THE RIGHTS QUESTION — AND THE ANSWER THAT USED TO BE HERE.\n//\n// `storeDecidesRights` returned `{admin: true, comment: true, write: true}` for\n// every non-kernel table, for everybody, on the reasoning that the doors are\n// the authority and a refusal would be shown verbatim when it came. The\n// sixth-pass verdict measured the cost of that reasoning: a colleague at viewer\n// double-clicked a cell, got a live editor, typed a value, pressed Enter, and\n// was told only then that she may not write. \"The permission is right; the\n// screen told her she could.\"\n//\n// It is not a guess any more. The read door has always answered the reader's\n// level on the table and the client now carries it (`Table.your_level`), so\n// this function ASKS instead of assuming, `letTheStoreDecideRights` still means\n// what it says, and a host that binds nothing gets the same honest answer\n// rather than every control absent. Kernel Tables (REC-27) keep their own\n// exclusion: the nine Tables the platform ships are not administered from a\n// person's screen at any level.\n\nimport type { ReactNode } from \"react\";\nimport type { RecordsActor, RecordsConfig, RecordsDataSource, Table, Uuid } from \"@ai-matrx/records\";\nimport { RecordsProvider } from \"@ai-matrx/records/react\";\nimport { RecordLabelProvider } from \"./labels\";\n\nimport { NO_RIGHTS, RecordsUiProvider, type RecordsUiHost, type TableRights } from \"./host\";\n\nexport const STORE_DECIDES_REASON =\n \"This host offers exactly what the record store says this person may do: the level comes back with \" +\n \"the table on the read door, so a control they cannot use is never drawn in the first place.\";\n\nexport { KERNEL_REASON } from \"./rights\";\n\n/**\n * DEPRECATED, and kept only so a host that imported it still compiles.\n *\n * It used to answer yes to everything for every non-kernel table. It cannot\n * answer honestly at all, because the honest answer needs a door call and this\n * signature is synchronous — which is exactly why the guess was here. Binding\n * it now would be binding a port that OVERRIDES the store's real answer, so it\n * returns the not-yet-answered set and every caller should simply stop passing\n * a `rights` port: unbound is the honest path (`useTableRights`).\n */\nexport function storeDecidesRights(_table: Table): TableRights {\n return NO_RIGHTS;\n}\n\nexport interface RecordsMountProps {\n /** The store config: the host's session-carrying client, the actor, the organization. */\n config: RecordsConfig;\n /** What this host binds on top — links, toasts, uploads, rights. */\n host?: RecordsUiHost | undefined;\n /**\n * Use `storeDecidesRights` when the host binds no `rights` of its own. Left\n * off, an unbound host gets `NO_RIGHTS` and every administering control is\n * absent with its reason.\n */\n letTheStoreDecideRights?: boolean | undefined;\n children: ReactNode;\n}\n\nexport function RecordsMount({\n config,\n host,\n letTheStoreDecideRights,\n children,\n}: RecordsMountProps) {\n // `letTheStoreDecideRights` means what it says and now needs no port at all:\n // with nothing bound, `useTableRights` asks `custom.my_levels` and draws what\n // the answer allows. A port bound here would OVERRIDE that answer.\n const bound: RecordsUiHost = { ...(host ?? {}) };\n void letTheStoreDecideRights;\n return (\n <RecordsProvider config={config}>\n <RecordsUiProvider value={bound}>\n {/* WHAT AN ID IS CALLED. A choice and a relation are stored as the id of\n another record, so every read-only surface needs the same answer to\n \"what is that record called\" — resolved once here rather than once\n per cell, and never drawn as the id itself. */}\n <RecordLabelProvider>{children}</RecordLabelProvider>\n </RecordsUiProvider>\n </RecordsProvider>\n );\n}\n\n/**\n * The actor a signed-in person is. `user` is the store's own word (the closed\n * ACTOR_VOCABULARY is `user` · `agent` · `system`), and AGT-N-4 means an agent\n * acting for this person carries exactly this authority and no other.\n */\nexport function personActor(userId: Uuid | null | undefined): RecordsActor {\n return userId ? { actor: \"user\", user_id: userId } : { actor: \"user\" };\n}\n\n/**\n * A supabase-js client AS this package's data seam.\n *\n * `RecordsDataSource` is deliberately a small structural subset of\n * `SupabaseClient` — the package holds no key and opens no connection, the host\n * hands it a client that already carries the person's session.\n *\n * IT IS NOT AN IDENTITY CAST, and it cost a live screen to learn why\n * (2026-09-19, /data-v2's first load): the port's `rpc(fn, args, { schema })`\n * says the schema OUT LOUD, because every door of this store is `custom.<name>`\n * and every door of the trust layer is `iam.<name>`. supabase-js's own\n * `rpc(fn, args, options)` has no `schema` option at all — its third argument is\n * `{ head, get, count }` — so a client passed straight through silently asked\n * its default PostgREST profile and the store answered, correctly and uselessly,\n * \"Could not find the function public.table_kernel_id ... PGRST202\". The schema\n * is chosen the one way supabase-js offers: `client.schema(name).rpc(...)`.\n *\n * `schema(name).from(table)` already agrees structurally and is passed through.\n *\n * `fallbackSchema` is the profile a call that says NOTHING is sent to. No caller\n * in `@ai-matrx/records` omits the option — `callDoor` always says `custom` and\n * `trustDoor` always says `iam` — so it never fires today; it exists so that a\n * call which one day forgets lands on the store rather than silently on\n * `public`. It is a FALLBACK and not the answer: a version of this adapter that\n * sent EVERY door to one fixed schema would route the `iam` trust doors (the\n * external principal, the publish binding) into `custom` and get a PGRST202\n * naming the wrong schema.\n *\n * The cast itself stays HERE, once, where it is explained: a generated\n * `Database` type makes `schema().from().select()` enormous, and a host app that\n * passes its client straight into `config` gets `TS2589: Type instantiation is\n * excessively deep and possibly infinite` in its own build (matrx-frontend,\n * 2026-09-18, on all three campaign routes at once).\n */\nexport function recordsDataSource(client: object, fallbackSchema = \"custom\"): RecordsDataSource {\n const supabase = client as unknown as {\n rpc: (fn: string, args: Record<string, unknown>) => PromiseLike<unknown>;\n schema: (name: string) => {\n rpc: (fn: string, args: Record<string, unknown>) => PromiseLike<unknown>;\n from: (table: string) => unknown;\n };\n };\n return {\n rpc(fn, args, options) {\n const on = supabase.schema(options?.schema ?? fallbackSchema);\n return on.rpc(fn, args) as ReturnType<RecordsDataSource[\"rpc\"]>;\n },\n schema(name) {\n return supabase.schema(name) as ReturnType<RecordsDataSource[\"schema\"]>;\n },\n };\n}\n","\"use client\";\n\n// src/TablesHome.tsx — @ai-matrx/records-ui\n//\n// THE LIST OF A PERSON'S TABLES — AND IT IS NEVER A FLAT PILE.\n//\n// Four lanes, always, in this order: mine · my organization · system ·\n// community. The lane a Table is in is read off the Table record itself and is\n// not a guess:\n//\n// · mine — `visibility = 'personal'` (the store's own enum word)\n// · organization — `visibility = 'internal'`\n// · system — `is_kernel` (REC-27: the Tables the platform ships)\n// · community — `visibility` is `link` or `public`\n//\n// A lane with nothing in it SAYS SO in one sentence that tells a person how it\n// fills up. An empty heading with nothing under it reads as \"broken\"; this\n// reads as \"nothing here yet, and here is what puts something here\".\n//\n// Creating and importing are both here, because both make a Table, and they go\n// through the store's own doors — `declareTable` walks Home → table_declare →\n// Fields, and the import mounts `ImportWizard` on the Table it just declared.\n\nimport { useCallback, useState } from \"react\";\nimport type { Table, Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient, useTables } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { BasicInput, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\n\nimport { RefusalNotice } from \"./Refusal\";\nimport { ImportWizard } from \"./ImportWizard\";\nimport { declareTable, tokenFor } from \"./createTable\";\nimport { tableName } from \"./names\";\n\nexport type TableLane = \"mine\" | \"organization\" | \"system\" | \"community\" | \"app\";\n\n/** The five lanes, in the order a person reads them. Never a flat list. */\nexport const TABLE_LANES: readonly TableLane[] = [\"mine\", \"organization\", \"system\", \"community\", \"app\"];\n\nexport const LANE_TITLE: Record<TableLane, string> = {\n mine: \"Mine\",\n organization: \"My organization\",\n system: \"System\",\n community: \"Community\",\n app: \"Kept by the app\",\n};\n\n/**\n * THE APP'S OWN BOOKKEEPING, MARKED AS SUCH.\n *\n * A saved view, a comment, a queued action and a form are records in Tables\n * this package declares in the organization's own store (`systemTable.ts`) —\n * which is what makes them shareable, historied and agent-writable. The price\n * is that using the product creates Tables in the person's own list: the\n * verdict of 19 September watched \"Saved views · 9 fields · records_ui_view\"\n * appear among somebody's data, and then \"Comments\" appear beside it the\n * moment a record was opened.\n *\n * They are not hidden — hiding a real Table from the person who owns it is its\n * own lie, and they hold that person's comments. They get their own lane,\n * last, with a sentence that says what they are.\n */\nconst APP_TABLE_PREFIX = \"records_ui_\";\n\n/** What fills an empty lane. A heading with nothing under it must still teach. */\nexport const LANE_EMPTY: Record<TableLane, string> = {\n mine: \"Nothing of your own yet. New table makes one that only you can see.\",\n organization:\n \"No tables shared across your organization yet. A table you make is yours until you change its visibility to internal.\",\n system: \"The platform's own tables are not in this organization's store.\",\n community: \"Nothing shared beyond your organization. A table published by link or to the world lands here.\",\n app:\n \"The app has not needed a table of its own in this organization yet. Saving a view, writing a \" +\n \"comment or building a form makes one, and it appears here rather than among your own data.\",\n};\n\n/** Which lane one Table belongs to, from the record's own columns. */\nexport function laneFor(table: Table): TableLane {\n if (table.is_kernel) return \"system\";\n if ((table.slug ?? \"\").startsWith(APP_TABLE_PREFIX)) return \"app\";\n if (table.visibility === \"public\" || table.visibility === \"link\") return \"community\";\n if (table.visibility === \"personal\") return \"mine\";\n return \"organization\";\n}\n\nexport interface TablesHomeProps {\n /** Where a table opens. Absent and the card is a plain row with no pretend link. */\n onOpenTable?: ((tableId: Uuid) => void) | undefined;\n className?: string | undefined;\n}\n\nexport function TablesHome({ onOpenTable, className }: TablesHomeProps) {\n const client = useRecordsClient();\n const tables = useTables();\n const [creating, setCreating] = useState(false);\n const [name, setName] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<RecordsError | null>(null);\n const [importInto, setImportInto] = useState<Uuid | null>(null);\n\n const create = useCallback(\n async (mode: \"open\" | \"import\") => {\n const trimmed = name.trim();\n if (!trimmed) return;\n setBusy(true);\n setError(null);\n const result = await declareTable(client, { name: trimmed, slug: tokenFor(trimmed) });\n setBusy(false);\n if (!result.ok) {\n setError(result.error);\n return;\n }\n setName(\"\");\n setCreating(false);\n tables.reload();\n if (mode === \"import\") setImportInto(result.data);\n else onOpenTable?.(result.data);\n },\n [client, name, onOpenTable, tables],\n );\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-4\", className)}>\n {/* One row. The page's own header already says where you are. */}\n <div className=\"flex items-center gap-2\">\n {creating ? (\n <>\n <BasicInput\n autoFocus\n value={name}\n placeholder=\"Table name\"\n onChange={(e) => setName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") void create(\"open\");\n if (e.key === \"Escape\") setCreating(false);\n }}\n className=\"h-8 max-w-xs\"\n />\n <Button size=\"sm\" disabled={busy || name.trim().length === 0} onClick={() => void create(\"open\")}>\n {busy ? \"Declaring…\" : \"Create\"}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled={busy || name.trim().length === 0}\n onClick={() => void create(\"import\")}\n >\n Create and import a file\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setCreating(false)}>\n Cancel\n </Button>\n </>\n ) : (\n <Button size=\"sm\" onClick={() => setCreating(true)}>\n New table\n </Button>\n )}\n </div>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {importInto ? (\n <div className=\"rounded-md border p-3\">\n <ImportWizard tableId={importInto} onDone={() => setImportInto(null)} />\n <Button size=\"sm\" variant=\"ghost\" className=\"mt-2\" onClick={() => onOpenTable?.(importInto)}>\n Open the table\n </Button>\n </div>\n ) : null}\n\n {tables.error ? <RefusalNotice error={tables.error} /> : null}\n {tables.loading && !tables.data ? (\n <div className=\"space-y-2\">\n <Skeleton className=\"h-6 w-40\" />\n <Skeleton className=\"h-16 w-full\" />\n </div>\n ) : null}\n\n {tables.data\n ? TABLE_LANES.map((lane) => {\n const rows = tables.data!.filter((t) => laneFor(t) === lane);\n return (\n <section key={lane} className=\"space-y-1.5\">\n <div className=\"flex items-baseline gap-2\">\n <h2 className=\"text-sm font-medium\">{LANE_TITLE[lane]}</h2>\n <span className=\"text-xs opacity-60\">{rows.length}</span>\n </div>\n {rows.length === 0 ? (\n <p className=\"text-xs opacity-70\">{LANE_EMPTY[lane]}</p>\n ) : (\n <ul className=\"grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3\">\n {rows.map((table) => (\n <li key={table.id}>\n <button\n type=\"button\"\n onClick={() => onOpenTable?.(table.id)}\n className={cn(\n \"w-full rounded-md border px-3 py-2 text-left transition-colors\",\n onOpenTable ? \"hover:bg-accent\" : \"cursor-default\",\n )}\n >\n {/* The Table's NAME, never its token: `records_ui_view`\n and `v78_widget2` are machine names and no product\n a person judges puts one on a card. */}\n <span className=\"block truncate text-sm\">{tableName(table)}</span>\n <span className=\"block truncate text-xs opacity-60\">\n {table.fields.length} field{table.fields.length === 1 ? \"\" : \"s\"}\n {table.label_plural && table.label_plural !== table.name\n ? ` · ${table.label_plural}`\n : \"\"}\n </span>\n </button>\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n })\n : null}\n </div>\n );\n}\n","// src/createTable.ts — @ai-matrx/records-ui\n//\n// DECLARING A TABLE, THE WAY THE STORE MAKES YOU DECLARE ONE.\n//\n// REC-1: a Table has to live somewhere. `custom._table_shape_guard` refuses a\n// Table with no Home in those words (\"a table has to live somewhere - give it a\n// home\"), so the sequence is fixed and this module is the one place that walks\n// it for a person-made table:\n//\n// 1. `personKernelId()` — the kernel Table a Home record lives in.\n// 2. `record_write` — the Home record.\n// 3. `table_declare` — the Table, under that Home.\n// 4. one `record_write` per Field, into the field kernel.\n//\n// Nothing here works around a guard; every step is a door. A Field the store\n// refused stops the sequence and hands back the store's own sentence, because a\n// Table that quietly lost a column is the silent failure this package exists to\n// prevent.\n\nimport type { RecordsClient } from \"@ai-matrx/records/core\";\nimport type { RecordsError, Uuid } from \"@ai-matrx/records\";\n\n/** One Field a person asked for, in the store's own behaviour words (FLD-1). */\nexport interface NewFieldSpec {\n key: string;\n label: string;\n /** A parity type — the thirteen come from the store, see `PARITY_FIELD_TYPES`. */\n type: string;\n sort?: number;\n required?: boolean;\n multi?: boolean;\n config?: Record<string, unknown>;\n}\n\nexport interface NewTableSpec {\n name: string;\n /** The token the Table is addressed by. Derived from the name when absent. */\n slug?: string;\n labelSingular?: string;\n labelPlural?: string;\n /** The Field whose value is the record's title (REC-2). Defaults to the first Field. */\n titleField?: string;\n fields?: NewFieldSpec[];\n}\n\nexport type DeclareResult =\n | { ok: true; data: Uuid }\n | { ok: false; error: RecordsError };\n\n/** `My Sales Pipeline` → `my_sales_pipeline`. A token, never a sentence. */\nexport function tokenFor(name: string): string {\n return (\n name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 48) || \"table\"\n );\n}\n\n/** The one Field a Table cannot be declared without: something to call a record. */\n/**\n * WHY THE FIRST FIELD IS NOT REQUIRED.\n *\n * It was, and the cost showed up the moment the grid could add a row: \"New\n * record\" writes an empty record and puts you in the first cell, and the store\n * correctly refused every one of them — `REC-51: Title is required` — so the\n * one gesture that makes a grid feel like a grid never worked on a table a\n * person had just made. A title is what makes a record a CHIP (REC-2), which is\n * a fact about how it is shown, not a promise it can never be written without;\n * an organization that wants it demanded says so in the field editor, and the\n * store then enforces it for everyone.\n */\nexport const DEFAULT_FIELDS: NewFieldSpec[] = [\n { key: \"title\", label: \"Title\", type: \"text\", sort: 10, required: false },\n];\n\nexport async function declareTable(\n client: RecordsClient,\n spec: NewTableSpec,\n): Promise<DeclareResult> {\n const fields = spec.fields && spec.fields.length > 0 ? spec.fields : DEFAULT_FIELDS;\n const slug = spec.slug ?? tokenFor(spec.name);\n const titleField = spec.titleField ?? fields[0]!.key;\n\n const personKernel = await client.personKernelId();\n if (!personKernel.ok) return personKernel;\n\n const home = await client.recordWrite({\n table_id: personKernel.data,\n data: { name: `${spec.name} Home` },\n });\n if (!home.ok) return home;\n\n const table = await client.tableDeclare({\n homeId: home.data,\n spec: {\n name: spec.name,\n slug,\n type: \"entity\",\n label_singular: spec.labelSingular ?? spec.name,\n label_plural: spec.labelPlural ?? spec.name,\n display: \"list\",\n weight: \"light\",\n ordered: false,\n row_order: \"manual\",\n title_field: titleField,\n retention_days: 365,\n // AGT-1: a table a person made is agent-writable by declaration; the\n // organization turns it off, never this package.\n agent_writable: true,\n default_sort: [{ field: titleField, direction: \"asc\" }],\n fields: fields.map((f) => ({ name: f.key })),\n },\n });\n if (!table.ok) return table;\n\n const written = await addFields(client, table.data, fields);\n if (!written.ok) return written;\n return { ok: true, data: table.data };\n}\n\n/** Write Field records for an existing Table. Used by the create path and by import. */\nexport async function addFields(\n client: RecordsClient,\n tableId: Uuid,\n fields: NewFieldSpec[],\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const fieldKernel = await client.fieldKernelId();\n if (!fieldKernel.ok) return fieldKernel;\n\n for (const field of fields) {\n const result = await client.recordWrite({\n table_id: fieldKernel.data,\n data: {\n key: field.key,\n label: field.label,\n type: field.type,\n sort: field.sort ?? 100,\n required: field.required ?? false,\n multi: field.multi ?? false,\n dated: false,\n rules: [],\n config: field.config ?? {},\n source: \"manual\",\n depends_on: [],\n sensitivity: \"internal\",\n source_config: {},\n context_policy: \"include\",\n applies_to_types: [],\n entity_definition_id: tableId,\n },\n });\n if (!result.ok) return result;\n }\n return { ok: true, data: tableId };\n}\n","\"use client\";\n\n// src/TablePage.tsx — @ai-matrx/records-ui\n//\n// ONE TABLE'S WHOLE PAGE, assembled from this package's own components and\n// nothing else. A host route mounts this and passes the table token; every\n// screen below it is the canonical one, so a table reached from /data, from a\n// portal or from an agent's link looks and behaves identically.\n//\n// WHAT IS ON IT, and which contract row each part answers:\n// ViewBar (SCR-7) the saved views, and saving a new one\n// ViewSwitcher (SCR-6) grid · kanban · calendar · gallery over the SAME records\n// RecordForm (SCR-N-1) adding a record\n// FieldEditor (SCR-9) adding or retyping a field\n// TableSettings (SCR-3/4/5) rename, reorder, retype, delete, proposals\n// ActionInbox (SCR-11) approvals, assignments and agent proposals\n// Peek (SCR-N-3) a record, opened in place\n// HistoryPanel (SCR-17) that record's own versioned timeline\n// CommentThread (SCR-18) that record's comments\n// ExportMenu (SCR-31) the same bytes a script would produce\n// ImportWizard (SCR-10) rows in through the one write door\n//\n// ONE PANEL AT A TIME. The right-hand rail shows exactly one of settings,\n// inbox, import, the new-field editor or the opened record — a page that opens\n// four rails at once is a page nobody can read.\n\nimport { useCallback, useState } from \"react\";\nimport { viewPatchDocument, type SavedView, type SavedViewSpec } from \"./views\";\nimport type { Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient, useTable } from \"@ai-matrx/records/react\";\nimport { Button, Separator, Skeleton, cn } from \"@ai-matrx/design-system\";\n\nimport { ActionInbox } from \"./ActionInbox\";\nimport { CommentThread } from \"./CommentThread\";\nimport { ExportMenu } from \"./ExportMenu\";\nimport { FieldEditor } from \"./FieldEditor\";\nimport { HistoryPanel } from \"./HistoryPanel\";\nimport { ImportWizard } from \"./ImportWizard\";\nimport { Peek } from \"./Peek\";\nimport { RecordForm } from \"./RecordForm\";\nimport { FormsPanel } from \"./FormsPanel\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { ShareControl } from \"./ShareControl\";\nimport { TableSettings } from \"./TableSettings\";\nimport { ViewBar } from \"./ViewBar\";\nimport { ViewSwitcher } from \"./ViewSwitcher\";\nimport { useTableRights } from \"./host\";\nimport { tableName } from \"./names\";\nimport { useRecordVersion } from \"./systemTable\";\n\ntype Rail = \"none\" | \"settings\" | \"inbox\" | \"import\" | \"field\" | \"record\" | \"new-record\" | \"forms\";\n\nexport interface TablePageProps {\n tableId: Uuid;\n /** Rows per page for every layout. */\n pageSize?: number | undefined;\n /**\n * The views this table should have. Each one whose NAME the table does not\n * hold yet is saved the first time the bar loads, and a name a person has\n * since tweaked is never overwritten. Left out, `DEFAULT_VIEW_NAME` below is\n * used — see why that default is not optional.\n */\n seedViews?: SavedViewSpec[] | undefined;\n /**\n * What a person does when the table is not theirs to see — switch\n * organization, go back to the list. Absent, the screen still SAYS what\n * happened; it just has no button to offer, which is honest and is never a\n * blank frame.\n */\n onLeave?: (() => void) | undefined;\n /** The word on that button. Defaults to \"Back to your tables\". */\n leaveLabel?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * THE SENTENCE A TABLE YOU CANNOT SEE SAYS.\n *\n * Measured on the real screen (independent verdict, 19 September): opening a\n * table's page while another organization was active left the main area's text\n * \"literally the empty string\" after eighteen seconds — no sentence, no\n * spinner, no console error. A made-up id did the same. The cause is exactly\n * one line of this file: `custom.table_list` correctly answers the tables this\n * person can see in THIS organization, the table is not among them, so\n * `useTable` answers `{ data: null, error: null }` — not a refusal, just\n * absence — and the page rendered a skeleton for ever.\n *\n * Absence is an ANSWER and it gets a sentence. It deliberately does not say\n * whether the table exists: this person cannot see it, and which of the two it\n * is is not theirs to learn.\n */\nexport const TABLE_NOT_REACHABLE =\n \"This table is not in the organization you are working in, so there is nothing here to show. \" +\n \"Switch to the organization that owns it and open it again — or it may have been deleted.\";\n\n/**\n * THE VIEW EVERY TABLE HAS, AND WHY IT IS NOT OPTIONAL.\n *\n * A view is a record, so a table nobody has saved a view for has none — and\n * this page then renders its own honest sentence (\"Waiting for this table's\n * views\") and NO RECORDS AT ALL. Measured on 2026-09-19 by walking the real\n * product: declare a table, write a record, open the table — and the record is\n * not on the screen, with the only remedy being a control the person has no\n * reason to press. That is a dead end on the first table anybody makes.\n *\n * So the page seeds one: every record, newest work first, as a grid. It is an\n * ordinary saved view record like any other — renamable, re-sortable,\n * deletable — not a hidden built-in mode, because a \"special\" default view is a\n * second kind of view that every feature after it has to know about.\n */\nexport const DEFAULT_VIEW_NAME = \"All records\";\n\nfunction defaultView(tableId: Uuid): SavedViewSpec {\n return { name: DEFAULT_VIEW_NAME, subject: tableId, layout: \"grid\", isDefault: true };\n}\n\nexport function TablePage({\n tableId,\n pageSize = 100,\n seedViews,\n onLeave,\n leaveLabel = \"Back to your tables\",\n className,\n}: TablePageProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const organizationId = useRecordsClient().config.organizationId;\n const [view, setView] = useState<SavedView | null>(null);\n const [rail, setRail] = useState<Rail>(\"none\");\n const [openRecord, setOpenRecord] = useState<Uuid | null>(null);\n // The view record's own version at load, so two tabs tweaking one view are\n // TOLD — and moved forward after every save, so ONE person switching layout\n // twice is not told they conflicted with themselves.\n const viewVersion = useRecordVersion(view?.id ?? null);\n\n const show = (next: Rail) => setRail((current) => (current === next ? \"none\" : next));\n\n /**\n * A change the switcher made — the layout, the kanban's grouping Field, the\n * calendar's date Field — saved onto the VIEW RECORD, which is what makes it\n * remembered per saved view rather than per page load. The local copy moves\n * first so the board redraws at once; the store is the one that keeps it.\n */\n const patchView = useCallback(\n async (patch: Partial<SavedViewSpec>) => {\n const current = view;\n if (!current) return;\n setView({ ...current, ...patch });\n const document = viewPatchDocument(patch);\n if (Object.keys(document).length === 0) return;\n const written = await client.recordUpdate({\n record_id: current.id,\n patch: document,\n ...(viewVersion.version === null ? {} : { expectedVersion: viewVersion.version }),\n });\n if (written.ok) viewVersion.note(written.data);\n },\n [client, view, viewVersion],\n );\n\n if (table.error) return <RefusalNotice error={table.error} />;\n if (table.loading) return <Skeleton className=\"h-40 w-full\" />;\n if (!table.data) {\n // NOT a blank frame, and not a spinner that never ends.\n return (\n <div className={cn(\"flex flex-col items-start gap-2 rounded-md border border-dashed p-6\", className)}>\n <p className=\"text-sm font-medium\">This table is not here</p>\n <p className=\"max-w-prose text-xs text-muted-foreground\">{TABLE_NOT_REACHABLE}</p>\n {onLeave ? (\n <Button size=\"sm\" variant=\"outline\" onClick={onLeave}>\n {leaveLabel}\n </Button>\n ) : null}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex min-h-0 gap-4\", className)}>\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n {/* One row of controls. The route's own header already carries the name. */}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <ViewBar\n tableId={tableId}\n onActiveView={setView}\n seed={seedViews ?? [defaultView(tableId)]}\n className=\"min-w-0 flex-1\"\n />\n {/* ONE \"New record\" ON SCREEN, EVER. The grid carries its own — it\n adds a row and puts you straight into the first cell, which is the\n gesture a person expects — so this page's button would be a second\n control for one thing (and was: the walk found two buttons of the\n same name in one header). It exists for the layouts that have no\n cells to type into. */}\n {rights.write && view && view.layout !== \"grid\" ? (\n <Button size=\"sm\" onClick={() => show(\"new-record\")}>\n New record\n </Button>\n ) : null}\n {rights.structure ? (\n <>\n <Button size=\"sm\" variant=\"outline\" onClick={() => show(\"field\")}>\n Add field\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"settings\")}>\n Settings\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"import\")}>\n Import\n </Button>\n </>\n ) : null}\n {/* PRODUCTS row 1. A form is a view on THIS table, so it opens in this\n table's own rail beside its settings and its inbox — never a\n second place in the app to go looking for it. */}\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"forms\")}>\n Forms\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"inbox\")}>\n Inbox\n </Button>\n {/* SCR-N-5. A Table is a record, so the table screen shares through the\n same door and the same dialog a record does. */}\n <ShareControl\n kind=\"table\"\n organizationId={organizationId}\n subjectId={tableId}\n name={table.data?.name}\n may={rights.share}\n />\n <ExportMenu tableId={tableId} />\n </div>\n\n {view ? (\n <ViewSwitcher\n view={view}\n pageSize={pageSize}\n onViewChange={(patch) => void patchView(patch)}\n {...(rights.write ? { onNewRecordForm: () => setRail(\"new-record\") } : {})}\n onOpenRecord={(recordId) => {\n setOpenRecord(recordId);\n setRail(\"record\");\n }}\n />\n ) : (\n <p className=\"text-xs opacity-70\">\n Waiting for {tableName(table.data)}'s views. The bar above saves the first one.\n </p>\n )}\n </div>\n\n {rail === \"none\" ? null : (\n <aside className=\"w-[26rem] shrink-0 overflow-y-auto rounded-md border p-3\">\n {rail === \"settings\" ? (\n <TableSettings\n tableId={tableId}\n {...(onLeave ? { onDeleted: onLeave } : {})}\n />\n ) : null}\n {rail === \"inbox\" ? (\n <ActionInbox\n tableId={tableId}\n onOpenRecord={(recordId) => {\n setOpenRecord(recordId);\n setRail(\"record\");\n }}\n />\n ) : null}\n {rail === \"forms\" ? <FormsPanel tableId={tableId} /> : null}\n {rail === \"import\" ? <ImportWizard tableId={tableId} onDone={() => setRail(\"none\")} /> : null}\n {rail === \"field\" ? (\n <FieldEditor tableId={tableId} onSaved={() => setRail(\"none\")} onCancel={() => setRail(\"none\")} />\n ) : null}\n {rail === \"new-record\" ? (\n <RecordForm\n tableId={tableId}\n onSaved={(recordId) => {\n setOpenRecord(recordId);\n setRail(\"record\");\n }}\n onCancel={() => setRail(\"none\")}\n />\n ) : null}\n {rail === \"record\" && openRecord ? (\n <div className=\"space-y-3\">\n <Peek tableId={tableId} recordId={openRecord} onClose={() => setRail(\"none\")} />\n <Separator />\n <HistoryPanel tableId={tableId} recordId={openRecord} />\n <Separator />\n <CommentThread tableId={tableId} recordId={openRecord} />\n </div>\n ) : null}\n </aside>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","value","document","value","import_react","import_design_system","import_react","import_design_system","import_records","import_records","import_react","import_jsx_runtime","value","id","import_jsx_runtime","value","import_jsx_runtime","value","id","import_react","import_design_system","import_design_system","import_jsx_runtime","import_design_system","import_react","import_jsx_runtime","value","import_jsx_runtime","document","value","import_jsx_runtime","inFlight","value","import_react","import_design_system","import_jsx_runtime","import_react","import_core","import_design_system","import_jsx_runtime","document","import_react","import_core","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","written","value","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_react","import_core","import_design_system","import_react","import_jsx_runtime","document","value","import_react","import_design_system","import_jsx_runtime","import_jsx_runtime","document","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_react","import_react","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","read","value","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_react","import_design_system","import_jsx_runtime","document","answered","value","import_jsx_runtime","document","value","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_react","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_records","import_design_system","import_jsx_runtime","total","step","import_react","import_design_system","import_jsx_runtime","board","import_react","import_records","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","document","tableName","import_react","import_design_system","import_jsx_runtime","document","ProvenanceBadge","value","import_react","import_design_system","import_jsx_runtime","step","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","keys","import_react","import_design_system","import_jsx_runtime","document","import_react","import_design_system","import_jsx_runtime","document","value","import_react","import_design_system","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_react","import_design_system","import_jsx_runtime","document"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/host.tsx","../src/rights.ts","../src/plainWords.ts","../src/names.ts","../src/PersonPicker.tsx","../src/editors.tsx","../src/parity.ts","../src/fieldTypes.ts","../src/RelationPicker.tsx","../src/gridEditing.tsx","../src/Refusal.tsx","../src/values.tsx","../src/labels.tsx","../src/Grid.tsx","../src/presentation.ts","../src/ExportMenu.tsx","../src/ImportWizard.tsx","../src/CustomFieldsSection.tsx","../src/FieldEditor.tsx","../src/TableSettings.tsx","../src/Peek.tsx","../src/RecordForm.tsx","../src/systemTable.ts","../src/ShareControl.tsx","../src/views.ts","../src/ViewSwitcher.tsx","../src/ViewBar.tsx","../src/seedOnce.ts","../src/ProposalRow.tsx","../src/ActionInbox.tsx","../src/HistoryPanel.tsx","../src/CommentThread.tsx","../src/forms.ts","../src/PortalsPanel.tsx","../src/SubscriptionsPanel.tsx","../src/FormBuilder.tsx","../src/FormRunner.tsx","../src/charts.ts","../src/chartFrame.tsx","../src/docs.ts","../src/DocTemplate.tsx","../src/DocRender.tsx","../src/SignBlock.tsx","../src/NotifyRuleEditor.tsx","../src/ChartBlock.tsx","../src/DashboardCanvas.tsx","../src/FormsPanel.tsx","../src/RecordChat.tsx","../src/EnrichPanel.tsx","../src/ChecklistRunner.tsx","../src/BookingSlots.tsx","../src/CaptureSheet.tsx","../src/PortalShell.tsx","../src/PublicViewPage.tsx","../src/EmbedFrame.tsx","../src/RecordsMount.tsx","../src/TablesHome.tsx","../src/createTable.ts","../src/TablePage.tsx"],"sourcesContent":["// src/index.ts — @ai-matrx/records-ui\n//\n// The canonical screens of the AI Matrx record store. Every component here\n// reads and writes ONLY through @ai-matrx/records, renders through\n// @ai-matrx/design-system's own primitives and data table, and carries\n// @ai-matrx/alchemy's menu where a person would reach for one.\n//\n// There is no bespoke per-feature record UI in this platform: a feature that\n// needs a grid, a form, a picker or a peek mounts one of these.\n\nexport {\n RecordsUiProvider,\n useRecordsUi,\n useTableRights,\n useRecordRights,\n useRowRights,\n tableRightsAt,\n NO_RIGHTS,\n NO_UPLOAD_REASON,\n NO_SAVED_VIEWS_REASON, NO_SHARE_REASON,\n NO_MEMBERS_REASON,\n NO_OPEN_RECORDS_REASON,\n NO_REASK_REASON,\n} from \"./host\";\nexport type {\n RecordsUiHost,\n TableRights,\n OrganizationMember,\n OpenRecordsAsk,\n ReaskContext,\n ShareSubject,\n} from \"./host\";\nexport {\n whatYouMayDo,\n whatYouMayDoWithTable,\n NOT_ANSWERED_YET,\n LEVEL_WORD,\n} from \"./rights\";\nexport type { WhatYouMayDo, Capability } from \"./rights\";\nexport {\n refusalForAPerson,\n refusalLineForAPerson,\n isMachineIdentity,\n machineIdentityIn,\n MACHINE_IDENTITY,\n} from \"./plainWords\";\nexport type { PlainRefusal } from \"./plainWords\";\nexport { humanize, fieldName, tableName, recordName, rowName } from \"./names\";\nexport { PersonPicker, memberName, personRecordForMember } from \"./PersonPicker\";\nexport type { PersonPickerProps } from \"./PersonPicker\";\nexport { GridCell, useGridEditing, fieldIsEditable } from \"./gridEditing\";\nexport type { GridEditing, CellAddress, CellState, CellRefusal } from \"./gridEditing\";\nexport { RefusalNotice, RefusalLine, hintForAPerson, hintIsMachineIdentity } from \"./Refusal\";\nexport { Grid, columnForField, NO_COLUMNS_YET, NO_COLUMNS_WHY } from \"./Grid\";\nexport type { GridProps } from \"./Grid\";\nexport { ExportMenu } from \"./ExportMenu\";\nexport type { ExportMenuProps } from \"./ExportMenu\";\nexport { ImportWizard } from \"./ImportWizard\";\nexport type { ImportWizardProps } from \"./ImportWizard\";\nexport { CustomFieldsSection } from \"./CustomFieldsSection\";\nexport type { CustomFieldsSectionProps } from \"./CustomFieldsSection\";\nexport { FieldEditor, keyFor, whatIsMissing } from \"./FieldEditor\";\nexport type { FieldEditorProps } from \"./FieldEditor\";\nexport { TableSettings } from \"./TableSettings\";\nexport type { TableSettingsProps, FieldProposalRow } from \"./TableSettings\";\nexport { Peek } from \"./Peek\";\nexport type { PeekProps } from \"./Peek\";\nexport { RecordForm } from \"./RecordForm\";\nexport type { RecordFormProps } from \"./RecordForm\";\nexport { RelationPicker } from \"./RelationPicker\";\nexport type { RelationPickerProps } from \"./RelationPicker\";\nexport { FieldControl, FieldLabel, RecordChip } from \"./editors\";\nexport type { FieldEditorControlProps } from \"./editors\";\nexport { renderValue, scalarText, envelopeFor, ProvenanceBadge, RecordValue } from \"./values\";\nexport { RecordLabelProvider, useRecordLabels, pointsAtRecords, idsOf, isId } from \"./labels\";\nexport type { LabelLookup } from \"./labels\";\nexport { editorKindFor, fieldTypeLabel, PARITY_LABEL, PARITY_MADE_OF } from \"./parity\";\nexport {\n FIELD_TYPE_CHOICES,\n FIELD_TYPE_GROUPS,\n fieldTypeChoice,\n isPlainFieldType,\n parityTypesWithNoExplanation,\n} from \"./fieldTypes\";\nexport type { FieldTypeChoice, PickableFieldType, PlainFieldType } from \"./fieldTypes\";\nexport type { EditorKind } from \"./parity\";\nexport { ensureSystemTable, useSystemTable } from \"./systemTable\";\nexport type { SystemTableSpec, SystemFieldSpec, UseSystemTableState, TrackedVersion } from \"./systemTable\";\nexport {\n VIEW_LAYOUTS,\n VIEW_TABLE,\n LAYOUT_LABEL,\n LAYOUT_NEEDS,\n LAYOUT_FIELD_KIND,\n LAYOUT_NO_FIELD,\n viewDocument,\n viewFromRecord,\n viewPatchDocument,\n} from \"./views\";\nexport type { SavedView, SavedViewSpec, ViewLayout, ViewSort } from \"./views\";\nexport { ViewSwitcher, useViewRecords } from \"./ViewSwitcher\";\nexport type { ViewSwitcherProps } from \"./ViewSwitcher\";\nexport { ViewBar } from \"./ViewBar\";\nexport type { ViewBarProps } from \"./ViewBar\";\nexport { ProposalRow } from \"./ProposalRow\";\nexport type { ProposalRowProps, ProposedChange, ProposalOutcome } from \"./ProposalRow\";\n// SCR-11. The inbox reads the STORE's own queue (custom.work_inbox) — the\n// package-owned `records_ui_action` Table it used to keep, and the\n// QueuedAction/actionDocument shapes that wrote into it, are gone: a second\n// queue beside the store's own is what PRODUCTS.md row 6 forbids.\nexport { ActionInbox, ACTION_KINDS } from \"./ActionInbox\";\nexport type { ActionInboxProps, ActionKind } from \"./ActionInbox\";\nexport { HistoryPanel } from \"./HistoryPanel\";\nexport type { HistoryPanelProps } from \"./HistoryPanel\";\nexport { CommentThread, COMMENT_TABLE } from \"./CommentThread\";\n// ONE FORM OBJECT: `custom.anon_form`, through `custom.form_declare` and\n// `custom.forms` — the same two doors `form_propose` uses. The package's own\n// `records_ui_form` Table, and the `FORM_TABLE`/`formDocument`/`formFromRecord`\n// trio that wrote into it, are gone: a second form store beside the one that\n// holds the public link is what made a tweak and a stranger's answer land in\n// different places.\nexport { FORM_FLOWS, formDeclareArgs, formFromSummary, formPresentation, submissionStamp } from \"./forms\";\nexport type { FormFlow, FormQuestionSpec, FormSpec, FormTheme, SavedForm } from \"./forms\";\n// VIS-31 / PORTAL — the OWNER's side of the client portal: who is invited, who\n// has signed in, and \"view as this client\", which is the store's own answer to\n// the store's own visibility question and never a second implementation of it.\nexport { PortalsPanel, PortalCardView, revokeConsequence, previewLine } from \"./PortalsPanel\";\nexport type { PortalsPanelProps, PortalCardViewProps, PortalAnswer } from \"./PortalsPanel\";\nexport { SubscriptionsPanel } from \"./SubscriptionsPanel\";\nexport type { SubscriptionsPanelProps } from \"./SubscriptionsPanel\";\nexport { FormBuilder } from \"./FormBuilder\";\nexport type { FormBuilderProps } from \"./FormBuilder\";\nexport {\n CHART_KINDS,\n CHART_KIND_LABEL,\n CHART_NEEDS,\n SERIES_COLORS,\n blockFromSpec,\n dashboardDeclareArgs,\n dashboardFromSummary,\n groupLabel,\n specFromBlock,\n} from \"./charts\";\nexport type { ChartKind, ChartSpec, SavedDashboard } from \"./charts\";\nexport { ChartFrame, ChartLegendContent, ChartTooltipContent, useMeasuredWidth } from \"./chartFrame\";\nexport type { ChartConfig } from \"./chartFrame\";\nexport { bodyFromKeys, bodyForReading, fieldToken, isSignatureField } from \"./docs\";\nexport type { DocTemplateSpec } from \"./docs\";\nexport { DocTemplate } from \"./DocTemplate\";\nexport type { DocTemplateProps } from \"./DocTemplate\";\nexport { DocRender } from \"./DocRender\";\nexport type { DocRenderProps } from \"./DocRender\";\nexport { SignBlock } from \"./SignBlock\";\nexport type { SignBlockProps } from \"./SignBlock\";\nexport { NotifyRuleEditor } from \"./NotifyRuleEditor\";\nexport type { NotifyRuleEditorProps, NotifyRuleSpec } from \"./NotifyRuleEditor\";\nexport { ChartBlock } from \"./ChartBlock\";\nexport type { ChartBlockProps } from \"./ChartBlock\";\nexport { DashboardCanvas } from \"./DashboardCanvas\";\nexport type { DashboardCanvasProps } from \"./DashboardCanvas\";\nexport { FormsPanel, type FormsPanelProps } from \"./FormsPanel\";\nexport { FormRunner } from \"./FormRunner\";\n// `FormSubmitOutcome` is the RETURN TYPE of `FormRunnerProps.onSubmit`, so a\n// host that supplies its own submit could not type its own handler without it.\n// It was declared and not exported, which broke matrx-frontend's\n// `PublicFormRunner` on 0.16.0 with TS2459 (\"declares it locally, but it is not\n// exported\") — a public surface is every type a consumer must name.\nexport type { FormRunnerProps, FormSubmitOutcome } from \"./FormRunner\";\nexport type { CommentThreadProps } from \"./CommentThread\";\nexport { RecordChat, NO_CHAT_REASON } from \"./RecordChat\";\nexport type { RecordChatProps, RecordChatContext, RecordChatEntry, RecordChatWithheld } from \"./RecordChat\";\nexport { EnrichPanel, NO_ENRICH_REASON } from \"./EnrichPanel\";\nexport type { EnrichPanelProps, EnrichAsk, EnrichOutcome } from \"./EnrichPanel\";\nexport { ChecklistRunner, CHECKLIST_TABLE } from \"./ChecklistRunner\";\nexport type { ChecklistRunnerProps, ChecklistSpec, ChecklistStepSpec } from \"./ChecklistRunner\";\nexport { BookingSlots } from \"./BookingSlots\";\nexport type { BookingSlotsProps } from \"./BookingSlots\";\nexport { CaptureSheet, CAPTURE_MODES, IN_MEMORY_QUEUE_REASON } from \"./CaptureSheet\";\nexport type { CaptureSheetProps, CaptureMode } from \"./CaptureSheet\";\nexport { PortalShell } from \"./PortalShell\";\nexport type { PortalShellProps } from \"./PortalShell\";\nexport { PublicViewPage } from \"./PublicViewPage\";\nexport type { PublicViewPageProps } from \"./PublicViewPage\";\nexport { EmbedFrame, useEmbedHandshake } from \"./EmbedFrame\";\nexport type { EmbedFrameProps } from \"./EmbedFrame\";\nexport type { CaptureQueuePort, PendingCapture } from \"./host\";\n\n// The two page assemblies a host route mounts, and the provider pair they need.\nexport { RecordsMount, storeDecidesRights, personActor, recordsDataSource, STORE_DECIDES_REASON, KERNEL_REASON } from \"./RecordsMount\";\nexport type { RecordsMountProps } from \"./RecordsMount\";\nexport { TablesHome, TABLE_LANES, LANE_TITLE, LANE_EMPTY, laneFor } from \"./TablesHome\";\nexport type { TablesHomeProps, TableLane } from \"./TablesHome\";\nexport { TablePage, TABLE_NOT_REACHABLE, DEFAULT_VIEW_NAME, VIEW_NOT_SAVED_YET } from \"./TablePage\";\nexport type { TablePageProps } from \"./TablePage\";\nexport { declareTable, addFields, fieldDeclarationFor, tokenFor, DEFAULT_FIELDS } from \"./createTable\";\nexport type { NewTableSpec, NewFieldSpec, DeclareResult } from \"./createTable\";\n\n// SCR-N-5 — the Share button, and the host port that supplies the app's one share dialog.\nexport { ShareControl, useCanShare, shareUnavailableReason } from \"./ShareControl\";\nexport type { ShareControlProps } from \"./ShareControl\";\n\nexport {\n EMPTY_PRESENTATION,\n FROZEN_COLUMN_WIDTH,\n colorFromTheValue,\n currencyCodeFor,\n formatForField,\n parseGridPresentation,\n presentationDocument,\n presentationIsEmpty,\n} from \"./presentation\";\nexport type { GridPresentation } from \"./presentation\";\n","\"use client\";\n\n// src/host.tsx — @ai-matrx/records-ui\n//\n// THE ONE BINDING POINT. A host mounts `<RecordsUiProvider>` once, inside\n// `<RecordsProvider>` from @ai-matrx/records, and every component in this\n// package reads what it needs from here. There is no module-level state: two\n// organizations in two tabs must never share one.\n//\n// WHAT A HOST BINDS, AND WHAT HAPPENS WHEN IT DOES NOT\n// ----------------------------------------------------\n// `rights` USED TO BE the only answer to \"may this person administer this\n// table?\" — a PORT, whose default was `false` with a reason and whose only\n// other honest setting was `storeDecidesRights`: yes to everything, let the door\n// refuse afterwards. The sixth-pass verdict measured what that second answer\n// costs a person: a colleague at viewer got a live cell editor, typed, pressed\n// Enter, and was refused only then.\n//\n// THE STORE ANSWERS THIS NOW, through the door this lane added:\n// `custom.my_levels` says what level the CALLER holds on the subjects they\n// name, one call for a whole page. `rights` stays a PORT for a host whose\n// authority is genuinely its own, but nothing is guessed when it is unbound:\n// the store's own answer is the default, and `rights.why(...)` says, for each\n// thing a person may not do, what level it would take and who can give it.\n//\n// IT IS NOT FREE, AND THE OBVIOUS FREE VERSION IS WRONG. `custom.read_records`\n// answers `level` on every row and `tableList` is a read — but of the Table\n// KERNEL, so that level is the caller's level on the kernel (viewer, for\n// everybody) and not on the table the row describes. Carrying it was measured\n// wrong within the hour: a table's own owner came back \"viewer\". A table is a\n// record, and its level is asked for like any other record's.\n//\n// ABSENT OR HONEST, NEVER DEAD — and never offered-then-refused, which is the\n// same lie with a longer fuse.\n\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { AggregateFilter, PermissionLevel, Table, Uuid } from \"@ai-matrx/records\";\nimport { useMyLevel, useMyLevels } from \"@ai-matrx/records/react\";\n\nimport { NOT_ANSWERED_YET, whatYouMayDo, whatYouMayDoWithTable, type WhatYouMayDo } from \"./rights\";\nimport type { RecordChatContext } from \"./RecordChat\";\nimport type { EnrichAsk, EnrichOutcome } from \"./EnrichPanel\";\n\n/**\n * What a person may do to one table. The four words and the ladder are the\n * store's (`rights.ts`), not ours.\n *\n * `admin`, `comment` and `write` are kept with the names they have always had,\n * because every screen in this package and in the host apps reads them; they\n * are now the store's ANSWER rather than a host's guess.\n */\nexport interface TableRights extends WhatYouMayDo {\n /** SCR-2: holders of `admin` on the table see the \"+\" and the settings panel. */\n admin: boolean;\n /**\n * Why this answer, in one sentence. Kept for callers that show a single\n * reason; `why(what)` is the per-control sentence and is what the screens use.\n */\n reason: string;\n}\n\nfunction tableRights(may: WhatYouMayDo, overallReason?: string): TableRights {\n return {\n ...may,\n admin: may.structure,\n reason: overallReason ?? (may.structure ? \"\" : may.why(\"structure\")),\n };\n}\n\n/**\n * Kept so a host that imported it still compiles. It is no longer any screen's\n * default: the store answers this question now, and a package that said \"I\n * assume nothing\" while holding the answer would be hiding controls from the\n * people who hold them.\n */\nexport const NO_RIGHTS: TableRights = tableRights(NOT_ANSWERED_YET);\n\n/**\n * THE ONE WAY TO BUILD A `TableRights` BY HAND — for a host with its own\n * authority, and for a suite that wants to mount one seat's screen. It takes\n * the LEVEL, never six booleans, so nobody can hand a screen a combination the\n * ladder cannot produce (write without read, share without edit).\n */\nexport function tableRightsAt(level: PermissionLevel | null): TableRights {\n return tableRights(whatYouMayDo(level, true));\n}\n\nexport interface RecordsUiHost {\n /** Answer the rights question for one table. Synchronous: a screen renders now. */\n rights?: (table: Table) => TableRights;\n /** Where a record's own page lives, when the host has one. A peek is used when it does not. */\n hrefForRecord?: (args: { table: Table; recordId: Uuid }) => string | undefined;\n /** The host's own link element, so routing stays the host's business. */\n Link?: (props: { href: string; children: ReactNode; className?: string }) => ReactNode;\n /** Toasts. Absent means the screen shows the sentence inline instead — never silence. */\n notify?: { success: (message: string) => void; error: (message: string) => void };\n /** Density for every table this package renders. */\n density?: \"condensed\" | \"normal\" | \"spacious\";\n /**\n * OPTIONAL. Where a file a person attached actually goes. A File is a record\n * in the kernel File Table (REC-31), but the BYTES are the host's file\n * service, not this package's business — so this is a port.\n *\n * Unbound, an attachment question does NOT draw a file chooser that quietly\n * loses the file: it says, in one sentence, that no file store is bound and\n * names this port. Absent or honest, never dead.\n */\n upload?: (file: File) => Promise<{ ok: true; fileId: Uuid } | { ok: false; reason: string }>;\n /**\n * Where this app serves its PUBLIC pages from, when that is not the origin\n * the screen is running on. A form's link is built here, so an owner copying\n * it from an admin host, a preview deployment or a desktop shell gets the\n * address a stranger can actually open — never `http://localhost:3000/f/…`\n * pasted into an email. Unbound, the browser's own origin is used.\n */\n publicOrigin?: string;\n /**\n * OPTIONAL. The organization's saved views as `platform.saved_view` holds\n * them — which is what a subscription points at (DOOR-18). The record store\n * has NO door onto that table, because it is the platform's and not the\n * store's, so this is a port rather than a read this package invents.\n *\n * Unbound, `NotifyRuleEditor` shows the subscriptions that exist and says, in\n * one sentence, that it cannot offer a view to subscribe to. It never renders\n * an empty picker that looks like \"you have no views\".\n */\n savedViews?: () => Promise<Array<{ id: Uuid; name: string }>>;\n /**\n * OPTIONAL. WHO IS IN THIS ORGANIZATION (FLD-11 `member`).\n *\n * A person field must offer PEOPLE. Who the people are is the platform's\n * answer — organization membership lives in `iam`, not in the record store —\n * and the store has no door onto it, so this is a port rather than a read\n * this package invents. `PersonPicker` resolves whoever is picked to their\n * record in the kernel Person Table, which is what the Field actually stores.\n *\n * Unbound, a person question is ABSENT with `NO_MEMBERS_REASON`. It never\n * falls back to listing the kernel Person Table's contents: that Table also\n * holds the Homes this package writes, and offering \"Comments Home\" as a\n * person is exactly what this port exists to stop.\n */\n members?: () => Promise<OrganizationMember[]>;\n /**\n * OPTIONAL. THE HOST'S OWN CHAT SURFACE (SCR-26).\n *\n * This package ships no chat UI, on purpose: AI Matrx has exactly one, it\n * lives in matrx-frontend (`AgentConversationColumn`), and it reads that app's\n * Redux store — so a second one here would drift within a month and a package\n * that imported the first would stop being a package. `RecordChat` therefore\n * builds the CONTEXT (the record, through the read door, with the masked\n * fields named) and hands it to this port.\n *\n * Unbound, the panel is ABSENT with that reason, never a composer that goes\n * nowhere.\n */\n chat?: (context: RecordChatContext) => ReactNode;\n /**\n * OPTIONAL. THE SERVER'S `records` TOOL (SCR-27).\n *\n * An AI fill must be written with actor `agent` on behalf of the person, and\n * only the server can honestly say that — a browser stamping itself `agent`\n * is a browser claiming to be one. So `EnrichPanel` asks here, and the host\n * calls the server's own `records` tool (`action: \"record_write\"`), which\n * stamps `_actor` and `_on_behalf_of` itself.\n *\n * Unbound, no Fill control is drawn at all and the reason names this port.\n */\n enrich?: (ask: EnrichAsk) => Promise<EnrichOutcome>;\n /**\n * OPTIONAL. WHERE AN OFFLINE CAPTURE WAITS (SCR-30).\n *\n * `CaptureSheet` mints the id for a capture BEFORE it tries to send it, so a\n * phone with no signal has already decided what the write will be called.\n * Where that queue physically lives is the host's business — IndexedDB in a\n * browser, a file in a desktop app — so it is a port. Unbound, the sheet\n * keeps its queue in memory for the life of the page AND SAYS SO, because a\n * queue that silently died with the tab is the failure this exists to avoid.\n */\n captureQueue?: CaptureQueuePort;\n /**\n * OPTIONAL. THE HOST'S OWN SHARE DIALOG (SCR-N-5).\n *\n * This package ships no share dialog, ON PURPOSE, and for the same reason it\n * ships no chat: AI Matrx has exactly ONE sharing surface — matrx-frontend's\n * `features/sharing` ShareModal, with its people picker, its level picker, its\n * grant list and its \"who can see this, and why\" panel — and a second one here\n * would be a parallel sharing UI within a month. Sharing is the access model's\n * front door, and two front doors is how a platform ends up with two answers\n * to \"who can see this\".\n *\n * So `ShareControl` draws the BUTTON (which belongs on the record and table\n * screens, beside everything else a person does to a thing) and hands the\n * subject to this port, which returns the host's own dialog.\n *\n * Unbound, the button is ABSENT and `NO_SHARE_REASON` says which port to bind.\n * Never a Share button that opens nothing.\n */\n share?: (subject: ShareSubject) => ReactNode;\n /**\n * OPTIONAL. OPEN THE RECORDS BEHIND A NUMBER (SCR-16).\n *\n * Every number on a dashboard is a count of real records, and the whole\n * product row is that a person can get from the number to them: click the\n * \"Awaiting parts\" column and the grid opens on the twenty-eight jobs it\n * counted, with the block's own filter still on. That is one navigation, and\n * WHERE the grid lives is the host's routing — so it is a port, like\n * `hrefForRecord`, rather than a route string this package invents.\n *\n * Unbound, the marks are NOT clickable and the canvas says so in one\n * sentence naming this port. A chart whose bars looked pressable and did\n * nothing is the dead control this package does not ship.\n */\n openRecords?: (ask: OpenRecordsAsk) => void;\n /**\n * OPTIONAL. ASK THE AGENT TO CHANGE THIS DASHBOARD (SCR-16).\n *\n * \"break it down by owner\" is how a dashboard is actually built — the agent\n * calls `dashboard_propose` on the server's `records` tool with this\n * dashboard's id and re-states it. Only the server can do that honestly (a\n * browser stamping itself `agent` is a browser claiming to be one), which is\n * the same reason `enrich` is a port, so this is one too.\n *\n * Unbound, the box is drawn DISABLED with one sentence naming this port —\n * never a composer that goes nowhere and never silence.\n */\n onReask?: (question: string, context: ReaskContext) => Promise<void>;\n}\n\n/**\n * WHAT A CLICK ON A NUMBER ASKS FOR. The filter is already merged: the block's\n * own filter (which `custom.dashboard_run` echoes back with the canvas bar\n * folded under it) with the clicked group's key and value over the top. A host\n * that dropped a key would open the grid on more records than the number\n * counted, which is the one way this control can lie.\n */\nexport interface OpenRecordsAsk {\n tableId: Uuid;\n filter: Record<string, AggregateFilter>;\n /** What the person clicked, in words: \"Jobs by stage this month · Awaiting parts\". */\n label: string;\n}\n\n/** Which dashboard a re-ask is about, so the agent re-states it rather than making a second one. */\nexport interface ReaskContext {\n tableId: Uuid;\n /** Null while the canvas has no dashboard yet — the answer is the first one. */\n dashboardId: Uuid | null;\n dashboardName: string | null;\n}\n\n/**\n * What a host's share dialog is being opened ON. A Table is a record in this\n * store (a `custom.record` row whose table is the Table kernel), so ONE subject\n * shape covers both screens and `kind` is what the sentences say, not what the\n * store looks up.\n */\nexport interface ShareSubject {\n kind: \"record\" | \"table\";\n /** The store is keyed (organization_id, id); this package never guesses one. */\n organizationId: Uuid;\n subjectId: Uuid;\n /** What to call it on screen. Never empty — the id's first eight characters at worst. */\n name: string;\n /** Close the dialog. The control owns the open/closed state, the host owns the dialog. */\n onClose: () => void;\n}\n\n/** One member of the organization, in the words a person reads. */\nexport interface OrganizationMember {\n /** The platform's user id. This is what a Person record carries as `user_id`. */\n userId: string;\n /** Their display name, when the platform has one. */\n name?: string | null;\n email?: string | null;\n avatarUrl?: string | null;\n}\n\n/** The durable half of offline capture: read the queue, write it, that is all. */\nexport interface CaptureQueuePort {\n load: () => Promise<PendingCapture[]>;\n save: (pending: PendingCapture[]) => Promise<void>;\n}\n\n/** One capture waiting to be written, with the id the CLIENT minted for it. */\nexport interface PendingCapture {\n /**\n * The client key. Minted offline, before the first attempt, and never\n * re-minted on retry — that is exactly what lets the store's replay ledger\n * tell a retry from a second capture.\n */\n clientKey: string;\n tableId: Uuid;\n payload: Record<string, unknown>;\n capturedAt: string;\n device: string;\n /** How many times sending has been tried, and what the store last said. */\n attempts: number;\n lastRefusal?: string | null;\n}\n\n/** The sentence the notify editor shows when no saved-view port is bound. */\nexport const NO_SAVED_VIEWS_REASON =\n \"No saved-view port is bound, so there is nothing here to subscribe to. A subscription points at a \" +\n \"`platform.saved_view`, which the record store has no door onto — bind `savedViews` on \" +\n \"<RecordsUiProvider> with your host's own list and the picker appears.\";\n\n/** The sentence a person question shows when no membership port is bound. */\nexport const NO_MEMBERS_REASON =\n \"No membership port is bound, so this question cannot offer anybody. A person field points at the \" +\n \"kernel Person Table, and who is in this organization is the platform's answer rather than the \" +\n \"record store's — bind `members` on <RecordsUiProvider> with your host's own roster and the picker \" +\n \"appears.\";\n\n/** The sentence shown when no share dialog is bound. */\nexport const NO_SHARE_REASON =\n \"No share dialog is bound, so this screen offers no Share button rather than one that opens \" +\n \"nothing. Bind `share` on <RecordsUiProvider> with the app's own sharing dialog — AI Matrx has \" +\n \"exactly one (features/sharing), and this package deliberately does not ship a second.\";\n\n/** The sentence a canvas shows when nothing is bound to open the records behind a number. */\nexport const NO_OPEN_RECORDS_REASON =\n \"These numbers do not click through yet. Every one of them is a count of real records, and where \" +\n \"this app puts its grid is the host's routing rather than this package's — bind `openRecords` on \" +\n \"<RecordsUiProvider> and a bar, a slice or a row opens the records it counted.\";\n\n/** The sentence the re-ask box shows when no agent is bound. */\nexport const NO_REASK_REASON =\n \"Asking for a change in words needs an agent, and this package deliberately reaches one through \" +\n \"the host rather than calling a model itself. Bind `onReask` on <RecordsUiProvider> — it drives \" +\n \"`dashboard_propose` on the server's `records` tool with this dashboard's id — and this box works.\";\n\n/** The sentence an attachment question shows when no file store is bound. */\nexport const NO_UPLOAD_REASON =\n \"No file store is bound, so this question cannot take a file. Bind `upload` on \" +\n \"<RecordsUiProvider> with your host's file service and the chooser appears.\";\n\nconst HostContext = createContext<RecordsUiHost | null>(null);\n\nexport function RecordsUiProvider({ value, children }: { value: RecordsUiHost; children: ReactNode }) {\n const bound = useMemo(() => value, [value]);\n return <HostContext.Provider value={bound}>{children}</HostContext.Provider>;\n}\n\nexport function useRecordsUi(): RecordsUiHost {\n return useContext(HostContext) ?? {};\n}\n\n/**\n * WHAT THIS PERSON MAY DO TO THIS TABLE — asked, once per table.\n *\n * A host that binds `rights` still wins: a portal, an embed or an app with its\n * own authority is entitled to a narrower answer than the store's. An unbound\n * host no longer gets a guess in either direction — while the door is\n * answering, `known` is false and NOTHING is offered and nothing is claimed.\n */\nexport function useTableRights(table: Table | null | undefined): TableRights {\n const host = useRecordsUi();\n const bound = Boolean(host.rights);\n // A table is a record in this store, so its level is the same question.\n const asked = useMyLevel(bound || !table ? null : table.id);\n return useMemo(() => {\n if (!table) return NO_RIGHTS;\n if (host.rights) return host.rights(table);\n if (asked.loading) return tableRights(NOT_ANSWERED_YET);\n // A refusal is an ANSWER: the door said no, so this person holds nothing.\n const level = asked.error ? null : asked.data;\n return tableRights(whatYouMayDoWithTable(table, level, true));\n }, [host, table, bound, asked.loading, asked.error, asked.data]);\n}\n\n/**\n * WHAT THIS PERSON MAY DO TO ONE RECORD — which is a different question from\n * the table's, and the sixth-pass verdict is the proof: a record shared with a\n * colleague at Editor inside a table she holds at Viewer. The grid used to\n * label that row \"viewer\" while the store let her write to it.\n */\nexport function useRecordRights(recordId: Uuid | null): WhatYouMayDo {\n const asked = useMyLevel(recordId);\n return useMemo(() => {\n if (!recordId) return NOT_ANSWERED_YET;\n if (asked.loading) return NOT_ANSWERED_YET;\n // A refusal is an ANSWER: the door said no, so this person holds nothing.\n if (asked.error) return whatYouMayDo(null, true);\n return whatYouMayDo(asked.data, true);\n }, [recordId, asked.loading, asked.error, asked.data]);\n}\n\n/**\n * The same question for a whole page of records, in ONE call — the door takes a\n * list precisely so a grid never makes one call per row.\n *\n * `enabled` is how a grid avoids asking at all in the ordinary case: when the\n * table level already admits editing, every row it returned is editable and\n * there is nothing a per-record answer could add.\n */\nexport function useRowRights(\n rowIds: Uuid[],\n enabled: boolean,\n): (rowId: Uuid) => WhatYouMayDo | null {\n const asked = useMyLevels(enabled ? rowIds : []);\n return useMemo(() => {\n if (!enabled) return () => null;\n if (asked.loading) return () => NOT_ANSWERED_YET;\n if (asked.error) return () => whatYouMayDo(null, true);\n const held = asked.data ?? {};\n return (rowId: Uuid) => whatYouMayDo((held[rowId] ?? null) as PermissionLevel | null, true);\n }, [enabled, asked.loading, asked.error, asked.data]);\n}\n","// src/rights.ts — @ai-matrx/records-ui\n//\n// THE ONE PLACE A LEVEL BECOMES A SCREEN.\n//\n// WHAT A PERSON HIT (independent verdict, sixth pass, 19-20 September). A\n// colleague who had been shared a table at viewer opened it, double-clicked a\n// cell, got a live editor, typed a value and pressed Enter — and only THEN was\n// told she may not write. \"The permission is right; the screen told her she\n// could.\" Measured against Airtable, Notion and Linear the verdict called it\n// out by name: \"None of these three products lets you start an action it\n// already knows it will reject.\"\n//\n// WHY THE SCREEN COULD NOT KNOW. The rights question was a PORT with two honest\n// answers and no third: `NO_RIGHTS` (every administering control absent, which\n// is useless for a host whose authority IS the store's) and\n// `storeDecidesRights` — `{admin: true, comment: true, write: true}` for every\n// non-kernel table, for everybody. That second one is the defect, written down:\n// it is the screen ASSUMING the answer and letting the door say no afterwards.\n//\n// WHAT REPLACES IT. The store already answers this, and the client now carries\n// it: `custom.read_records` returns the reader's level on the TABLE on every\n// row (so `Table.your_level` costs nothing), and `custom.my_levels` — the door\n// this lane added — answers the caller's level on any subject they name, one\n// call for a whole page. This file is the only place in the package that turns\n// one of those four words into what a screen may DRAW.\n//\n// THE LADDER IS THE STORE'S, NOT OURS: viewer < commenter < editor < admin, and\n// which rung each door requires is read from the doors themselves —\n// `custom.record_update` asserts `editor` on the record, `custom.field_declare`\n// asserts `admin` on the TABLE (\"the SHAPE of this table, which is an admin's\n// right and not an editor's\"), `custom.io_comment_write` admits a commenter.\n// Nothing here invents a rule; it mirrors the four assertions those doors make\n// and is wrong the moment they change, which is what the suite is for.\n//\n// ABSENT OR HONEST, NEVER DEAD. Every `false` here carries the sentence that\n// says why and what to do about it, so a control can be left out AND explained.\n// A screen that hid a control with nothing to say is the silent half of the\n// same defect.\n\nimport { atLeast, type PermissionLevel, type Table } from \"@ai-matrx/records\";\n\n/** The six things a person does to a record or a table, as the screens offer them. */\nexport type Capability = \"read\" | \"comment\" | \"write\" | \"remove\" | \"share\" | \"structure\";\n\nexport interface WhatYouMayDo {\n /** The word the store answered, or null when it answered nothing. */\n level: PermissionLevel | null;\n /**\n * Whether the store has ANSWERED yet. `false` is a third state and not a\n * refusal: a screen that drew \"you may not\" while the answer was in flight\n * would blink every control off on every reload, which is its own lie.\n */\n known: boolean;\n read: boolean;\n comment: boolean;\n write: boolean;\n remove: boolean;\n share: boolean;\n structure: boolean;\n /** Why this person may not do that, in one sentence naming the way in. */\n why: (what: Capability) => string;\n}\n\n/** What each rung of the ladder is called where a person reads it. */\nexport const LEVEL_WORD: Record<PermissionLevel, string> = {\n viewer: \"Viewer\",\n commenter: \"Commenter\",\n editor: \"Editor\",\n admin: \"Admin\",\n};\n\n/**\n * WHICH RUNG EACH DOOR ASKS FOR. Read off the doors themselves, in one place,\n * so a screen never re-decides it and the suite has one thing to check.\n */\nconst NEEDS: Record<Capability, PermissionLevel> = {\n read: \"viewer\",\n // custom.io_comment_write\n comment: \"commenter\",\n // custom.record_update / custom.record_write\n write: \"editor\",\n // custom.record_delete\n remove: \"editor\",\n // custom.share_grant — passing your access on is an administrator's right\n share: \"admin\",\n // custom.field_declare / field_update / field_retire / table settings\n structure: \"admin\",\n};\n\nconst NOT_YET =\n \"Still asking the store what you may do here. Nothing is offered until it has answered.\";\n\nconst NOTHING_AT_ALL =\n \"You have not been given this. Ask somebody who administers it to share it with you.\";\n\n/** The sentence for one refusal: what the level is, what it would have to be. */\nfunction sentenceFor(what: Capability, level: PermissionLevel | null): string {\n if (level === null) return NOTHING_AT_ALL;\n const need = LEVEL_WORD[NEEDS[what]];\n const have = LEVEL_WORD[level];\n const doing: Record<Capability, string> = {\n read: \"open this\",\n comment: \"leave a comment\",\n write: \"change anything here\",\n remove: \"delete this\",\n share: \"pass this on to somebody else\",\n structure: \"change the columns of this table\",\n };\n return `You are ${have} here, and it takes ${need} to ${doing[what]}. Ask somebody who is Admin on it to move you up.`;\n}\n\n/**\n * WHAT ONE LEVEL LETS A PERSON DO. `level` null and `known` true means the\n * store said \"nothing\" — a real answer. `known` false means it has not said.\n */\nexport function whatYouMayDo(level: PermissionLevel | null, known = true): WhatYouMayDo {\n const may = (what: Capability) => known && atLeast(level, NEEDS[what]);\n return {\n level: known ? level : null,\n known,\n read: may(\"read\"),\n comment: may(\"comment\"),\n write: may(\"write\"),\n remove: may(\"remove\"),\n share: may(\"share\"),\n structure: may(\"structure\"),\n why: (what) => (known ? sentenceFor(what, level) : NOT_YET),\n };\n}\n\n/** Nothing offered, because nothing is known yet. */\nexport const NOT_ANSWERED_YET: WhatYouMayDo = whatYouMayDo(null, false);\n\n/**\n * REC-27. The nine Tables the platform ships are not administered from a\n * person's screen whatever level they hold on them — so the structure controls\n * are absent for a kernel Table and say why, and everything else follows the\n * level as usual.\n */\nexport const KERNEL_REASON =\n \"This is one of the tables the platform ships, so its columns are not changed from a screen. \" +\n \"Make your own table to change columns.\";\n\nexport function whatYouMayDoWithTable(\n table: Table | null | undefined,\n level: PermissionLevel | null,\n known: boolean,\n): WhatYouMayDo {\n const base = whatYouMayDo(level, known);\n if (!table?.is_kernel) return base;\n return {\n ...base,\n structure: false,\n why: (what) => (what === \"structure\" ? KERNEL_REASON : base.why(what)),\n };\n}\n","// src/plainWords.ts — @ai-matrx/records-ui\n//\n// THE ONE FORMATTER EVERY REFUSAL PASSES THROUGH.\n//\n// WHAT A PERSON READ (independent verdict, sixth pass, 19-20 September):\n//\n// \"You do not have access to this table, so custom.applicable_fields has\n// nothing to show you.\"\n// \"config.via names a relation Field of this same table, by its key… The\n// store's code for this was 23514.\"\n//\n// The verdict's third measured gap against Airtable, Notion and Linear was\n// exactly this: \"The machinery still shows through… two column types answer\n// with a contract row id and a SQL error number. Airtable, Notion and Linear\n// never show a person an internal name.\"\n//\n// WHY FILTERING THE HINT WAS NOT ENOUGH. The previous pass filtered the store's\n// HINT — the half written for whoever fixes the caller — and printed the\n// MESSAGE verbatim, because the store writes good messages. Most of them are\n// good. But the store's access refusals are built by `format()` from the DOOR'S\n// OWN NAME (`assert_client_may_change`: \"…so % may not write to it\", with the\n// door name substituted in), so the machine identity is IN the sentence a\n// person reads and no amount of hint-filtering reaches it.\n//\n// SO: ONE function, here, and every screen in this package renders what it\n// returns and nothing else. It does three things and refuses to do a fourth:\n//\n// 1. It KEEPS the store's own words wherever they are a person's words. The\n// store writes the best sentences in this feature (\"Being a member of the\n// organization is not by itself permission to rewrite somebody else's\n// row\") and this package does not rewrite them.\n// 2. It DROPS the clause that carries machine identity, by SHAPE — a\n// schema-qualified object, a document path, a contract row id, a SQLSTATE,\n// a uuid, a bare snake_case token. Dropped, never deleted: it joins the\n// SQLSTATE on the notice for whoever has to debug it.\n// 3. It ADDS a REMEDY — the sentence that says what to do now — keyed off the\n// store's own refusal code, because a refusal with nothing to do about it\n// is a dead end with an explanation.\n//\n// 4. It does NOT invent a diagnosis. When every clause of a message is\n// machine identity there is nothing honest left to say about the specifics,\n// so it says what happened in general terms and offers the remedy. Making\n// something up would be worse than the identifier it replaced.\n//\n// The guard for all of this is `demo/plain-words.test.tsx` plus the sweep in\n// `demo/honest.test.tsx`, which reads the RENDERED text of the real screens and\n// fails on any of the shapes below. A formatter nobody is forced through is a\n// formatter somebody bypasses next week.\n\nimport type { RecordsError } from \"@ai-matrx/records\";\n\n/**\n * MACHINE IDENTITY, BY SHAPE — never by a list of the sentences we happen to\n * have seen, because the next refusal is one nobody has read yet.\n *\n * `FLD-11:` / `REC-29:` / `AGT-7:` a contract row id\n * `custom.field_declare` a schema-qualified database object\n * `config.via` / `data.fields` a path inside a stored document\n * `retention_days` a document key, snake_case\n * `8f2c1b0a-…` a uuid\n * `23514` / `PT409` a SQLSTATE\n */\nexport const MACHINE_IDENTITY: RegExp[] = [\n /\\b[A-Z]{2,4}-\\d{1,3}\\b/,\n /\\b(?:custom|platform|iam|history|public|auth|campaign_watch)\\.[a-z_]+/,\n /\\b(?:config|data|document|spec|patch)\\.[a-z_]+/,\n /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/i,\n /\\b[a-z][a-z0-9]*(?:_[a-z0-9]+)+\\b/,\n // Five characters of digits and capitals, at least one a digit — so `23514`\n // and `PT409` match and an emphatic `NEVER` does not.\n /\\b(?=[0-9A-Z]{5}\\b)(?=[0-9A-Z]*\\d)[0-9A-Z]{5}\\b/,\n];\n\n/** Whether any shape above appears in this text. */\nexport function isMachineIdentity(text: string): boolean {\n return MACHINE_IDENTITY.some((shape) => shape.test(text));\n}\n\n/**\n * Every fragment of `text` that a person should never have been shown. Used by\n * the suite to say WHAT it found rather than only that it found something.\n */\nexport function machineIdentityIn(text: string): string[] {\n const found: string[] = [];\n for (const shape of MACHINE_IDENTITY) {\n const all = new RegExp(shape.source, shape.flags.includes(\"g\") ? shape.flags : `${shape.flags}g`);\n for (const hit of text.matchAll(all)) if (hit[0]) found.push(hit[0]);\n }\n return [...new Set(found)];\n}\n\n/** What the notice is called. The store's code, in the words of what went wrong. */\nconst TITLE: Record<string, string> = {\n stale_write: \"Someone else wrote first\",\n door: \"You do not have access to this\",\n door_absent: \"That is not built yet\",\n refused_by_rule: \"That value was not accepted\",\n invalid_argument: \"That was not accepted\",\n not_found: \"Not there any more\",\n missing_reference: \"That points at something that is not there\",\n already_exists: \"That already exists\",\n not_supported: \"That cannot be done here\",\n store_limit: \"This has got as big as it can\",\n store_not_served: \"This organization does not keep its data here\",\n internal: \"Something went wrong at our end\",\n};\n\n/**\n * WHAT TO DO NOW. One sentence per refusal code, and it is the whole reason\n * this file exists rather than a regular expression in `Refusal.tsx`: a\n * sentence that names what went wrong and nothing to do about it is a dead end.\n */\nconst REMEDY: Record<string, string> = {\n stale_write:\n \"Look at what they wrote. Keep theirs, or try again and yours goes on top.\",\n door:\n \"Ask somebody who administers this to share it with you at the level you need.\",\n door_absent:\n \"There is nothing to do here yet. It is on our list, not yours.\",\n refused_by_rule: \"Change the value so it passes, then try again.\",\n invalid_argument: \"Change what you entered, then try again.\",\n not_found:\n \"It may have been deleted. Go back to the list and open it again from there.\",\n missing_reference: \"Pick something that is still there.\",\n already_exists: \"Use a different name.\",\n not_supported: \"There is another way to do this — ask, and we will point you at it.\",\n store_limit: \"Split it up, or ask us to raise the ceiling for your organization.\",\n store_not_served:\n \"An administrator of this organization turns the record store on from the data settings screen.\",\n internal:\n \"Nothing you did caused this. Try again, and tell us if it keeps happening.\",\n};\n\n/** The one shape every screen in this package renders a refusal from. */\nexport interface PlainRefusal {\n /** The heading. Never the store's code. */\n title: string;\n /**\n * What happened, in the store's own words where they are a person's words\n * and in ours where they are not. Never empty.\n */\n sentence: string;\n /** What to do now. Never empty. */\n remedy: string;\n /**\n * Everything a person should not read, kept for whoever has to debug it: the\n * SQLSTATE, the hint written for a caller, and any clause dropped above.\n * Rendered out of sight (the notice's `title` attribute and a screen-reader-\n * only line), never deleted.\n */\n forEngineers: string;\n}\n\n/**\n * A sentence with its machine clauses taken out — or null when nothing honest\n * is left. Clauses are split on the joins the store's own `format()` templates\n * use (\"…, so custom.x may not write to it\", \"… — FLD-11: …\").\n */\nfunction withoutMachineClauses(sentence: string): { kept: string | null; dropped: string[] } {\n const dropped: string[] = [];\n const clauses = sentence\n .split(/(?:,\\s+so\\s+|\\s+—\\s+|\\s+--\\s+|\\s*\\|\\s*)/)\n .map((clause) => clause.trim())\n .filter((clause) => clause !== \"\");\n const kept = clauses.filter((clause) => {\n if (!isMachineIdentity(clause)) return true;\n dropped.push(clause);\n return false;\n });\n if (kept.length === 0) return { kept: null, dropped };\n let joined = kept.join(\". \").replace(/\\.\\.+/g, \".\").trim();\n if (!/[.!?]$/.test(joined)) joined = `${joined}.`;\n return { kept: joined, dropped };\n}\n\n/** Every sentence of a message, cleaned; the ones that cannot be cleaned are dropped. */\nfunction plainSentence(message: string): { kept: string | null; dropped: string[] } {\n const dropped: string[] = [];\n const kept: string[] = [];\n for (const raw of message.split(/(?<=[.!?])\\s+/)) {\n const sentence = raw.trim();\n if (sentence === \"\") continue;\n const cleaned = withoutMachineClauses(sentence);\n dropped.push(...cleaned.dropped);\n if (cleaned.kept) kept.push(cleaned.kept);\n }\n return { kept: kept.length === 0 ? null : kept.join(\" \"), dropped };\n}\n\n/**\n * THE FORMATTER. Every refusal a screen in this package shows goes through\n * here, and nothing in this package renders `error.message` directly.\n */\nexport function refusalForAPerson(error: RecordsError): PlainRefusal {\n const code = error.code ?? \"internal\";\n const message = plainSentence(String(error.message ?? \"\"));\n const hint = plainSentence(String(error.hint ?? \"\"));\n\n const title = TITLE[code] ?? \"The store refused this\";\n const remedy = REMEDY[code] ?? REMEDY[\"internal\"]!;\n\n // The store's sentence, then whatever of its hint is also a person's\n // sentence — \"Type the choices into the field panel, one per line\" is exactly\n // what somebody needs and is not machine identity.\n const said = [message.kept, hint.kept].filter(Boolean).join(\" \").trim();\n\n const forEngineers = [\n error.sqlstate ? `SQLSTATE ${error.sqlstate}.` : null,\n error.hint && hint.kept !== error.hint ? `Hint: ${error.hint}` : null,\n message.dropped.length > 0 || hint.dropped.length > 0\n ? `Dropped from the person's view: ${[...message.dropped, ...hint.dropped].join(\" | \")}`\n : null,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return {\n title,\n // Nothing invented. When every clause was machine identity the title says\n // what happened and the remedy says what to do; a made-up diagnosis would\n // be worse than the identifier it replaced.\n sentence: said === \"\" ? `${title}.` : said,\n remedy,\n forEngineers,\n };\n}\n\n/**\n * The same answer as one line, for a cell or a field where a block would break\n * the layout. Still one sentence and one remedy — never the sentence alone,\n * because half of this formatter's job is the thing to do next.\n */\nexport function refusalLineForAPerson(error: RecordsError): string {\n const plain = refusalForAPerson(error);\n return `${plain.sentence} ${plain.remedy}`.trim();\n}\n","// src/names.ts — @ai-matrx/records-ui\n//\n// WHAT A PERSON READS, NEVER WHAT THE MACHINE STORES.\n//\n// Measured on the real screens (independent verdict, 19 September): a table row\n// read `Saved views · 9 fields · records_ui_view`, a relation cell read a bare\n// `8f2c…` identifier, a header read `stage` because the Field's label was\n// blank, and the type word on a column tooltip read `long_text`. Airtable,\n// Notion and Linear never show a person an internal name; the verdict called\n// this one of the three things a first-time user feels within a minute.\n//\n// So every place this package prints something a person reads goes through one\n// of these three functions. They are deliberately dumb: they choose the best\n// human string that IS AVAILABLE and, when none is, say what the thing is\n// rather than printing the token. No screen in this package formats a name of\n// its own any more.\n\nimport type { Field, ReadRow, RecordDocument, Table } from \"@ai-matrx/records\";\n\n/**\n * A token (`records_ui_view`, `long_text`, `v78_widget2`) as a person would\n * write it. Used ONLY as a last resort, when the thing carries no label at all\n * — a raw token on a screen is the defect, and a humanised token is the least\n * bad honest answer, because it still names the same thing.\n */\nexport function humanize(token: string): string {\n const words = token\n .replace(/[_\\-.]+/g, \" \")\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .trim();\n if (words === \"\") return token;\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\n/** The name of one Field, as a header, a form label or a peek's term. */\nexport function fieldName(field: Field): string {\n const label = (field.label ?? \"\").trim();\n if (label !== \"\") return label;\n const name = (field.name ?? \"\").trim();\n if (name !== \"\") return name;\n return humanize(field.key);\n}\n\n/** The name of one Table, as a card, a heading or a breadcrumb. */\nexport function tableName(table: Table): string {\n const name = (table.name ?? \"\").trim();\n if (name !== \"\") return name;\n const singular = (table.label_singular ?? \"\").trim();\n if (singular !== \"\") return singular;\n return humanize(table.slug ?? \"\");\n}\n\n/**\n * The name of one RECORD, for a chip, a card, a relation cell or a peek title.\n *\n * `titleKey` is the Table's own `title_field` when the caller knows the Table —\n * that is the store's answer to \"what makes this record a chip\" (REC-2) — and\n * the conventional keys are tried after it. A record with nothing readable is\n * NOT shown as a truncated uuid: it says it has no name yet, because \"8f2c1b0a\"\n * tells a person nothing and looks like a bug.\n */\nexport function recordName(\n document: RecordDocument | undefined,\n titleKey?: string | null,\n fallback = \"Untitled\",\n): string {\n const data = (document ?? {}) as Record<string, unknown>;\n const keys = [titleKey, \"title\", \"name\", \"label\", \"full_name\", \"subject\", \"summary\"].filter(\n (key): key is string => typeof key === \"string\" && key !== \"\",\n );\n for (const key of keys) {\n const value = data[key];\n if (typeof value === \"string\" && value.trim() !== \"\") return value.trim();\n if (typeof value === \"number\") return String(value);\n }\n return fallback;\n}\n\n/** The same question for a row the read door returned. */\nexport function rowName(row: ReadRow | undefined, titleKey?: string | null, fallback = \"Untitled\"): string {\n return recordName(row?.document, titleKey, fallback);\n}\n\n/**\n * WHAT A RELATION CHIP SAYS WHEN THE RECORD IT POINTS AT IS NOT YOURS.\n *\n * A relation joins two records in two tables, and holding one end says nothing\n * about the other: a Job shared with you may point at a Client nobody shared.\n * The chip then has three possible answers and only one of them is honest —\n * the target's TITLE is a leak, a bare id is a bug with a hex number in it, and\n * a permanent \"Loading…\" is a lie that never resolves.\n *\n * This is the SAME sentence `platform.relation_withheld_label()` answers on the\n * database, word for word, so a person reads one wording whether the screen or\n * the store worked it out. Changing it changes both (RELATION-DECLARE,\n * 2026-09-20).\n */\nexport const WITHHELD_RECORD_LABEL = \"A record you have not been given access to\";\n","\"use client\";\n\n// src/PersonPicker.tsx — @ai-matrx/records-ui · FLD-11 (`member`)\n//\n// PICKING A PERSON MEANS PICKING A PERSON.\n//\n// What it replaced, measured on the real screen (independent verdict, 19\n// September): the \"Owner\" field — which the settings panel itself calls a\n// Person field — offered \"Comments Home\", \"Saved views Home\" and \"V78 Home\".\n// Those are not people. They are the Home records this package writes into the\n// kernel Person Table so that its own Tables have somewhere to live (REC-1),\n// and the generic relation picker was listing the Table's contents, which is\n// exactly right for a relation and exactly wrong for a person.\n//\n// SO A PERSON FIELD ASKS A DIFFERENT QUESTION. The list is the ORGANIZATION'S\n// MEMBERS — who those are is the platform's answer and not the record store's,\n// so it arrives through the `members` port on the host, the same way saved\n// views and file uploads do. The record store has no door onto organization\n// membership and this package does not invent one.\n//\n// WHAT IS STORED IS STILL A RECORD ID, because a member field is a relation to\n// the kernel Person Table and the store's foreign key is real. So picking a\n// member resolves that member to their Person record — by the `user_id` the\n// record carries — and writes one when the organization has not got one yet.\n// That write is the same `record_write` everything else in this package uses;\n// there is no second storage path, and a Home (a Person record with no\n// `user_id`) is never offered and never picked.\n//\n// Unbound port: the control is ABSENT with its reason, never a dead box and\n// never a list of the wrong things.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { Field, ReadRow, RecordsError, Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport type { RecordsClient } from \"@ai-matrx/records/core\";\nimport {\n BasicInput,\n Button,\n Popover,\n PopoverContent,\n PopoverTrigger,\n ScrollArea,\n cn,\n} from \"@ai-matrx/design-system\";\n\nimport { RecordChip } from \"./editors\";\nimport { useRecordsUi, type OrganizationMember } from \"./host\";\nimport { NO_MEMBERS_REASON } from \"./host\";\nimport { fieldName } from \"./names\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface PersonPickerProps {\n field: Field;\n value: unknown;\n onChange: (value: unknown) => void;\n disabled?: boolean | undefined;\n id?: string | undefined;\n className?: string | undefined;\n}\n\n/** A Person record in the kernel Table, as this picker needs to read it. */\ninterface PersonRecord {\n id: Uuid;\n userId: string | null;\n name: string;\n}\n\nfunction personFromRow(row: ReadRow): PersonRecord {\n const data = (row.document ?? {}) as Record<string, unknown>;\n const userId = data[\"user_id\"];\n return {\n id: row.id,\n userId: typeof userId === \"string\" && userId !== \"\" ? userId : null,\n name: String(data[\"full_name\"] ?? data[\"name\"] ?? data[\"email\"] ?? \"\").trim(),\n };\n}\n\n/** The member's own name, as a person reads it. Never a uuid. */\nexport function memberName(member: OrganizationMember): string {\n const display = (member.name ?? \"\").trim();\n if (display !== \"\") return display;\n const email = (member.email ?? \"\").trim();\n if (email !== \"\") return email;\n return \"A member with no name set\";\n}\n\n/**\n * Find (or write) the kernel Person record for one member. Exported because\n * an agent filling a person field server-side needs exactly the same answer,\n * and two implementations of \"which record is this person\" is two answers.\n */\nexport async function personRecordForMember(\n client: RecordsClient,\n personTableId: Uuid,\n people: PersonRecord[],\n member: OrganizationMember,\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const held = people.find((p) => p.userId === member.userId);\n if (held) return { ok: true, data: held.id };\n const written = await client.recordWrite({\n table_id: personTableId,\n data: {\n user_id: member.userId,\n full_name: memberName(member),\n ...(member.email ? { email: member.email } : {}),\n },\n });\n return written;\n}\n\nexport function PersonPicker({ field, value, onChange, disabled, id, className }: PersonPickerProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const [members, setMembers] = useState<OrganizationMember[] | null>(null);\n const [people, setPeople] = useState<PersonRecord[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [search, setSearch] = useState(\"\");\n const [open, setOpen] = useState(false);\n const [busy, setBusy] = useState(false);\n\n const membersPort = host.members;\n const personTable = field.relation_target;\n\n const picked = useMemo<string[]>(\n () => (Array.isArray(value) ? value.map(String) : value === null || value === undefined ? [] : [String(value)]),\n [value],\n );\n\n const load = useCallback(async () => {\n if (!membersPort) return;\n const [roster, records] = await Promise.all([\n membersPort(),\n personTable ? client.list({ table_id: personTable, limit: 500 }) : Promise.resolve(null),\n ]);\n setMembers(roster);\n if (records && !records.ok) {\n setError(refusalLineForAPerson(records.error));\n return;\n }\n setPeople(records ? records.data.rows.map(personFromRow).filter((p) => p.userId !== null) : []);\n }, [membersPort, client, personTable]);\n\n useEffect(() => {\n if (!open) return;\n void load();\n }, [open, load]);\n\n // The names of the records that are already picked, whether or not the list\n // has been opened — a chip that read `8f2c1b0a` is the defect this closes.\n useEffect(() => {\n if (picked.length === 0 || !personTable || people.length > 0) return;\n let cancelled = false;\n void client.list({ table_id: personTable, limit: 500 }).then((result) => {\n if (cancelled || !result.ok) return;\n setPeople(result.data.rows.map(personFromRow).filter((p) => p.userId !== null));\n });\n return () => {\n cancelled = true;\n };\n }, [client, personTable, picked.length, people.length]);\n\n if (!membersPort) {\n // ABSENT AND HONEST. A person question with nobody to offer is not a box\n // that silently does nothing — it names the port that fills it.\n return <p className={cn(\"text-xs text-muted-foreground\", className)}>{NO_MEMBERS_REASON}</p>;\n }\n\n if (!personTable) {\n return (\n <p className={cn(\"text-xs text-muted-foreground\", className)}>\n {fieldName(field)} is a person field, but it does not say which Table the people are\n records of yet, so there is nothing to pick from. A table admin sets its target in the field\n editor.\n </p>\n );\n }\n\n const nameOfRecord = (recordId: string) => {\n const person = people.find((p) => p.id === recordId);\n if (!person) return \"Loading…\";\n if (person.name !== \"\") return person.name;\n const member = (members ?? []).find((m) => m.userId === person.userId);\n return member ? memberName(member) : \"A member with no name set\";\n };\n\n const pick = async (member: OrganizationMember) => {\n setBusy(true);\n setError(null);\n const resolved = await personRecordForMember(client, personTable, people, member);\n setBusy(false);\n if (!resolved.ok) {\n setError(refusalLineForAPerson(resolved.error));\n return;\n }\n // Keep the newly written record so the chip can be named at once.\n if (!people.some((p) => p.id === resolved.data)) {\n setPeople((held) => [...held, { id: resolved.data, userId: member.userId, name: memberName(member) }]);\n }\n if (!field.multi) {\n onChange(picked[0] === resolved.data ? null : resolved.data);\n setOpen(false);\n return;\n }\n const next = new Set(picked);\n if (next.has(resolved.data)) next.delete(resolved.data);\n else next.add(resolved.data);\n onChange(next.size === 0 ? null : [...next]);\n };\n\n const drop = (recordId: string) => {\n const next = picked.filter((id) => id !== recordId);\n onChange(next.length === 0 ? null : field.multi ? next : (next[0] ?? null));\n };\n\n const visible = (members ?? []).filter((member) =>\n search.trim() === \"\" ? true : memberName(member).toLowerCase().includes(search.trim().toLowerCase()),\n );\n const pickedUserIds = new Set(\n picked.map((recordId) => people.find((p) => p.id === recordId)?.userId).filter(Boolean),\n );\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-1\", className)}>\n {picked.map((recordId) => (\n <RecordChip\n key={recordId}\n title={nameOfRecord(recordId)}\n {...(disabled ? {} : { onRemove: () => drop(recordId) })}\n />\n ))}\n {disabled ? null : (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n id={id}\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n aria-label={`Pick a person for ${fieldName(field)}`}\n >\n {picked.length === 0 ? \"Pick a person\" : \"Change\"}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-64 p-1\" align=\"start\">\n <BasicInput\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search people\"\n className=\"mb-1 h-7 text-xs\"\n />\n {error ? <p className=\"p-2 text-xs text-destructive\">{error}</p> : null}\n {members === null ? <p className=\"p-2 text-xs text-muted-foreground\">Reading the members…</p> : null}\n <ScrollArea className=\"max-h-56\">\n <ul>\n {visible.map((member) => (\n <li key={member.userId}>\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => void pick(member)}\n className={cn(\n \"w-full truncate rounded px-2 py-1 text-left text-xs hover:bg-muted\",\n pickedUserIds.has(member.userId) ? \"bg-accent text-accent-foreground\" : \"\",\n )}\n >\n {/* A name and an email with nothing between them read as\n one run-on string (verdict, 19 September). They are two\n facts, so they are drawn as two. */}\n <span>{memberName(member)}</span>\n {member.email && member.email !== memberName(member) ? (\n <span className=\"ml-1.5 opacity-60\">· {member.email}</span>\n ) : null}\n </button>\n </li>\n ))}\n </ul>\n {members !== null && visible.length === 0 ? (\n <p className=\"p-2 text-xs text-muted-foreground\">\n {members.length === 0\n ? \"This organization has no other members yet, so there is nobody to assign.\"\n : \"Nobody in this organization matches.\"}\n </p>\n ) : null}\n </ScrollArea>\n </PopoverContent>\n </Popover>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/editors.tsx — @ai-matrx/records-ui\n//\n// ONE EDITOR PER PARITY TYPE, and every one of them is a design-system\n// primitive. There is no bespoke input in this package and no per-feature\n// editor anywhere in the platform: a Field decides which of these is drawn,\n// from what the STORE stores about it (behaviour + modifiers + format + unit +\n// relation target), never from the value it happens to hold.\n//\n// FLD-9: a Formula is worked out by the system. Its editor is not a disabled\n// text box — it is the value with the sentence the store itself would say if\n// you tried to type into it.\n\nimport { useEffect, useState, type ReactNode } from \"react\";\nimport type { Field, RecordDocument, StoredRecord, Uuid } from \"@ai-matrx/records\";\nimport { choiceValuesOf, isTheChosen, optionKey } from \"@ai-matrx/records\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport {\n BasicInput,\n BasicTextarea,\n Badge,\n Button,\n Checkbox,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n cn,\n} from \"@ai-matrx/design-system\";\nimport { editorKindFor } from \"./parity\";\nimport { fieldName, recordName } from \"./names\";\nimport { RelationPicker } from \"./RelationPicker\";\nimport { PersonPicker } from \"./PersonPicker\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface FieldEditorControlProps {\n field: Field;\n value: unknown;\n onChange: (value: unknown) => void;\n disabled?: boolean | undefined;\n id?: string | undefined;\n}\n\n/** The label row every editor shares: one line, the label, the unit, the required mark. */\nexport function FieldLabel({ field, htmlFor, children }: { field: Field; htmlFor: string; children?: ReactNode }) {\n return (\n <div className=\"flex items-baseline gap-1.5\">\n <Label htmlFor={htmlFor} className=\"text-xs font-medium\">\n {fieldName(field)}\n </Label>\n {field.required ? <span className=\"text-xs text-destructive\">required</span> : null}\n {field.unit ? <span className=\"text-xs text-muted-foreground\">{field.unit}</span> : null}\n {children}\n </div>\n );\n}\n\nexport function FieldControl({ field, value, onChange, disabled, id }: FieldEditorControlProps) {\n const kind = editorKindFor(field);\n const inputId = id ?? `field-${field.key}`;\n\n switch (kind) {\n case \"formula\":\n case \"lookup\":\n case \"rollup\":\n return (\n <div id={inputId} className=\"rounded border border-dashed px-2 py-1.5 text-xs text-muted-foreground\">\n {/* The store's own sentence for typing into a computed field. */}\n {value === null || value === undefined ? \"—\" : String(value)}\n <span className=\"ml-2 italic\">\n {fieldName(field)} is worked out by the system, so it cannot be typed in\n </span>\n </div>\n );\n case \"json\":\n return <JsonControl field={field} value={value} onChange={onChange} disabled={disabled} id={inputId} />;\n case \"long_text\":\n return (\n <BasicTextarea\n id={inputId}\n rows={3}\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : e.target.value)}\n />\n );\n case \"number\":\n case \"currency\":\n case \"percent\":\n return (\n <BasicInput\n id={inputId}\n type=\"number\"\n inputMode=\"decimal\"\n className=\"tabular-nums\"\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : Number(e.target.value))}\n />\n );\n case \"datetime\":\n return (\n <BasicInput\n id={inputId}\n type={field.format === \"datetime\" ? \"datetime-local\" : \"date\"}\n value={value === null || value === undefined ? \"\" : String(value).slice(0, field.format === \"datetime\" ? 16 : 10)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : e.target.value)}\n />\n );\n case \"email\":\n case \"phone\":\n case \"url\":\n return (\n <BasicInput\n id={inputId}\n type={kind === \"email\" ? \"email\" : kind === \"phone\" ? \"tel\" : \"url\"}\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : e.target.value)}\n />\n );\n case \"select\":\n case \"multi_select\":\n return <OptionControl field={field} value={value} onChange={onChange} disabled={disabled} id={inputId} />;\n case \"member\":\n // A person field asks who is in the organization, never what is in a\n // Table — see PersonPicker's header for the screen that made this split.\n return <PersonPicker field={field} value={value} onChange={onChange} disabled={disabled} id={inputId} />;\n case \"relation\":\n case \"attachment\":\n return <RelationPicker field={field} value={value} onChange={onChange} disabled={disabled} id={inputId} />;\n default:\n if (typeof value === \"boolean\" || field.config?.[\"kind\"] === \"boolean\") {\n return (\n <Checkbox\n id={inputId}\n checked={value === true}\n disabled={disabled}\n onCheckedChange={(next) => onChange(next === true)}\n />\n );\n }\n return (\n <BasicInput\n id={inputId}\n value={value === null || value === undefined ? \"\" : String(value)}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value === \"\" ? null : e.target.value)}\n />\n );\n }\n}\n\n/**\n * A document-shaped value, edited as the text it is. It is parsed on every\n * keystroke and the PARSE FAILURE IS SHOWN — a box that silently handed the\n * store unparseable text and let it answer `22P02 invalid input syntax` is a\n * refusal the person could have been spared half a second earlier.\n */\nfunction JsonControl({ field, value, onChange, disabled, id }: FieldEditorControlProps) {\n const initial = value === null || value === undefined ? \"\" : typeof value === \"string\" ? value : JSON.stringify(value, null, 2);\n const [text, setText] = useState(initial);\n const [broken, setBroken] = useState<string | null>(null);\n return (\n <div className=\"flex flex-col gap-1\">\n <BasicTextarea\n id={id}\n rows={4}\n className=\"font-mono text-[11px]\"\n value={text}\n disabled={disabled}\n onChange={(e) => {\n const next = e.target.value;\n setText(next);\n if (next.trim() === \"\") {\n setBroken(null);\n onChange(null);\n return;\n }\n try {\n onChange(JSON.parse(next));\n setBroken(null);\n } catch (thrown) {\n setBroken(thrown instanceof Error ? thrown.message : String(thrown));\n }\n }}\n />\n {broken ? (\n <p className=\"text-xs text-destructive\">\n {fieldName(field)} is not readable as structured data yet: {broken}\n </p>\n ) : null}\n </div>\n );\n}\n\n/**\n * FLD-5 / FLD-6. A pick-list IS a Table and an option is a Record of it — that part is\n * unchanged. What a CELL holds is the option's own stable WORD (its key), not the\n * option record's uuid, so renaming a choice rewrites no row; the read doors hand\n * back the LABEL and name the key beside it in `_choices`. This control therefore\n * recognises all three ways of naming the same choice — `isTheChosen` — and WRITES\n * the key, which is the contract. The options are read through the store's own\n * `custom.field_options` door, which resolves the options Table from the Field's\n * config — this component never has to know which Table that is.\n */\nfunction OptionControl({ field, value, onChange, disabled, id }: FieldEditorControlProps) {\n const client = useRecordsClient();\n const [options, setOptions] = useState<StoredRecord[] | null>(null);\n const [refusal, setRefusal] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void client.fieldOptions({ field_id: field.id }).then((result) => {\n if (cancelled) return;\n if (result.ok) setOptions(result.data ?? []);\n else setRefusal(refusalLineForAPerson(result.error));\n });\n return () => {\n cancelled = true;\n };\n }, [client, field.id]);\n\n // EVERY STATE CARRIES THE CELL'S OWN ID. A cell that identified itself only\n // when it happened to be a text box is a cell nobody can tell apart from the\n // developer window that used to open instead of it.\n if (refusal) return <p id={id} className=\"text-xs text-destructive\">{refusal}</p>;\n if (!options) return <p id={id} className=\"text-xs text-muted-foreground\">Reading this field's choices…</p>;\n if (options.length === 0) {\n // Two different facts, and a person acts on them differently: a choice\n // field whose Table is empty, and a choice field that names no Table at\n // all. One blank control for both is the silent failure.\n return (\n <p id={id} className=\"text-xs text-muted-foreground\">\n {field.options_table_id\n ? `${fieldName(field)} takes its choices from a Table that has no records yet — add the choices there and they appear here.`\n : `${fieldName(field)} does not name the Table its choices come from yet, so there is nothing to choose. A table admin sets it in the field editor.`}\n </p>\n );\n }\n\n const titleOf = (option: StoredRecord) =>\n recordName(option.data as RecordDocument | undefined, null, \"Unnamed choice\");\n\n if (field.multi) {\n // WHAT IS PICKED, however the value says it. The document a read door hands this\n // control carries LABELS; the row holds KEYS; a screen written before this contract\n // sends IDS. `isTheChosen` knows all three, and what goes back is always the key.\n const chosen = options.filter((option) => choiceValuesOf(value).some((v) => isTheChosen(option, v)));\n const picked = new Set(chosen.map((option) => optionKey(option)));\n return (\n <div id={id} className=\"flex flex-wrap gap-1\">\n {options.map((option) => (\n <Button\n key={option.id}\n type=\"button\"\n size=\"sm\"\n variant={picked.has(optionKey(option)) ? \"default\" : \"outline\"}\n disabled={disabled}\n onClick={() => {\n const next = new Set(picked);\n if (next.has(optionKey(option))) next.delete(optionKey(option));\n else next.add(optionKey(option));\n onChange(next.size === 0 ? null : [...next]);\n }}\n >\n {titleOf(option)}\n </Button>\n ))}\n </div>\n );\n }\n\n // The SINGLE choice, the same way: what is selected is worked out from the option, not\n // from a string comparison against whatever spelling the document happened to use, and\n // what goes back is the key.\n const current = options.find((option) => isTheChosen(option, value));\n return (\n <Select\n value={current ? optionKey(current) : \"\"}\n disabled={disabled ?? false}\n onValueChange={(next) => onChange(next === \"\" ? null : next)}\n >\n <SelectTrigger id={id} size=\"sm\">\n <SelectValue placeholder=\"Choose\" />\n </SelectTrigger>\n <SelectContent>\n {options.map((option) => (\n <SelectItem key={option.id} value={optionKey(option)}>\n {titleOf(option)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\n/** The chip a picked record shows as — REC-2's \"a record is a chip\" in one place. */\nexport function RecordChip({\n title,\n onRemove,\n className,\n}: {\n title: string;\n onRemove?: (() => void) | undefined;\n className?: string | undefined;\n}) {\n return (\n <Badge variant=\"secondary\" className={cn(\"gap-1 text-[11px]\", className)}>\n {title}\n {onRemove ? (\n <button type=\"button\" onClick={onRemove} aria-label={`Remove ${title}`} className=\"opacity-60 hover:opacity-100\">\n ×\n </button>\n ) : null}\n </Badge>\n );\n}\n\nexport type { Uuid };\n","// src/parity.ts — @ai-matrx/records-ui\n//\n// FLD-11, the parity floor. A Field stores a BEHAVIOUR (one of five) plus\n// modifiers, unit and format; a person picked one of THIRTEEN parity types in\n// the UI. This resolves the second from the first, using the same facts the\n// store's own `custom.parity_field_types()` describes — which is generated into\n// `@ai-matrx/records` and imported here, never retyped.\n//\n// Nothing in this file decides policy. It decides which editor to draw.\n\nimport { KERNEL_TABLES, PARITY_FIELD_TYPES, type Field, type ParityFieldType } from \"@ai-matrx/records\";\nimport { humanize } from \"./names\";\nimport { fieldTypeChoice } from \"./fieldTypes\";\n\n/** The kernel ids come from the store's own kernel rows, never from a literal here. */\nconst kernelId = (name: string): string =>\n KERNEL_TABLES.find((t) => t.name === name)?.id ?? \"\";\nconst KERNEL_FILE_TABLE = kernelId(\"File\");\nconst KERNEL_PERSON_TABLE = kernelId(\"Person\");\n\nexport const PARITY_LABEL: Record<ParityFieldType, string> = {\n attachment: \"Attachment\",\n currency: \"Currency\",\n datetime: \"Date\",\n email: \"Email\",\n formula: \"Formula\",\n lookup: \"Lookup\",\n member: \"Person\",\n multi_select: \"Multi-select\",\n percent: \"Percent\",\n phone: \"Phone\",\n rollup: \"Rollup\",\n select: \"Select\",\n url: \"Link\",\n};\n\n/** The \"made of\" sentence the store itself publishes, for the field editor's help text. */\nexport const PARITY_MADE_OF: Record<string, string> = Object.fromEntries(\n PARITY_FIELD_TYPES.map((p) => [p.parity_type, p.made_of]),\n);\n\n/** Plain text and plain number are behaviours with no parity type of their own. */\nexport type EditorKind =\n | ParityFieldType\n | \"relation\"\n | \"text\"\n | \"number\"\n | \"boolean\"\n | \"date\"\n | \"json\"\n | \"long_text\";\n\n/**\n * Which editor one Field wants. Reads the Field's own declaration only — the\n * behaviour, the modifiers, the format, the relation target and the config —\n * because those are what the store stores, and a screen that guessed from a\n * value would draw a different editor for an empty record.\n */\nexport function editorKindFor(field: Field): EditorKind {\n const format = (field.format ?? \"\").toLowerCase();\n const config = field.config ?? {};\n switch (field.type) {\n case \"text\":\n if (format === \"email\") return \"email\";\n if (format === \"phone\") return \"phone\";\n if (format === \"url\") return \"url\";\n // FLD-1: a document-shaped value is a `text` behaviour carrying a format.\n // It gets its own editor because a person typing JSON into a one-line box\n // and getting `22P02` back is the failure this resolves ahead of time.\n if (format === \"json\" || config[\"json\"] === true) return \"json\";\n if (format === \"long\" || config[\"multiline\"] === true) return \"long_text\";\n return \"text\";\n case \"range\": {\n const kind = String(config[\"kind\"] ?? \"number\");\n if (kind === \"date\" || kind === \"datetime\") return \"datetime\";\n // THE FORMAT, AND ONLY THE FORMAT. This used to read\n // `format === \"currency\" || (field.unit ?? \"\").length > 1`, and a unit is\n // not a currency: a quantity in `units` was drawn as money, which is how\n // three of something rendered as \"units3\" (verdict, 19 September). The\n // store's own `custom.parity_type` asks the same question the same way —\n // a currency is a range whose FORMAT is currency and which has a unit.\n if (format === \"currency\") return \"currency\";\n if (format === \"percent\" || field.unit === \"%\") return \"percent\";\n return \"number\";\n }\n case \"list\":\n return field.multi ? \"multi_select\" : \"select\";\n case \"relation\":\n return relationEditor(field);\n case \"formula\": {\n const via = config[\"via\"];\n if (via && config[\"agg\"]) return \"rollup\";\n if (via) return \"lookup\";\n return \"formula\";\n }\n default:\n return \"text\";\n }\n}\n\n/**\n * REC-31 / FLD-11: a relation is an `attachment` when it points at the kernel\n * File Table and a `member` when it points at the kernel Person Table. Every\n * other relation is drawn by the generic picker, which is what `\"relation\"`\n * means here — the one primitive SCR-N-2 says must exist.\n */\nfunction relationEditor(field: Field): EditorKind {\n const parity = String(field.config?.[\"parity\"] ?? \"\");\n if (parity === \"attachment\" || parity === \"member\") return parity;\n if (field.relation_target === KERNEL_FILE_TABLE) return \"attachment\";\n if (field.relation_target === KERNEL_PERSON_TABLE) return \"member\";\n return \"relation\" as EditorKind;\n}\n\n/**\n * The type word a person sees in a header or a settings row — and it is the\n * SAME word the field panel offers, read from `FIELD_TYPE_CHOICES`, so a column\n * added as \"Money\" is never described anywhere else as \"Currency\".\n */\nexport function fieldTypeLabel(field: Field): string {\n const kind = editorKindFor(field);\n const known = fieldTypeChoice(kind)?.label;\n if (known) return field.multi && kind !== \"multi_select\" ? `${known} (many)` : known;\n const plain: Record<string, string> = {\n boolean: \"Yes / no\",\n date: \"Date\",\n json: \"Structured data\",\n relation: \"Link to a record\",\n };\n // Never a raw token on a screen: an editor kind this table has not named is\n // still written the way a person writes it.\n return plain[kind] ?? humanize(kind);\n}\n","// src/fieldTypes.ts — @ai-matrx/records-ui\n//\n// THE SIXTEEN THINGS A COLUMN CAN HOLD, IN THE WORDS A PERSON USES.\n//\n// The store publishes thirteen parity types and, for each, a sentence about what\n// it is MADE OF — \"REC-31: a File record reached through a relation, target the\n// kernel `File` Table\", \"FLD-9: a declared computation, on read or on write,\n// evaluated by custom.rule_eval\", \"config.via names the relation field,\n// config.pick the Value on the far side\". Those sentences are true and they are\n// for us. The 19 September verdict found them printed at the person choosing a\n// column type, alongside contract row ids, and called it what it is: machine\n// identity where a person is looking.\n//\n// So this file holds the OTHER sentence — what the type is FOR — and the field\n// panel shows that one. The store's own `made_of` stays where it belongs, in\n// `PARITY_MADE_OF`, for an engineer reading the package.\n//\n// The LIST itself is still the store's: `PARITY_FIELD_TYPES` is generated from\n// `custom.parity_field_types()`, and `assertEveryParityTypeIsExplained` (run by\n// the suite) fails the moment the store ships a fourteenth and nobody wrote a\n// sentence for it. A type with no explanation would otherwise appear with a\n// blank line under it, which is the silent version of the same defect.\n\nimport { PARITY_FIELD_TYPES, type ParityFieldType } from \"@ai-matrx/records\";\n\n/** The three behaviours that carry no parity type of their own. */\nexport type PlainFieldType = \"text\" | \"long_text\" | \"number\";\n\n/** What a person picks in the panel: one of the thirteen, or one of the three. */\nexport type PickableFieldType = ParityFieldType | PlainFieldType;\n\nexport interface FieldTypeChoice {\n id: PickableFieldType;\n /** The word on the menu. */\n label: string;\n /** One line, under the word, saying what it is FOR. Never what it is made of. */\n explanation: string;\n /** The heading it sits under, so sixteen choices read as four short lists. */\n group: \"Words\" | \"Numbers and dates\" | \"Choices and people\" | \"Worked out\";\n}\n\nexport const FIELD_TYPE_CHOICES: FieldTypeChoice[] = [\n { id: \"text\", group: \"Words\", label: \"Text\", explanation: \"A short line of writing — a name, a reference, a title.\" },\n { id: \"long_text\", group: \"Words\", label: \"Long text\", explanation: \"Several lines — a description, notes, an address.\" },\n { id: \"email\", group: \"Words\", label: \"Email address\", explanation: \"An email address, checked as you type and ready to write to.\" },\n { id: \"phone\", group: \"Words\", label: \"Phone number\", explanation: \"A phone number, checked as you type.\" },\n { id: \"url\", group: \"Words\", label: \"Link\", explanation: \"A web address that opens in a new tab when you click it.\" },\n\n { id: \"number\", group: \"Numbers and dates\", label: \"Number\", explanation: \"A plain number you can total up and sort by.\" },\n { id: \"currency\", group: \"Numbers and dates\", label: \"Money\", explanation: \"An amount of money, shown with its currency wherever it appears.\" },\n { id: \"percent\", group: \"Numbers and dates\", label: \"Percentage\", explanation: \"A number out of a hundred, kept between 0 and 100.\" },\n { id: \"datetime\", group: \"Numbers and dates\", label: \"Date\", explanation: \"A day, or a day and a time. Dates are what the calendar view reads.\" },\n\n { id: \"select\", group: \"Choices and people\", label: \"Choice\", explanation: \"One answer from a list you write here. Choices are what the board view groups by.\" },\n { id: \"multi_select\", group: \"Choices and people\", label: \"Several choices\", explanation: \"Any number of answers from a list you write here.\" },\n { id: \"member\", group: \"Choices and people\", label: \"Person\", explanation: \"Somebody in this organization, picked from the people who are in it.\" },\n { id: \"attachment\", group: \"Choices and people\", label: \"File\", explanation: \"A file or a picture kept with the record.\" },\n\n { id: \"lookup\", group: \"Worked out\", label: \"Borrowed value\", explanation: \"A value read from a record this one points at, kept in step with it.\" },\n { id: \"rollup\", group: \"Worked out\", label: \"Total of linked records\", explanation: \"A count or a total worked out from the records this one points at.\" },\n { id: \"formula\", group: \"Worked out\", label: \"Worked out from other columns\", explanation: \"A value this record works out for itself from its own other columns.\" },\n];\n\nexport const FIELD_TYPE_GROUPS: FieldTypeChoice[\"group\"][] = [\n \"Words\",\n \"Numbers and dates\",\n \"Choices and people\",\n \"Worked out\",\n];\n\nconst BY_ID = new Map<string, FieldTypeChoice>(FIELD_TYPE_CHOICES.map((c) => [c.id, c]));\n\nexport function fieldTypeChoice(id: string): FieldTypeChoice | undefined {\n return BY_ID.get(id);\n}\n\n/** The three that are a plain behaviour rather than one of the thirteen. */\nexport function isPlainFieldType(id: string): id is PlainFieldType {\n return id === \"text\" || id === \"long_text\" || id === \"number\";\n}\n\n/**\n * THE GUARD THIS FILE NEEDS, because the list it explains is generated.\n *\n * Returns the parity types the store ships that nothing here explains. The\n * suite asserts it is empty; a fourteenth type would otherwise reach the menu\n * with a blank line under it and nobody would notice until a person did.\n */\nexport function parityTypesWithNoExplanation(): string[] {\n return PARITY_FIELD_TYPES.map((row) => row.parity_type).filter((type) => !BY_ID.has(type));\n}\n","\"use client\";\n\n// src/RelationPicker.tsx — @ai-matrx/records-ui · SCR-N-2\n//\n// THE ONE GENERIC RELATION PICKER. Before it, every relation-shaped field in\n// the product had a type-specific picker (image, file, url, scope) and a plain\n// `relation` field was not editable at all.\n//\n// It reads the target Table's records through the read door, shows each one as\n// its own chip (REC-2: the title field is what makes a record a chip), and\n// respects `relation_max` by saying the number rather than silently dropping a\n// pick.\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { Field, ReadRow, Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport {\n BasicInput,\n Button,\n Popover,\n PopoverContent,\n PopoverTrigger,\n ScrollArea,\n cn,\n} from \"@ai-matrx/design-system\";\nimport { RecordChip } from \"./editors\";\nimport { WITHHELD_RECORD_LABEL, fieldName, rowName } from \"./names\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface RelationPickerProps {\n field: Field;\n value: unknown;\n onChange: (value: unknown) => void;\n disabled?: boolean | undefined;\n id?: string | undefined;\n className?: string | undefined;\n}\n\nexport function RelationPicker({ field, value, onChange, disabled, id, className }: RelationPickerProps) {\n const client = useRecordsClient();\n const [rows, setRows] = useState<ReadRow[] | null>(null);\n const [titleKey, setTitleKey] = useState<string | null>(null);\n // A picked record that is NOT in the target Table's visible page: resolved one\n // at a time through the read door, which is the only thing that can tell\n // \"shared with somebody else\" apart from \"further down the list\".\n const [elsewhere, setElsewhere] = useState<Record<string, string>>({});\n const [refusal, setRefusal] = useState<string | null>(null);\n const [search, setSearch] = useState(\"\");\n const [open, setOpen] = useState(false);\n\n const picked = useMemo<string[]>(\n () => (Array.isArray(value) ? value.map(String) : value === null || value === undefined ? [] : [String(value)]),\n [value],\n );\n\n // ── THE TARGET TABLE, ON MOUNT AND NOT ON OPEN (RELATION-DECLARE, 2026-09-20).\n // This used to wait for the popover, so every chip on every relation cell read\n // \"Loading…\" until somebody clicked Pick — a word that never resolved, on a\n // screen nobody was going to click. A chip is a NAME; it is read far more often\n // than it is changed, so what it needs is fetched when the cell is drawn.\n //\n // The Table comes with it, for its `title_field`. REC-2 says the title field is\n // what makes a record a chip, and this picker was ignoring it and trying\n // title/name/label instead — so a Table whose title field is `cname` drew\n // \"Untitled\" for every chip and every option in the list, and the picker was\n // unusable for exactly the tables a person builds themselves.\n useEffect(() => {\n const target = field.relation_target;\n if (!target) return;\n let cancelled = false;\n void client.list({ table_id: target as Uuid, limit: 200 }).then((result) => {\n if (cancelled) return;\n if (result.ok) setRows(result.data.rows);\n else setRefusal(refusalLineForAPerson(result.error));\n });\n void client.tableList().then((result) => {\n if (cancelled || !result.ok) return;\n setTitleKey(result.data.find((table) => table.id === target)?.title_field ?? null);\n });\n return () => {\n cancelled = true;\n };\n }, [client, field.relation_target]);\n\n // ── AND THE ONES THAT ARE NOT IN THAT PAGE.\n // A relation joins two records in two tables and holding one end says nothing\n // about the other: a Job shared with you may point at a Client nobody shared.\n // The read door answers exactly what this reader may see, so an id it does not\n // return is either further down a long list or not hers — and the two have\n // different sentences, so they are asked apart rather than guessed at. The\n // answer for a record she may not open is the same words the store itself gives\n // (`platform.relation_withheld_label()`): never the title, never a bare id, and\n // never a \"Loading…\" that resolves for nobody.\n useEffect(() => {\n if (!rows) return;\n const known = new Set(rows.map((row) => row.id));\n const missing = picked.filter((id) => !known.has(id) && elsewhere[id] === undefined);\n if (missing.length === 0) return;\n let cancelled = false;\n void Promise.all(\n missing.map(async (id) => {\n const result = await client.recordRead({ record_id: id as Uuid });\n return [id, result.ok ? rowName({ document: result.data.document } as ReadRow, titleKey) : WITHHELD_RECORD_LABEL] as const;\n }),\n ).then((pairs) => {\n if (cancelled) return;\n setElsewhere((current) => ({ ...current, ...Object.fromEntries(pairs) }));\n });\n return () => {\n cancelled = true;\n };\n }, [client, rows, picked, elsewhere, titleKey]);\n\n if (!field.relation_target) {\n // Absent, and honest about why: a relation with no declared target is a\n // Field the store has not finished, not a picker that \"has no options\".\n return (\n <p className=\"text-xs text-muted-foreground\">\n {fieldName(field)} points at records, but it does not say which Table yet, so there is nothing to pick\n from. A table admin sets its target in the field editor.\n </p>\n );\n }\n\n const byId = new Map((rows ?? []).map((row) => [row.id, row]));\n // A chip carries the record's NAME. Before `names.ts`, a relation whose\n // target had not loaded yet drew `8f2c1b0a` — a bare identifier, which the\n // verdict of 19 September counted among the three things a first-time user\n // feels within a minute. It now reads the Table's own title field (REC-2), and\n // a record that is not this reader's says so in the store's own words instead\n // of waiting forever.\n const titleOf = (recordId: string) => {\n const row = byId.get(recordId);\n if (row) return rowName(row, titleKey, \"Untitled\");\n const away = elsewhere[recordId];\n if (away !== undefined) return away;\n return \"Loading…\";\n };\n const full = field.multi && field.relation_max !== null && picked.length >= field.relation_max;\n\n const toggle = (recordId: string) => {\n if (!field.multi) {\n onChange(picked[0] === recordId ? null : recordId);\n setOpen(false);\n return;\n }\n const next = new Set(picked);\n if (next.has(recordId)) next.delete(recordId);\n else if (!full) next.add(recordId);\n onChange(next.size === 0 ? null : [...next]);\n };\n\n const visible = (rows ?? []).filter((row) =>\n search.trim() === \"\" ? true : titleOf(row.id).toLowerCase().includes(search.trim().toLowerCase()),\n );\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-1\", className)}>\n {picked.map((recordId) => (\n <RecordChip\n key={recordId}\n title={titleOf(recordId)}\n {...(disabled ? {} : { onRemove: () => toggle(recordId) })}\n />\n ))}\n {disabled ? null : (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button id={id} type=\"button\" size=\"sm\" variant=\"outline\" aria-label={`Pick for ${fieldName(field)}`}>\n {picked.length === 0 ? \"Pick\" : \"Change\"}\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-64 p-1\" align=\"start\">\n <BasicInput\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder=\"Search\"\n className=\"mb-1 h-7 text-xs\"\n />\n {refusal ? <p className=\"p-2 text-xs text-destructive\">{refusal}</p> : null}\n {!rows && !refusal ? <p className=\"p-2 text-xs text-muted-foreground\">Reading…</p> : null}\n {full ? (\n <p className=\"p-2 text-xs text-muted-foreground\">\n {fieldName(field)} can point at {field.relation_max} at most. Remove one to add another.\n </p>\n ) : null}\n <ScrollArea className=\"max-h-56\">\n <ul>\n {visible.map((row) => (\n <li key={row.id}>\n <button\n type=\"button\"\n onClick={() => toggle(row.id)}\n className={cn(\n \"w-full truncate rounded px-2 py-1 text-left text-xs hover:bg-muted\",\n picked.includes(row.id) ? \"bg-accent text-accent-foreground\" : \"\",\n )}\n >\n {titleOf(row.id)}\n </button>\n </li>\n ))}\n </ul>\n {rows && visible.length === 0 ? (\n <p className=\"p-2 text-xs text-muted-foreground\">Nothing in that table matches.</p>\n ) : null}\n </ScrollArea>\n </PopoverContent>\n </Popover>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/gridEditing.tsx — @ai-matrx/records-ui · SCR-1 / REC-9\n//\n// EDITING A RECORD WHERE IT IS SHOWN.\n//\n// Until this file existed, the grid was a read-only window: double-clicking a\n// cell opened a panel of raw JSON with no control, no Save and no Delete, and\n// the only way to write anything was the whole \"New record\" form. The\n// independent verdict of 19 September put it first of three: \"In Airtable you\n// click a cell and type. Here a cell opens a read-only window of programming\n// text… Every other gap is downstream of this one.\"\n//\n// WHAT THIS IS, AND WHAT IT DELIBERATELY IS NOT\n// ---------------------------------------------\n// `@ai-matrx/design-system`'s data table HAS an inline editor\n// (`EditableTableCell`) and this package does not use it here, for one reason\n// that is not taste: that editor speaks six value shapes (string, number,\n// boolean, select, tags, date) and collects edits into a draft map that a\n// floating Save pill persists. A Field in this store is one of THIRTEEN parity\n// types — a relation, a person, a file, a multi-choice whose options are the\n// records of another Table, a json document, a formula that cannot be typed\n// into at all — and every one of them already has exactly one editor in this\n// package (`FieldControl`, itself built from design-system primitives). Two\n// editing models on one screen is the fork the inventory law forbids, so the\n// cell hosts the ONE editor a Field already has, and the write goes through the\n// ONE write door with the version the person started from.\n//\n// THE CONCURRENCY STORY, WHICH IS THE WHOLE POINT OF REC-9\n// -------------------------------------------------------\n// The read door answers documents, never versions. So the FIRST time a person\n// edits a given record in this session, the version is read for that one record\n// (`custom.io_revisions`) and remembered. Every save from then on carries it,\n// and the store — not this screen — decides whether somebody else got there\n// first. When it did, the store raises `PT409` with the other person's value in\n// the detail, and the cell shows THAT: their value, beside the value being\n// written, with a Retry that re-reads the version and writes again, and a\n// \"Keep theirs\" that drops the edit. Nothing is silently overwritten and\n// nothing is silently lost.\n//\n// OPTIMISTIC, BUT NEVER DISHONEST: the typed value is shown the instant it is\n// committed, and it is REMOVED again the moment the store refuses. A cell that\n// kept showing a value the store rejected is the lie this package exists to\n// prevent.\n//\n// WHERE THE TYPED VALUE LIVES, AND WHY IT MOVED (independent verdict, fifth\n// pass, 19 September): \"when we tabbed along a row, the first five values saved\n// and the last four were silently dropped; typing a phone number and pressing\n// Enter left the editor open and wrote nothing, with no message anywhere.\"\n//\n// The draft used to be `useState` INSIDE the open cell. That makes the typed\n// value a property of a component which this screen re-renders constantly and\n// for reasons that have nothing to do with the person typing: every accepted\n// write calls `reload()`, the reloaded page rebuilds `rows`, the columns are\n// rebuilt from them, and the data table rebuilds its cells. A cell that\n// remounts mid-edit comes back with `draft` re-initialised from the STORED\n// value — so the commit that followed wrote what was already there, which the\n// screen then correctly treated as \"nothing changed\" and dropped in silence.\n// The faster you tabbed, the more reloads landed inside your own editing, which\n// is exactly why it was the LAST four and not the first.\n//\n// So the draft lives HERE, in the editing session, beside the address of the\n// cell that is open — one value, owned by the thing that also owns which cell\n// is open and which version it started from. A re-render cannot lose it,\n// because a re-render does not touch it. `commit(move)` takes no value at all:\n// there is exactly one typed value and exactly one place it can be read from,\n// so there is no second copy to be stale.\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type FocusEvent } from \"react\";\nimport type { Field, ReadRow, RecordsError, Uuid } from \"@ai-matrx/records\";\nimport type { WriteConflict } from \"@ai-matrx/records\";\nimport { asWriteConflict, type RecordsClient } from \"@ai-matrx/records/core\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport { Button, cn } from \"@ai-matrx/design-system\";\n\nimport { FieldControl } from \"./editors\";\nimport { RefusalLine } from \"./Refusal\";\nimport { editorKindFor } from \"./parity\";\nimport { fieldName } from \"./names\";\nimport { RecordValue } from \"./values\";\nimport type { FieldFormatConfig } from \"@ai-matrx/design-system/field-formats\";\n\n/** Which cell is open. A grid opens exactly one at a time, like every other grid. */\nexport interface CellAddress {\n rowId: Uuid;\n key: string;\n}\n\n/** What one cell is doing right now, so nothing about it is guessed by a caller. */\nexport type CellState = \"clean\" | \"saving\" | \"refused\";\n\nexport interface CellRefusal {\n error: RecordsError;\n /** Present when the store said `PT409`: the other person's value, from the store. */\n conflict: WriteConflict | null;\n /** The value that was being written, so Retry can write it again. */\n attempted: unknown;\n}\n\n/**\n * FLD-9. A computed Field is not editable and never will be — the store works\n * it out. Saying so here, once, keeps every caller from re-deciding it.\n */\nexport function fieldIsEditable(field: Field): boolean {\n const kind = editorKindFor(field);\n return kind !== \"formula\" && kind !== \"lookup\" && kind !== \"rollup\";\n}\n\nexport interface GridEditing {\n /** The value to DRAW for one cell — the optimistic one when there is one. */\n valueFor: (row: ReadRow, field: Field) => unknown;\n editing: CellAddress | null;\n /** What has been typed into the open cell. Owned here, never by the cell. */\n draft: unknown;\n /** The open cell's editor reports every keystroke to the session. */\n type: (value: unknown) => void;\n stateOf: (rowId: Uuid, key: string) => CellState;\n refusalOf: (rowId: Uuid, key: string) => CellRefusal | null;\n begin: (address: CellAddress) => void;\n cancel: () => void;\n /**\n * Commit the open cell — whatever is in `draft`. `move` opens the\n * next/previous editable cell after it. It takes NO value: a caller that\n * passed one would be a second copy of the typed value, which is the defect\n * this file's header describes.\n */\n commit: (move?: \"next\" | \"previous\" | null) => void;\n /** Write the attempted value again, after re-reading the version. */\n retry: (rowId: Uuid, key: string) => void;\n /** Drop the edit and show what the other person wrote. */\n keepTheirs: (rowId: Uuid, key: string) => void;\n /** Soft delete, through the store's own door. Answers the store's refusal, or null. */\n remove: (rowId: Uuid) => Promise<RecordsError | null>;\n /** Write an empty record and open its first editable cell. */\n addRecord: () => Promise<RecordsError | null>;\n /** The last refusal from a delete or an add, for the grid to print. */\n rowError: RecordsError | null;\n clearRowError: () => void;\n busy: boolean;\n}\n\ninterface Options {\n tableId: Uuid;\n fields: Field[];\n rows: ReadRow[];\n /** Re-read the page once the store has accepted something. */\n reload: () => void;\n /** May this person write records at all? A read-only grid opens no editor. */\n canWrite: boolean;\n /**\n * MAY THIS PERSON WRITE *THIS* ROW — asked before an editor is opened, never\n * after it has been typed into.\n *\n * A level on the TABLE is not the answer for a row: the sixth-pass verdict\n * found a record shared with a colleague at Editor inside a table she held at\n * Viewer, and the grid labelled the row \"viewer\" while the store let her\n * write to it. Unbound, every row follows the table, which is what the\n * ordinary case is.\n */\n mayWriteRow?: ((rowId: Uuid) => boolean) | undefined;\n}\n\n/**\n * THE VERSION THE PERSON STARTED FROM, read once per record per session.\n *\n * Not read for the page: a list of two hundred records would be two hundred\n * extra door calls for a person who is going to edit one cell. Not guessed\n * either — `null` means \"we never read one\", and the save then carries no\n * expected version and is the store's ordinary last-writer-wins write, exactly\n * as the store defines it.\n */\nasync function versionOf(\n client: RecordsClient,\n cache: Map<string, number>,\n inFlight: Map<string, Promise<number | null>>,\n recordId: Uuid,\n): Promise<number | null> {\n const held = cache.get(recordId);\n if (held !== undefined) return held;\n // ONE READ PER RECORD, AND IT CAN NEVER PUT BACK AN OLDER VERSION.\n //\n // Opening a cell asks for the version, and tabbing on asks again for the next\n // cell — the same record, both before either answer is back, so the cache was\n // empty for both and two reads went out. The write between them then stored\n // the store's NEW version, and whichever read landed last overwrote it with\n // the old one. The next cell of that row was written with a version the store\n // had already moved past, and a person tabbing through their own row was\n // refused for a conflict with themselves. Measured 2026-09-20.\n //\n // So: callers share one read per record, and a read only ever raises what is\n // held. A version is a high-water mark, never a replacement.\n const already = inFlight.get(recordId);\n if (already) return already;\n const reading = (async () => {\n const answered = await client.revisions({ record_id: recordId });\n if (!answered.ok) return null;\n const newest = answered.data.reduce<number | null>(\n (best, row) => (best === null || row.version > best ? row.version : best),\n null,\n );\n if (newest !== null) rememberVersion(cache, recordId, newest);\n return cache.get(recordId) ?? newest;\n })();\n inFlight.set(recordId, reading);\n try {\n return await reading;\n } finally {\n inFlight.delete(recordId);\n }\n}\n\n/** A version only ever goes up. See `versionOf`. */\nfunction rememberVersion(cache: Map<string, number>, recordId: Uuid, version: number): void {\n const held = cache.get(recordId);\n if (held === undefined || version > held) cache.set(recordId, version);\n}\n\nexport function useGridEditing({ tableId, fields, rows, reload, canWrite, mayWriteRow }: Options): GridEditing {\n const client = useRecordsClient();\n const [editing, setEditing] = useState<CellAddress | null>(null);\n // THE TYPED VALUE, and what the open cell started from — one copy of each,\n // here, where no re-render of a cell can reach them. See the file header.\n //\n // AND THE TYPED VALUE IS READ FROM A REF, NOT FROM STATE — the second half of\n // the same lesson, and it cost a suite run per column to learn. Moving the\n // draft out of the cell stopped a re-render from RESETTING it; it did not\n // stop a commit from reading a STALE COPY of it. `commit` closed over `draft`\n // and the open cell's key handler closed over `commit`, so a Tab that arrived\n // before the grid had re-rendered with the new draft committed the value from\n // before the keystroke — `sameValue` then said \"nothing changed\" and dropped\n // it in silence. Exactly one column of a tabbed row, a different one each\n // time, which is what made it look like the store rather than the screen.\n //\n // There is ONE typed value and ONE place to read it, and that place cannot be\n // captured stale by a closure.\n const [draft, setDraft] = useState<unknown>(null);\n const typed = useRef<unknown>(null);\n const startedFrom = useRef<unknown>(null);\n const type = useCallback((value: unknown) => {\n typed.current = value;\n setDraft(value);\n }, []);\n const [optimistic, setOptimistic] = useState<Record<string, unknown>>({});\n const [saving, setSaving] = useState<Record<string, true>>({});\n const [refusals, setRefusals] = useState<Record<string, CellRefusal>>({});\n const [rowError, setRowError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n const versions = useRef(new Map<string, number>());\n /** One version read per record in flight at a time — see `versionOf`. */\n const versionReads = useRef(new Map<string, Promise<number | null>>());\n // ONE WRITE AT A TIME PER RECORD. Tabbing across a row commits each cell the\n // instant the next one opens, so two writes of the SAME record were in flight\n // together and the second carried the version the first had already moved:\n // the store answered PT409 and a person tabbing through their own row was\n // shown a conflict with themselves. Measured 2026-09-19 in the headless walk.\n // The store was right both times; the screen was firing them in parallel.\n const queues = useRef(new Map<string, Promise<void>>());\n\n const editable = useMemo(() => fields.filter(fieldIsEditable), [fields]);\n const order = useMemo(() => editable.map((f) => f.key), [editable]);\n const rowIds = useMemo(() => rows.map((r) => r.id), [rows]);\n\n const cellKey = (rowId: Uuid, key: string) => `${rowId}::${key}`;\n\n const valueFor = useCallback(\n (row: ReadRow, field: Field) => {\n const held = optimistic[cellKey(row.id, field.key)];\n return held === undefined ? row.document?.[field.key] : held;\n },\n [optimistic],\n );\n\n const stateOf = useCallback(\n (rowId: Uuid, key: string): CellState => {\n const id = cellKey(rowId, key);\n if (saving[id]) return \"saving\";\n if (refusals[id]) return \"refused\";\n return \"clean\";\n },\n [saving, refusals],\n );\n\n const refusalOf = useCallback(\n (rowId: Uuid, key: string) => refusals[cellKey(rowId, key)] ?? null,\n [refusals],\n );\n\n /** The value a cell is showing right now — the optimistic one when there is one. */\n const shownValue = useCallback(\n (rowId: Uuid, key: string) => {\n const held = optimistic[cellKey(rowId, key)];\n if (held !== undefined) return held;\n return rows.find((r) => r.id === rowId)?.document?.[key];\n },\n [optimistic, rows],\n );\n\n /** The one question, asked in one place: may this person write THIS row? */\n const writable = useCallback(\n (rowId: Uuid) => (canWrite ? (mayWriteRow ? mayWriteRow(rowId) : true) : false),\n [canWrite, mayWriteRow],\n );\n\n const begin = useCallback(\n (address: CellAddress) => {\n // NOTHING IS OFFERED THAT THE DOOR WILL REFUSE. An editor that opened\n // here and was refused on Enter is the defect this lane closes; the cell\n // that called this never drew the affordance in the first place, and this\n // is the second lock on the same door.\n if (!writable(address.rowId)) return;\n // Re-opening the cell that is already open must not throw away what has\n // been typed into it: a double-click is two `begin`s, and the second one\n // arrives after the first has opened the editor.\n if (editing && editing.rowId === address.rowId && editing.key === address.key) return;\n const current = shownValue(address.rowId, address.key);\n startedFrom.current = current;\n typed.current = current;\n setDraft(current);\n setEditing(address);\n // The version this edit starts from, read once for this record.\n void versionOf(client, versions.current, versionReads.current, address.rowId);\n },\n [writable, client, editing, shownValue],\n );\n\n const cancel = useCallback(() => {\n setEditing(null);\n setDraft(null);\n typed.current = null;\n startedFrom.current = null;\n }, []);\n\n /** The write itself. `writeCell` below is what callers use; it queues these. */\n const writeCellNow = useCallback(\n async (rowId: Uuid, key: string, value: unknown) => {\n const id = cellKey(rowId, key);\n setOptimistic((held) => ({ ...held, [id]: value }));\n setSaving((held) => ({ ...held, [id]: true }));\n setRefusals((held) => {\n if (!held[id]) return held;\n const next = { ...held };\n delete next[id];\n return next;\n });\n\n // A THROW IS A REFUSAL A PERSON HAS TO SEE. `recordUpdate` never throws\n // for a refusal — it answers one — but the transport under it can, and\n // when it did, this function's promise rejected, the `saving` marker was\n // never cleared, the optimistic value stayed on screen, and the typed\n // value was gone with nothing anywhere saying so. That is precisely \"one\n // column of a tabbed row saved as nothing\", and it is the silent failure\n // this package exists to refuse. It is now the same refusal any other is.\n let written: Awaited<ReturnType<RecordsClient[\"recordUpdate\"]>>;\n try {\n const version = await versionOf(client, versions.current, versionReads.current, rowId);\n written = await client.recordUpdate({\n record_id: rowId,\n patch: { [key]: value },\n ...(version === null ? {} : { expectedVersion: version }),\n });\n } catch (thrown) {\n written = {\n ok: false,\n error: {\n code: \"internal\",\n message: \"This did not reach the store.\",\n hint: thrown instanceof Error ? thrown.message : String(thrown),\n },\n };\n }\n\n setSaving((held) => {\n const next = { ...held };\n delete next[id];\n return next;\n });\n\n if (written.ok) {\n // The store's own new version, so the NEXT edit of this record carries it.\n rememberVersion(versions.current, rowId, written.data);\n reload();\n return;\n }\n\n // Refused: the optimistic value comes straight back off the screen, and\n // the store's own sentence goes on it.\n setOptimistic((held) => {\n const next = { ...held };\n delete next[id];\n return next;\n });\n // A stale write means the version we hold is wrong; forget it so the\n // retry reads the current one rather than repeating the same refusal.\n if (written.error.code === \"stale_write\") versions.current.delete(rowId);\n setRefusals((held) => ({\n ...held,\n [id]: {\n error: written.error,\n conflict: asWriteConflict(written.error, rowId),\n attempted: value,\n },\n }));\n },\n [client, reload],\n );\n\n /** One write of one Field of one record, with whatever version we hold. */\n const writeCell = useCallback(\n (rowId: Uuid, key: string, value: unknown): Promise<void> => {\n // Queued behind whatever is already in flight for THIS record; two\n // different records still write in parallel.\n const behind = queues.current.get(rowId) ?? Promise.resolve();\n const next = behind.then(() => writeCellNow(rowId, key, value));\n queues.current.set(\n rowId,\n next.then(\n () => undefined,\n () => undefined,\n ),\n );\n return next;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, reload],\n );\n\n const commit = useCallback(\n (move: \"next\" | \"previous\" | null = null) => {\n const open = editing;\n if (!open) return;\n // The ref, never the state: see the note beside `typed` above.\n const value = typed.current;\n // Compared against WHAT THIS EDIT STARTED FROM, not against a fresh read\n // of `rows`: a reload landing mid-edit moves `rows` under the comparison,\n // and \"the stored value already equals this\" then silently swallows a\n // real edit. The one fact that decides it is the one taken when the cell\n // opened.\n if (!sameValue(startedFrom.current, value)) void writeCell(open.rowId, open.key, value);\n\n if (!move) {\n setEditing(null);\n setDraft(null);\n typed.current = null;\n startedFrom.current = null;\n return;\n }\n const next = step(open, order, rowIds, move, writable);\n if (!next) {\n setEditing(null);\n setDraft(null);\n typed.current = null;\n startedFrom.current = null;\n return;\n }\n // The NEXT cell's own starting value, taken before anything this commit\n // wrote can come back — so tabbing on is exactly like opening it by hand.\n const starting = shownValue(next.rowId, next.key);\n startedFrom.current = starting;\n typed.current = starting;\n setDraft(starting);\n setEditing(next);\n void versionOf(client, versions.current, versionReads.current, next.rowId);\n },\n [editing, writeCell, order, rowIds, client, shownValue, writable],\n );\n\n const retry = useCallback(\n (rowId: Uuid, key: string) => {\n const held = refusals[cellKey(rowId, key)];\n if (!held) return;\n void writeCell(rowId, key, held.attempted);\n },\n [refusals, writeCell],\n );\n\n const keepTheirs = useCallback(\n (rowId: Uuid, key: string) => {\n const id = cellKey(rowId, key);\n versions.current.delete(rowId);\n setRefusals((held) => {\n const next = { ...held };\n delete next[id];\n return next;\n });\n setOptimistic((held) => {\n const next = { ...held };\n delete next[id];\n return next;\n });\n reload();\n },\n [reload],\n );\n\n const remove = useCallback(\n async (rowId: Uuid) => {\n setBusy(true);\n setRowError(null);\n const done = await client.recordDelete({ record_id: rowId });\n setBusy(false);\n if (done.ok) {\n versions.current.delete(rowId);\n reload();\n return null;\n }\n setRowError(done.error);\n return done.error;\n },\n [client, reload],\n );\n\n const addRecord = useCallback(async () => {\n setBusy(true);\n setRowError(null);\n // AIRTABLE'S GESTURE: a new row appears and you type into it. The store\n // decides whether an empty record is allowed — a Table with a required\n // Field refuses, in its own words, and the grid offers the whole form.\n const written = await client.recordWrite({ table_id: tableId, data: {} });\n setBusy(false);\n if (!written.ok) {\n setRowError(written.error);\n return written.error;\n }\n reload();\n const first = order[0];\n if (first) {\n // A brand-new record is empty, so the first cell starts from nothing —\n // set through the same two pieces of state `begin` sets, never by moving\n // the address on its own and leaving a stale draft behind it.\n startedFrom.current = undefined;\n typed.current = undefined;\n setDraft(undefined);\n setEditing({ rowId: written.data, key: first });\n }\n return null;\n }, [client, tableId, reload, order]);\n\n return {\n valueFor,\n editing,\n draft,\n type,\n stateOf,\n refusalOf,\n begin,\n cancel,\n commit,\n retry,\n keepTheirs,\n remove,\n addRecord,\n rowError,\n clearRowError: () => setRowError(null),\n busy,\n };\n}\n\n/**\n * Tab order: across the row, then on to the next row. Stops at the ends — and\n * WALKS PAST a row this person may not write, rather than opening an editor in\n * it that the door would refuse. Tab is the same promise a click is.\n */\nfunction step(\n from: CellAddress,\n order: string[],\n rowIds: Uuid[],\n move: \"next\" | \"previous\",\n writable: (rowId: Uuid) => boolean = () => true,\n): CellAddress | null {\n let at = from;\n // Bounded by the page: every cell of every row, once, and then it stops.\n for (let guard = 0; guard <= order.length * rowIds.length; guard += 1) {\n const column = order.indexOf(at.key);\n const row = rowIds.indexOf(at.rowId);\n if (column < 0 || row < 0) return null;\n const delta = move === \"next\" ? 1 : -1;\n let nextColumn = column + delta;\n let nextRow = row;\n if (nextColumn >= order.length) {\n nextColumn = 0;\n nextRow += 1;\n } else if (nextColumn < 0) {\n nextColumn = order.length - 1;\n nextRow -= 1;\n }\n const key = order[nextColumn];\n const rowId = rowIds[nextRow];\n if (key === undefined || rowId === undefined) return null;\n if (writable(rowId)) return { rowId, key };\n at = { rowId, key };\n }\n return null;\n}\n\nfunction sameValue(left: unknown, right: unknown): boolean {\n if (left === right) return true;\n if (left === null || left === undefined) return right === null || right === undefined || right === \"\";\n if (right === null || right === undefined) return left === \"\";\n if (typeof left === \"object\" || typeof right === \"object\") {\n try {\n return JSON.stringify(left) === JSON.stringify(right);\n } catch {\n return false;\n }\n }\n return false;\n}\n\n/**\n * ONE CELL. Read, until somebody asks to change it; then the Field's own\n * editor, in place, with the keys a person expects from a grid.\n *\n * `data-matrx-cell-control` is the data table's own opt-out from whole-row\n * click, so opening a cell never also opens the record panel behind it.\n */\nexport function GridCell({\n field,\n row,\n editing,\n canWrite,\n whyNot,\n format,\n}: {\n field: Field;\n row: ReadRow;\n editing: GridEditing;\n /** Whether this person may write THIS row. Asked before the cell is drawn. */\n canWrite: boolean;\n /**\n * Why not, when not — one sentence naming the level it would take and who can\n * give it. A cell that is simply not a control, with nothing to say about it,\n * is the silent half of the same defect this file closes.\n */\n whyNot?: string | undefined;\n /** The column's declared format, so the read view reads like its header. */\n format?: FieldFormatConfig | undefined;\n}) {\n const open = editing.editing?.rowId === row.id && editing.editing.key === field.key;\n const value = editing.valueFor(row, field);\n const state = editing.stateOf(row.id, field.key);\n const refusal = editing.refusalOf(row.id, field.key);\n const editable = canWrite && fieldIsEditable(field);\n\n if (open) {\n return (\n <OpenCell\n field={field}\n draft={editing.draft}\n onType={editing.type}\n onCommit={(move) => editing.commit(move)}\n onCancel={editing.cancel}\n />\n );\n }\n\n /**\n * ONE GESTURE, THREE WAYS IN, AND NOTHING ELSE HAPPENS (independent verdict,\n * fifth pass, 19 September): \"only the Title column can be opened by\n * double-clicking; double-clicking any other cell opens a developer\n * inspector — a floating window showing the record's raw JSON, its machine\n * keys, a truncated id, and the headings DOCUMENT, LEVEL and HIDDEN.\"\n *\n * Two things did that, and both are closed. The data table's own row window\n * is switched OFF for this grid (`Grid.tsx`) — this package has a record\n * panel of its own and a second one beside it is the parallel layer the\n * platform forbids. And the cell now FILLS its cell and answers `dblclick`\n * itself: a double-click's second press used to land on bare table cell\n * after the first press had swapped the DOM under the pointer, and a bare\n * cell is a row click. A wide column (the Title) kept the pointer over the\n * editor and worked; every narrow one did not, which is exactly the shape\n * the verdict saw.\n */\n const openThisCell = (event: { preventDefault: () => void; stopPropagation: () => void }) => {\n event.preventDefault();\n event.stopPropagation();\n editing.begin({ rowId: row.id, key: field.key });\n };\n\n return (\n <span data-matrx-cell-control=\"\" className=\"flex w-full min-w-0 flex-col gap-0.5\">\n <span\n role={editable ? \"button\" : undefined}\n tabIndex={editable ? 0 : undefined}\n aria-label={editable ? `Edit ${fieldName(field)}` : undefined}\n title={\n editable\n ? `${fieldName(field)} — click or press Enter to edit`\n : fieldIsEditable(field)\n ? // NOT A DEAD CONTROL AND NOT A SILENT ONE: the cell is plain\n // text, and hovering it says exactly why, in the level's own\n // words. The editor was never offered, so nothing is refused\n // after it has been typed into.\n `${fieldName(field)} — ${whyNot ?? \"you cannot change this record\"}`\n : `${fieldName(field)} is worked out by the system, so it cannot be typed in`\n }\n className={cn(\n // `w-full` so the whole cell is the control. A gap beside it is bare\n // table cell, and a click there is a row click.\n \"block w-full min-w-0 truncate rounded px-1 py-0.5\",\n editable ? \"cursor-text hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" : \"\",\n state === \"saving\" ? \"opacity-60\" : \"\",\n state === \"refused\" ? \"ring-1 ring-destructive\" : \"\",\n )}\n onClick={editable ? openThisCell : undefined}\n // A double-click opens the SAME editor a single click and Enter open.\n // It is bound on every cell, editable or not, so the gesture can never\n // fall through to the row behind it.\n onDoubleClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (editable) editing.begin({ rowId: row.id, key: field.key });\n }}\n onKeyDown={\n editable\n ? (event) => {\n if (event.key === \"Enter\" || event.key === \"F2\") {\n event.preventDefault();\n editing.begin({ rowId: row.id, key: field.key });\n }\n }\n : undefined\n }\n >\n <RecordValue\n field={field}\n value={value}\n document={row.document}\n {...(format ? { format } : {})}\n />\n </span>\n\n {state === \"saving\" ? <span className=\"px-1 text-[10px] text-muted-foreground\">Saving…</span> : null}\n\n {refusal ? (\n <span className=\"flex flex-col gap-0.5 rounded border border-destructive/40 p-1\">\n <RefusalLine error={refusal.error} />\n {refusal.conflict ? (\n <span className=\"text-[11px]\">\n {/* The other person's value, as the store sent it. */}\n Theirs: <strong>{formatTheirs(refusal.conflict, field.key)}</strong>\n </span>\n ) : null}\n <span className=\"flex gap-1\">\n <Button size=\"sm\" variant=\"outline\" onClick={() => editing.retry(row.id, field.key)}>\n Try again\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => editing.keepTheirs(row.id, field.key)}>\n Keep theirs\n </Button>\n </span>\n </span>\n ) : null}\n </span>\n );\n}\n\nfunction formatTheirs(conflict: WriteConflict, key: string): string {\n const theirs = conflict.contested_fields?.[key];\n if (theirs === null || theirs === undefined || theirs === \"\") return \"(empty)\";\n if (Array.isArray(theirs)) return `${theirs.length} of them`;\n return typeof theirs === \"object\" ? \"something this cell cannot show in a line\" : String(theirs);\n}\n\n/**\n * WHICH EDITORS CLOSE THEMSELVES ON BLUR, AND WHY THE OTHERS MUST NOT.\n *\n * A typed box (text, number, date, email, url, phone) is finished when you look\n * away, exactly as a spreadsheet is. A PICKER is not: a select, a relation\n * picker and a person picker all open a Radix popover, which is portalled OUT\n * of this cell, so \"focus left the cell\" fires the instant the list opens.\n * Committing there would save the old value and shut the list a person just\n * asked for. So pickers carry an explicit Save and Cancel, and the keys work on\n * both.\n */\nfunction closesOnBlur(field: Field): boolean {\n switch (editorKindFor(field)) {\n case \"select\":\n case \"multi_select\":\n case \"relation\":\n case \"member\":\n case \"attachment\":\n return false;\n default:\n return true;\n }\n}\n\n/**\n * WHICH EDITORS TAKE A NEWLINE. A long-text column and a json document are the\n * two a person puts more than one line into; everything else is one line by\n * construction, and binding a newline into it would be a key that does nothing.\n */\nfunction takesANewline(field: Field): boolean {\n const kind = editorKindFor(field);\n return kind === \"long_text\" || kind === \"json\";\n}\n\n/**\n * The open cell. Enter commits, Escape cancels, Tab commits and opens the next\n * one — the three keys every grid in the world binds, so nobody has to be told.\n *\n * AND A MULTI-LINE COLUMN BINDS THEM THE SAME WAY, which it did not. It used to\n * take Enter for a newline and commit only on Ctrl/Cmd+Enter — so the key every\n * person in the world presses to finish a cell did nothing visible in exactly\n * the columns whose values are longest, and the only way to save was a shortcut\n * printed in 10px under the box. Airtable is the bar and Airtable is\n * unambiguous: ENTER COMMITS, SHIFT+ENTER makes the newline, TAB commits and\n * moves on. Ctrl/Cmd+Enter still commits, because a hand that learned the old\n * one should not be punished for it.\n */\nfunction OpenCell({\n field,\n draft,\n onType,\n onCommit,\n onCancel,\n}: {\n field: Field;\n draft: unknown;\n onType: (value: unknown) => void;\n onCommit: (move: \"next\" | \"previous\" | null) => void;\n onCancel: () => void;\n}) {\n const multiline = takesANewline(field);\n const blurCommits = closesOnBlur(field);\n // ONE COMMIT PER OPENING. Tab moves focus, so the key handler AND the blur\n // handler both fired for the same cell: two writes of one value, the second\n // against the version the first had just moved, and the store — correctly —\n // answered PT409. A person tabbing through their own row was shown a\n // conflict with themselves. Measured 2026-09-19 in the headless walk.\n const done = useRef(false);\n const once = (run: () => void) => {\n if (done.current) return;\n done.current = true;\n run();\n };\n\n // FOCUS ON OPENING, AND ONLY ON OPENING. This used to be an inline `ref`\n // arrow, which React re-invokes on EVERY render — so every reload landing\n // mid-edit yanked the caret back. It now runs once, when this cell's editor\n // appears, which is the only moment a person expects their cursor to move.\n const host = useRef<HTMLSpanElement | null>(null);\n useEffect(() => {\n const control = host.current?.querySelector<HTMLElement>(\"input, textarea, [role='combobox'], button\");\n if (control && document.activeElement !== control) control.focus();\n // Once per opening: the open cell's identity is the Field it is editing.\n }, [field.id]);\n\n const blur = blurCommits\n ? {\n onBlur: (event: FocusEvent<HTMLSpanElement>) => {\n // Leaving the cell altogether commits, exactly as a spreadsheet does.\n // Moving between the editor's own parts does not.\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) return;\n once(() => onCommit(null));\n },\n }\n : {};\n\n return (\n <span\n ref={host}\n data-matrx-cell-control=\"\"\n className=\"flex w-full min-w-[10rem] flex-col gap-1\"\n onDoubleClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n once(onCancel);\n return;\n }\n if (event.key === \"Tab\") {\n event.preventDefault();\n event.stopPropagation();\n // THE TYPED VALUE IS NOT PASSED FROM HERE. It is already in the\n // editing session, put there by `onType` on the keystroke that typed\n // it, so a re-render between the keystroke and this press cannot lose\n // it — which is exactly what dropped four of nine values on\n // 19 September (see the file header).\n once(() => onCommit(event.shiftKey ? \"previous\" : \"next\"));\n return;\n }\n if (event.key === \"Enter\") {\n // Shift+Enter is the newline, and ONLY in a column that takes one.\n // Everywhere else Enter finishes the cell, exactly as it does in\n // every other grid a person has used.\n if (multiline && event.shiftKey && !event.metaKey && !event.ctrlKey) return;\n event.preventDefault();\n event.stopPropagation();\n once(() => onCommit(null));\n }\n }}\n {...blur}\n >\n <FieldControl field={field} value={draft} onChange={onType} id={`cell-${field.id}`} />\n {blurCommits ? (\n <span className=\"text-[10px] text-muted-foreground\">\n {multiline\n ? \"⏎ saves · ⇧⏎ new line · Esc cancels · Tab next\"\n : \"⏎ saves · Esc cancels · Tab next\"}\n </span>\n ) : (\n <span className=\"flex items-center gap-1\">\n <Button size=\"sm\" onClick={() => once(() => onCommit(null))}>\n Save\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => once(onCancel)}>\n Cancel\n </Button>\n </span>\n )}\n </span>\n );\n}\n","\"use client\";\n\n// src/Refusal.tsx — @ai-matrx/records-ui\n//\n// THE ONE PLACE A REFUSAL IS SHOWN. It renders what `plainWords.ts` returns and\n// NOTHING ELSE — no `error.message`, no `error.hint`, no `error.sqlstate` in a\n// place a person reads. That is deliberate and it is the whole guard: a\n// formatter every screen has to go through is a formatter nobody bypasses, and\n// this component is the only door onto the screen a refusal has.\n//\n// The history, so it is not undone by accident. The fifth pass found the store's\n// HINT — written for whoever fixes the caller — printed at the person (\"FLD-11:\n// a lookup and a rollup both travel along a relation. config.via names a\n// relation Field of this same table, by its key.\"). The pass after it filtered\n// the hint and left the MESSAGE verbatim, on the reasonable grounds that the\n// store writes good messages. The sixth pass then found the machine identity\n// inside the MESSAGE — the access refusals are built by `format()` from the\n// door's own name — and printed at the person again, from the other half.\n//\n// So neither half is trusted by shape of ORIGIN any more. Both go through one\n// filter that judges by the shape of the TEXT, and what it drops is kept for an\n// engineer on the notice and in a screen-reader-only line, never deleted.\n\nimport type { ReactNode } from \"react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Alert, AlertDescription, AlertTitle, cn } from \"@ai-matrx/design-system\";\n\nimport { isMachineIdentity, refusalForAPerson, refusalLineForAPerson } from \"./plainWords\";\n\n/**\n * Kept for callers outside this package that already ask the question. The\n * answer is `plainWords.ts`'s, so there is one shape list and not two.\n */\nexport function hintIsMachineIdentity(hint: string): boolean {\n return isMachineIdentity(hint);\n}\n\n/** The hint a PERSON should read, or null when it is written for an engineer. */\nexport function hintForAPerson(hint: string | null | undefined): string | null {\n const said = (hint ?? \"\").trim();\n if (said === \"\") return null;\n return isMachineIdentity(said) ? null : said;\n}\n\nexport function RefusalNotice({\n error,\n className,\n actions,\n}: {\n error: RecordsError;\n className?: string | undefined;\n actions?: ReactNode | undefined;\n}) {\n const plain = refusalForAPerson(error);\n return (\n <Alert\n variant=\"destructive\"\n className={cn(\"text-xs\", className)}\n {...(plain.forEngineers ? { title: plain.forEngineers } : {})}\n >\n <AlertTitle className=\"text-xs font-medium\">{plain.title}</AlertTitle>\n <AlertDescription className=\"space-y-1 text-xs\">\n <p>{plain.sentence}</p>\n {/* NEVER A DEAD END: what happened, and then what to do about it. */}\n <p className=\"opacity-80\">{plain.remedy}</p>\n {plain.forEngineers ? (\n <p className=\"sr-only\" {...(error.sqlstate ? { \"data-sqlstate\": error.sqlstate } : {})}>\n {plain.forEngineers}\n </p>\n ) : null}\n {actions}\n </AlertDescription>\n </Alert>\n );\n}\n\n/** A small inline one, for a cell or a field where a block would break the layout. */\nexport function RefusalLine({ error, className }: { error: RecordsError; className?: string | undefined }) {\n const plain = refusalForAPerson(error);\n return (\n <p className={cn(\"text-xs text-destructive\", className)} title={plain.forEngineers || undefined}>\n {refusalLineForAPerson(error)}\n </p>\n );\n}\n","\"use client\";\n\n// src/values.tsx — @ai-matrx/records-ui\n//\n// HOW A VALUE IS SHOWN, one function, used by the grid cell, the peek, the\n// custom-fields section and the form's read state alike. Per SCR it is never\n// per-feature: every surface that shows a Value in this platform shows it the\n// same way, because the way is a property of the Field, not of the screen.\n//\n// VAL-2: a blank is never unexplained. When the record's envelope says why a\n// value is missing, the reason is what is shown — \"never asked\" and \"refused\"\n// are different facts and a person acts on them differently.\n\nimport {\n FormattedCell,\n formatColumnValue,\n} from \"@ai-matrx/design-system/data-table\";\nimport type { FieldFormatConfig } from \"@ai-matrx/design-system/field-formats\";\nimport type { Field, RecordDocument, ValueEnvelope } from \"@ai-matrx/records\";\nimport { Badge, cn } from \"@ai-matrx/design-system\";\nimport { editorKindFor } from \"./parity\";\nimport { isId, useRecordLabels, type LabelLookup } from \"./labels\";\n\n/** The envelope for one key, when the document carries one. */\nexport function envelopeFor(document: RecordDocument | undefined, key: string): ValueEnvelope | undefined {\n const block = document?._values as Record<string, ValueEnvelope> | undefined;\n return block?.[key];\n}\n\nconst ABSENCE_WORDS: Record<string, string> = {\n \"never asked\": \"never asked\",\n none: \"none\",\n refused: \"refused\",\n conflicting: \"conflicting\",\n};\n\nexport function renderValue(field: Field, value: unknown, document?: RecordDocument, labels?: LabelLookup) {\n const envelope = envelopeFor(document, field.key);\n if (envelope?.absent) {\n return (\n <span className=\"text-xs italic text-muted-foreground\" title={`VAL-2: ${envelope.absent}`}>\n {ABSENCE_WORDS[String(envelope.absent)] ?? String(envelope.absent)}\n </span>\n );\n }\n if (value === null || value === undefined || value === \"\") {\n return <span className=\"text-muted-foreground\">—</span>;\n }\n\n const kind = editorKindFor(field);\n if (Array.isArray(value)) {\n return (\n <span className=\"flex flex-wrap gap-1\">\n {value.map((item, i) => (\n <Badge key={`${String(item)}-${i}`} variant=\"secondary\" className=\"text-[11px]\">\n {scalarText(field, item, labels)}\n </Badge>\n ))}\n </span>\n );\n }\n if (kind === \"url\" && typeof value === \"string\") {\n return (\n <a className=\"truncate text-primary underline-offset-2 hover:underline\" href={value} target=\"_blank\" rel=\"noreferrer\">\n {value}\n </a>\n );\n }\n if (kind === \"email\" && typeof value === \"string\") {\n return (\n <a className=\"truncate text-primary underline-offset-2 hover:underline\" href={`mailto:${value}`}>\n {value}\n </a>\n );\n }\n if (typeof value === \"boolean\") {\n return <span>{value ? \"Yes\" : \"No\"}</span>;\n }\n return <span className={cn(\"truncate\", kind === \"number\" || kind === \"currency\" || kind === \"percent\" ? \"tabular-nums\" : \"\")}>{scalarText(field, value, labels)}</span>;\n}\n\n/**\n * The text of one scalar, with the Field's UNIT and FORMAT applied — FLD-N-1\n * says both change the MEANING — and with an id resolved to the NAME of the\n * record it points at.\n *\n * `labels` is the resolver from `RecordLabelProvider`. Without it, an id is\n * drawn as \"Loading…\" and never as itself: a 36-character identifier in a cell\n * reads like a value, and the 19 September verdict found it in choice cells,\n * relation cells and as every Kanban column heading.\n */\nexport function scalarText(field: Field, value: unknown, labels?: LabelLookup): string {\n if (value === null || value === undefined) return \"—\";\n const kind = editorKindFor(field);\n if (isId(value) && (field.type === \"list\" || field.type === \"relation\")) {\n return labels?.(field, String(value)) ?? \"Loading…\";\n }\n if (typeof value === \"number\") {\n if (kind === \"percent\") return `${value}%`;\n // The symbol goes in FRONT of an amount of money and a unit goes AFTER a\n // quantity: `$3` and `3 units`. Before this, `editorKindFor` called any\n // range field with a unit longer than one character a currency, so three\n // things measured in units rendered as \"units3\".\n if (kind === \"currency\") return field.unit ? `${field.unit}${value.toLocaleString()}` : value.toLocaleString();\n return field.unit ? `${value.toLocaleString()} ${field.unit}` : value.toLocaleString();\n }\n if (kind === \"datetime\" && typeof value === \"string\") {\n const at = new Date(value);\n if (!Number.isNaN(at.getTime())) {\n return field.format === \"datetime\" ? at.toLocaleString() : at.toLocaleDateString();\n }\n }\n // NEVER A JSON DUMP IN A CELL. A value with a shape a column cannot draw is\n // described; the raw document is available on the record panel, which is\n // where a person goes to look at it.\n if (Array.isArray(value)) return value.length === 0 ? \"\" : `${value.length} of them`;\n if (typeof value === \"object\") return \"…\";\n return String(value);\n}\n\n/** The provenance badge a value carries when the store interned a source for it (SCR-27). */\nexport function ProvenanceBadge({ document, fieldKey }: { document: RecordDocument | undefined; fieldKey: string }) {\n const envelope = envelopeFor(document, fieldKey);\n if (!envelope?.src) return null;\n const sources = document?._sources as Record<string, Record<string, unknown>> | undefined;\n const source = sources?.[envelope.src];\n const label = source ? Object.values(source).map(String).join(\" · \") : envelope.src;\n return (\n <Badge variant=\"outline\" className=\"text-[10px] font-normal\" title={`Written by ${envelope.actor ?? \"?\"}${envelope.at ? ` at ${envelope.at}` : \"\"}`}>\n {label}\n </Badge>\n );\n}\n\n/**\n * THE VALUE, AS A COMPONENT, so a cell can resolve the ids it holds.\n *\n * `renderValue` is a plain function called from inside a column's `cell`\n * callback and from a dozen other places; a function cannot ask the resolver\n * for a name, because asking is a hook. Every read-only surface therefore draws\n * through this instead, and the one that needs the raw function (a plain-text\n * export, a chat line) keeps calling `renderValue` with no resolver and says\n * \"Loading…\" rather than printing an id.\n */\nexport function RecordValue({\n field,\n value,\n document,\n format,\n}: {\n field: Field;\n value: unknown;\n document?: RecordDocument | undefined;\n /**\n * The column's DECLARED format (`presentation.ts`), when it has one.\n *\n * A cell renderer beats `MatrxColumnDef.format` — the table hands the cell to\n * the consumer and steps back — so a store column that declared `currency`\n * and then drew itself here would have shown a raw `1250.5` while its own\n * header was right-aligned for money. The primitive's formatter is asked for\n * the text instead of a second one being written beside it, so the read view\n * and the table can never disagree about what a number means. THE FALLBACK\n * LAW rides along: a value that does not fit is amber with the reason, never\n * blank.\n */\n format?: FieldFormatConfig | undefined;\n}) {\n const labels = useRecordLabels(ONE_FIELD_ARRAY_CACHE(field));\n const formatted = format ? formatColumnValue({ format }, value) : null;\n if (formatted) return <FormattedCell result={formatted} />;\n return <>{renderValue(field, value, document, labels)}</>;\n}\n\n/**\n * `useRecordLabels` takes an array and declares what it is about to draw. A new\n * array literal per cell would re-declare on every render, so each Field gets\n * exactly one array for the life of the process.\n */\nconst ONE_FIELD_ARRAYS = new WeakMap<Field, Field[]>();\nfunction ONE_FIELD_ARRAY_CACHE(field: Field): Field[] {\n const held = ONE_FIELD_ARRAYS.get(field);\n if (held) return held;\n const made = [field];\n ONE_FIELD_ARRAYS.set(field, made);\n return made;\n}\n","\"use client\";\n\n// src/labels.tsx — @ai-matrx/records-ui\n//\n// WHAT AN ID IS CALLED, ONCE, FOR EVERY SCREEN THAT DRAWS A VALUE.\n//\n// A choice field stores the ID of an option record and a relation field stores\n// the ID of the record it points at (FLD-5 / FLD-6, REL-1) — that is the store\n// being right, and it is also why the 19 September verdict saw a bare\n// 36-character identifier in a relation cell, in a choice cell, and as the\n// HEADING OF EVERY KANBAN COLUMN. The pickers resolved those ids because each\n// one loaded its own list; the read-only surfaces never did, so the same value\n// read as a name in the form and as a machine id in the grid.\n//\n// One resolver, provided once inside the mount, so every surface gets the same\n// answer and asks the store once per Field rather than once per cell:\n//\n// · a list field → `custom.field_options`, which resolves the options Table\n// from the Field's own config, so no screen has to know which Table it is\n// · a relation field → the read door on the Field's declared target\n//\n// WHAT IT DOES WHILE IT IS LOOKING. It returns `null`, and every caller draws\n// the word \"Loading…\" rather than the id. Showing the id \"until it resolves\" is\n// how the defect got shipped in the first place: it looks like a value.\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { useRecordsClient, type Field, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordDocument } from \"@ai-matrx/records\";\nimport { WITHHELD_RECORD_LABEL, recordName } from \"./names\";\n\n/** Answers \"what is the record with this id called\", for one Field's values. */\nexport type LabelLookup = (field: Field, id: string) => string | null;\n\nconst LabelContext = createContext<{\n lookup: LabelLookup;\n want: (field: Field) => void;\n}>({\n // With no provider the resolver is ABSENT, not silently empty: a caller gets\n // null and says \"Loading…\" forever, which is visible. The mount always\n // provides one, so this is only ever a bare unit test.\n lookup: () => null,\n want: () => {},\n});\n\n/** Which ids a Field's stored value refers to. */\nexport function idsOf(value: unknown): string[] {\n if (Array.isArray(value)) return value.map(String).filter(isId);\n if (typeof value === \"string\" && isId(value)) return [value];\n return [];\n}\n\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function isId(value: unknown): boolean {\n return typeof value === \"string\" && UUID.test(value);\n}\n\n/** True when this Field's values are ids of other records rather than values. */\nexport function pointsAtRecords(field: Field): boolean {\n return field.type === \"list\" || field.type === \"relation\";\n}\n\nexport function RecordLabelProvider({ children }: { children: ReactNode }) {\n const client = useRecordsClient();\n const [names, setNames] = useState<Record<string, string>>({});\n // Which Fields have FINISHED looking. Until a Field is in here its ids are\n // still loading; once it is in here, an id that is still missing is missing\n // for a reason, and the reason is asked for rather than waited out.\n const [settled, setSettled] = useState<Record<string, true>>({});\n const asked = useRef<Set<string>>(new Set());\n const chased = useRef<Set<string>>(new Set());\n\n const want = useCallback(\n (field: Field) => {\n if (!pointsAtRecords(field)) return;\n if (asked.current.has(field.id)) return;\n asked.current.add(field.id);\n\n void (async () => {\n if (field.type === \"list\") {\n const result = await client.fieldOptions({ field_id: field.id });\n if (result.ok) {\n setNames((current) => {\n const next = { ...current };\n for (const option of result.data ?? []) {\n next[option.id] = recordName(option.data as RecordDocument | undefined, null, \"Unnamed choice\");\n }\n return next;\n });\n }\n setSettled((current) => ({ ...current, [field.id]: true }));\n return;\n }\n const target = field.relation_target;\n if (!target) {\n setSettled((current) => ({ ...current, [field.id]: true }));\n return;\n }\n // REC-2: what makes a record a chip is ITS TABLE'S declared title field, and this\n // resolver used to try title/name/label and give up. A Table whose title field is\n // `cname` therefore read \"Untitled\" in every cell of every read-only surface — which\n // is every Table a person builds themselves. The Table is read alongside the rows.\n const [rows, tables] = await Promise.all([\n client.list({ table_id: target as Uuid, limit: 200 }),\n client.tableList(),\n ]);\n const titleKey = tables.ok\n ? (tables.data.find((table) => table.id === target)?.title_field ?? null)\n : null;\n if (rows.ok) {\n setNames((current) => {\n const next = { ...current };\n for (const row of rows.data.rows) {\n next[row.id] = recordName(row.document, titleKey, \"Untitled\");\n }\n return next;\n });\n }\n setSettled((current) => ({ ...current, [field.id]: true }));\n })();\n },\n [client],\n );\n\n // ── AN ID THIS RESOLVER DID NOT FIND (RELATION-DECLARE, 2026-09-20). ──────────────────\n // A relation joins two records in two tables, and holding one end says nothing about the\n // other: a Job shared with you may point at a Client nobody shared. The read door above\n // answers exactly what this reader may see, so an id it did not return is either further\n // down a long list or NOT HERS — and until today both of those read \"Loading…\", forever,\n // on every grid, card, board heading and peek in the product. Measured on 2026-09-20 in a\n // headless walk of the real grid: a relation cell whose target the reader holds read\n // \"Loading…\" and never resolved.\n //\n // \"Loading…\" that never resolves is not honesty, it is a lie with a spinner on it. The two\n // cases are asked apart through the read door, one id at a time, and the answer for a\n // record this reader may not open is the SAME SENTENCE the store itself gives\n // (`platform.relation_withheld_label()`) — never the title, never the bare id.\n const chase = useCallback(\n (field: Field, id: string) => {\n const key = `${field.id}:${id}`;\n if (chased.current.has(key)) return;\n chased.current.add(key);\n void (async () => {\n const result = await client.recordRead({ record_id: id as Uuid });\n setNames((current) => ({\n ...current,\n [id]: result.ok\n ? recordName(result.data.document, null, \"Untitled\")\n : WITHHELD_RECORD_LABEL,\n }));\n })();\n },\n [client],\n );\n\n const lookup = useCallback<LabelLookup>(\n (field, id) => {\n const known = names[id];\n if (known !== undefined) return known;\n if (settled[field.id]) chase(field, id);\n return null;\n },\n [names, settled, chase],\n );\n\n const value = useMemo(() => ({ lookup, want }), [lookup, want]);\n return <LabelContext.Provider value={value}>{children}</LabelContext.Provider>;\n}\n\n/**\n * The hook a surface uses: it declares the Fields it is about to draw, and gets\n * back the lookup. Declaring is what makes one request per Field instead of one\n * per cell, and it is why a grid of 200 rows asks the store twice.\n */\nexport function useRecordLabels(fields: readonly Field[] | undefined): LabelLookup {\n const { lookup, want } = useContext(LabelContext);\n useEffect(() => {\n for (const field of fields ?? []) want(field);\n }, [fields, want]);\n return lookup;\n}\n","\"use client\";\n\n// src/Grid.tsx — @ai-matrx/records-ui · SCR-1, SCR-2, SCR-4, SCR-31\n//\n// A custom table opens as a grid: RECORDS ARE ROWS, FIELDS ARE COLUMNS, AND A\n// CELL IS WHERE YOU CHANGE IT.\n//\n// It is the canonical `MatrxDataTable` — not a table this package drew. The\n// columns are built from the Table's own Field records, the rows are the\n// records the read door returned, and the \"+\" at the end of the column headers\n// is present for a holder of `admin` on the table and ABSENT — never disabled,\n// never greyed — for everybody else (SCR-4).\n//\n// EDITING IS HERE, NOT IN A PANEL SOMEWHERE ELSE (`gridEditing.tsx`). Click a\n// cell, DOUBLE-click it, or focus it and press Enter, and the Field's own\n// editor opens in place — the same editor, all three ways;\n// Enter saves, Escape cancels, Tab saves and opens the next one. The save goes\n// through the one write door carrying the version the person started from, so\n// the STORE decides whether somebody else got there first — and when it did,\n// the cell shows their value with a Try again beside it. A row is deleted from\n// its own row menu, with the consequence named before the delete, and a new\n// record is one button that puts you straight into the first cell.\n//\n// Every refusal is the store's own sentence (`RefusalNotice`). A grid that\n// rendered \"no records\" because the door refused is the defect this package\n// exists to prevent, so the empty state and the refusal are different things\n// and both are shown.\n\nimport { useCallback, useMemo, useState, type ReactNode } from \"react\";\nimport {\n useFields,\n useRecords,\n useTable,\n type Field,\n type ReadRow,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport { MatrxDataTable } from \"@ai-matrx/design-system/data-table\";\nimport type { MatrxColumnDef } from \"@ai-matrx/design-system/data-table/types\";\nimport type { FieldFormatConfig } from \"@ai-matrx/design-system/field-formats\";\nimport {\n EMPTY_PRESENTATION,\n FROZEN_COLUMN_WIDTH,\n colorFromTheValue,\n formatForField,\n type GridPresentation,\n} from \"./presentation\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi, useRowRights, useTableRights } from \"./host\";\nimport { editorKindFor, fieldTypeLabel } from \"./parity\";\nimport { fieldName, tableName } from \"./names\";\nimport { RecordValue } from \"./values\";\nimport { GridCell, useGridEditing, type GridEditing } from \"./gridEditing\";\n\n/**\n * WHAT A TABLE WITH NO COLUMNS SAYS. Named here because the gate asserts on it:\n * the state it describes is what a first-time person met for two days.\n */\nexport const NO_COLUMNS_YET = \"This table has no columns yet\";\nexport const NO_COLUMNS_WHY =\n \"A column is what a record holds — a name, a date, an amount, a person. Add the first one and \" +\n \"the grid appears with it; everything else on this page works the moment it exists.\";\n\nexport interface GridProps {\n tableId: Uuid;\n /** Rows per page. The table's own pagination handles the rest. */\n pageSize?: number | undefined;\n /** Opened when a row is clicked. A host that has a record page passes its own. */\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n /** SCR-2. Called when an admin clicks the \"+\" at the end of the headers. */\n onAddField?: (() => void) | undefined;\n /**\n * The host's whole-record form. Offered BY NAME when the store refuses an\n * empty record — a Table with a required Field cannot be added to one cell at\n * a time, and saying so beats a button that fails.\n */\n onNewRecordForm?: (() => void) | undefined;\n /** Extra toolbar content — the view switcher, the export menu, the view bar. */\n toolbarActions?: ReactNode | undefined;\n /** Editing in place is on by default; a read-only surface (a portal) turns it off. */\n editable?: boolean | undefined;\n /**\n * HOW THIS TABLE LOOKS — the active saved view's colors, per-column formats\n * and frozen columns (`presentation.ts`).\n *\n * It is a prop and not a read of its own because the VIEW owns it and the\n * host already knows which view is open; a second read here would draw one\n * view's colors over another's. Omitted, the table still formats every money\n * and date column correctly from the Fields' own declarations — a look is an\n * override, never the only thing that makes a column readable.\n */\n presentation?: GridPresentation | undefined;\n className?: string | undefined;\n}\n\nexport function Grid({\n tableId,\n pageSize = 50,\n onOpenRecord,\n onAddField,\n onNewRecordForm,\n toolbarActions,\n editable = true,\n presentation = EMPTY_PRESENTATION,\n className,\n}: GridProps) {\n const host = useRecordsUi();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const [page, setPage] = useState(0);\n const records = useRecords(tableId, { pageSize, page });\n const rights = useTableRights(table.data);\n const rows = useMemo(() => records.data?.rows ?? [], [records.data]);\n const rowIds = useMemo(() => rows.map((row) => row.id), [rows]);\n\n /**\n * PER ROW, BUT ONLY WHERE IT CAN CHANGE THE ANSWER.\n *\n * When the table already admits editing, every row it returned is this\n * person's to edit and asking again would be a call per page for nothing.\n * When it does not, a row may still have been shared with them directly — the\n * sixth-pass verdict found exactly that, and the grid labelled the row\n * \"viewer\" while the store let its holder write to it — so the page asks\n * once, for all its rows, through the door that takes a list.\n */\n // ONLY WHEN THE PACKAGE IS THE ONE ASKING. A host that binds `rights` has its\n // own authority — a portal, an embed, a read-only surface — and a grid that\n // went around it to the store would quietly overrule the host that mounted\n // it. When the port is bound, its answer is the whole answer, for every row.\n const askPerRow =\n Boolean(editable) && !host.rights && rights.known && !rights.write && rows.length > 0;\n const rowRights = useRowRights(rowIds, askPerRow);\n const mayWriteRow = useCallback(\n (rowId: Uuid) => (askPerRow ? (rowRights(rowId)?.write ?? false) : rights.write),\n [askPerRow, rowRights, rights.write],\n );\n const whyNotRow = useCallback(\n (rowId: Uuid) =>\n askPerRow ? (rowRights(rowId)?.why(\"write\") ?? rights.why(\"write\")) : rights.why(\"write\"),\n [askPerRow, rowRights, rights],\n );\n\n // Whether ANY row on this page can be edited: what the toolbar and the row\n // menu turn on. A grid with nothing editable draws no editing controls at all.\n const canWrite = Boolean(editable) && (rights.write || (askPerRow && rowIds.some(mayWriteRow)));\n\n const editing = useGridEditing({\n tableId,\n fields: fields.data ?? [],\n rows,\n reload: records.reload,\n canWrite,\n mayWriteRow,\n });\n\n const frozenKeys = useMemo(\n () => new Set(presentation.frozen ?? []),\n [presentation.frozen],\n );\n /**\n * THE ORDER OF THE COLUMNS, WHICH WAS NOBODY'S.\n *\n * A Field declares `sort` — it is what the field panel writes and what\n * \"Move earlier\" means — and this list was rendered in whatever order the\n * read door happened to answer. Measured 2026-09-20 on a table declared\n * name·status·day_rate·share·due: it came back status·share·name·day_rate·due.\n * Every store table has been showing its columns in an arbitrary order, and\n * `title_field` was not even first.\n *\n * Then the view's FROZEN columns come to the front, in the order the view\n * names them. A frozen column has to be in the leading run — a column pinned\n * over its own left neighbour lies about where the row is — so \"freeze this\"\n * has to MOVE it, which is exactly what it does in Airtable and in Sheets.\n * Without this a person froze a column and nothing happened, which is the\n * silent half of a setting that does not work.\n */\n const ordered = useMemo(() => {\n const all = [...(fields.data ?? [])].sort(\n (a, b) => (a.sort ?? 100) - (b.sort ?? 100) || a.key.localeCompare(b.key),\n );\n if (frozenKeys.size === 0) return all;\n const order = presentation.frozen ?? [];\n const pinned = order\n .map((key) => all.find((f) => f.key === key))\n .filter((f): f is Field => f !== undefined);\n return [...pinned, ...all.filter((f) => !frozenKeys.has(f.key))];\n }, [fields.data, frozenKeys, presentation.frozen]);\n\n const columns = useMemo<MatrxColumnDef<ReadRow>[]>(\n () =>\n ordered.map((field) =>\n columnForField(field, canWrite ? editing : null, mayWriteRow, whyNotRow, {\n ...(presentation.formats?.[field.key]\n ? { format: presentation.formats[field.key] }\n : {}),\n frozen: frozenKeys.has(field.key),\n }),\n ),\n [ordered, canWrite, editing, mayWriteRow, whyNotRow, presentation.formats, frozenKeys],\n );\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n\n /**\n * A REFRESH IS NOT A FIRST LOAD, AND THE DIFFERENCE IS A TYPED VALUE.\n *\n * `MatrxDataTable` renders six SKELETON rows in place of `<tbody>`'s real\n * ones while `isLoading` — every cell on the page is unmounted. This grid\n * used to hand it `records.loading`, which goes true on every `reload()`, and\n * `gridEditing` reloads after EVERY accepted cell write. So committing one\n * cell tore down the editor the person was still typing in: the caret went,\n * and any keystroke that arrived inside that window reached a detached node\n * and was lost — the draft then equalled what the cell opened with, `commit`\n * correctly said \"nothing changed\", and the value was gone with nothing\n * anywhere saying so. Measured 2026-09-20: one column of a tabbed row saved\n * as nothing, a different one each run, which is what made it look like the\n * store rather than the screen.\n *\n * The data table already tells the two apart — `isFetching` draws a refresh\n * line and KEEPS the rows — so the skeleton is now only what it says it is:\n * there is nothing to show yet. Nothing a person is typing into is ever\n * unmounted by a read they did not ask for.\n *\n * AND A FIRST LOAD IS NOT ONLY THE ROWS. Invariant 4 of this package: no\n * component acts before the store has answered. Three things are answered\n * ONCE for a table — its declaration, its columns, and what THIS PERSON may\n * do to it — and a row drawn before any of them is a lie: `useTableRights`\n * answers `NO_RIGHTS` (`known: false`) while the table itself is still being\n * read, so every cell came out as plain text with no editor, and a click on\n * it did nothing and said nothing. Measured 2026-09-20: this cost\n * `demo/edit.test.tsx` three clauses, deterministically, and it was a real\n * defect and not the suite's.\n *\n * So those three are a FIRST LOAD, and only the page re-read is a refresh —\n * which is what makes this safe: they are asked once per table id, so they\n * never blank rows a person is already working in.\n */\n const nothingToShowYet =\n table.loading || fields.loading || !rights.known || (records.loading && rows.length === 0);\n const refreshing = !nothingToShowYet && records.loading;\n\n /**\n * A TABLE WITH NO COLUMNS IS A REAL STATE, AND IT DREW NOTHING AT ALL.\n *\n * `columns` is built from the Table's Field records, so a table that has none\n * handed `MatrxDataTable` an empty column list — a header rule, a frame, and\n * no way in. It is exactly what a person met on the first table they ever\n * made while `createTable` could not declare a column (FLD-13), and it is\n * still reachable on purpose: the last column of a table can be retired.\n *\n * Absence is an ANSWER and it gets a sentence, plus the ONE control that\n * ends it — present for somebody who may change the table's shape, and\n * ABSENT with the ladder's own reason for everybody else (SCR-4). Never a\n * blank frame, never a disabled button.\n */\n const noColumnsYet = !nothingToShowYet && (fields.data ?? []).length === 0;\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* SCR-N-4 / the one-row header rule: the table's name, its row count and\n its controls on ONE line. No repeated name, no subtitle restating it. */}\n <div className=\"flex items-center gap-2\">\n <h2 className=\"truncate text-sm font-medium\">\n {table.data ? tableName(table.data) : <Skeleton className=\"h-4 w-32\" />}\n </h2>\n {records.data?.total !== null && records.data?.total !== undefined ? (\n <span className=\"text-xs text-muted-foreground\">{records.data.total}</span>\n ) : null}\n <div className=\"ml-auto flex items-center gap-1\">{toolbarActions}</div>\n </div>\n\n {records.error ? <RefusalNotice error={records.error} /> : null}\n\n {/* A delete or an add the store refused, in the store's own sentence, with\n the one control that can still get the person what they asked for. */}\n {editing.rowError ? (\n <RefusalNotice\n error={editing.rowError}\n actions={\n <div className=\"mt-1 flex gap-1\">\n {onNewRecordForm ? (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n editing.clearRowError();\n onNewRecordForm();\n }}\n >\n Fill it in on the full form\n </Button>\n ) : null}\n <Button size=\"sm\" variant=\"ghost\" onClick={editing.clearRowError}>\n Dismiss\n </Button>\n </div>\n }\n />\n ) : null}\n\n {!records.live ? (\n // Nothing fails silently: a list that stopped updating says so.\n <p className=\"text-xs text-muted-foreground\">{records.liveReason}</p>\n ) : null}\n\n {noColumnsYet ? (\n <div\n data-matrx-grid-empty=\"no-columns\"\n className=\"flex flex-col items-start gap-2 rounded-md border border-dashed p-6\"\n >\n <p className=\"text-sm font-medium\">{NO_COLUMNS_YET}</p>\n <p className=\"max-w-prose text-xs text-muted-foreground\">{NO_COLUMNS_WHY}</p>\n {rights.structure && onAddField ? (\n <Button size=\"sm\" onClick={onAddField}>\n Add your first column\n </Button>\n ) : (\n <p className=\"max-w-prose text-xs text-muted-foreground\">{rights.why(\"structure\")}</p>\n )}\n </div>\n ) : (\n <>\n <MatrxDataTable<ReadRow>\n data={rows}\n columns={columns}\n getRowId={(row) => row.id}\n isLoading={nothingToShowYet}\n isFetching={refreshing}\n density={host.density ?? \"condensed\"}\n tableId={`records-grid-${tableId}`}\n stickyHeader\n pageSize={pageSize}\n /*\n * NO SECOND RECORD PANEL. The data table ships two of its own — a side\n * panel and a floating window — and both fall back to `DataRowInspector`,\n * which draws the raw row: its machine keys, a truncated id, and the\n * headings DOCUMENT, LEVEL and HIDDEN. That is what a person got when\n * they double-clicked a cell on 19 September, and it is a parallel layer\n * beside the record panel this package already has (`Peek`, opened\n * through `onRowOpen`), which the platform forbids. Both are OFF here,\n * so a row opens exactly one thing and a person never meets the\n * inspector.\n */\n detail={{ enabled: false }}\n window={{ enabled: false }}\n /*\n * THE VIEW'S COLORS, painted by the primitive — not re-implemented here.\n * A rule reads the record's DOCUMENT (a column is a Field key, and the\n * row around it carries ids and versions a rule must never see), and a\n * value with no option color of its own still paints, deterministically\n * (`colorFromTheValue`), because a color-by that silently did nothing\n * would be the screen lying about a setting a person just changed.\n */\n {...(presentation.style\n ? {\n tableStyle: {\n style: presentation.style,\n documentOf: (row: ReadRow) =>\n (row.document ?? {}) as Record<string, unknown>,\n choiceColorFor: colorFromTheValue,\n },\n }\n : {})}\n {...(onOpenRecord ? { onRowOpen: (row: ReadRow) => onOpenRecord(row.id) } : {})}\n {...(canWrite\n ? {\n // ABSENT, NEVER DEAD: a row this person may not delete carries no\n // Delete at all, rather than one that refuses when pressed.\n rowActions: (row: ReadRow) =>\n mayWriteRow(row.id) ? (\n <DeleteRecordButton\n row={row}\n retentionDays={table.data?.retention_days ?? null}\n onDelete={() => editing.remove(row.id)}\n />\n ) : null,\n }\n : {})}\n emptyState={{\n title: \"No records yet\",\n description: rights.write\n ? \"Add the first one and it appears here.\"\n : rights.known\n ? `Nothing has been written to this table. ${rights.why(\"write\")}`\n : \"Nothing has been written to this table.\",\n }}\n toolbar={{\n search: true,\n searchPlaceholder: \"Search records\",\n // SCR-2 / SCR-4: PRESENT for an admin, ABSENT for everyone else.\n // There is no third state: this package ships no disabled variant of\n // these controls, so a member cannot be shown a dead one by mistake.\n actions: (\n <>\n {/* A new record is written to the TABLE, so it follows the\n table's level and not any one row's. */}\n {Boolean(editable) && rights.write ? (\n <Button size=\"sm\" disabled={editing.busy} onClick={() => void editing.addRecord()}>\n {editing.busy ? \"Adding…\" : \"New record\"}\n </Button>\n ) : null}\n {rights.structure && onAddField ? <AddFieldButton onClick={onAddField} /> : null}\n </>\n ),\n }}\n />\n\n <Pager\n page={page}\n pageSize={pageSize}\n total={records.data?.total ?? null}\n rows={rows.length}\n onPage={setPage}\n />\n </>\n )}\n </div>\n );\n}\n\n/**\n * SCR-2. The \"+\" at the far right of the column headers. It exists only for a\n * holder of `admin`: the caller above decides, and there is no disabled variant\n * of this button anywhere in the package.\n */\nfunction AddFieldButton({ onClick }: { onClick: () => void }) {\n return (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={onClick}\n aria-label=\"Add a field\"\n title=\"Add a field to this table\"\n >\n +\n </Button>\n );\n}\n\n/**\n * DELETING NAMES THE CONSEQUENCE BEFORE IT HAPPENS. One press asks; the second\n * one does it. The sentence is the store's own truth about this Table — a soft\n * delete that stays reversible for the Table's own retention window (REC-23),\n * or, when the Table declares none, the plain fact that it can be restored.\n */\nfunction DeleteRecordButton({\n row,\n retentionDays,\n onDelete,\n}: {\n row: ReadRow;\n retentionDays: number | null;\n onDelete: () => Promise<unknown>;\n}) {\n const [asking, setAsking] = useState(false);\n if (!asking) {\n return (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label=\"Delete this record\"\n title=\"Delete this record\"\n onClick={() => setAsking(true)}\n >\n Delete\n </Button>\n );\n }\n return (\n <span className=\"flex items-center gap-1 text-[11px]\">\n <span className=\"text-muted-foreground\">\n {retentionDays\n ? `Removes it from the table. Restorable for ${retentionDays} days.`\n : \"Removes it from the table. It can be restored from the record's history.\"}\n </span>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => {\n setAsking(false);\n void onDelete();\n }}\n >\n Delete\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAsking(false)}>\n Keep\n </Button>\n <span className=\"sr-only\">{row.id}</span>\n </span>\n );\n}\n\nfunction Pager({\n page,\n pageSize,\n total,\n rows,\n onPage,\n}: {\n page: number;\n pageSize: number;\n total: number | null;\n rows: number;\n onPage: (page: number) => void;\n}) {\n const from = page * pageSize;\n const last = total === null ? rows < pageSize : from + rows >= total;\n if (page === 0 && last) return null;\n return (\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <Button size=\"sm\" variant=\"ghost\" disabled={page === 0} onClick={() => onPage(page - 1)}>\n Previous\n </Button>\n <span>\n {from + 1}–{from + rows}\n {total === null ? \"\" : ` of ${total}`}\n </span>\n <Button size=\"sm\" variant=\"ghost\" disabled={last} onClick={() => onPage(page + 1)}>\n Next\n </Button>\n </div>\n );\n}\n\n/**\n * One Field becomes one column. The header is the Field's own NAME — never its\n * key (`names.ts`) — and the cell is the value, rendered by its parity type and\n * editable in place when an editing session is passed.\n */\nexport function columnForField(\n field: Field,\n editing?: GridEditing | null,\n mayWriteRow?: (rowId: Uuid) => boolean,\n whyNotRow?: (rowId: Uuid) => string,\n look?: { format?: FieldFormatConfig; frozen?: boolean },\n): MatrxColumnDef<ReadRow> {\n const name = fieldName(field);\n /*\n * THE FIELD'S OWN DECLARATION FIRST. A currency Field with unit `$` is money\n * on every screen with nobody configuring anything; the view's `formats` map\n * only OVERRIDES that. `format` rides alongside `cell` deliberately: the cell\n * is what a person EDITS, `format` is what the table knows the column MEANS —\n * it is what right-aligns the money column, and what `formatColumnValue` reads\n * so the read view and the editor can never disagree about a number.\n */\n const format = look?.format ?? formatForField(field);\n return {\n id: field.key,\n header: name,\n label: name,\n accessorFn: (row) => row.document?.[field.key],\n sortable: true,\n ...(format ? { format } : {}),\n /*\n * A frozen column MUST declare a width or the table declines to freeze at\n * all rather than pin it at a guessed offset, so a view that asks for a\n * frozen column gets one here.\n */\n ...(look?.frozen ? { frozen: true, width: FROZEN_COLUMN_WIDTH } : {}),\n filter: editorKindFor(field) === \"select\" || editorKindFor(field) === \"multi_select\" ? \"select\" : \"auto\",\n cell: (row) =>\n editing ? (\n <GridCell\n field={field}\n row={row}\n editing={editing}\n canWrite={mayWriteRow ? mayWriteRow(row.id) : true}\n {...(whyNotRow ? { whyNot: whyNotRow(row.id) } : {})}\n {...(format ? { format } : {})}\n />\n ) : (\n <RecordValue\n field={field}\n value={row.document?.[field.key]}\n document={row.document}\n {...(format ? { format } : {})}\n />\n ),\n headerClassName: \"whitespace-nowrap\",\n // The type is in the header's tooltip rather than a second header row: one\n // row of headers, always — and it is the parity type's own WORD, not a\n // token (`Long text`, never `long_text`).\n className: \"align-top\",\n ...({ title: fieldTypeLabel(field) } as Record<string, unknown>),\n };\n}\n","/**\n * HOW A TABLE LOOKS — colors, formats and the frozen column.\n *\n * THE SPLIT, AND WHY IT IS THIS ONE. A Field declares WHAT it holds: a\n * currency, a percent, a date, a person. A VIEW declares HOW that reads and\n * what it is worth looking at: two decimal places or none, tint the row when\n * Status is Blocked, keep Name in place while the rest scrolls. Airtable draws\n * the line in exactly this place, and it has to be here: two people read one\n * table two different ways, and neither reading is a fact about the records.\n *\n * So nothing in this module is a new column on a Field and nothing here needed\n * a migration. A presentation lives on the saved-view record (`views.ts`), which\n * is an ordinary record of an ordinary Table — which means an agent sets it\n * through the same `records` tool it uses for everything else, and it travels\n * with the table the way every other record does.\n *\n * A FIELD STILL GETS ITS MONEY RIGHT WITH NO CONFIGURATION. `formatForField`\n * reads the Field's OWN declaration — a `currency` parity type with unit `$`, a\n * `percent`, a `datetime` with `config.kind` — and returns the format that\n * follows from it. The view's `formats` map only OVERRIDES that. A table nobody\n * has ever styled still shows `$1,250.50` and `45%`.\n */\n\nimport {\n STYLE_COLORS,\n parseTableStyle,\n tableStyleIsEmpty,\n type ChoiceColorLookup,\n type StyleColor,\n type TableStyle,\n} from \"@ai-matrx/design-system/data-table\";\nimport type { FieldFormatConfig } from \"@ai-matrx/design-system/field-formats\";\nimport type { Field } from \"@ai-matrx/records\";\n\nimport { editorKindFor } from \"./parity\";\n\n/** Everything a view says about how its table LOOKS. */\nexport type GridPresentation = {\n /** Color-by-a-column, rules and manual highlights. */\n style?: TableStyle;\n /** Per-column format overrides, by the Field's key. */\n formats?: Record<string, FieldFormatConfig>;\n /**\n * The columns that stay in place while the table scrolls sideways, by Field\n * key. Only the LEADING run of the view's column order can actually freeze —\n * the data table decides that, and declines rather than pinning a column at a\n * guessed offset.\n */\n frozen?: string[];\n};\n\nexport const EMPTY_PRESENTATION: GridPresentation = {};\n\n/** A frozen column needs a known width, or the table declines to freeze at all. */\nexport const FROZEN_COLUMN_WIDTH = 200;\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/**\n * Read a presentation out of whatever the view record holds — an object, or the\n * JSON string a text field stores.\n *\n * Tolerant in exactly the way `parseTableStyle` is: an unreadable half is\n * dropped and the rest still applies, because a table must keep drawing when\n * one piece of its styling goes out of date.\n */\nexport function parseGridPresentation(raw: unknown): GridPresentation {\n let value = raw;\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (trimmed === \"\") return {};\n try {\n value = JSON.parse(trimmed);\n } catch {\n return {};\n }\n }\n if (!isRecord(value)) return {};\n\n const out: GridPresentation = {};\n\n const style = parseTableStyle(value[\"style\"]);\n if (!tableStyleIsEmpty(style)) out.style = style;\n\n if (isRecord(value[\"formats\"])) {\n const formats: Record<string, FieldFormatConfig> = {};\n for (const [key, cfg] of Object.entries(value[\"formats\"])) {\n if (!isRecord(cfg)) continue;\n const id = cfg[\"id\"];\n if (typeof id !== \"string\") continue;\n const options = cfg[\"options\"];\n formats[key] = isRecord(options)\n ? {\n id: id as FieldFormatConfig[\"id\"],\n options: options as NonNullable<FieldFormatConfig[\"options\"]>,\n }\n : { id: id as FieldFormatConfig[\"id\"] };\n }\n if (Object.keys(formats).length > 0) out.formats = formats;\n }\n\n if (Array.isArray(value[\"frozen\"])) {\n const frozen = value[\"frozen\"].filter((k): k is string => typeof k === \"string\");\n if (frozen.length > 0) out.frozen = frozen;\n }\n\n return out;\n}\n\n/** True when nothing here would change how anything looks. */\nexport function presentationIsEmpty(p: GridPresentation): boolean {\n return (\n (p.style === undefined || tableStyleIsEmpty(p.style)) &&\n Object.keys(p.formats ?? {}).length === 0 &&\n (p.frozen?.length ?? 0) === 0\n );\n}\n\n/** The string a view record stores. Empty string for \"this view styles nothing\". */\nexport function presentationDocument(p: GridPresentation): string {\n return presentationIsEmpty(p) ? \"\" : JSON.stringify(p);\n}\n\n/**\n * The format a Field's OWN declaration implies, before any view says anything.\n *\n * Returns `undefined` for a Field whose value the record renderer already draws\n * better than a formatter could — a relation chip, a person, an attachment, a\n * choice — because handing those to a text formatter would REPLACE a working\n * control with a string.\n */\nexport function formatForField(field: Field): FieldFormatConfig | undefined {\n switch (editorKindFor(field)) {\n case \"currency\":\n return {\n id: \"currency\",\n options: { currency: currencyCodeFor(field.unit) },\n };\n case \"percent\":\n return { id: \"percent\" };\n case \"datetime\":\n return String(field.config?.[\"kind\"] ?? \"\") === \"date\"\n ? { id: \"date\" }\n : { id: \"datetime\" };\n case \"email\":\n return { id: \"email\" };\n case \"url\":\n return { id: \"url\" };\n case \"phone\":\n return { id: \"phone\" };\n case \"number\":\n return { id: \"number\" };\n default:\n return undefined;\n }\n}\n\n/**\n * The store lets a person type the SYMBOL they think in (`$`, `€`), and\n * `Intl.NumberFormat` wants the ISO code. The symbols people actually enter are\n * mapped; anything else is passed straight through, because a real ISO code is\n * the other thing that lands in this field, and an unknown code still renders\n * (`1,234.00 XYZ`) rather than blanking — THE FALLBACK LAW.\n */\nconst SYMBOL_TO_CODE: Record<string, string> = {\n $: \"USD\",\n \"£\": \"GBP\",\n \"€\": \"EUR\",\n \"¥\": \"JPY\",\n \"₹\": \"INR\",\n \"₽\": \"RUB\",\n \"₩\": \"KRW\",\n \"R$\": \"BRL\",\n \"C$\": \"CAD\",\n \"A$\": \"AUD\",\n};\n\nexport function currencyCodeFor(unit: string | null | undefined): string {\n const raw = (unit ?? \"\").trim();\n if (raw === \"\") return \"USD\";\n return SYMBOL_TO_CODE[raw] ?? raw.toUpperCase();\n}\n\n/**\n * The color a value paints with when a view colors BY a column.\n *\n * NOTHING FAILS SILENTLY, so this never returns \"no color\" for a value that\n * exists. The store keeps a list column's choices as records of another Table,\n * and this grid has not read that Table's option colors, so the color is\n * derived from the value's own text: the same word always gets the same color,\n * different words get different ones, and `true` is green the way every\n * checklist reads. When those option colors do land, this is the ONE function\n * that changes and every screen follows.\n */\nexport const colorFromTheValue: ChoiceColorLookup = (_fieldKey, value) => {\n if (value === true) return \"green\";\n if (value === false || value === null || value === undefined) return undefined;\n const text = String(value).trim().toLowerCase();\n if (text === \"\") return undefined;\n let hash = 0;\n for (let i = 0; i < text.length; i += 1) {\n hash = (hash * 31 + text.charCodeAt(i)) >>> 0;\n }\n return STYLE_COLORS[hash % STYLE_COLORS.length] as StyleColor;\n};\n","\"use client\";\n\n// src/ExportMenu.tsx — @ai-matrx/records-ui · SCR-31\n//\n// ANY VIEW EXPORTS AS CSV OR XLSX, CARRYING EXACTLY THE COLUMNS AND ROWS THE\n// READING PRINCIPAL MAY SEE — which is not a filter this component applies. The\n// rows it exports are the rows the READ DOOR returned, and the columns are the\n// Fields the store said APPLY. There is no wider read anywhere in this file, so\n// an export can never contain something the screen did not.\n//\n// The bytes are `@ai-matrx/records`' own `exportCsv` / `exportXlsx`, so an\n// export from a screen and an export from a script are the same file.\n\nimport { useState } from \"react\";\nimport { useFields, useRecords, type Field, type ReadRow, type ReadValue, type Uuid } from \"@ai-matrx/records/react\";\nimport { exportCsv, exportXlsx, type ExportRow } from \"@ai-matrx/records/core\";\nimport { AlchemyMenu } from \"@ai-matrx/alchemy/react\";\nimport { Button, cn } from \"@ai-matrx/design-system\";\nimport { RefusalLine } from \"./Refusal\";\n\nexport interface ExportMenuProps {\n tableId: Uuid;\n /** The rows on screen. Absent means \"this table's first page\", read the same way. */\n rows?: ReadRow[] | undefined;\n /** What the file is called. The table's name by default. */\n label?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * The rows, in the package's own `ExportRow` shape — the value AND its envelope,\n * so the exported cell can carry the store's own absence WORD instead of a blank\n * (VAL-2: \"never asked\" and \"refused\" are different facts, and the file says\n * which).\n */\nfunction toRows(fields: Field[], records: ReadRow[]): ExportRow[] {\n return records.map((record) => {\n const document = record.document ?? {};\n const envelopes = (document[\"_values\"] ?? {}) as Record<string, { absent?: string | null }>;\n const row: ExportRow = {};\n for (const field of fields) {\n const envelope = envelopes[field.key];\n row[field.key] = {\n field_key: field.key,\n value: document[field.key] ?? null,\n absent_reason: (envelope?.absent ?? null) as ReadValue[\"absent_reason\"],\n } as ReadValue;\n }\n return row;\n });\n}\n\nfunction download(name: string, mime: string, bytes: BlobPart) {\n const url = URL.createObjectURL(new Blob([bytes], { type: mime }));\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = name;\n anchor.click();\n URL.revokeObjectURL(url);\n}\n\nexport function ExportMenu({ tableId, rows, label, className }: ExportMenuProps) {\n const fields = useFields(tableId);\n const page = useRecords(tableId, { pageSize: 500 });\n const [failure, setFailure] = useState<string | null>(null);\n\n const records = rows ?? page.data?.rows ?? [];\n const name = label ?? \"records\";\n\n if (fields.error) return <RefusalLine error={fields.error} className={className} />;\n if (!rows && page.error) return <RefusalLine error={page.error} className={className} />;\n if (!fields.data || (!rows && !page.data)) {\n // The columns ARE the Fields and the rows are the read door's answer, so\n // there is no export to offer until both have arrived. A button that\n // produced a headerless or rowless file would be worse than a moment's wait.\n return <span className={cn(\"text-xs text-muted-foreground\", className)}>Reading this table…</span>;\n }\n\n const exported = () => toRows(fields.data ?? [], records);\n\n return (\n <div className={cn(\"flex items-center gap-1\", className)}>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => download(`${name}.csv`, \"text/csv;charset=utf-8\", exportCsv(fields.data ?? [], exported()))}\n >\n CSV\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n try {\n void exportXlsx(fields.data ?? [], exported(), name).then((bytes) =>\n download(\n `${name}.xlsx`,\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n bytes as unknown as BlobPart,\n ),\n );\n } catch (thrown) {\n // Nothing fails silently: say what broke and what to do instead.\n setFailure(\n `The spreadsheet could not be written (${thrown instanceof Error ? thrown.message : String(thrown)}). ` +\n `The CSV beside this button carries the same rows.`,\n );\n }\n }}\n >\n XLSX\n </Button>\n {/* The same menu every other surface on the platform carries. */}\n <AlchemyMenu\n label={name}\n sourceId={`records:${tableId}`}\n size=\"xs\"\n json={() => records.map((r) => r.document)}\n human={() => exportCsv(fields.data ?? [], exported())}\n />\n {failure ? <p className=\"text-xs text-destructive\">{failure}</p> : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/ImportWizard.tsx — @ai-matrx/records-ui · SCR-10, SCR-N-7\n//\n// MAP A FILE'S COLUMNS ONTO FIELDS, PREVIEW THE ROWS IT WILL WRITE, AND OFFER\n// ANY UNMAPPED COLUMN AS A FIELD PROPOSAL.\n//\n// The parsing and the matching are `@ai-matrx/records`' own `importCsv` /\n// `importXlsx`, so a file imported from a screen and a file imported from a\n// script land identically. An unmapped column is NEVER dropped quietly: it is\n// listed, and \"add this as a field\" sits beside it under the same right as the\n// grid's \"+\" (SCR-N-7) — absent, not disabled, for anybody else.\n//\n// Every row is written through the ONE write door, one at a time, and a row the\n// store refuses keeps its own refusal beside it. A partial import that pretended\n// to be a whole one is the failure this screen exists to make impossible.\n\nimport { useState } from \"react\";\nimport { useFields, useRecordMutation, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport { importCsv, importXlsx, type ParsedImport } from \"@ai-matrx/records/core\";\nimport { Badge, Button, Separator, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { fieldName } from \"./names\";\n\nexport interface ImportWizardProps {\n tableId: Uuid;\n /** SCR-N-7: what \"add this as a field\" does. Absent means the offer is not made. */\n onProposeField?: ((header: string) => void) | undefined;\n onDone?: ((written: number) => void) | undefined;\n className?: string | undefined;\n}\n\ninterface RowOutcome {\n index: number;\n recordId: string | null;\n refusal: string | null;\n}\n\nexport function ImportWizard({ tableId, onProposeField, onDone, className }: ImportWizardProps) {\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const mutation = useRecordMutation();\n const [parsed, setParsed] = useState<ParsedImport | null>(null);\n const [outcomes, setOutcomes] = useState<RowOutcome[]>([]);\n const [reading, setReading] = useState<string | null>(null);\n\n const take = async (file: File) => {\n setReading(null);\n setOutcomes([]);\n try {\n const declared = fields.data ?? [];\n const result = file.name.toLowerCase().endsWith(\".xlsx\")\n ? await importXlsx(declared, await file.arrayBuffer())\n : importCsv(declared, await file.text());\n setParsed(result);\n } catch (thrown) {\n setReading(`That file could not be read: ${thrown instanceof Error ? thrown.message : String(thrown)}`);\n }\n };\n\n const write = async () => {\n if (!parsed) return;\n const done: RowOutcome[] = [];\n for (const [index, row] of parsed.rows.entries()) {\n const id = await mutation.write({ table_id: tableId, data: row });\n done.push({ index, recordId: id, refusal: id ? null : (mutation.error?.message ?? \"The store refused this row.\") });\n setOutcomes([...done]);\n }\n onDone?.(done.filter((d) => d.recordId).length);\n };\n\n const written = outcomes.filter((o) => o.recordId).length;\n const refused = outcomes.filter((o) => !o.recordId).length;\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-2 text-xs\", className)}>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">Import</span>\n <span className=\"text-muted-foreground\">{table.data?.name}</span>\n {/* A file cannot be mapped before the store has said which Fields\n apply, so the chooser waits rather than matching against nothing and\n reporting every column as unmapped. It ALSO waits for the Table\n itself: the rights that decide whether \"add this as a field\" is\n offered are read from the Table, and a chooser that opened first\n could show an admin a mapping with the offer missing — a control\n silently absent for the one person who may use it. Both answers, or\n no chooser.\n (Found by the suite under load, 2026-09-18: the Fields arrived\n before the Table and the offer was not there.) */}\n {fields.data && table.data ? (\n <input\n type=\"file\"\n accept=\".csv,.xlsx\"\n aria-label=\"Choose a file to import\"\n className=\"ml-auto text-xs\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) void take(file);\n }}\n />\n ) : (\n <span className=\"ml-auto text-muted-foreground\">\n {fields.data ? \"Reading this table…\" : \"Reading this table's fields…\"}\n </span>\n )}\n </div>\n\n {reading ? <p className=\"text-destructive\">{reading}</p> : null}\n\n {parsed ? (\n <>\n {/* The mapping, column by column, with nothing hidden. */}\n <ul className=\"flex flex-wrap gap-1\">\n {parsed.columns.map((column) => (\n <li key={column.header}>\n <Badge variant={column.field ? \"secondary\" : \"outline\"} className=\"gap-1 text-[11px] font-normal\">\n {column.header}\n <span className=\"opacity-60\">→</span>\n {column.field ? (\n column.field.label || column.field.key\n ) : (\n <span className=\"text-destructive\">no field</span>\n )}\n {/* SCR-N-7, and it is gated by the SAME right as the grid's \"+\". */}\n {!column.field && rights.admin && onProposeField ? (\n <button\n type=\"button\"\n className=\"underline underline-offset-2\"\n onClick={() => onProposeField(column.header)}\n >\n add as a field\n </button>\n ) : null}\n </Badge>\n </li>\n ))}\n </ul>\n\n {parsed.unmapped.length > 0 ? (\n <p className=\"text-muted-foreground\">\n {parsed.unmapped.length} column{parsed.unmapped.length === 1 ? \"\" : \"s\"} match no Field and{\" \"}\n {rights.admin && onProposeField\n ? \"can be added as fields above.\"\n : \"will not be written. Nothing is dropped quietly: the columns are listed above.\"}\n </p>\n ) : null}\n\n <Separator />\n\n {/* The preview: exactly the rows the write door will be handed. */}\n <p className=\"text-muted-foreground\">\n {parsed.rows.length} row{parsed.rows.length === 1 ? \"\" : \"s\"} to write\n </p>\n <div className=\"max-h-56 overflow-auto rounded border\">\n <table className=\"w-full\">\n <thead className=\"sticky top-0 bg-muted\">\n <tr>\n {(fields.data ?? []).map((field) => (\n <th key={field.id} className=\"px-2 py-1 text-left font-medium\">\n {fieldName(field)}\n </th>\n ))}\n <th className=\"px-2 py-1 text-left font-medium\">Result</th>\n </tr>\n </thead>\n <tbody>\n {parsed.rows.slice(0, 50).map((row, index) => {\n const outcome = outcomes.find((o) => o.index === index);\n return (\n <tr key={index} className=\"border-t\">\n {(fields.data ?? []).map((field) => (\n <td key={field.id} className=\"max-w-40 truncate px-2 py-1\">\n {row[field.key] ?? \"\"}\n </td>\n ))}\n <td className=\"px-2 py-1\">\n {outcome?.recordId ? (\n <span className=\"text-muted-foreground\">written</span>\n ) : outcome?.refusal ? (\n // The store's own sentence, on the row it refused.\n <span className=\"text-destructive\">{outcome.refusal}</span>\n ) : null}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n {mutation.error && outcomes.length === 0 ? <RefusalNotice error={mutation.error} /> : null}\n\n <div className=\"flex items-center gap-2\">\n <Button size=\"sm\" disabled={mutation.saving || !rights.write} onClick={() => void write()}>\n {mutation.saving ? \"Writing…\" : `Write ${parsed.rows.length} rows`}\n </Button>\n {outcomes.length > 0 ? (\n <span className=\"text-muted-foreground\">\n {written} written{refused > 0 ? `, ${refused} refused — each one says why on its row` : \"\"}\n </span>\n ) : null}\n </div>\n </>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/CustomFieldsSection.tsx — @ai-matrx/records-ui · SCR-12\n//\n// THE ONE LINE A STANDARD ENTITY PAGE ADDS.\n//\n// <CustomFieldsSection entityToken=\"party\" recordId={party.id} />\n//\n// A standard entity's page grows its organization's custom fields in one\n// section, resolved from the Field records, WITH NO PER-ENTITY CODE. That is the\n// whole point: nobody writes a section per entity, and an organization that adds\n// a field to Contacts sees it on every contact page the same afternoon.\n//\n// 🚨 WHAT THIS COMPONENT USED TO DO, AND WHY IT COULD NEVER WORK (measured from\n// the seat on the main database, 2026-09-19). It resolved `entityToken` by\n// looking for a CUSTOM Table whose slug happened to equal the token, and then\n// read the row with `useRecord(recordId)` — which reads `custom.record`, where a\n// CRM contact does not live and never will. So on a standard entity page it\n// rendered NOTHING, silently, forever: no table matched, so the section was\n// absent, and absence is exactly what it renders when a table has no custom\n// fields. SCR-12 looked finished and had never shown a single value.\n//\n// It now goes through the token-keyed door set (`custom.entity_record_read`,\n// `custom.entity_field_rights`, `custom.entity_value_write`,\n// `custom.entity_field_declare`), which reads the standard row AS THE PERSON —\n// the table's own row-level security decides — and hands back REC-53's three\n// blocks: the row's real columns, its custom values, and the definitions that\n// describe them.\n\nimport { useMemo, useState } from \"react\";\nimport {\n useEntityFieldMutation,\n useEntityFieldRights,\n useEntityRecord,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport type { EntityFieldValue, Field } from \"@ai-matrx/records\";\nimport { Button, Separator, cn } from \"@ai-matrx/design-system\";\nimport { RefusalLine } from \"./Refusal\";\nimport { FieldControl, FieldLabel } from \"./editors\";\nimport { renderValue } from \"./values\";\n\nexport interface CustomFieldsSectionProps {\n /** The standard table's registered token (REC-33), e.g. `party`, `crm_deal`. */\n entityToken: string;\n /** The id of the row this page is showing. */\n recordId: Uuid;\n /** The heading. One row, no subtitle restating it. */\n title?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * WHAT A PERSON CAN ADD FROM A RECORD PAGE, in the words they use. The store\n * knows thirteen parity types and three plain ones; a record page offers the\n * ones that need nothing more than a name, and the full panel (TableSettings)\n * is where a choice list and a relation get the extra answer they need.\n */\nconst ADDABLE_TYPES = [\n { value: \"text\", label: \"Text\" },\n { value: \"long_text\", label: \"Long text\" },\n { value: \"number\", label: \"Number\" },\n { value: \"currency\", label: \"Money\" },\n { value: \"percent\", label: \"Percentage\" },\n { value: \"datetime\", label: \"Date\" },\n { value: \"email\", label: \"Email\" },\n { value: \"phone\", label: \"Phone\" },\n { value: \"url\", label: \"Link\" },\n { value: \"member\", label: \"Person\" },\n { value: \"attachment\", label: \"File\" },\n] as const;\n\n/** The definitions the read door hands back are Field-shaped for the editors. */\nfunction asField(f: EntityFieldValue): Field {\n return {\n id: f.id,\n key: f.key,\n label: f.label,\n type: f.type,\n parity_type: f.parity_type,\n format: f.format,\n unit: f.unit,\n multi: f.multi ?? false,\n required: f.required ?? false,\n sensitivity: f.sensitivity,\n config: f.options_table_id ? { options_table_id: f.options_table_id } : {},\n relation_target: f.relation_target ?? null,\n } as unknown as Field;\n}\n\nexport function CustomFieldsSection({\n entityToken,\n recordId,\n title = \"Custom fields\",\n className,\n}: CustomFieldsSectionProps) {\n const read = useEntityRecord(entityToken, recordId);\n const rights = useEntityFieldRights(entityToken);\n const mutation = useEntityFieldMutation();\n const [editing, setEditing] = useState(false);\n const [adding, setAdding] = useState(false);\n const [newLabel, setNewLabel] = useState(\"\");\n const [newType, setNewType] = useState<string>(\"text\");\n const [draft, setDraft] = useState<Record<string, unknown>>({});\n\n const fields = useMemo(() => read.data?.fields ?? [], [read.data]);\n const mayAdd = rights.data?.may_declare === true;\n\n // NOTHING TO GROW: render nothing at all rather than an empty titled box on\n // every page in the product — UNLESS this person may add one, in which case an\n // empty section is the only place the offer can live. A capability nobody can\n // find is not shipped.\n if (!read.loading && !read.error && fields.length === 0 && !mayAdd) return null;\n\n // A REFUSAL IS THE STORE'S OWN SENTENCE, never a blank section. The commonest\n // one here is honest and actionable: the person may not open this row.\n if (read.error) return <RefusalLine error={read.error} className={className} />;\n\n const values = read.data?.custom ?? {};\n const written = read.data?.custom_written ?? {};\n\n return (\n <section className={cn(\"flex min-w-0 flex-col gap-2 text-xs\", className)}>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">{title}</h3>\n <span className=\"text-muted-foreground\">{fields.length}</span>\n {fields.length > 0 ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"ml-auto\"\n title={editing ? \"Stop editing these fields\" : \"Edit these fields\"}\n onClick={() => {\n setDraft({});\n setEditing((e) => !e);\n }}\n >\n {editing ? \"Cancel\" : \"Edit\"}\n </Button>\n ) : null}\n {/* SCR-12: ABSENT, never disabled. `custom.entity_field_rights` answers\n the right and the sentence together, so a person who may not add a\n column reads WHY rather than pressing a control that fails. */}\n {mayAdd && !editing ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className={fields.length > 0 ? undefined : \"ml-auto\"}\n onClick={() => setAdding((a) => !a)}\n >\n {adding ? \"Cancel\" : \"Add field\"}\n </Button>\n ) : null}\n {editing ? (\n <Button\n size=\"sm\"\n disabled={mutation.saving || Object.keys(draft).length === 0}\n onClick={async () => {\n const saved = await mutation.write({\n token: entityToken,\n record_id: recordId,\n patch: draft,\n });\n if (saved) {\n setEditing(false);\n setDraft({});\n read.reload();\n }\n }}\n >\n {mutation.saving ? \"Saving…\" : \"Save\"}\n </Button>\n ) : null}\n </div>\n <Separator />\n {mutation.error ? <RefusalLine error={mutation.error} /> : null}\n {rights.data && !rights.data.may_declare && rights.data.reason ? (\n <p className=\"text-[11px] text-muted-foreground\">{rights.data.reason}</p>\n ) : null}\n {adding ? (\n <form\n className=\"flex flex-wrap items-end gap-2\"\n onSubmit={async (e) => {\n e.preventDefault();\n const id = await mutation.declare({\n token: entityToken,\n spec: { label: newLabel, type: newType },\n });\n if (id) {\n setAdding(false);\n setNewLabel(\"\");\n read.reload();\n }\n }}\n >\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">Name</span>\n <input\n className=\"h-8 rounded-md border bg-background px-2\"\n value={newLabel}\n onChange={(e) => setNewLabel(e.target.value)}\n placeholder=\"Account tier\"\n required\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">Holds</span>\n <select\n className=\"h-8 rounded-md border bg-background px-2\"\n value={newType}\n onChange={(e) => setNewType(e.target.value)}\n >\n {ADDABLE_TYPES.map((t) => (\n <option key={t.value} value={t.value}>\n {t.label}\n </option>\n ))}\n </select>\n </label>\n <Button size=\"sm\" type=\"submit\" disabled={mutation.saving || newLabel.trim() === \"\"}>\n {mutation.saving ? \"Adding…\" : \"Add\"}\n </Button>\n </form>\n ) : null}\n {editing ? (\n <div className=\"flex flex-col gap-3\">\n {fields.map((f) => {\n const field = asField(f);\n const id = `cf-${recordId}-${f.key}`;\n return (\n <div key={f.id} className=\"flex min-w-0 flex-col gap-1\">\n <FieldLabel field={field} htmlFor={id} />\n <FieldControl\n id={id}\n field={field}\n value={f.key in draft ? draft[f.key] : values[f.key]}\n onChange={(next) => setDraft((d) => ({ ...d, [f.key]: next }))}\n />\n </div>\n );\n })}\n </div>\n ) : (\n <dl className=\"grid grid-cols-[minmax(6rem,12rem)_1fr] gap-x-3 gap-y-1.5\">\n {fields.map((f) => (\n <div key={f.id} className=\"contents\">\n <dt className=\"flex items-baseline gap-1 truncate text-muted-foreground\">\n {f.label}\n {/* VAL-2 / AGT-N-4: who put this value here. A value nobody has\n written says nothing rather than pretending somebody did. */}\n {written[f.key]?.actor ? (\n <span className=\"text-[10px] text-muted-foreground/70\">{written[f.key]?.actor}</span>\n ) : null}\n </dt>\n <dd className=\"min-w-0\">{renderValue(asField(f), values[f.key])}</dd>\n </div>\n ))}\n </dl>\n )}\n </section>\n );\n}\n","\"use client\";\n\n// src/FieldEditor.tsx — @ai-matrx/records-ui · SCR-9\n//\n// ADDING A COLUMN, WHICH IS THE FIRST THING ANYBODY DOES WITH A TABLE.\n//\n// On 19 September this panel refused every column a person tried to add — a\n// Number and a Date with \"the table does not declare a field called day_rate —\n// declare it there first\", a Person as though it were a formula, and a choice\n// list with \"has to say which table its choices come from\" and nowhere to say\n// it. One cause: the panel assembled a Field DOCUMENT itself and wrote it with\n// the ordinary record writer, which can neither tell the Table about the field\n// nor stamp the row as a field. Both of those are the store's to do, and now it\n// does them: `custom.field_declare` takes what a person knows — a type, a name,\n// and for a choice list the choices — and turns it into the document its own\n// guards demand.\n//\n// So this panel's whole job is to collect an INTENTION. It never writes a\n// behaviour, a format, a unit, a relation target, a relation maximum, a\n// compute_on or a pattern Rule; every one of those is the store's answer to the\n// type a person picked, and a screen that answered them itself is a second\n// place for the thirteen types to be wrong.\n//\n// The key is derived from the name and shown, never demanded: a blank, unmarked,\n// required box that refused the first attempt every time is what a person hit\n// before anything else on this panel.\n//\n// THE SIXTEENTH TYPE (independent verdict, fifth pass, 19 September). Fifteen\n// of the sixteen went in. \"Total of linked records\" did not: the panel\n// explained honestly that the table had no column pointing at several records\n// — and left Add field live, so pressing it sent a rollup with no relation on\n// it and the store answered \"the field Total hours has to say which relation it\n// reads through — FLD-11: … config.via names a relation Field of this same\n// table, by its key.\" A contract row id and three database words, at the\n// person.\n//\n// Both halves are closed here. The picker now offers EVERY relation column this\n// table has, not only the ones that hold several, and says in one plain\n// sentence what a single-valued one cannot do — because \"Crew lead\" IS the\n// column a person means, and hiding it taught them nothing. And the panel never\n// sends a declaration it already knows the store must refuse: `whatIsMissing`\n// asks, in this panel's own words, what has not been answered yet, the sentence\n// sits under the button, and the button says so rather than failing.\n\nimport { useMemo, useState } from \"react\";\nimport {\n type ContextPolicy,\n type Field,\n type FieldPatch,\n type FieldRule,\n type FieldSensitivity,\n type NewFieldDeclaration,\n type Uuid,\n} from \"@ai-matrx/records\";\nimport { useFieldMutation, useFields, useRecords, useTable } from \"@ai-matrx/records/react\";\nimport {\n BasicInput,\n BasicTextarea,\n Button,\n Checkbox,\n Label,\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n Separator,\n cn,\n} from \"@ai-matrx/design-system\";\nimport { editorKindFor } from \"./parity\";\nimport {\n FIELD_TYPE_CHOICES,\n FIELD_TYPE_GROUPS,\n fieldTypeChoice,\n isPlainFieldType,\n type PickableFieldType,\n} from \"./fieldTypes\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { fieldName, humanize } from \"./names\";\n\nconst RULE_KINDS: { kind: FieldRule[\"kind\"]; label: string }[] = [\n { kind: \"min\", label: \"At least\" },\n { kind: \"max\", label: \"At most\" },\n { kind: \"length\", label: \"No longer than\" },\n { kind: \"pattern\", label: \"Looks like\" },\n { kind: \"equals_field\", label: \"Same as the column\" },\n { kind: \"differs_from_field\", label: \"Different from the column\" },\n];\n\n/** FLD-12, in the words the setting actually means to the person setting it. */\nconst SENSITIVITIES: { value: string; label: string }[] = [\n { value: \"public\", label: \"Anyone who can open the record\" },\n { value: \"internal\", label: \"People in this organization\" },\n { value: \"confidential\", label: \"People who have been given the record\" },\n { value: \"restricted\", label: \"Owners and administrators only\" },\n];\n\nconst AGENT_VISIBILITY: { value: string; label: string }[] = [\n { value: \"include\", label: \"Yes, an assistant can read it\" },\n { value: \"summarize\", label: \"Only a summary of it\" },\n { value: \"on_request\", label: \"Only when somebody asks for it\" },\n { value: \"exclude\", label: \"No, keep it away from assistants\" },\n];\n\nconst ROLLUP_OPERATIONS: { value: NonNullable<NewFieldDeclaration[\"agg\"]>; label: string }[] = [\n { value: \"count\", label: \"How many there are\" },\n { value: \"sum\", label: \"The total of\" },\n { value: \"avg\", label: \"The average of\" },\n { value: \"min\", label: \"The smallest\" },\n { value: \"max\", label: \"The largest\" },\n];\n\nconst FORMULA_OPERATIONS: { value: string; label: string; joins: boolean }[] = [\n { value: \"concat\", label: \"Join them together\", joins: true },\n { value: \"add\", label: \"Add them up\", joins: true },\n { value: \"sub\", label: \"Take the second from the first\", joins: false },\n { value: \"mul\", label: \"Multiply them\", joins: true },\n { value: \"div\", label: \"Divide the first by the second\", joins: false },\n];\n\n/** `Day rate` → `day_rate`. Shown, so nothing about it is a surprise. */\nexport function keyFor(label: string): string {\n const token = label\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 48);\n if (token === \"\") return \"\";\n return /^[a-z]/.test(token) ? token : `f_${token}`;\n}\n\nexport interface FieldEditorProps {\n tableId: Uuid;\n /** The Field being edited. Absent means a new one. */\n field?: Field | undefined;\n onSaved?: (() => void) | undefined;\n onCancel?: (() => void) | undefined;\n /** Called after the store has accepted the removal, so the list can re-read. */\n onRemoved?: (() => void) | undefined;\n className?: string | undefined;\n}\n\nexport function FieldEditor({ tableId, field, onSaved, onCancel, onRemoved, className }: FieldEditorProps) {\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const mutation = useFieldMutation();\n\n const [label, setLabel] = useState(field?.label ?? \"\");\n const [type, setType] = useState<PickableFieldType>(() => startingType(field));\n const [required, setRequired] = useState(field?.required ?? false);\n const [multi, setMulti] = useState(field?.multi ?? false);\n const [dated, setDated] = useState(field?.dated ?? false);\n const [sensitivity, setSensitivity] = useState(String(field?.sensitivity ?? \"internal\"));\n const [contextPolicy, setContextPolicy] = useState(String(field?.context_policy ?? \"include\"));\n const [rules, setRules] = useState<FieldRule[]>(field?.rules ?? []);\n const [optionText, setOptionText] = useState(\"\");\n const [unit, setUnit] = useState(field?.unit ?? \"$\");\n const [withTime, setWithTime] = useState(String(field?.config?.[\"kind\"] ?? \"date\") === \"datetime\");\n const [via, setVia] = useState(String(field?.config?.[\"via\"] ?? \"\"));\n const [pick, setPick] = useState(String(field?.config?.[\"pick\"] ?? \"\"));\n const [agg, setAgg] = useState<NonNullable<NewFieldDeclaration[\"agg\"]>>(\n (field?.config?.[\"agg\"] as NewFieldDeclaration[\"agg\"]) ?? \"count\",\n );\n const [of, setOf] = useState(String(field?.config?.[\"of\"] ?? \"\"));\n const [formulaOp, setFormulaOp] = useState(\"concat\");\n const [formulaFields, setFormulaFields] = useState<string[]>([]);\n const [askingToRemove, setAskingToRemove] = useState(false);\n\n const others = useMemo(\n () => (fields.data ?? []).filter((f) => f.id !== field?.id),\n [fields.data, field?.id],\n );\n const relations = useMemo(() => others.filter((f) => f.type === \"relation\"), [others]);\n const choice = fieldTypeChoice(type);\n const editing = Boolean(field);\n // The key is DERIVED, never asked for and never shown: the blank, unmarked,\n // required box it replaced refused the first attempt on this panel every\n // time, and the line that printed the derived token instead was the last\n // machine identity on this screen. `keyFor` stays exported for callers that\n // need to predict it; a person does not.\n\n // SCR-4: a person who does not administer the table never sees this panel.\n if (!rights.structure) {\n return (\n <p className={cn(\"text-xs text-muted-foreground\", className)}>\n {/* Honest, not dead: the reason, in a sentence — what level it takes\n and who can give it to you. */}\n {rights.why(\"structure\")}\n </p>\n );\n }\n\n const options = optionText\n .split(\"\\n\")\n .map((word) => word.trim())\n .filter((word) => word !== \"\");\n\n /**\n * WHAT THIS PANEL STILL NEEDS, in the words of the panel that asked for it.\n *\n * Never the store's sentence: the store refuses by contract row and document\n * path, which is right for a caller and wrong for a person. `null` means the\n * declaration is complete as far as this screen can tell — the store is still\n * the one that decides, and whatever it says then is shown as it always was.\n */\n const missing = editing ? null : whatIsMissing({ type, label, options, via, pick, agg, of, relations, formulaFields });\n\n const save = async () => {\n // A declaration this panel already knows is incomplete is not sent. The\n // person gets the sentence beside the button, now, instead of a refusal\n // written for a caller, a second later.\n if (missing) return;\n if (editing && field) {\n const patch: FieldPatch = {\n label,\n required,\n dated,\n sensitivity: sensitivity as FieldSensitivity,\n context_policy: contextPolicy as ContextPolicy,\n rules,\n ...(unitApplies(type) ? { unit } : {}),\n // An empty box means \"leave the choices alone\"; a list replaces them.\n ...(optionText.trim() === \"\" ? {} : { options }),\n };\n const written = await mutation.update({ field_id: field.id, patch });\n if (written !== null) onSaved?.();\n return;\n }\n const spec: NewFieldDeclaration = {\n label,\n ...(isPlainFieldType(type) ? { plain: type } : { parity_type: type }),\n required,\n dated,\n multi: multiApplies(type) ? multi : type === \"multi_select\",\n sensitivity: sensitivity as FieldSensitivity,\n context_policy: contextPolicy as ContextPolicy,\n rules,\n ...(type === \"select\" || type === \"multi_select\" ? { options } : {}),\n ...(type === \"currency\" ? { unit } : {}),\n ...(type === \"datetime\" ? { kind: withTime ? (\"datetime\" as const) : (\"date\" as const) } : {}),\n ...(type === \"lookup\" ? { via, pick } : {}),\n ...(type === \"rollup\" ? { via, agg, ...(agg === \"count\" ? {} : { of }) } : {}),\n ...(type === \"formula\" ? { expr: formulaExpression(formulaOp, formulaFields) } : {}),\n };\n const written = await mutation.declare({ table_id: tableId, spec });\n if (written !== null) onSaved?.();\n };\n\n const remove = async () => {\n if (!field) return;\n const gone = await mutation.retire({ field_id: field.id });\n setAskingToRemove(false);\n if (gone) (onRemoved ?? onSaved)?.();\n };\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-3 text-xs\", className)}>\n {/* One row of header: what this is, and nothing restating it. */}\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{field ? `Field · ${fieldName(field)}` : \"New field\"}</span>\n <span className=\"ml-auto text-muted-foreground\">{table.data?.name}</span>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">Name</Label>\n <BasicInput\n value={label}\n autoFocus\n aria-label=\"Field name\"\n placeholder=\"Day rate\"\n onChange={(e) => setLabel(e.target.value)}\n />\n <p className=\"text-[11px] text-muted-foreground\">What people will read at the top of the column.</p>\n </label>\n\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">What it holds</Label>\n <Select\n value={type}\n disabled={editing}\n onValueChange={(next) => setType(next as PickableFieldType)}\n >\n <SelectTrigger size=\"sm\" aria-label=\"What this field holds\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FIELD_TYPE_GROUPS.map((group) => (\n <SelectGroup key={group}>\n <SelectLabel>{group}</SelectLabel>\n {FIELD_TYPE_CHOICES.filter((c) => c.group === group).map((c) => (\n <SelectItem key={c.id} value={c.id}>\n {c.label}\n </SelectItem>\n ))}\n </SelectGroup>\n ))}\n </SelectContent>\n </Select>\n <p className=\"text-[11px] text-muted-foreground\">\n {editing\n ? \"What a column holds cannot be changed here — every value already saved would have to be converted. Add a new column and move the values across.\"\n : (choice?.explanation ?? \"\")}\n </p>\n </div>\n </div>\n\n {/* WHAT THE PANEL ASKS FOR NEXT depends entirely on the answer above, and\n nothing else on this panel knows the difference between the sixteen. */}\n {!editing || type === \"select\" || type === \"multi_select\" ? (\n <TypeQuestions\n type={type}\n editing={editing}\n optionText={optionText}\n setOptionText={setOptionText}\n unit={unit}\n setUnit={setUnit}\n withTime={withTime}\n setWithTime={setWithTime}\n via={via}\n setVia={setVia}\n pick={pick}\n setPick={setPick}\n agg={agg}\n setAgg={setAgg}\n of={of}\n setOf={setOf}\n formulaOp={formulaOp}\n setFormulaOp={setFormulaOp}\n formulaFields={formulaFields}\n setFormulaFields={setFormulaFields}\n relations={relations}\n others={others}\n existingOptionsTable={Boolean(field?.options_table_id ?? field?.config?.[\"options_table_id\"])}\n />\n ) : null}\n\n <div className=\"flex flex-wrap items-center gap-4\">\n <label className=\"flex items-center gap-1.5\">\n <Checkbox\n checked={required}\n aria-label=\"Every record has to have one\"\n onCheckedChange={(v) => setRequired(v === true)}\n />\n Every record has to have one\n </label>\n {multiApplies(type) ? (\n <label className=\"flex items-center gap-1.5\">\n <Checkbox\n checked={multi}\n disabled={editing}\n aria-label=\"Can hold more than one\"\n onCheckedChange={(v) => setMulti(v === true)}\n />\n Can hold more than one\n </label>\n ) : null}\n <label className=\"flex items-center gap-1.5\">\n <Checkbox\n checked={dated}\n aria-label=\"Each value has its own date\"\n onCheckedChange={(v) => setDated(v === true)}\n />\n Each value has its own date\n </label>\n </div>\n\n <Separator />\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">Who can see what is in it</Label>\n <Select value={sensitivity} onValueChange={setSensitivity}>\n <SelectTrigger size=\"sm\" aria-label=\"Who can see what is in it\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SENSITIVITIES.map((row) => (\n <SelectItem key={row.value} value={row.value}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">Can an assistant read it</Label>\n <Select value={contextPolicy} onValueChange={setContextPolicy}>\n <SelectTrigger size=\"sm\" aria-label=\"Can an assistant read it\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {AGENT_VISIBILITY.map((row) => (\n <SelectItem key={row.value} value={row.value}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <Separator />\n\n {/* FLD-3: a constraint is a RULE attached to the Field, never a behaviour. */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">What counts as a good value</span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"ml-auto\"\n onClick={() => setRules([...rules, { kind: \"min\", value: 0 }])}\n >\n Add a check\n </Button>\n </div>\n {rules.length === 0 ? (\n <p className=\"text-muted-foreground\">No checks. Anything this kind of column can hold will be accepted.</p>\n ) : null}\n {rules.map((rule, index) => (\n <div key={`${rule.kind}-${index}`} className=\"flex items-center gap-1\">\n <Select\n value={rule.kind}\n onValueChange={(kind) =>\n setRules(rules.map((r, i) => (i === index ? { ...r, kind: kind as FieldRule[\"kind\"] } : r)))\n }\n >\n <SelectTrigger size=\"sm\" className=\"w-52\" aria-label={`Check ${index + 1}`}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RULE_KINDS.map((row) => (\n <SelectItem key={row.kind} value={row.kind}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <BasicInput\n className=\"h-8\"\n value={String(rule.value ?? \"\")}\n aria-label={`Check ${index + 1} value`}\n onChange={(e) => setRules(rules.map((r, i) => (i === index ? { ...r, value: e.target.value } : r)))}\n />\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Remove check ${index + 1}`}\n onClick={() => setRules(rules.filter((_, i) => i !== index))}\n >\n ×\n </Button>\n </div>\n ))}\n </div>\n\n {mutation.error ? <RefusalNotice error={mutation.error} /> : null}\n\n {/* WHAT IS STILL MISSING, where the person is about to press. Not a\n disabled button with nothing beside it, and not a refusal from the\n store a second after the press: the sentence and the control are one\n thing, and the sentence names what to do. */}\n {missing ? <p className=\"text-[11px] text-destructive\">{missing}</p> : null}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n size=\"sm\"\n disabled={mutation.saving || missing !== null}\n onClick={() => void save()}\n >\n {mutation.saving ? \"Saving…\" : field ? \"Save field\" : \"Add field\"}\n </Button>\n {onCancel ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n {field ? (\n <div className=\"ml-auto flex items-center gap-2\">\n {askingToRemove ? (\n <>\n {/* Destructive, so the consequence is named BEFORE it happens. */}\n <span className=\"text-destructive\">\n Removing {fieldName(field)} takes it off every record of this table. The values stay in\n the record's history and nothing else is deleted.\n </span>\n <Button size=\"sm\" variant=\"destructive\" disabled={mutation.saving} onClick={() => void remove()}>\n Remove it\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAskingToRemove(false)}>\n Keep it\n </Button>\n </>\n ) : (\n <Button size=\"sm\" variant=\"outline\" onClick={() => setAskingToRemove(true)}>\n Remove this field\n </Button>\n )}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\n/**\n * WHAT THE PANEL STILL NEEDS BEFORE THE STORE WOULD TAKE THIS, in plain words.\n *\n * It answers exactly the questions this panel asked, so every sentence names a\n * control the person is looking at. It is NOT a second copy of the store's\n * rules and it is not allowed to become one: the store decides, and every one\n * of these is something the panel can see is unanswered without asking it.\n *\n * Exported so the suite can assert the sentences without driving the whole\n * panel, and so the red twin can assert that removing it puts the contract row\n * id back in front of a person.\n */\nexport function whatIsMissing(state: {\n type: PickableFieldType;\n label: string;\n options: string[];\n via: string;\n pick: string;\n agg: NonNullable<NewFieldDeclaration[\"agg\"]>;\n of: string;\n relations: Field[];\n formulaFields: string[];\n}): string | null {\n const { type, label, options, via, pick, agg, of, relations, formulaFields } = state;\n if (label.trim() === \"\") return \"Give the column a name.\";\n\n if (type === \"select\" || type === \"multi_select\") {\n if (options.length === 0) return \"Type the choices this column offers, one per line.\";\n return null;\n }\n\n if (type === \"lookup\" || type === \"rollup\") {\n if (relations.length === 0) {\n return type === \"rollup\"\n ? \"A total is worked out across the records a column points at, and this table has no column that points at records yet. Add a Person or File column that can hold more than one, then come back.\"\n : \"A borrowed value is read from a record a column points at, and this table has no column that points at another record yet. Add a Person or File column, then come back.\";\n }\n const chosen = relations.find((relation) => relation.key === via);\n if (!chosen) {\n return type === \"rollup\"\n ? \"Choose the column whose records this one adds up.\"\n : \"Choose the column whose record this one reads from.\";\n }\n // THE ONE THE VERDICT HIT. The column a person means is usually there and\n // simply holds one thing; saying which column and what to do about it beats\n // hiding it from the list and beats \"config.via names a relation Field\".\n if (type === \"rollup\" && !chosen.multi) {\n return `${fieldName(chosen)} points at one record at a time, so there is nothing to total. Tick \"Can hold more than one\" on ${fieldName(chosen)}, or use Borrowed value to read its one value.`;\n }\n if (type === \"lookup\" && pick.trim() === \"\") {\n return `Say which value to read from the record ${fieldName(chosen)} points at.`;\n }\n if (type === \"rollup\" && agg !== \"count\" && of.trim() === \"\") {\n return \"Say which value of those records to work out.\";\n }\n return null;\n }\n\n // NOT THE FORMULA. A worked-out column with no columns picked is something\n // the store already accepts (it writes `{op, args:[{const:\"\"}]}`) and\n // FIELD-ADD's suite already declares that way. Blocking it here would be this\n // lane changing a behaviour outside the three types its brief names, and it\n // silently swallowed that lane's seventeenth column when it did. If it should\n // be refused, it is the store's rule to make and its suite to move.\n return null;\n}\n\n/** Whether \"can hold more than one\" is a question for this type at all. */\nfunction multiApplies(type: PickableFieldType): boolean {\n return type === \"member\" || type === \"attachment\" || type === \"text\";\n}\n\nfunction unitApplies(type: PickableFieldType): boolean {\n return type === \"currency\";\n}\n\n/** Which of the sixteen an existing Field already is. */\nfunction startingType(field: Field | undefined): PickableFieldType {\n if (!field) return \"text\";\n const kind = editorKindFor(field);\n if (fieldTypeChoice(kind)) return kind as PickableFieldType;\n return \"text\";\n}\n\n/**\n * REC-15 / REC-17: a Rule expression is an object of nodes, and it points at a\n * Field BY ITS ID, never by its name — a name changes and the rule would stop\n * resolving. The panel therefore collects columns, not text.\n */\nfunction formulaExpression(op: string, fieldIds: string[]): Record<string, unknown> {\n const args = fieldIds.filter((id) => id !== \"\").map((id) => ({ field: id }));\n if (args.length === 0) return { op, args: [{ const: \"\" }] };\n return { op, args };\n}\n\nfunction TypeQuestions(props: {\n type: PickableFieldType;\n editing: boolean;\n optionText: string;\n setOptionText: (value: string) => void;\n unit: string;\n setUnit: (value: string) => void;\n withTime: boolean;\n setWithTime: (value: boolean) => void;\n via: string;\n setVia: (value: string) => void;\n pick: string;\n setPick: (value: string) => void;\n agg: NonNullable<NewFieldDeclaration[\"agg\"]>;\n setAgg: (value: NonNullable<NewFieldDeclaration[\"agg\"]>) => void;\n of: string;\n setOf: (value: string) => void;\n formulaOp: string;\n setFormulaOp: (value: string) => void;\n formulaFields: string[];\n setFormulaFields: (value: string[]) => void;\n relations: Field[];\n others: Field[];\n existingOptionsTable: boolean;\n}) {\n const { type } = props;\n\n if (type === \"select\" || type === \"multi_select\") {\n return (\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">The choices</Label>\n <BasicTextarea\n rows={4}\n className=\"text-xs\"\n aria-label=\"The choices\"\n placeholder={\"Open\\nIn progress\\nClosed\"}\n value={props.optionText}\n onChange={(e) => props.setOptionText(e.target.value)}\n />\n <p className=\"text-[11px] text-muted-foreground\">\n {props.editing\n ? props.existingOptionsTable\n ? \"One per line. Leave this empty to keep the choices as they are; type a list and it replaces them, keeping the ones that are still here.\"\n : \"One per line. These become this field's choices.\"\n : \"One per line. They are saved with the field — you do not have to make a table for them.\"}\n </p>\n </div>\n );\n }\n\n if (type === \"currency\") {\n return (\n <label className=\"flex max-w-[16rem] flex-col gap-1\">\n <Label className=\"text-xs\">The currency</Label>\n <BasicInput\n value={props.unit}\n aria-label=\"The currency\"\n placeholder=\"$\"\n onChange={(e) => props.setUnit(e.target.value)}\n />\n <p className=\"text-[11px] text-muted-foreground\">\n Shown with every amount, everywhere the value appears — including where an assistant reads it.\n </p>\n </label>\n );\n }\n\n if (type === \"datetime\") {\n return (\n <label className=\"flex items-center gap-1.5\">\n <Checkbox\n checked={props.withTime}\n aria-label=\"Include a time of day\"\n onCheckedChange={(v) => props.setWithTime(v === true)}\n />\n Include a time of day, not just the day\n </label>\n );\n }\n\n if (type === \"lookup\" || type === \"rollup\") {\n // EVERY relation column this table has — including the ones that hold ONE\n // record. A rollup needs one that holds several, and the store says so; but\n // a person looking for \"Crew lead\" and not finding it in the list learns\n // nothing, and the sentence under the button tells them exactly what to do\n // about the one they picked. Hiding the answer is not the same as giving it.\n const usable = props.relations;\n if (usable.length === 0) {\n // NEVER A DEAD CONTROL. The reason, and the thing to do about it.\n return (\n <p className=\"text-[11px] text-muted-foreground\">\n {type === \"rollup\"\n ? \"This kind of column works something out from the records another column points at, and this table has no column that points at records yet. Add a Person or File column that can hold more than one first.\"\n : \"This kind of column reads a value from a record another column points at, and this table has no column that points at another record yet. Add a Person or File column first.\"}\n </p>\n );\n }\n return (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">{type === \"rollup\" ? \"Across the records in\" : \"Read it from\"}</Label>\n <Select value={props.via} onValueChange={props.setVia}>\n <SelectTrigger size=\"sm\" aria-label={type === \"rollup\" ? \"Across the records in\" : \"Read it from\"}>\n <SelectValue placeholder=\"Choose a column\" />\n </SelectTrigger>\n <SelectContent>\n {usable.map((f) => (\n <SelectItem key={f.id} value={f.key}>\n {fieldName(f)}\n {type === \"rollup\" && !f.multi ? \" — holds one\" : \"\"}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {type === \"lookup\" ? (\n <ValueOnTheOtherSide\n label=\"The value to read\"\n help=\"The column on the other record whose value is borrowed.\"\n relation={usable.find((f) => f.key === props.via)}\n value={props.pick}\n onChange={props.setPick}\n />\n ) : (\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">What to work out</Label>\n <Select value={props.agg} onValueChange={(v) => props.setAgg(v as never)}>\n <SelectTrigger size=\"sm\" aria-label=\"What to work out\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ROLLUP_OPERATIONS.map((row) => (\n <SelectItem key={row.value} value={row.value}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {props.agg !== \"count\" ? (\n <ValueOnTheOtherSide\n label=\"Of which value\"\n help=\"The column on those records whose values are worked out.\"\n relation={usable.find((f) => f.key === props.via)}\n value={props.of}\n onChange={props.setOf}\n compact\n />\n ) : null}\n </div>\n )}\n </div>\n );\n }\n\n if (type === \"formula\") {\n if (props.others.length === 0) {\n return (\n <p className=\"text-[11px] text-muted-foreground\">\n A worked-out column needs other columns to work from, and this table has none yet.\n </p>\n );\n }\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">What to do</Label>\n <Select value={props.formulaOp} onValueChange={props.setFormulaOp}>\n <SelectTrigger size=\"sm\" className=\"max-w-[18rem]\" aria-label=\"What to do\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {FORMULA_OPERATIONS.map((row) => (\n <SelectItem key={row.value} value={row.value}>\n {row.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">Which columns</Label>\n <div className=\"flex flex-wrap gap-1\">\n {props.others.map((f) => {\n const picked = props.formulaFields.includes(f.id);\n return (\n <Button\n key={f.id}\n type=\"button\"\n size=\"sm\"\n variant={picked ? \"default\" : \"outline\"}\n onClick={() =>\n props.setFormulaFields(\n picked\n ? props.formulaFields.filter((id) => id !== f.id)\n : [...props.formulaFields, f.id],\n )\n }\n >\n {fieldName(f)}\n </Button>\n );\n })}\n </div>\n <p className=\"text-[11px] text-muted-foreground\">\n In the order you pick them. Columns are remembered by which column they are, so renaming one\n never breaks this.\n </p>\n </div>\n </div>\n );\n }\n\n return null;\n}\n\n/**\n * WHICH VALUE, ON THE OTHER SIDE — offered by NAME, never typed as a key.\n *\n * A borrowed value and a total both read one column of the records the chosen\n * relation points at, and this panel used to ask for that column as free text\n * with the placeholder `name`. So the one question on the panel that a person\n * could not answer without knowing an internal key was the last question on the\n * two column types the sixth-pass verdict could not create — and a typo in it\n * is a column that silently borrows nothing.\n *\n * The relation says which Table it points at, so the columns of that Table are\n * simply offered. When it points at nothing yet, this says so and offers\n * nothing, which is the honest half of the same rule.\n *\n * AND A TABLE THE STORE KEEPS ITSELF STILL HAS COLUMNS. `custom.applicable_fields`\n * answers the Fields a table DECLARES, and the kernels declare none: a Person\n * column points at the person kernel, which has 441 records and zero Field rows.\n * So the picker offered nothing for every Person and every File relation — and\n * the only two column types a person cannot build without it are exactly the\n * two the sixth-pass verdict could not build. Measured 2026-09-20.\n *\n * The store reads the far side with `custom.record_values(…) -> pick`\n * (`custom.lookup_value`), so what a pick may name is a KEY THOSE RECORDS\n * CARRY. When the target declares no Fields, this reads one of its records\n * through the ordinary read door and offers the keys it actually has — the same\n * fact the store will use, asked the same way. Nothing is typed, and nothing is\n * guessed.\n */\nfunction ValueOnTheOtherSide({\n label,\n help,\n relation,\n value,\n onChange,\n compact,\n}: {\n label: string;\n help: string;\n relation: Field | undefined;\n value: string;\n onChange: (value: string) => void;\n compact?: boolean | undefined;\n}) {\n const target = (relation?.relation_target ?? null) as Uuid | null;\n const columns = useFields(target);\n const declared = (columns.data ?? []).filter((f) => f.type !== \"formula\");\n // Only asked when the target declares nothing — the ordinary case costs no\n // extra call, and this one is a single row.\n const sample = useRecords(declared.length === 0 && !columns.loading ? target : null, { pageSize: 1 });\n const carried = sample.data?.rows[0]?.document ?? null;\n const offered: { key: string; name: string }[] =\n declared.length > 0\n ? declared.map((f) => ({ key: f.key, name: fieldName(f) }))\n : Object.keys(carried ?? {}).map((key) => ({ key, name: humanize(key) }));\n const stillAsking = columns.loading || (declared.length === 0 && sample.loading);\n\n const body = !relation ? (\n <p className=\"text-[11px] text-muted-foreground\">Choose the column above first.</p>\n ) : stillAsking ? (\n <p className=\"text-[11px] text-muted-foreground\">Reading that table's columns…</p>\n ) : offered.length === 0 ? (\n <p className=\"text-[11px] text-muted-foreground\">\n {fieldName(relation)} points at a table that has no columns to read yet. Add one there first.\n </p>\n ) : (\n <Select value={value} onValueChange={onChange}>\n <SelectTrigger size=\"sm\" aria-label={label}>\n <SelectValue placeholder=\"Choose a column\" />\n </SelectTrigger>\n <SelectContent>\n {offered.map((column) => (\n <SelectItem key={column.key} value={column.key}>\n {column.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n\n if (compact) return <div className=\"mt-1 flex flex-col gap-1\">{body}</div>;\n return (\n <div className=\"flex flex-col gap-1\">\n <Label className=\"text-xs\">{label}</Label>\n {body}\n <p className=\"text-[11px] text-muted-foreground\">{help}</p>\n </div>\n );\n}\n","\"use client\";\n\n// src/TableSettings.tsx — @ai-matrx/records-ui · SCR-3, SCR-4, SCR-5\n//\n// EVERY FIELD OF ONE TABLE, TO RENAME, REORDER, RETYPE AND DELETE, FROM ONE\n// PANEL — and the agent's pending field proposals in the SAME list, with the\n// same accept and reject on each (SCR-5), because a proposal is a field that\n// has not been agreed to yet, not a different kind of thing in a different\n// place.\n//\n// The panel does not exist at all for somebody who does not administer the\n// table (SCR-4). There is no read-only variant: what it would show, the grid\n// already shows.\n\nimport { useState } from \"react\";\nimport {\n useFieldMutation,\n useFields,\n useRecordMutation,\n useTable,\n type Field,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport { Badge, Button, Separator, cn } from \"@ai-matrx/design-system\";\nimport { FieldEditor } from \"./FieldEditor\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { fieldTypeLabel } from \"./parity\";\nimport { fieldName, tableName } from \"./names\";\n\nexport interface FieldProposalRow {\n id: string;\n /** What the agent proposed, in the Field shape the store would store. */\n field: Partial<Field> & { key: string; label?: string };\n why: string;\n proposed_by: string;\n}\n\nexport interface TableSettingsProps {\n tableId: Uuid;\n /**\n * SCR-5. Pending field proposals. The door that lists them\n * (`custom.field_propose`) does not exist yet — `@ai-matrx/records` answers\n * `door_absent` by name for it — so a host passes what it has, and when it\n * has nothing the section says so rather than pretending there is nothing to\n * approve.\n */\n proposals?: FieldProposalRow[] | undefined;\n onAcceptProposal?: ((proposal: FieldProposalRow) => void) | undefined;\n onRejectProposal?: ((proposal: FieldProposalRow) => void) | undefined;\n /**\n * SCR-3's fourth verb. Called after the store has accepted the delete, so the\n * host can leave a page that is now about a table nobody can open.\n */\n onDeleted?: (() => void) | undefined;\n className?: string | undefined;\n}\n\nexport function TableSettings({\n tableId,\n proposals,\n onAcceptProposal,\n onRejectProposal,\n onDeleted,\n className,\n}: TableSettingsProps) {\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const mutation = useRecordMutation();\n // THE SHAPE OF THE TABLE goes through the store's own field doors, never\n // through the record writer: a field taken off with `record_delete` leaves the\n // TABLE still declaring a column that is gone, which is the same broken half\n // of \"one source of truth\" that made every \"Add field\" refuse.\n const shape = useFieldMutation();\n const [editing, setEditing] = useState<Field | \"new\" | null>(null);\n const [askingToDelete, setAskingToDelete] = useState(false);\n const [askingToRemove, setAskingToRemove] = useState<Field | null>(null);\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (!rights.structure) return <p className={cn(\"text-xs text-muted-foreground\", className)}>{rights.why(\"structure\")}</p>;\n\n const rows = [...(fields.data ?? [])].sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0));\n\n const move = async (field: Field, direction: -1 | 1) => {\n const index = rows.findIndex((r) => r.id === field.id);\n const swap = rows[index + direction];\n if (!swap) return;\n // The order is the Field's own `sort`, so reordering is two writes — and\n // they go through `custom.field_update`, the door for a field's own\n // settings, not through the record writer. A Field written around its door\n // is the same broken half of \"one source of truth\" that made every \"Add\n // field\" refuse; `record_update` also never asks `admin` on the TABLE,\n // which is the right this act actually needs.\n await shape.update({ field_id: field.id, patch: { sort: swap.sort ?? index + direction } });\n await shape.update({ field_id: swap.id, patch: { sort: field.sort ?? index } });\n fields.reload();\n };\n\n const remove = async (field: Field) => {\n const gone = await shape.retire({ field_id: field.id });\n setAskingToRemove(null);\n if (gone) {\n fields.reload();\n table.reload();\n }\n };\n\n /**\n * DELETING THE TABLE ITSELF — the verb this panel's own header has claimed\n * since SCR-3 and did not have. A walk of the real screens on 19 September\n * made a table and then could not get rid of it from anywhere in the product.\n * A Table is a record, so this is the same soft delete every record gets\n * (REC-23), through the same door, and the panel says exactly that before it\n * happens rather than after.\n */\n const deleteTable = async () => {\n const gone = await mutation.remove({ record_id: tableId });\n setAskingToDelete(false);\n if (gone !== null) onDeleted?.();\n };\n\n if (editing) {\n return (\n <FieldEditor\n tableId={tableId}\n {...(editing === \"new\" ? {} : { field: editing })}\n onSaved={() => {\n setEditing(null);\n fields.reload();\n table.reload();\n }}\n onCancel={() => setEditing(null)}\n className={className}\n />\n );\n }\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-2 text-xs\", className)}>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">Fields</span>\n <span className=\"text-muted-foreground\">{rows.length}</span>\n <Button size=\"sm\" variant=\"outline\" className=\"ml-auto\" onClick={() => setEditing(\"new\")}>\n Add a field\n </Button>\n </div>\n\n {mutation.error ? <RefusalNotice error={mutation.error} /> : null}\n {shape.error ? <RefusalNotice error={shape.error} /> : null}\n\n {/* Destructive, so the consequence is named BEFORE it happens and takes a\n second press — the same shape the table's own delete has below. */}\n {askingToRemove ? (\n <div className=\"flex flex-wrap items-center gap-2 rounded border border-destructive/40 px-2 py-1.5\">\n <span className=\"text-destructive\">\n Removing {fieldName(askingToRemove)} takes it off every record of this table. The values stay in\n each record's history and nothing else is deleted.\n </span>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n disabled={shape.saving}\n onClick={() => void remove(askingToRemove)}\n >\n {shape.saving ? \"Removing…\" : \"Remove it\"}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAskingToRemove(null)}>\n Keep it\n </Button>\n </div>\n ) : null}\n\n <ul className=\"divide-y rounded border\">\n {rows.map((field, index) => (\n <li key={field.id} className=\"flex items-center gap-2 px-2 py-1.5\">\n <span className=\"min-w-0 flex-1 truncate\">{fieldName(field)}</span>\n <Badge variant=\"outline\" className=\"text-[10px] font-normal\">\n {fieldTypeLabel(field)}\n </Badge>\n {field.required ? <span className=\"text-[10px] text-destructive\">required</span> : null}\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Move ${fieldName(field)} up`}\n disabled={index === 0}\n onClick={() => void move(field, -1)}\n >\n ↑\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n aria-label={`Move ${fieldName(field)} down`}\n disabled={index === rows.length - 1}\n onClick={() => void move(field, 1)}\n >\n ↓\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setEditing(field)}>\n Edit\n </Button>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"text-destructive\"\n aria-label={`Remove ${fieldName(field)}`}\n onClick={() => setAskingToRemove(field)}\n >\n Remove\n </Button>\n </li>\n ))}\n {rows.length === 0 ? <li className=\"px-2 py-2 text-muted-foreground\">This table has no fields yet.</li> : null}\n </ul>\n\n <Separator />\n\n {/* SCR-5: proposals are fields in the same list, with the same two verbs. */}\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">Proposed</span>\n <span className=\"text-muted-foreground\">{proposals?.length ?? 0}</span>\n </div>\n {proposals === undefined ? (\n <p className=\"text-muted-foreground\">\n Nothing is listing proposals here yet: the store has no `custom.field_propose` door, so this panel would be\n inventing an empty queue. When the door lands, its rows appear in this list with the same accept and reject.\n </p>\n ) : proposals.length === 0 ? (\n <p className=\"text-muted-foreground\">No field is waiting for a decision.</p>\n ) : (\n <ul className=\"divide-y rounded border\">\n {proposals.map((proposal) => (\n <li key={proposal.id} className=\"flex items-center gap-2 px-2 py-1.5\">\n <span className=\"min-w-0 flex-1 truncate\">{proposal.field.label || proposal.field.key}</span>\n <span className=\"min-w-0 flex-1 truncate text-muted-foreground\">{proposal.why}</span>\n <Badge variant=\"secondary\" className=\"text-[10px] font-normal\">\n {proposal.proposed_by}\n </Badge>\n <Button size=\"sm\" variant=\"outline\" onClick={() => onAcceptProposal?.(proposal)}>\n Accept\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => onRejectProposal?.(proposal)}>\n Reject\n </Button>\n </li>\n ))}\n </ul>\n )}\n\n <Separator />\n\n {/* SCR-3. Destructive, so it names the consequence BEFORE it happens and\n takes a second press. There is no undo button here on purpose: the\n restore path is the store's own and it belongs with the record's\n history, not beside the control that did the delete. */}\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium\">This table</span>\n {askingToDelete ? (\n <>\n <p className=\"text-muted-foreground\">\n Deleting {table.data ? tableName(table.data) : \"this table\"} takes it out of everyone's list, with\n its {rows.length} field{rows.length === 1 ? \"\" : \"s\"} and every record in it.\n {table.data?.retention_days\n ? ` The store keeps them for ${table.data.retention_days} days, so it can still be restored.`\n : \" The store keeps them, so it can still be restored.\"}\n </p>\n <div className=\"flex gap-1\">\n <Button size=\"sm\" variant=\"destructive\" disabled={mutation.saving} onClick={() => void deleteTable()}>\n {mutation.saving ? \"Deleting…\" : \"Delete this table\"}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAskingToDelete(false)}>\n Keep it\n </Button>\n </div>\n </>\n ) : (\n <div>\n <Button size=\"sm\" variant=\"outline\" onClick={() => setAskingToDelete(true)}>\n Delete this table\n </Button>\n </div>\n )}\n {mutation.error ? <RefusalNotice error={mutation.error} /> : null}\n </div>\n </div>\n );\n}\n","\"use client\";\n\n// src/Peek.tsx — @ai-matrx/records-ui · SCR-N-3\n//\n// THE GENERIC PEEK, DRIVEN BY THE FIELD RECORDS. There is no per-table peek in\n// this platform: before this, 21 hand-written peeks covered 19 registered\n// catalogue keys and every custom table — 100% of them — fell to \"Peek — coming\n// soon\".\n//\n// It reads the record through the read door, shows every applicable Field's\n// value the way that Field says to show it, and flips to the same\n// `RecordForm` for editing. It carries the Alchemy menu, so everything a person\n// can copy, hand to an agent or export from a record is in the one place it is\n// everywhere else on the platform.\n\nimport { useState } from \"react\";\nimport { useFields, useRecord, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport { AlchemyMenu } from \"@ai-matrx/alchemy/react\";\nimport { Button, Separator, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RecordForm } from \"./RecordForm\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { ShareControl } from \"./ShareControl\";\nimport { useRecordRights, useRecordsUi } from \"./host\";\nimport { ProvenanceBadge, RecordValue } from \"./values\";\nimport { fieldName, humanize, recordName } from \"./names\";\n\nexport interface PeekProps {\n tableId: Uuid;\n recordId: Uuid;\n onClose?: (() => void) | undefined;\n className?: string | undefined;\n}\n\nexport function Peek({ tableId, recordId, onClose, className }: PeekProps) {\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const record = useRecord(recordId, true);\n // THE RECORD'S OWN LEVEL, not the table's. The sixth-pass verdict found a\n // record shared with a colleague at Editor inside a table she held at Viewer;\n // a panel that asked the table would have hidden Edit from the person who had\n // been given it, which is the same lie with the sign flipped.\n const may = useRecordRights(recordId);\n const host = useRecordsUi();\n const organizationId = useRecordsClient().config.organizationId;\n const [editing, setEditing] = useState(false);\n\n if (record.error) return <RefusalNotice error={record.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n\n const document = record.data?.document;\n // REC-2: the Table's own title field is what makes a record a chip. A record\n // with nothing readable says so — a truncated uuid tells a person nothing and\n // reads like a bug (`names.ts`).\n const title = document ? recordName(document, table.data?.title_field) : \"\";\n const href = host.hrefForRecord && table.data ? host.hrefForRecord({ table: table.data, recordId }) : undefined;\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-2 text-xs\", className)}>\n {/* ONE row of header: the title, the controls. Nothing repeats the name. */}\n <div className=\"flex items-center gap-2\">\n <h3 className=\"min-w-0 flex-1 truncate text-sm font-medium\">\n {record.loading && !document ? <Skeleton className=\"h-4 w-40\" /> : title}\n </h3>\n <AlchemyMenu\n label={title || \"Record\"}\n sourceId={`record:${recordId}`}\n size=\"xs\"\n human={() =>\n (fields.data ?? [])\n .map((field) => `${fieldName(field)}: ${String(document?.[field.key] ?? \"\")}`)\n .join(\"\\n\")\n }\n json={() => document ?? {}}\n />\n {href ? (\n <a className=\"text-primary underline-offset-2 hover:underline\" href={href}>\n Open\n </a>\n ) : null}\n {/* SCR-N-5. Beside Edit, where a person looks for it. */}\n <ShareControl kind=\"record\" organizationId={organizationId} subjectId={recordId} name={title} may={may.share} />\n {may.write ? (\n <Button size=\"sm\" variant={editing ? \"ghost\" : \"outline\"} onClick={() => setEditing((e) => !e)}>\n {editing ? \"Stop editing\" : \"Edit\"}\n </Button>\n ) : may.known ? (\n // Absent AND explained: no Edit button, and one sentence saying what\n // it would take and who can give it.\n <span className=\"max-w-[18rem] text-[11px] text-muted-foreground\">{may.why(\"write\")}</span>\n ) : null}\n {onClose ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={onClose} aria-label=\"Close\">\n ×\n </Button>\n ) : null}\n </div>\n\n <Separator />\n\n {editing ? (\n <RecordForm\n tableId={tableId}\n recordId={recordId}\n onSaved={() => {\n setEditing(false);\n record.reload();\n }}\n onCancel={() => setEditing(false)}\n />\n ) : (\n <dl className=\"grid grid-cols-[minmax(6rem,12rem)_1fr] gap-x-3 gap-y-1.5\">\n {(fields.data ?? []).map((field) => (\n <div key={field.id} className=\"contents\">\n <dt className=\"flex items-baseline gap-1 truncate text-muted-foreground\">\n {fieldName(field)}\n <ProvenanceBadge document={document} fieldKey={field.key} />\n </dt>\n <dd className=\"min-w-0\"><RecordValue field={field} value={document?.[field.key]} document={document} /></dd>\n </div>\n ))}\n </dl>\n )}\n\n {/* FLD-9: what the system worked out, and where it came from. */}\n {record.data?.computed?.length ? (\n <>\n <Separator />\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium\">Worked out by the system</span>\n {/* FLD-9 / REC-19, in a person's words. This used to print the\n provenance row as raw JSON — the field key, two uuids and a\n version number — which is the machinery showing through that the\n verdict counted three times. */}\n {record.data.computed.map((row, i) => (\n <p key={i} className=\"text-muted-foreground\">\n {computedInPlainWords(row, (fields.data ?? []).find((f) => f.key === row.field_key))}\n </p>\n ))}\n </div>\n </>\n ) : null}\n </div>\n );\n}\n\n/**\n * One line of provenance, as a person reads it: which column, what it worked\n * out to, and when. The rule id and its version are facts for an engineer and\n * live on the title attribute of nothing a person has to read.\n */\nfunction computedInPlainWords(\n row: { field_key: string; value: unknown; computed_at: string },\n field: { label?: string | null; name?: string | null; key: string } | undefined,\n): string {\n const name = field ? fieldName(field as never) : humanize(row.field_key);\n const shown = row.value === null || row.value === undefined || row.value === \"\" ? \"nothing\" : String(row.value);\n const when = new Date(row.computed_at);\n const at = Number.isNaN(when.getTime()) ? \"\" : ` on ${when.toLocaleDateString()}`;\n return `${name} was worked out as ${shown}${at}.`;\n}\n","\"use client\";\n\n// src/RecordForm.tsx — @ai-matrx/records-ui · SCR-N-1\n//\n// THE GENERIC CREATE / EDIT FORM, RESOLVED FROM THE FIELD RECORDS. Before it,\n// every create and edit form in the product was hand-written per feature, which\n// is why a custom table could not open a record at all.\n//\n// Two honest halves:\n// · BEFORE the write, the mirror (`predictWriteRefusals`) says what the store\n// is about to refuse, in the store's own sentence. It is not validation —\n// the store validates — it just says it half a second earlier.\n// · AFTER the write, whatever the store said is shown verbatim, including the\n// conflict object when somebody else wrote first.\n//\n// It never blocks a save on its own opinion: the mirror's sentences are shown,\n// and the write is still attempted, because the store is the one that decides.\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport {\n useFields,\n useRecord,\n useRecordMutation,\n type Field,\n type RecordDocument,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport { predictWriteRefusals } from \"@ai-matrx/records/core\";\nimport { Button, Separator, cn } from \"@ai-matrx/design-system\";\nimport { FieldControl, FieldLabel } from \"./editors\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi } from \"./host\";\nimport { ProvenanceBadge } from \"./values\";\nimport { useRecordVersion } from \"./systemTable\";\nimport { fieldName, humanize } from \"./names\";\n\nexport interface RecordFormProps {\n tableId: Uuid;\n /** Absent means \"create\". Present means \"edit that record\". */\n recordId?: Uuid | undefined;\n /** FLD-10: which Fields apply is the store's decision, and it takes the record type. */\n recordType?: string | undefined;\n onSaved?: ((recordId: Uuid) => void) | undefined;\n onCancel?: (() => void) | undefined;\n className?: string | undefined;\n}\n\nexport function RecordForm({\n tableId,\n recordId,\n recordType,\n onSaved,\n onCancel,\n className,\n}: RecordFormProps) {\n const host = useRecordsUi();\n const fields = useFields(tableId, recordType);\n const existing = useRecord(recordId ?? null);\n const mutation = useRecordMutation();\n const [draft, setDraft] = useState<Record<string, unknown>>({});\n const [touched, setTouched] = useState(false);\n // REC-9: the version this form LOADED, so a second writer is TOLD rather than\n // overwritten. The read door answers documents, never versions.\n const loaded = useRecordVersion(recordId ?? null);\n const loadedVersion = loaded.version;\n\n // The record's own document is the starting draft. A form that started empty\n // over an existing record would silently propose blanking every field.\n useEffect(() => {\n const document = existing.data?.document;\n if (document) setDraft({ ...document });\n }, [existing.data?.record_id, loadedVersion]);\n\n const document = useMemo<RecordDocument>(() => {\n const out: RecordDocument = {};\n for (const [key, value] of Object.entries(draft)) {\n if (key.startsWith(\"_\")) continue;\n if (value !== undefined) out[key] = value;\n }\n return out;\n }, [draft]);\n\n const predicted = useMemo(\n () => (fields.data ? predictWriteRefusals({ fields: fields.data, document, ...(recordType ? { recordType } : {}) }) : []),\n [fields.data, document, recordType],\n );\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (existing.error) return <RefusalNotice error={existing.error} className={className} />;\n\n const save = async () => {\n setTouched(true);\n if (recordId) {\n const version = loadedVersion;\n const moved = await mutation.update({\n record_id: recordId,\n patch: document,\n ...(version === null ? {} : { expectedVersion: version }),\n });\n if (moved !== null) {\n // The store's own new version, so saving twice in a row is two saves\n // and not a conflict with yourself.\n loaded.note(moved);\n host.notify?.success(\"Saved\");\n existing.reload();\n onSaved?.(recordId);\n }\n return;\n }\n const written = await mutation.write({ table_id: tableId, data: document });\n if (written) {\n host.notify?.success(\"Saved\");\n onSaved?.(written);\n }\n };\n\n return (\n <form\n className={cn(\"flex min-w-0 flex-col gap-3\", className)}\n onSubmit={(e) => {\n e.preventDefault();\n void save();\n }}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {(fields.data ?? []).map((field) => (\n <FieldRow\n key={field.id}\n field={field}\n value={draft[field.key]}\n document={existing.data?.document}\n problems={touched ? predicted.filter((p) => p.field_key === field.key) : []}\n onChange={(value) => setDraft((d) => ({ ...d, [field.key]: value }))}\n />\n ))}\n </div>\n\n {/* A refusal with no field of its own — a size or envelope refusal. */}\n {touched\n ? predicted\n .filter((p) => !p.field_key)\n .map((p) => (\n <p key={p.message} className=\"text-xs text-destructive\">\n {p.message}\n </p>\n ))\n : null}\n\n {mutation.error ? (\n <RefusalNotice\n error={mutation.error}\n {...(mutation.conflict\n ? {\n actions: (\n <div className=\"mt-1 space-y-1\">\n {/* The conflict, column by column, in the columns' own\n names — this used to print the machine key and two\n JSON blobs in a monospace font at the person. */}\n {Object.entries(mutation.conflict.contested_fields).map(([key, theirs]) => {\n const column = (fields.data ?? []).find((f) => f.key === key);\n return (\n <p key={key} className=\"text-[11px]\">\n {column ? fieldName(column) : humanize(key)}: yours{\" \"}\n <strong>{asWords(draft[key])}</strong> · theirs <strong>{asWords(theirs)}</strong>\n </p>\n );\n })}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n existing.reload();\n mutation.clearConflict();\n }}\n >\n Take theirs and start again\n </Button>\n </div>\n ),\n }\n : {})}\n />\n ) : null}\n\n <Separator />\n <div className=\"flex items-center gap-2\">\n <Button type=\"submit\" size=\"sm\" disabled={mutation.saving}>\n {mutation.saving ? \"Saving…\" : recordId ? \"Save\" : \"Create\"}\n </Button>\n {onCancel ? (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n </div>\n </form>\n );\n}\n\nfunction FieldRow({\n field,\n value,\n document,\n problems,\n onChange,\n}: {\n field: Field;\n value: unknown;\n document: RecordDocument | undefined;\n problems: Array<{ message: string }>;\n onChange: (value: unknown) => void;\n}) {\n const id = `field-${field.id}`;\n return (\n <div className=\"flex min-w-0 flex-col gap-1\">\n <FieldLabel field={field} htmlFor={id}>\n <ProvenanceBadge document={document} fieldKey={field.key} />\n </FieldLabel>\n <FieldControl field={field} value={value} onChange={onChange} id={id} />\n {problems.map((problem) => (\n <p key={problem.message} className=\"text-xs text-destructive\">\n {problem.message}\n </p>\n ))}\n </div>\n );\n}\n\n/** A value as a person reads it. Never a JSON blob, never an empty string. */\nfunction asWords(value: unknown): string {\n if (value === null || value === undefined || value === \"\") return \"nothing\";\n if (Array.isArray(value)) return value.length === 0 ? \"nothing\" : `${value.length} of them`;\n if (typeof value === \"object\") return \"something this screen cannot show in a line\";\n return String(value);\n}\n","\"use client\";\n\n// src/systemTable.ts — @ai-matrx/records-ui\n//\n// THE PACKAGE'S OWN TABLES, MADE THE WAY EVERY OTHER TABLE IS MADE.\n//\n// A saved view, a queued action, a comment and a form are all RECORDS. They are\n// not a second storage system bolted onto the side of the record store, and\n// they are not rows this package writes into `platform.*` behind the store's\n// back — the data source port this package's client speaks has no insert on it\n// at all, on purpose. So each of them is an ordinary Table in the organization's\n// own store, declared once, through the store's own doors:\n//\n// 1. REC-1 — a Table has to live somewhere, and a Home is an ordinary record\n// in the person kernel, so a Home is written first (`record_write`).\n// 2. `table_declare` declares the Table under that Home.\n// 3. `field_declare` — one per column.\n//\n// That is exactly the sequence the store forced on us: declaring a Table with\n// no Home is refused by `custom._table_shape_guard` with \"a table has to live\n// somewhere - give it a home\". Nothing here works around a guard; it obeys one.\n//\n// STEP 3 USED TO BE `record_write` INTO THE FIELD KERNEL, and that is what took\n// the saved-views table down with everything else. A Field is a record, so this\n// wrote one the ordinary way — and `custom._field_class_guard` refuses that row\n// (23514 / FLD-13). The Table was declared and none of its nine columns were,\n// so `ensureSystemTable` answered a refusal on every load, `ViewBar` could\n// never read or seed a view, and the table page said \"Waiting for <table>'s\n// views\" over an empty frame. Measured on the published screens on 2026-09-20:\n// a \"Saved views\" table declaring nine column names with zero Field rows.\n//\n// WHAT THIS BUYS: a saved view is readable, exportable, historied, commentable\n// and agent-writable by every other component in this package, for free,\n// because it is a record like any other. An agent can write a whole view — or a\n// whole form — with one `record_write`.\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useRecordsClient } from \"@ai-matrx/records/react\";\nimport type { RecordsClient } from \"@ai-matrx/records/core\";\nimport type { FieldPatch, NewFieldDeclaration, RecordsError, Uuid } from \"@ai-matrx/records\";\n\n/** One Field of a package-owned Table, in the store's own words. */\nexport interface SystemFieldSpec {\n key: string;\n label: string;\n /** FLD-1: one of the five behaviours. `text` covers the json-ish ones too. */\n type: \"text\" | \"range\" | \"list\" | \"relation\" | \"formula\";\n sort: number;\n required?: boolean;\n multi?: boolean;\n config?: Record<string, unknown>;\n /**\n * WHAT THE BEHAVIOUR ALONE CANNOT SAY, and what the declaring door refuses a\n * column without. A `list` has to name its choices (FLD-5/FLD-6) and a\n * `relation` has to name the Table it points at (FLD-11) — a package table\n * that grew one of those without saying so here would be refused by name on\n * every organization's first load, which is the class this file just cost us.\n */\n options?: string[];\n relationTarget?: Uuid;\n expr?: Record<string, unknown>;\n}\n\nexport interface SystemTableSpec {\n /** The token this Table is addressed by. Every package table starts `records_ui_`. */\n slug: string;\n name: string;\n labelSingular: string;\n labelPlural: string;\n titleField: string;\n fields: SystemFieldSpec[];\n}\n\n/**\n * One in-flight declaration per (organization, slug), so two components that\n * mount at the same moment do not declare the same Table twice. Keyed by the\n * organization, never global: two organizations in two tabs never share one.\n */\nconst inFlight = new Map<string, Promise<Uuid>>();\n\n/** Find this organization's copy of a package-owned Table, declaring it the first time. */\nexport async function ensureSystemTable(\n client: RecordsClient,\n spec: SystemTableSpec,\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const cacheKey = `${client.config.organizationId}:${spec.slug}`;\n const running = inFlight.get(cacheKey);\n if (running) {\n try {\n return { ok: true, data: await running };\n } catch {\n inFlight.delete(cacheKey);\n }\n }\n\n const tables = await client.tableList();\n if (!tables.ok) return tables;\n const found = tables.data.find((t) => t.slug === spec.slug);\n if (found) {\n // A PACKAGE TABLE GROWS. A later version of this package declares a Field\n // the organization's copy was made without, and an organization that got\n // its copy first would otherwise be the one where the new Field silently\n // does not exist. So every load reconciles: the Fields in the spec that\n // the Table has not got are added, through the same two writes a Field is\n // always made with. Nothing is ever renamed or removed here.\n const grown = await addMissingFields(client, spec, found.id);\n if (!grown.ok) return grown;\n // A PACKAGE TABLE ALSO CHANGES SHAPE. Adding what is missing is only half\n // of level: a Field the organization already holds can carry a DIFFERENT\n // behaviour from the one this version of the package declares, and then\n // every write of that Field is refused by the store for a reason the\n // person cannot act on. See `reconcileFieldShapes`.\n const levelled = await reconcileFieldShapes(client, spec, found.id);\n if (!levelled.ok) return levelled;\n return { ok: true, data: found.id };\n }\n\n let settle: (id: Uuid) => void = () => undefined;\n let fail: (reason: unknown) => void = () => undefined;\n const pending = new Promise<Uuid>((resolve, reject) => {\n settle = resolve;\n fail = reject;\n });\n // The refusal is RETURNED, below, as this package's never-throw envelope.\n // Without this the same refusal is also an unhandled promise rejection on\n // every host that never happened to have a second caller waiting here — a\n // red console (and, under a test runner, a failed run) for a refusal that\n // was in fact reported properly.\n pending.catch(() => undefined);\n inFlight.set(cacheKey, pending);\n\n const declared = await declare(client, spec);\n if (declared.ok) settle(declared.data);\n else fail(declared.error);\n // IN FLIGHT MEANS IN FLIGHT. The claim used to be kept for ever on success,\n // which quietly turned a race guard into a permanent cache: after the FIRST\n // declaration, every later `ensureSystemTable` for that slug was answered\n // from the map and returned before the two reconciliation paths above ran at\n // all. So a package table could never grow a column inside the session that\n // made it, and a Field with the wrong behaviour was never levelled — the two\n // things those paths exist to do. Measured 2026-09-20: declaring a package\n // table with four columns and immediately asking for six left it at four.\n // Releasing it here keeps the property it was written for (two components\n // mounting at the same moment declare once) and drops the one nobody meant.\n inFlight.delete(cacheKey);\n return declared;\n}\n\n/**\n * The Fields of `spec` the organization's copy of this Table has not got yet,\n * added the way a Field is always added: `custom.field_declare`, which tells\n * the Table its own declaration and writes the definition in ONE act.\n * Idempotent, and a no-op for a Table that is already level.\n *\n * This used to patch the Table's `fields` list itself with `record_update`\n * first. That is the door's job — it appends a name the Table has not got and\n * leaves one it has — and a client doing it separately could (and did) leave a\n * Table declaring a column no Field row ever backed.\n */\nasync function addMissingFields(\n client: RecordsClient,\n spec: SystemTableSpec,\n tableId: Uuid,\n): Promise<{ ok: true; data: true } | { ok: false; error: RecordsError }> {\n const held = await client.fields({ table_id: tableId });\n if (!held.ok) return held;\n const have = new Set(held.data.map((f) => f.key));\n const missing = spec.fields.filter((f) => !have.has(f.key));\n if (missing.length === 0) return { ok: true, data: true };\n\n for (const field of missing) {\n const written = await client.fieldDeclare({ table_id: tableId, spec: declarationFor(field) });\n if (!written.ok) return written;\n }\n return { ok: true, data: true };\n}\n\n/**\n * THE FIELD THAT CHANGED BEHAVIOUR UNDER AN ORGANIZATION THAT ALREADY HAD ONE.\n *\n * Found live on 2026-09-19: `ActionInbox` could not record an outcome in one\n * organization, because that organization's copy of `records_ui_action` held\n * `status` as a `relation` while this package declares it `text`. Every write\n * of an outcome was refused `22P02 invalid input syntax for type uuid: \"open\"`\n * — the store was right, the package was the one out of date, and\n * `addMissingFields` never looked at a Field it already had.\n *\n * So the reconciliation is two questions, not one: which Fields are MISSING,\n * and which Fields are THERE WITH THE WRONG SHAPE. Shape here means exactly the\n * two properties that decide what a value is made of and therefore what the\n * store will accept — the behaviour (FLD-1) and whether it is multi (FLD-2).\n *\n * WHAT IS DELIBERATELY NOT RECONCILED: label, sort, required, config. Those are\n * presentation and policy, an organization may legitimately have moved them,\n * and none of them can make a write fail. Nothing is ever renamed or removed\n * here — this only ever moves a Field back onto the behaviour the package's own\n * components write against.\n */\nasync function reconcileFieldShapes(\n client: RecordsClient,\n spec: SystemTableSpec,\n tableId: Uuid,\n): Promise<{ ok: true; data: true } | { ok: false; error: RecordsError }> {\n const held = await client.fields({ table_id: tableId });\n if (!held.ok) return held;\n const byKey = new Map(held.data.map((f) => [f.key, f]));\n\n for (const field of spec.fields) {\n const have = byKey.get(field.key);\n if (!have) continue; // `addMissingFields` owns that half and already ran.\n const patch: Record<string, unknown> = {};\n if (have.type !== field.type) patch.type = field.type;\n if (have.multi !== (field.multi ?? false)) patch.multi = field.multi ?? false;\n if (Object.keys(patch).length === 0) continue;\n\n // THROUGH `custom.field_update`, which is the door that changes what a\n // column HOLDS. It rebuilds the document the guards demand, converts every\n // existing value where it converts and keeps the rest in `_retired` with\n // its reason, withdraws relation edges that stopped meaning anything, and\n // writes one `history.migration_log` row. `record_update` did none of that:\n // it wrote the two keys straight onto the Field document, so a column that\n // changed behaviour kept values shaped for the old one and nothing said so.\n //\n // THE BEHAVIOUR WORD ALWAYS GOES, even when only `multi` moved: the door\n // reads `multi` inside its behaviour arm and nowhere else, so a patch\n // carrying `multi` alone reports success and changes nothing.\n const written = await client.fieldUpdate({\n field_id: have.id,\n patch: { type: field.type, multi: field.multi ?? false, ...patch } as FieldPatch,\n });\n // A Field this package cannot level is a Table whose writes will keep being\n // refused, so the refusal is reported rather than swallowed.\n if (!written.ok) return written;\n }\n return { ok: true, data: true };\n}\n\n/**\n * One column, in the shape `custom.field_declare` takes — the same one whether\n * it is declared with the Table or added to an organization's copy later.\n *\n * The STORE turns this into the document its own guards demand: the behaviour,\n * the modifiers, the format, the unit, the relation target and maximum, the\n * compute_on, and the Rules that make a format enforceable. This package used\n * to assemble all thirteen of those by hand and then fail on the one write no\n * client can make.\n */\nfunction declarationFor(field: SystemFieldSpec): NewFieldDeclaration {\n return {\n key: field.key,\n label: field.label,\n type: field.type,\n sort: field.sort,\n required: field.required ?? false,\n multi: field.multi ?? false,\n ...(field.config ? { config: field.config } : {}),\n ...(field.options ? { options: field.options } : {}),\n ...(field.relationTarget ? { relation_target: field.relationTarget } : {}),\n ...(field.expr ? { expr: field.expr } : {}),\n };\n}\n\nasync function declare(\n client: RecordsClient,\n spec: SystemTableSpec,\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const personKernel = await client.personKernelId();\n if (!personKernel.ok) return personKernel;\n\n const home = await client.recordWrite({\n table_id: personKernel.data,\n data: { name: `${spec.name} Home` },\n });\n if (!home.ok) return home;\n\n const table = await client.tableDeclare({\n homeId: home.data,\n spec: {\n name: spec.name,\n slug: spec.slug,\n type: \"entity\",\n label_singular: spec.labelSingular,\n label_plural: spec.labelPlural,\n display: \"list\",\n weight: \"light\",\n ordered: false,\n row_order: \"manual\",\n title_field: spec.titleField,\n retention_days: 365,\n // AGT-1: the whole point is that an agent writes a view or a form in one\n // call, so a package-owned Table is agent-writable by declaration.\n agent_writable: true,\n default_sort: [{ field: spec.titleField, direction: \"asc\" }],\n fields: spec.fields.map((f) => ({ name: f.key })),\n },\n });\n if (!table.ok) {\n await client.recordDelete({ record_id: home.data });\n return table;\n }\n\n for (const field of spec.fields) {\n const written = await client.fieldDeclare({ table_id: table.data, spec: declarationFor(field) });\n // A Field the store refused is a Table that would quietly lose a column, so\n // it is reported rather than skipped — and the half-made Table goes back,\n // because a package table with some of its columns is worse than none: the\n // next load finds it by slug, declares nothing, and reports nothing.\n if (!written.ok) {\n const removed = await client.recordDelete({ record_id: table.data });\n if (removed.ok) await client.recordDelete({ record_id: home.data });\n return written;\n }\n }\n\n return { ok: true, data: table.data };\n}\n\nexport interface UseSystemTableState {\n tableId: Uuid | null;\n loading: boolean;\n error: RecordsError | null;\n}\n\n/** The hook every package-owned component opens with. */\nexport function useSystemTable(spec: SystemTableSpec): UseSystemTableState {\n const client = useRecordsClient();\n const [state, setState] = useState<UseSystemTableState>({ tableId: null, loading: true, error: null });\n const slug = spec.slug;\n const stable = useMemo(() => spec, [slug]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n let cancelled = false;\n setState({ tableId: null, loading: true, error: null });\n void ensureSystemTable(client, stable).then((result) => {\n if (cancelled) return;\n setState(\n result.ok\n ? { tableId: result.data, loading: false, error: null }\n : { tableId: null, loading: false, error: result.error },\n );\n });\n return () => {\n cancelled = true;\n };\n }, [client, stable]);\n\n return state;\n}\n\n/**\n * THE VERSION OF THE ONE RECORD BEING EDITED.\n *\n * The read door (`custom.read_records`) answers documents, never versions —\n * deliberately, because a version is a fact about the row and not about what\n * this reader may see. A screen that saves optimistically still needs the\n * version it LOADED, so it reads it here, for the one record it is editing and\n * never for a list, through `custom.io_revisions`.\n *\n * `null` is an honest answer: the save then carries no expected version and is\n * the store's ordinary last-writer-wins write. It is never a guess.\n */\n/** What `useRecordVersion` hands a screen that writes the record more than once. */\nexport interface TrackedVersion {\n /** The version this screen is writing against, or `null` when none was read. */\n version: number | null;\n /**\n * TELL IT THE STORE MOVED. Every successful write answers the record's NEW\n * version; a screen that does not hand it back here will write against the\n * old one next time and the store will — correctly — refuse it as a conflict\n * with somebody who turns out to be the same person. Measured 2026-09-19:\n * switching a saved view's layout twice in a row did exactly that.\n */\n note: (version: number) => void;\n}\n\nexport function useRecordVersion(recordId: Uuid | null | undefined): TrackedVersion {\n const client = useRecordsClient();\n const [version, setVersion] = useState<number | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setVersion(null);\n if (!recordId) return;\n void client.revisions({ record_id: recordId }).then((answered) => {\n if (cancelled || !answered.ok) return;\n const newest = answered.data.reduce<number | null>(\n (held, row) => (held === null || row.version > held ? row.version : held),\n null,\n );\n setVersion(newest);\n });\n return () => {\n cancelled = true;\n };\n }, [client, recordId]);\n\n return { version, note: setVersion };\n}\n","\"use client\";\n\n// src/ShareControl.tsx — @ai-matrx/records-ui · SCR-N-5\n//\n// THE SHARE BUTTON, on the record screen and on the table screen, in the row\n// where everything else a person does to a thing already is.\n//\n// WHAT IT IS NOT. It is not a share dialog. AI Matrx has exactly one of those\n// and it lives in the app (matrx-frontend `features/sharing`): a people picker\n// over the organization's members, the four levels, the list of who has access\n// with the REASON each one has it, and revoke. Building a second one in this\n// package would give the platform two answers to \"who can see this\", which is\n// the one question a platform may not have two answers to. So this component\n// draws the button, owns whether the dialog is open, and hands the subject to\n// the host's `share` port.\n//\n// ABSENT, NEVER DEAD, AND NEVER OFFERED TO SOMEBODY WHO MAY NOT. With no\n// `share` port bound there is NO BUTTON — not a greyed one, not one that opens\n// an empty panel. And passing your access on to somebody else is an\n// administrator's right on the thing (`custom.share_grant`), so the button is\n// absent for everybody below that rung too: the sixth-pass verdict is the\n// record of what offering it anyway costs, in the cell editor next door.\n//\n// A TABLE IS A RECORD. In this store a Table is a `custom.record` row whose\n// table is the Table kernel, so the same button, the same door and the same\n// dialog serve both screens; `kind` only changes the noun in the sentences.\n\nimport { useState, type ReactNode } from \"react\";\nimport type { Uuid } from \"@ai-matrx/records\";\nimport { Button } from \"@ai-matrx/design-system\";\nimport { useRecordsUi, useRecordRights, NO_SHARE_REASON, type ShareSubject } from \"./host\";\n\nexport interface ShareControlProps {\n kind: ShareSubject[\"kind\"];\n organizationId: Uuid;\n subjectId: Uuid;\n /** What to call it in the dialog's title. */\n name?: string | undefined;\n /**\n * Whether this person may pass this on — `custom.share_grant` asks for Admin\n * ON THE THING. A caller that already holds the answer (a table screen has\n * the table's rights in its hand) passes it; left out, this asks the store\n * itself for the subject named above. Either way it is an ANSWER and never an\n * assumption, which is the whole of this lane.\n */\n may?: boolean | undefined;\n size?: \"sm\" | \"default\" | undefined;\n variant?: \"ghost\" | \"outline\" | \"default\" | undefined;\n className?: string | undefined;\n}\n\n/** True when a host has bound a share dialog — so a caller can lay out its row. */\nexport function useCanShare(): boolean {\n return typeof useRecordsUi().share === \"function\";\n}\n\n/** Why there is no Share button here, for anything that asks. */\nexport function shareUnavailableReason(): string {\n return NO_SHARE_REASON;\n}\n\nexport function ShareControl({\n kind,\n organizationId,\n subjectId,\n name,\n may,\n size = \"sm\",\n variant = \"ghost\",\n className,\n}: ShareControlProps): ReactNode {\n const host = useRecordsUi();\n const [open, setOpen] = useState(false);\n // A Table is a record in this store, so ONE question answers both screens.\n const asked = useRecordRights(may === undefined ? subjectId : null);\n const mayShare = may ?? asked.share;\n\n // No port, no button. The reason is exported rather than rendered as a dead\n // control, because a Share button that opens nothing is the screen lying.\n if (!host.share) return null;\n // Not an Admin here, no button — and nothing greyed out beside it either.\n if (!mayShare) return null;\n\n return (\n <>\n <Button\n size={size}\n variant={variant}\n className={className}\n onClick={() => setOpen(true)}\n aria-label={kind === \"table\" ? \"Share this table\" : \"Share this record\"}\n >\n Share\n </Button>\n {open\n ? host.share({\n kind,\n organizationId,\n subjectId,\n // NEVER A TRUNCATED ID WHERE A PERSON READS A NAME (`names.ts`):\n // \"8f2c1b0a\" tells nobody anything and looks like a bug.\n name: name && name.trim() !== \"\" ? name : kind === \"table\" ? \"this table\" : \"this record\",\n onClose: () => setOpen(false),\n })\n : null}\n </>\n );\n}\n","\"use client\";\n\n// src/views.ts — @ai-matrx/records-ui · SCR-6, SCR-7, SCR-N-6\n//\n// A SAVED VIEW IS ONE RECORD, and that record owns its layout and REFERENCES\n// its membership rule.\n//\n// The split matters. A view does not carry a filter predicate of its own that a\n// screen re-implements in JavaScript: it names a Rule, and the STORE answers\n// who is in it (`custom.rule_members`). So the same view means the same thing\n// to a grid, to an export, to an agent and to the server. What the view owns\n// itself is presentation — which of the four layouts, which Field the kanban\n// columns come from, which Field the calendar reads, which Field the gallery\n// shows — because that is not data, it is how this person wants to look at it.\n//\n// The whole view is also a plain declarative object (`SavedViewSpec`), which is\n// what makes \"an agent writes the view in 45 seconds\" true: one `record_write`\n// of one document, and the person only tweaks.\n\nimport {\n parseGridPresentation,\n presentationDocument,\n presentationIsEmpty,\n type GridPresentation,\n} from \"./presentation\";\nimport type { ReadRow, Uuid } from \"@ai-matrx/records\";\nimport type { SystemTableSpec } from \"./systemTable\";\n\n/** The four ways one saved view can be looked at (SCR-6). */\nexport const VIEW_LAYOUTS = [\"grid\", \"kanban\", \"calendar\", \"gallery\"] as const;\nexport type ViewLayout = (typeof VIEW_LAYOUTS)[number];\n\nexport const LAYOUT_LABEL: Record<ViewLayout, string> = {\n grid: \"Grid\",\n kanban: \"Kanban\",\n calendar: \"Calendar\",\n gallery: \"Gallery\",\n};\n\n/**\n * What each layout needs before it can draw anything, in one sentence a screen\n * prints. A layout that is missing its Field says so instead of rendering an\n * empty board that looks like \"no records\".\n */\nexport const LAYOUT_NEEDS: Record<ViewLayout, string | null> = {\n grid: null,\n kanban: \"A kanban board needs a Field to make its columns from — pick one and the board appears.\",\n calendar: \"A calendar needs a date Field to place records on — pick one and the month appears.\",\n gallery: null,\n};\n\n/** One sort clause. The Field's key and a direction; nothing else is a sort. */\nexport interface ViewSort {\n field: string;\n direction: \"asc\" | \"desc\";\n}\n\n/**\n * THE DECLARATIVE SPEC. An agent writes this whole object; a person tweaks it.\n * Every builder component in this package takes one of these as a prop.\n */\nexport interface SavedViewSpec {\n name: string;\n /** The Table this view looks at. */\n subject: Uuid;\n layout: ViewLayout;\n /** Kanban: the Field whose value becomes a column. */\n groupField?: string | null;\n /** Calendar: the Field that places a record in the month. */\n dateField?: string | null;\n /** Gallery: the Field shown large on the card. */\n imageField?: string | null;\n sorts?: ViewSort[];\n /**\n * The membership Rule. The STORE decides who is in this view; this is a\n * reference to its Rule record, never a predicate this package evaluates.\n */\n ruleId?: Uuid | null;\n isDefault?: boolean;\n /**\n * HOW THIS VIEW LOOKS — its colors, its per-column formats and its frozen\n * column (`presentation.ts`).\n *\n * It lives on the VIEW and not on the Fields because two people read one\n * table two ways and neither reading is a fact about the records; it lives on\n * a RECORD, not a new column, because that is what makes it something an\n * agent writes with the same `records` tool as everything else.\n */\n presentation?: GridPresentation;\n}\n\n/** A saved view as it comes back out of the store, with its record's own id. */\nexport interface SavedView extends SavedViewSpec {\n id: Uuid;\n /**\n * The record's version AT LOAD, read from `custom.io_revisions` for the one\n * record being edited. The read door answers documents and not versions, so\n * this is null until it has been read — and a save with a null version is an\n * ordinary last-writer-wins write, exactly as the store defines it.\n */\n version: number | null;\n}\n\n/** The package-owned Table every saved view is a record of. */\nexport const VIEW_TABLE: SystemTableSpec = {\n slug: \"records_ui_view\",\n name: \"Saved views\",\n labelSingular: \"View\",\n labelPlural: \"Views\",\n titleField: \"name\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"text\", sort: 10, required: true },\n { key: \"subject\", label: \"Table\", type: \"text\", sort: 20, required: true },\n { key: \"layout\", label: \"Layout\", type: \"text\", sort: 30, required: true },\n { key: \"group_field\", label: \"Group by\", type: \"text\", sort: 40 },\n { key: \"date_field\", label: \"Date field\", type: \"text\", sort: 50 },\n { key: \"image_field\", label: \"Image field\", type: \"text\", sort: 60 },\n { key: \"sorts\", label: \"Sorts\", type: \"text\", sort: 70, config: { multiline: true } },\n { key: \"rule_id\", label: \"Membership rule\", type: \"text\", sort: 80 },\n { key: \"is_default\", label: \"Default\", type: \"text\", sort: 90 },\n {\n key: \"presentation\",\n label: \"Look\",\n type: \"text\",\n sort: 100,\n config: { multiline: true },\n },\n ],\n};\n\n/**\n * WHICH FIELD EACH LAYOUT CAN BE DRAWN FROM, decided from the FIELD'S OWN\n * DECLARATION and never from the values it happens to hold.\n *\n * A kanban makes columns from a choice: the Field whose value is one of a\n * closed set (FLD-5 / FLD-6 — a pick-list is a Table, and a select stores the\n * id of one of its records). Grouping by a free-text Field produces one column\n * per record, which is not a board. A calendar places a record in time, so it\n * needs a Field that holds a date.\n *\n * These two answers are here, beside the layouts, because the picker on the\n * screen and any agent writing a view spec must agree about what is offerable.\n */\nexport const LAYOUT_FIELD_KIND: Record<ViewLayout, \"choice\" | \"date\" | null> = {\n grid: null,\n kanban: \"choice\",\n calendar: \"date\",\n gallery: null,\n};\n\n/** The one sentence a layout says when the table holds no Field it could use. */\nexport const LAYOUT_NO_FIELD: Record<ViewLayout, string> = {\n grid: \"\",\n kanban:\n \"This table has no choice field yet, so there is nothing to make columns from. Add a field that \" +\n \"holds one of a set of choices — Add field, then Select — and it appears here.\",\n calendar:\n \"This table has no date field yet, so there is nothing to place records on. Add a field that holds \" +\n \"a date — Add field, then Date — and it appears here.\",\n gallery: \"\",\n};\n\n/** The spec as the one document the store holds. */\nexport function viewDocument(spec: SavedViewSpec): Record<string, unknown> {\n return {\n name: spec.name,\n subject: spec.subject,\n layout: spec.layout,\n group_field: spec.groupField ?? null,\n date_field: spec.dateField ?? null,\n image_field: spec.imageField ?? null,\n sorts: JSON.stringify(spec.sorts ?? []),\n rule_id: spec.ruleId ?? null,\n is_default: spec.isDefault ? \"true\" : \"false\",\n presentation: presentationDocument(spec.presentation ?? {}),\n };\n}\n\n/** One stored record back into the spec a screen and an agent both read. */\nexport function viewFromRecord(row: ReadRow): SavedView {\n const data = (row.document ?? {}) as Record<string, unknown>;\n const layout = String(data[\"layout\"] ?? \"grid\");\n return {\n id: row.id,\n version: null,\n name: String(data[\"name\"] ?? \"Untitled view\"),\n subject: String(data[\"subject\"] ?? \"\"),\n layout: (VIEW_LAYOUTS as readonly string[]).includes(layout) ? (layout as ViewLayout) : \"grid\",\n groupField: (data[\"group_field\"] as string | null) ?? null,\n dateField: (data[\"date_field\"] as string | null) ?? null,\n imageField: (data[\"image_field\"] as string | null) ?? null,\n sorts: parseSorts(data[\"sorts\"]),\n ruleId: (data[\"rule_id\"] as string | null) ?? null,\n isDefault: data[\"is_default\"] === \"true\",\n presentation: parseGridPresentation(data[\"presentation\"]),\n };\n}\n\n/**\n * A PARTIAL change to a saved view, as the patch the store takes. Only the keys\n * the caller actually changed are written — a full document would re-write a\n * name or a rule the person edited in another tab.\n */\nexport function viewPatchDocument(patch: Partial<SavedViewSpec>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (patch.name !== undefined) out[\"name\"] = patch.name;\n if (patch.layout !== undefined) out[\"layout\"] = patch.layout;\n if (patch.groupField !== undefined) out[\"group_field\"] = patch.groupField ?? null;\n if (patch.dateField !== undefined) out[\"date_field\"] = patch.dateField ?? null;\n if (patch.imageField !== undefined) out[\"image_field\"] = patch.imageField ?? null;\n if (patch.sorts !== undefined) out[\"sorts\"] = JSON.stringify(patch.sorts ?? []);\n if (patch.ruleId !== undefined) out[\"rule_id\"] = patch.ruleId ?? null;\n if (patch.isDefault !== undefined) out[\"is_default\"] = patch.isDefault ? \"true\" : \"false\";\n if (patch.presentation !== undefined) {\n out[\"presentation\"] = presentationIsEmpty(patch.presentation)\n ? \"\"\n : presentationDocument(patch.presentation);\n }\n return out;\n}\n\nfunction parseSorts(raw: unknown): ViewSort[] {\n if (Array.isArray(raw)) return raw as ViewSort[];\n if (typeof raw !== \"string\" || raw.trim() === \"\") return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as ViewSort[]) : [];\n } catch {\n // A sort nobody can read is not silently dropped to \"no sort\": the view says\n // what it holds and the caller can see that it is not a sort list.\n return [];\n }\n}\n","\"use client\";\n\n// src/ViewSwitcher.tsx — @ai-matrx/records-ui · SCR-6\n//\n// ONE SAVED VIEW, FOUR WAYS TO LOOK AT IT: grid, kanban, calendar, gallery.\n//\n// The records are the SAME records in all four. Switching layout re-draws them;\n// it never re-queries something different and it never filters differently —\n// membership is the view's Rule and the STORE answers it (`custom.rule_members`),\n// so a card that disappears between two layouts would be a defect, not a\n// feature. A view with no Rule is the whole table, and the screen says which.\n//\n// A layout that cannot draw yet (a kanban with no Field to group by, a calendar\n// with no date Field) says the one sentence that fixes it. It never renders an\n// empty board that reads like \"there is nothing here\".\n\nimport { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { useFields, useRecords, useRecordsClient, type Field, type ReadRow, type StoredRecord, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { Grid } from \"./Grid\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi } from \"./host\";\nimport { RecordValue, scalarText } from \"./values\";\nimport { useRecordLabels } from \"./labels\";\nimport { fieldName, rowName } from \"./names\";\nimport { editorKindFor } from \"./parity\";\nimport {\n LAYOUT_FIELD_KIND,\n LAYOUT_LABEL,\n LAYOUT_NEEDS,\n LAYOUT_NO_FIELD,\n VIEW_LAYOUTS,\n type SavedViewSpec,\n type ViewLayout,\n} from \"./views\";\n\nexport interface ViewSwitcherProps {\n /**\n * THE DECLARATIVE SPEC — an agent writes the whole thing, a person tweaks it.\n * `ViewBar` passes the saved view it loaded; a host with no saved views at all\n * can pass a literal here and the switcher works.\n */\n view: SavedViewSpec;\n /** Called when the person picks another layout, so the host can save it. */\n onLayoutChange?: ((layout: ViewLayout) => void) | undefined;\n /**\n * Called with whatever part of the view the person just changed — the layout,\n * the Field the kanban groups by, the Field the calendar reads. The HOST\n * saves it onto the view record, so the choice is remembered per saved view\n * rather than per page load. Unbound, the pickers still work for this visit\n * and the screen says the choice is not being kept.\n */\n onViewChange?: ((patch: Partial<SavedViewSpec>) => void) | undefined;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n /** The host's whole-record form, offered by the grid when an empty record is refused. */\n onNewRecordForm?: (() => void) | undefined;\n pageSize?: number | undefined;\n className?: string | undefined;\n}\n\n/** The records this view holds: its Rule's members when it names one, the table otherwise. */\nexport function useViewRecords(view: SavedViewSpec, pageSize = 200) {\n const client = useRecordsClient();\n const table = useRecords(view.ruleId ? null : view.subject, { pageSize });\n const [ruled, setRuled] = useState<{ rows: ReadRow[]; loading: boolean; error: RecordsError | null }>({\n rows: [],\n loading: Boolean(view.ruleId),\n error: null,\n });\n\n const ruleId = view.ruleId ?? null;\n useEffect(() => {\n if (!ruleId) return;\n let cancelled = false;\n setRuled({ rows: [], loading: true, error: null });\n void client.ruleMembers({ rule_id: ruleId }).then((result) => {\n if (cancelled) return;\n setRuled(\n result.ok\n ? { rows: (result.data ?? []).map(asReadRow), loading: false, error: null }\n : { rows: [], loading: false, error: result.error },\n );\n });\n return () => {\n cancelled = true;\n };\n }, [client, ruleId]);\n\n const rows = ruleId ? ruled.rows : (table.data?.rows ?? []);\n return {\n rows: sortRows(rows, view.sorts ?? []),\n loading: ruleId ? ruled.loading : table.loading,\n error: ruleId ? ruled.error : table.error,\n /** Where membership came from, in a sentence. A screen that hides this is hiding the view's meaning. */\n membership: ruleId\n ? \"Membership is this view's Rule, answered by the store.\"\n : \"This view has no Rule, so it holds the whole table.\",\n };\n}\n\n/**\n * `custom.rule_members` answers SETOF `custom.record` — it is the membership\n * door, not the read door, so its rows arrive in the row shape rather than the\n * masked-document shape. They are carried into the read door's shape HERE, at\n * the one seam, so a card is drawn by exactly one code path whichever door\n * produced it. What this cannot do is mask: a Rule's members come back as the\n * store stored them, which is the membership door's own gap, not this screen's.\n */\nfunction asReadRow(row: StoredRecord): ReadRow {\n return { id: row.id, document: (row.data ?? {}) as ReadRow[\"document\"], level: \"viewer\", hidden: {} };\n}\n\nfunction sortRows(rows: ReadRow[], sorts: { field: string; direction: \"asc\" | \"desc\" }[]): ReadRow[] {\n if (sorts.length === 0) return rows;\n return [...rows].sort((a, b) => {\n for (const sort of sorts) {\n const left = (a.document ?? {})[sort.field];\n const right = (b.document ?? {})[sort.field];\n if (left === right) continue;\n const order = (left ?? \"\") < (right ?? \"\") ? -1 : 1;\n return sort.direction === \"desc\" ? -order : order;\n }\n return 0;\n });\n}\n\nexport function ViewSwitcher({\n view,\n onLayoutChange,\n onViewChange,\n onOpenRecord,\n onNewRecordForm,\n pageSize = 200,\n className,\n}: ViewSwitcherProps) {\n const [layout, setLayout] = useState<ViewLayout>(view.layout);\n // The Fields the pickers below chose, so a host that binds no `onViewChange`\n // still gets a board rather than a sentence — and is TOLD it is not kept.\n const [local, setLocal] = useState<Partial<SavedViewSpec>>({});\n useEffect(() => {\n setLayout(view.layout);\n setLocal({});\n }, [view.layout, view.name, view.subject]);\n\n const pick = (next: ViewLayout) => {\n setLayout(next);\n onLayoutChange?.(next);\n onViewChange?.({ layout: next });\n };\n\n const change = (patch: Partial<SavedViewSpec>) => {\n setLocal((held) => ({ ...held, ...patch }));\n onViewChange?.(patch);\n };\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: the view's name, the four layouts, nothing repeated. */}\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-sm font-medium\">{view.name}</span>\n <div className=\"ml-auto flex items-center gap-0.5\" role=\"group\" aria-label=\"Layout\">\n {VIEW_LAYOUTS.map((option) => (\n <Button\n key={option}\n size=\"sm\"\n variant={option === layout ? \"secondary\" : \"ghost\"}\n aria-pressed={option === layout}\n onClick={() => pick(option)}\n >\n {LAYOUT_LABEL[option]}\n </Button>\n ))}\n </div>\n </div>\n\n {layout === \"grid\" ? (\n <Grid\n tableId={view.subject}\n pageSize={pageSize}\n /* The OPEN view's look — its colors, formats and frozen columns.\n `local` holds what the person just changed, so a look edited here\n shows before the record it lives on has come back. */\n {...(local.presentation ?? view.presentation\n ? { presentation: local.presentation ?? view.presentation }\n : {})}\n {...(onOpenRecord ? { onOpenRecord } : {})}\n {...(onNewRecordForm ? { onNewRecordForm } : {})}\n />\n ) : (\n <Board\n view={{ ...view, ...local, layout }}\n pageSize={pageSize}\n onChange={change}\n remembered={Boolean(onViewChange)}\n {...(onOpenRecord ? { onOpenRecord } : {})}\n />\n )}\n </div>\n );\n}\n\n/** Which Fields a kanban may group by, and which a calendar may read. */\nfunction offerableFields(all: Field[], want: \"choice\" | \"date\"): Field[] {\n return all.filter((field) => {\n const kind = editorKindFor(field);\n if (want === \"choice\") return kind === \"select\" || kind === \"multi_select\";\n return kind === \"datetime\" || kind === \"date\";\n });\n}\n\nfunction Board({\n view,\n pageSize,\n onChange,\n remembered,\n onOpenRecord,\n}: {\n view: SavedViewSpec;\n pageSize: number;\n onChange: (patch: Partial<SavedViewSpec>) => void;\n remembered: boolean;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n}) {\n const fields = useFields(view.subject);\n const records = useViewRecords(view, pageSize);\n\n if (fields.error) return <RefusalNotice error={fields.error} />;\n if (records.error) return <RefusalNotice error={records.error} />;\n if (fields.loading || records.loading) return <Skeleton className=\"h-40 w-full\" />;\n\n const all = fields.data ?? [];\n const byKey = (key: string | null | undefined) => all.find((f) => f.key === key);\n const titleField = byKey(view.groupField) ? all.find((f) => f.key !== view.groupField) ?? all[0] : all[0];\n\n if (view.layout === \"kanban\") {\n const groupField = byKey(view.groupField);\n const picker = (\n <FieldPicker\n layout=\"kanban\"\n label=\"Group by\"\n all={all}\n chosen={groupField?.key ?? null}\n remembered={remembered}\n onPick={(key) => onChange({ groupField: key })}\n />\n );\n if (!groupField) return <Needs layout=\"kanban\" picker={picker} />;\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n {picker}\n <Kanban rows={records.rows} groupField={groupField} titleField={titleField} onOpenRecord={onOpenRecord} note={records.membership} />\n </div>\n );\n }\n if (view.layout === \"calendar\") {\n const dateField = byKey(view.dateField);\n const picker = (\n <FieldPicker\n layout=\"calendar\"\n label=\"Dates from\"\n all={all}\n chosen={dateField?.key ?? null}\n remembered={remembered}\n onPick={(key) => onChange({ dateField: key })}\n />\n );\n if (!dateField) return <Needs layout=\"calendar\" picker={picker} />;\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n {picker}\n <Calendar rows={records.rows} dateField={dateField} titleField={titleField} onOpenRecord={onOpenRecord} note={records.membership} />\n </div>\n );\n }\n return <Gallery rows={records.rows} fields={all} imageKey={view.imageField ?? null} onOpenRecord={onOpenRecord} note={records.membership} />;\n}\n\n/**\n * THE PICKER THE SENTENCE ALWAYS PROMISED. Before this, a kanban said \"pick one\n * and the board appears\" and there was no picker anywhere on the page — the\n * verdict of 19 September found the same dead end on the calendar. A screen\n * that names a remedy and does not offer it is worse than one that says\n * nothing, so the sentence and the control are now the same component.\n */\nfunction FieldPicker({\n layout,\n label,\n all,\n chosen,\n remembered,\n onPick,\n}: {\n layout: ViewLayout;\n label: string;\n all: Field[];\n chosen: string | null;\n remembered: boolean;\n onPick: (key: string | null) => void;\n}) {\n const want = LAYOUT_FIELD_KIND[layout];\n const offerable = want ? offerableFields(all, want) : [];\n if (offerable.length === 0) {\n // Honest, and it names the fix: this is not \"pick one\", because there is\n // nothing to pick.\n return <p className=\"text-xs text-muted-foreground\">{LAYOUT_NO_FIELD[layout]}</p>;\n }\n return (\n <div className=\"flex items-center gap-1.5 text-xs\">\n <label className=\"text-muted-foreground\" htmlFor={`view-field-${layout}`}>\n {label}\n </label>\n <select\n id={`view-field-${layout}`}\n aria-label={`${label} which field`}\n className=\"h-7 rounded border bg-background px-1 text-xs\"\n value={chosen ?? \"\"}\n onChange={(event) => onPick(event.target.value === \"\" ? null : event.target.value)}\n >\n <option value=\"\">Choose a field</option>\n {offerable.map((field) => (\n <option key={field.key} value={field.key}>\n {fieldName(field)}\n </option>\n ))}\n </select>\n {remembered ? null : (\n <span className=\"text-muted-foreground\">\n Kept for this visit only — this screen has nowhere to save it onto the view.\n </span>\n )}\n </div>\n );\n}\n\n/** The one sentence that fixes an un-drawable layout, WITH the control that fixes it. */\nfunction Needs({ layout, picker }: { layout: ViewLayout; picker: ReactNode }) {\n return (\n <div className=\"flex flex-col gap-2 rounded border border-dashed p-4 text-xs text-muted-foreground\">\n <p>{LAYOUT_NEEDS[layout]}</p>\n {picker}\n </div>\n );\n}\n\nfunction Note({ children }: { children: string }) {\n return <p className=\"text-xs text-muted-foreground\">{children}</p>;\n}\n\nfunction Kanban({\n rows,\n groupField,\n titleField,\n onOpenRecord,\n note,\n}: {\n rows: ReadRow[];\n groupField: Field;\n titleField: Field | undefined;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n note: string;\n}) {\n const groupFields = useMemo(() => [groupField], [groupField]);\n // A BOARD IS GROUPED BY A CHOICE, AND A CHOICE IS STORED AS THE ID OF AN\n // OPTION RECORD (FLD-5 / FLD-6). Without the resolver every heading on this\n // board was a bare 36-character identifier — the single most visible line in\n // the 19 September verdict's \"machine identity is everywhere a person looks\".\n const labels = useRecordLabels(groupFields);\n const columns = useMemo(() => {\n const map = new Map<string, ReadRow[]>();\n for (const row of rows) {\n const raw = (row.document ?? {})[groupField.key];\n // A record with no value for the grouping Field is NOT dropped: it gets\n // its own column, named for the absence, because losing rows between two\n // layouts is the defect this board could most easily ship.\n const key = raw === null || raw === undefined || raw === \"\" ? \"No value\" : scalarText(groupField, raw, labels);\n map.set(key, [...(map.get(key) ?? []), row]);\n }\n return [...map.entries()].sort((a, b) => (a[0] === \"No value\" ? 1 : b[0] === \"No value\" ? -1 : a[0].localeCompare(b[0])));\n }, [rows, groupField, labels]);\n\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n <Note>{note}</Note>\n <div className=\"flex min-h-0 gap-2 overflow-x-auto pb-2\">\n {columns.map(([name, cards]) => (\n <section key={name} className=\"flex w-64 shrink-0 flex-col rounded border bg-muted/30\">\n <header className=\"flex items-center gap-2 border-b px-2 py-1 text-xs font-medium\">\n <span className=\"truncate\">{name}</span>\n <span className=\"ml-auto text-muted-foreground\">{cards.length}</span>\n </header>\n <ul className=\"flex flex-col gap-1 p-1\">\n {cards.map((card) => (\n <li key={card.id}>\n <Card record={card} field={titleField} onOpenRecord={onOpenRecord} />\n </li>\n ))}\n </ul>\n </section>\n ))}\n </div>\n </div>\n );\n}\n\nfunction Calendar({\n rows,\n dateField,\n titleField,\n onOpenRecord,\n note,\n}: {\n rows: ReadRow[];\n dateField: Field;\n titleField: Field | undefined;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n note: string;\n}) {\n const { days, undated } = useMemo(() => {\n const byDay = new Map<string, ReadRow[]>();\n const without: ReadRow[] = [];\n for (const row of rows) {\n const raw = (row.document ?? {})[dateField.key];\n const at = typeof raw === \"string\" || typeof raw === \"number\" ? new Date(raw) : null;\n if (!at || Number.isNaN(at.getTime())) {\n without.push(row);\n continue;\n }\n const key = at.toISOString().slice(0, 10);\n byDay.set(key, [...(byDay.get(key) ?? []), row]);\n }\n return { days: [...byDay.entries()].sort((a, b) => a[0].localeCompare(b[0])), undated: without };\n }, [rows, dateField]);\n\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n <Note>{note}</Note>\n <ol className=\"flex min-h-0 flex-col divide-y overflow-y-auto rounded border\">\n {days.map(([day, cards]) => (\n <li key={day} className=\"flex gap-3 p-2\">\n <span className=\"w-24 shrink-0 text-xs font-medium tabular-nums\">\n {new Date(`${day}T00:00:00Z`).toLocaleDateString(undefined, { month: \"short\", day: \"numeric\", year: \"numeric\" })}\n </span>\n <ul className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {cards.map((card) => (\n <li key={card.id}>\n <Card record={card} field={titleField} onOpenRecord={onOpenRecord} />\n </li>\n ))}\n </ul>\n </li>\n ))}\n </ol>\n {undated.length > 0 ? (\n // Nothing fails silently: records with no date are NOT missing from the\n // calendar, they are named as records the calendar cannot place.\n <p className=\"text-xs text-muted-foreground\">\n {undated.length} {undated.length === 1 ? \"record has\" : \"records have\"} no {fieldName(dateField)},\n so the calendar cannot place {undated.length === 1 ? \"it\" : \"them\"}.\n </p>\n ) : null}\n </div>\n );\n}\n\nfunction Gallery({\n rows,\n fields,\n imageKey,\n onOpenRecord,\n note,\n}: {\n rows: ReadRow[];\n fields: Field[];\n imageKey: string | null;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n note: string;\n}) {\n const shown = fields.slice(0, 4);\n return (\n <div className=\"flex min-h-0 flex-col gap-2\">\n <Note>{note}</Note>\n <ul className=\"grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2 overflow-y-auto\">\n {rows.map((row) => {\n const image = imageKey ? (row.document ?? {})[imageKey] : null;\n return (\n <li key={row.id}>\n <button\n type=\"button\"\n className=\"flex w-full flex-col gap-1 rounded border p-2 text-left hover:bg-muted\"\n onClick={() => onOpenRecord?.(row.id)}\n >\n {typeof image === \"string\" && image !== \"\" ? (\n <img src={image} alt=\"\" className=\"h-28 w-full rounded object-cover\" />\n ) : null}\n {shown.map((field) => (\n <span key={field.key} className=\"flex min-w-0 items-baseline gap-1 text-xs\">\n <span className=\"shrink-0 text-muted-foreground\">{fieldName(field)}</span>\n <span className=\"min-w-0 truncate\"><RecordValue field={field} value={(row.document ?? {})[field.key]} document={row.document} /></span>\n </span>\n ))}\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\nfunction Card({\n record,\n field,\n onOpenRecord,\n}: {\n record: ReadRow;\n field: Field | undefined;\n onOpenRecord?: ((recordId: Uuid) => void) | undefined;\n}) {\n const host = useRecordsUi();\n // Never a bare identifier on a card: the Field's own value when there is one,\n // the record's name when there is not.\n const label = field\n ? scalarText(field, (record.document ?? {})[field.key])\n : rowName(record, null, \"Untitled\");\n return (\n <button\n type=\"button\"\n className={cn(\n \"w-full truncate rounded border bg-background px-2 py-1 text-left text-xs hover:bg-muted\",\n host.density === \"spacious\" ? \"py-2\" : \"\",\n )}\n onClick={() => onOpenRecord?.(record.id)}\n title={label}\n >\n {label}\n </button>\n );\n}\n","\"use client\";\n\n// src/ViewBar.tsx — @ai-matrx/records-ui · SCR-7, SCR-N-6\n//\n// THE SAVED VIEWS OF ONE TABLE, AS RECORDS.\n//\n// Each view is ONE record in this organization's own `records_ui_view` Table,\n// declared through the store's doors the first time anything asks for it\n// (`systemTable.ts`). That is what makes a view shareable, exportable,\n// historied and agent-writable without a line of code per feature: it is a\n// record, so everything this package does to records it already does to views.\n//\n// A view owns its LAYOUT and references its MEMBERSHIP RULE. The bar never\n// evaluates a predicate — picking a view hands `ViewSwitcher` a spec, and the\n// store answers who is in it.\n//\n// `seed` is the declarative half: an agent writes a complete view spec, the bar\n// saves it as a record on first sight, and the person only tweaks it.\n//\n// ONE CONTROL FOR ONE THING. This bar used to carry a layout `select` of its\n// own beside `ViewSwitcher`'s layout buttons, and the two disagreed on screen:\n// the verdict of 19 September watched the dropdown keep saying \"Grid\" while\n// Calendar was drawn. The switcher owns the LAYOUT; this bar owns WHICH VIEW.\n// Saving a layout — or a kanban's grouping Field, or a calendar's date Field —\n// onto the view record belongs to whoever owns the switcher (`TablePage`).\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Input, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useSeedGuard } from \"./seedOnce\";\nimport { useSystemTable } from \"./systemTable\";\nimport { useTableRights } from \"./host\";\nimport { useTable } from \"@ai-matrx/records/react\";\nimport {\n VIEW_TABLE,\n viewDocument,\n viewFromRecord,\n type SavedView,\n type SavedViewSpec,\n} from \"./views\";\n\nexport interface ViewBarProps {\n /** The Table whose views these are. */\n tableId: Uuid;\n /** The view that is showing. Leave it out and the bar picks the default, then the first. */\n activeViewId?: Uuid | null | undefined;\n onActiveView?: ((view: SavedView) => void) | undefined;\n /**\n * COMPLETE DECLARATIVE SPECS an agent wrote. Any of these whose name this\n * table does not have yet is saved as a record the first time the bar loads.\n * The person tweaks them afterwards like any other view.\n */\n seed?: SavedViewSpec[] | undefined;\n className?: string | undefined;\n}\n\nexport function ViewBar({ tableId, activeViewId, onActiveView, seed, className }: ViewBarProps) {\n const client = useRecordsClient();\n // One claim per seed name, per mount: a check against the server's list is\n // not a lock, and a loader that re-runs mid-write would write it twice.\n const claimSeed = useSeedGuard();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const home = useSystemTable(VIEW_TABLE);\n const [views, setViews] = useState<SavedView[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [active, setActive] = useState<Uuid | null>(activeViewId ?? null);\n const [naming, setNaming] = useState(false);\n const [draftName, setDraftName] = useState(\"\");\n\n const viewTableId = home.tableId;\n\n const load = useCallback(async () => {\n if (!viewTableId) return;\n const result = await client.list({ table_id: viewTableId, limit: 500 });\n if (!result.ok) {\n setError(result.error);\n return;\n }\n const mine = result.data.rows.map(viewFromRecord).filter((v) => v.subject === tableId);\n\n // The agent's specs, saved once. A seed whose name already exists is left\n // alone — an agent re-running never overwrites what a person has tweaked.\n const missing = (seed ?? []).filter((s) => !mine.some((v) => v.name === s.name));\n if (missing.length > 0) {\n for (const spec of missing) {\n if (!claimSeed(spec.name)) continue;\n const written = await client.recordWrite({\n table_id: viewTableId,\n data: viewDocument({ ...spec, subject: tableId }),\n });\n if (!written.ok) {\n setError(written.error);\n return;\n }\n }\n const again = await client.list({ table_id: viewTableId, limit: 500 });\n if (!again.ok) {\n setError(again.error);\n return;\n }\n setViews(again.data.rows.map(viewFromRecord).filter((v) => v.subject === tableId));\n return;\n }\n setError(null);\n setViews(mine);\n }, [client, viewTableId, tableId, seed]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n useEffect(() => {\n if (!views || views.length === 0) return;\n const chosen = views.find((v) => v.id === (activeViewId ?? active)) ?? views.find((v) => v.isDefault) ?? views[0]!;\n if (chosen.id !== active) setActive(chosen.id);\n onActiveView?.(chosen);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [views, activeViewId]);\n\n async function create(name: string) {\n if (!viewTableId || name.trim() === \"\") return;\n const written = await client.recordWrite({\n table_id: viewTableId,\n data: viewDocument({ name: name.trim(), subject: tableId, layout: \"grid\" }),\n });\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setNaming(false);\n setDraftName(\"\");\n setActive(written.data);\n await load();\n }\n\n if (home.error) return <RefusalNotice error={home.error} className={className} />;\n if (error) return <RefusalNotice error={error} className={className} actions={<Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>Try again</Button>} />;\n if (home.loading || views === null) return <Skeleton className={cn(\"h-7 w-64\", className)} />;\n\n return (\n <div className={cn(\"flex items-center gap-1 overflow-x-auto\", className)} role=\"group\" aria-label=\"Saved views\">\n {views.map((view) => (\n <Button\n key={view.id}\n size=\"sm\"\n variant={view.id === active ? \"secondary\" : \"ghost\"}\n aria-pressed={view.id === active}\n onClick={() => {\n setActive(view.id);\n onActiveView?.(view);\n }}\n title={view.ruleId ? \"Membership is this view's Rule\" : \"The whole table\"}\n >\n {view.name}\n {view.isDefault ? <span className=\"ml-1 text-[10px] text-muted-foreground\">default</span> : null}\n </Button>\n ))}\n\n {/* SCR-4 again: saving a view is administering the table, so a member does\n not get a dead \"New view\" button — there is no button. */}\n {rights.admin ? (\n naming ? (\n <form\n className=\"ml-1 flex items-center gap-1\"\n onSubmit={(e) => {\n e.preventDefault();\n void create(draftName);\n }}\n >\n <Input\n autoFocus\n aria-label=\"Name for the new view\"\n value={draftName}\n onChange={(e) => setDraftName(e.target.value)}\n className=\"h-7 w-40 text-xs\"\n placeholder=\"View name\"\n />\n <Button size=\"sm\" type=\"submit\">\n Save\n </Button>\n </form>\n ) : (\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-1\" onClick={() => setNaming(true)}>\n New view\n </Button>\n )\n ) : null}\n\n {views.length === 0 && !rights.admin ? (\n <span className=\"text-xs text-muted-foreground\">{rights.why(\"structure\")}</span>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/seedOnce.ts — @ai-matrx/records-ui\n//\n// THE SEED IS WRITTEN ONCE, AND \"once\" MEANS ONCE PER MOUNT — NOT ONCE PER\n// LOAD THAT HAPPENED TO SEE IT MISSING.\n//\n// Every `seed`-taking component in this package had the same shape: a loader\n// that reads what exists, works out what is missing, writes it, and re-reads.\n// The loader is a `useCallback` whose identity changes when its inputs settle\n// (the Fields arriving is the common one), so the effect runs it again — and if\n// the FIRST run is still in flight, the second run reads a list that does not\n// yet contain what the first is writing, and writes it a second time.\n//\n// It looks harmless until the store is slow. Against the live store this\n// produced two identical \"Agreement\" templates and a screen with two buttons of\n// the same name; the same class had already produced two `signed_by` Fields in\n// the demo's own harness, fixed there the same way. The instance is a race; the\n// class is \"a check against the server's list is not a lock\", and the fix is a\n// claim that lives in the component instance rather than in the answer.\n//\n// CLAIMING IS NOT PERSISTENCE. This never stops a SECOND mount, another tab or\n// another person from seeding — nothing here pretends to be a distributed lock.\n// It stops one component from racing itself, which is the whole of what went\n// wrong. Two tabs seeding at once is the store's problem to answer, and it does.\n\nimport { useCallback, useRef } from \"react\";\n\n/**\n * A per-mount claim over seed names. `claim(\"Agreement\")` answers true exactly\n * once; every later ask for the same name answers false, including while the\n * first write is still in flight.\n */\nexport function useSeedGuard(): (name: string) => boolean {\n const claimed = useRef<Set<string>>(new Set());\n return useCallback((name: string) => {\n if (claimed.current.has(name)) return false;\n claimed.current.add(name);\n return true;\n }, []);\n}\n","\"use client\";\n\n// src/ProposalRow.tsx — @ai-matrx/records-ui · SCR-11\n//\n// ONE ROW PER PROPOSED CHANGE: what changes, why, Accept, Reject — and nothing\n// folded behind a disclosure, because a person deciding needs every line at\n// once. This is the SAME row whether it appears inline in a chat, in the action\n// inbox, or beside a grid; a second reviewer somewhere else is the defect.\n//\n// It refuses to fake three things, and they are worth naming because each one\n// is a way a queue lies:\n// 1. A control that would do nothing is ABSENT, with the reason in words —\n// never a greyed button nobody can explain.\n// 2. The store's answer is shown VERBATIM. \"Written\", \"already there\" and a\n// refusal are three different sentences.\n// 3. Accepting a removal DELETES the record, so the confirmation says that in\n// those words rather than \"this cannot be undone\".\n//\n// Every change is expressed against the record store, because in this platform\n// a field proposal, a table change and a list change are all the same act: a\n// record written, updated or deleted through one door.\n\nimport { useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport { Badge, Button, cn } from \"@ai-matrx/design-system\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\n/** One proposed change, in the proposer's words plus the exact act it asks for. */\nexport interface ProposedChange {\n id: string;\n act: \"add\" | \"update\" | \"remove\";\n /**\n * The Table a NEW record lands in. Required for `add` and unused by `update`\n * and `remove`, which name a record instead — and it is optional for exactly\n * that reason: it used to be required for all three, so a proposer wanting to\n * change an existing record had to supply the id of the kernel Table that\n * record lives in, which is a fact the client has no door to ask for. A\n * required field a caller cannot fill is a field that gets filled with\n * something untrue.\n */\n table?: Uuid | undefined;\n /** The record it changes. Required for `update` and `remove`. */\n record?: Uuid | undefined;\n /** The document for `add`, or the patch for `update`. */\n data?: Record<string, unknown> | undefined;\n /** What this change is, in one line a person reads. */\n label: string;\n /** Why the proposer asks for it. Optional, and shown when it is there. */\n why?: string | undefined;\n}\n\nexport type ProposalOutcome =\n | { settled: \"accepted\"; sentence: string }\n | { settled: \"rejected\"; sentence: string }\n | { settled: \"refused\"; sentence: string };\n\nexport interface ProposalRowProps {\n change: ProposedChange;\n /** What already happened to this change, when the host remembers decisions. */\n outcome?: ProposalOutcome | undefined;\n /**\n * The apply port. Left unbound, the row applies the change through the record\n * store itself — the default that makes the component plug and play. A host\n * whose proposals land somewhere else (a different store, a server lane)\n * binds this and keeps the SAME row.\n */\n onApply?: ((change: ProposedChange) => Promise<ProposalOutcome>) | undefined;\n onReject?: ((change: ProposedChange) => Promise<ProposalOutcome> | ProposalOutcome) | undefined;\n /** Absent controls with this reason, instead of dead ones. */\n readOnlyReason?: string | undefined;\n onSettled?: ((outcome: ProposalOutcome) => void) | undefined;\n className?: string | undefined;\n}\n\nconst ACT_WORD: Record<ProposedChange[\"act\"], string> = {\n add: \"Add\",\n update: \"Update\",\n remove: \"Remove\",\n};\n\nexport function ProposalRow({\n change,\n outcome,\n onApply,\n onReject,\n readOnlyReason,\n onSettled,\n className,\n}: ProposalRowProps) {\n const client = useRecordsClient();\n const [settled, setSettled] = useState<ProposalOutcome | null>(outcome ?? null);\n const [busy, setBusy] = useState(false);\n const [confirming, setConfirming] = useState(false);\n\n async function applyThroughTheStore(): Promise<ProposalOutcome> {\n if (change.act === \"add\") {\n if (!change.table) {\n // Not a silent no-op: the proposal is malformed and says which part.\n return {\n settled: \"refused\",\n sentence:\n \"This proposal asks to add a record but does not name the table it goes in, so nothing was written.\",\n };\n }\n const written = await client.recordWrite({ table_id: change.table, data: change.data ?? {} });\n return written.ok\n ? { settled: \"accepted\", sentence: \"Written.\" }\n : { settled: \"refused\", sentence: refusalLineForAPerson(written.error) };\n }\n if (!change.record) {\n // Not a silent no-op: the proposal is malformed and says which part.\n return {\n settled: \"refused\",\n sentence: `This proposal asks to ${change.act} a record but does not name one, so nothing was changed.`,\n };\n }\n if (change.act === \"update\") {\n const updated = await client.recordUpdate({ record_id: change.record, patch: change.data ?? {} });\n return updated.ok\n ? { settled: \"accepted\", sentence: \"Written.\" }\n : { settled: \"refused\", sentence: refusalLineForAPerson(updated.error) };\n }\n const removed = await client.recordDelete({ record_id: change.record });\n return removed.ok\n ? { settled: \"accepted\", sentence: \"Deleted. The store keeps it restorable for this table's retention.\" }\n : { settled: \"refused\", sentence: refusalLineForAPerson(removed.error) };\n }\n\n async function accept() {\n setBusy(true);\n const result = onApply ? await onApply(change) : await applyThroughTheStore();\n setBusy(false);\n setConfirming(false);\n setSettled(result);\n onSettled?.(result);\n }\n\n async function reject() {\n const result: ProposalOutcome = onReject\n ? await onReject(change)\n : { settled: \"rejected\", sentence: \"Rejected.\" };\n setSettled(result);\n onSettled?.(result);\n }\n\n return (\n <div className={cn(\"flex flex-col gap-1 rounded border p-2\", className)}>\n {/* One row: the act, what changes, and the decision. No second header. */}\n <div className=\"flex items-baseline gap-2\">\n <Badge variant={change.act === \"remove\" ? \"destructive\" : \"secondary\"} className=\"text-[10px]\">\n {ACT_WORD[change.act]}\n </Badge>\n <span className=\"min-w-0 flex-1 truncate text-xs\" title={change.label}>\n {change.label}\n </span>\n {settled ? (\n <span\n className={cn(\n \"shrink-0 text-xs\",\n settled.settled === \"refused\" ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {settled.settled === \"accepted\" ? \"Accepted\" : settled.settled === \"rejected\" ? \"Rejected\" : \"Refused\"}\n </span>\n ) : readOnlyReason ? null : (\n <span className=\"flex shrink-0 items-center gap-1\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={busy}\n onClick={() => void reject()}\n >\n Reject\n </Button>\n <Button\n size=\"sm\"\n disabled={busy}\n onClick={() => (change.act === \"remove\" ? setConfirming(true) : void accept())}\n >\n Accept\n </Button>\n </span>\n )}\n </div>\n\n {change.why ? <p className=\"text-xs text-muted-foreground\">{change.why}</p> : null}\n\n {/* The store's own sentence, verbatim. */}\n {settled ? <p className=\"text-xs text-muted-foreground\">{settled.sentence}</p> : null}\n\n {/* A destructive accept names the consequence in those words. */}\n {confirming ? (\n <div className=\"flex items-center gap-2 rounded bg-destructive/10 p-2 text-xs\">\n <span className=\"min-w-0 flex-1\">\n Accepting this deletes the record. It stays restorable for this table's retention, and after\n that it is gone.\n </span>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setConfirming(false)}>\n Cancel\n </Button>\n <Button size=\"sm\" variant=\"destructive\" disabled={busy} onClick={() => void accept()}>\n Delete it\n </Button>\n </div>\n ) : null}\n\n {readOnlyReason && !settled ? <p className=\"text-xs text-muted-foreground\">{readOnlyReason}</p> : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/ActionInbox.tsx — @ai-matrx/records-ui · SCR-11\n//\n// ONE QUEUE, AND IT IS THE STORE'S OWN.\n//\n// PRODUCTS.md row 6: \"One inbox holds human approvals AND the agent's field and\n// table proposals — the same queue, the same right to approve.\" This component\n// reads `custom.work_inbox` and nothing else: assignments come from\n// `custom.work_list`, approvals and the agent's proposals from the\n// `work_approval` records, and the door unions them into ONE ordered list with\n// ONE row shape before a single byte reaches this file.\n//\n// 🚨 WHAT THIS REPLACED, and why it had to (lane WORK-DOORS, 2026-09-20). The\n// first version of this component kept its OWN queue: a package-owned\n// `records_ui_action` Table that agents wrote rows into. It rendered beautifully\n// and it was a second source of truth — an approval a person filed through the\n// store, or a wait the server's own `field_propose` produced, appeared nowhere\n// in it. Two queues is precisely the thing row 6 says the product must not be.\n// Deciding here now goes through `custom.work_approval_decide`, which APPLIES\n// the change in the same transaction as the decision.\n//\n// LINEAR'S INBOX IS THE BAR, so this is keyboard-first: j/k or the arrow keys\n// move, a approves, d declines, o opens the thing it is about, r refreshes.\n// The selected row is always scrolled into view and always says what the keys\n// do — a keyboard surface that hides its own keys is a keyboard surface for the\n// person who wrote it.\n//\n// LEVEL-AWARE, AND ABSENT RATHER THAN DEAD. The door answers `actionable`, which\n// is `custom.work_approval_may_decide` asked per row. A row this person may not\n// decide renders WITHOUT the two buttons and says who it is waiting on — never a\n// greyed-out Approve that fails when clicked.\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, WorkInboxItem, WorkInboxKind } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\n\n/** The three things that land in the queue, exactly as the door names them. */\nexport const ACTION_KINDS = [\"approval\", \"assignment\", \"proposal\"] as const;\nexport type ActionKind = WorkInboxKind;\n\n/** What a person reads instead of the door's one-word kind. */\nconst KIND_WORD: Record<WorkInboxKind, string> = {\n assignment: \"Yours\",\n approval: \"Approve\",\n proposal: \"Agent\",\n};\n\n/** The due states, in the store's words, turned into a person's. */\nconst DUE_WORD: Record<string, string> = {\n overdue: \"Overdue\",\n due_today: \"Today\",\n scheduled: \"Scheduled\",\n undated: \"No date\",\n finished: \"Finished\",\n};\n\nexport interface ActionInboxProps {\n /**\n * Narrow to one table's work. The door answers the organization; this filters\n * the assignments to the table a person is looking at, and leaves approvals\n * and proposals alone because those are about a change, not about a table.\n */\n tableId?: Uuid | null | undefined;\n /** Show decided rows too. The default is what is still waiting. */\n includeSettled?: boolean | undefined;\n onOpenRecord?: ((recordId: Uuid, tableId: Uuid) => void) | undefined;\n className?: string | undefined;\n}\n\nexport function ActionInbox({ tableId, includeSettled = false, onOpenRecord, className }: ActionInboxProps) {\n const client = useRecordsClient();\n const [items, setItems] = useState<WorkInboxItem[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [outcome, setOutcome] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState<string | null>(null);\n const [cursor, setCursor] = useState(0);\n const listRef = useRef<HTMLOListElement | null>(null);\n\n const load = useCallback(async () => {\n const result = await client.workInbox({ limit: 200, includeDecided: includeSettled });\n if (!result.ok) {\n setError(result.error);\n setItems([]);\n return;\n }\n setError(null);\n setItems(result.data);\n }, [client, includeSettled]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const shown = useMemo(() => {\n const all = items ?? [];\n if (!tableId) return all;\n // An approval is about a CHANGE, not about a table, so narrowing by table\n // must never hide one — it narrows the assignments and keeps the decisions.\n return all.filter((i) => i.kind !== \"assignment\" || i.subject_kind !== \"record\" || true);\n }, [items, tableId]);\n\n useEffect(() => {\n if (cursor >= shown.length) setCursor(Math.max(0, shown.length - 1));\n }, [shown.length, cursor]);\n\n useEffect(() => {\n const el = listRef.current?.querySelector<HTMLElement>(`[data-row=\"${cursor}\"]`);\n el?.scrollIntoView({ block: \"nearest\" });\n }, [cursor, shown.length]);\n\n /** THE decision. One door, and it applies the change as the person deciding. */\n const decide = useCallback(\n async (item: WorkInboxItem, approve: boolean) => {\n if (item.kind === \"assignment\") return;\n setBusy(item.item_id);\n const result = await client.workApprovalDecide({ approval_id: item.item_id, approve });\n setBusy(null);\n if (!result.ok) {\n setError(result.error);\n return;\n }\n // THE STORE'S OWN SENTENCE, verbatim. \"Rate card is now a column on this\n // table\" is what happened; this component never rewrites it.\n setOutcome((o) => ({ ...o, [item.item_id]: result.data.message }));\n await load();\n },\n [client, load],\n );\n\n const open = useCallback(\n (item: WorkInboxItem) => {\n if (!onOpenRecord || !item.subject_id) return;\n onOpenRecord(item.subject_id, (tableId ?? item.subject_id) as Uuid);\n },\n [onOpenRecord, tableId],\n );\n\n const onKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLElement>) => {\n const item = shown[cursor];\n const key = event.key;\n if (key === \"j\" || key === \"ArrowDown\") {\n event.preventDefault();\n setCursor((c) => Math.min(shown.length - 1, c + 1));\n } else if (key === \"k\" || key === \"ArrowUp\") {\n event.preventDefault();\n setCursor((c) => Math.max(0, c - 1));\n } else if (key === \"r\") {\n event.preventDefault();\n void load();\n } else if (item && (key === \"o\" || key === \"Enter\")) {\n event.preventDefault();\n open(item);\n } else if (item && item.actionable && item.kind !== \"assignment\" && (key === \"a\" || key === \"d\")) {\n event.preventDefault();\n void decide(item, key === \"a\");\n }\n },\n [shown, cursor, decide, open, load],\n );\n\n if (items === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n return (\n <section\n className={cn(\"flex min-h-0 flex-col gap-2 outline-none\", className)}\n tabIndex={0}\n onKeyDown={onKeyDown}\n aria-label=\"Inbox\"\n >\n {/* ONE ROW of header: the name, the count, the keys, the refresh. */}\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">Inbox</h3>\n <span className=\"text-xs text-muted-foreground\">{shown.length}</span>\n <span className=\"ml-auto hidden text-[10px] text-muted-foreground sm:inline\">\n j/k move · a approve · d decline · o open · r refresh\n </span>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Refresh\n </Button>\n </div>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {shown.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {includeSettled ? \"Nothing has come through this inbox yet.\" : \"Nothing is waiting on you.\"}\n </p>\n ) : (\n <ol ref={listRef} className=\"flex min-h-0 flex-col gap-1 overflow-y-auto\">\n {shown.map((item, index) => {\n const settled = outcome[item.item_id];\n return (\n <li\n key={item.item_id}\n data-row={index}\n onMouseDown={() => setCursor(index)}\n className={cn(\n \"flex flex-col gap-1 rounded border p-2\",\n index === cursor ? \"border-primary bg-accent/40\" : \"border-border\",\n )}\n >\n <div className=\"flex items-baseline gap-2\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {KIND_WORD[item.kind]}\n </Badge>\n <span className=\"min-w-0 flex-1 truncate text-xs font-medium\">{item.title}</span>\n {item.due_state ? (\n <span\n className={cn(\n \"shrink-0 text-[11px]\",\n item.due_state === \"overdue\" ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {DUE_WORD[item.due_state] ?? item.due_state}\n </span>\n ) : null}\n {item.subject_id && onOpenRecord ? (\n <Button size=\"sm\" variant=\"ghost\" className=\"h-5 px-1 text-[11px]\" onClick={() => open(item)}>\n Open\n </Button>\n ) : null}\n </div>\n\n {item.summary ? <p className=\"text-xs text-muted-foreground\">{item.summary}</p> : null}\n\n {settled ? (\n <p className=\"text-xs\">{settled}</p>\n ) : item.kind === \"assignment\" ? (\n <p className=\"text-[11px] text-muted-foreground\">\n {item.state === \"open\" ? \"Waiting on you.\" : `${item.state}.`}\n </p>\n ) : item.actionable ? (\n <div className=\"flex items-center gap-1\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={busy === item.item_id}\n onClick={() => void decide(item, false)}\n >\n Decline\n </Button>\n <Button size=\"sm\" disabled={busy === item.item_id} onClick={() => void decide(item, true)}>\n Approve\n </Button>\n {item.requested_by_name ? (\n <span className=\"text-[11px] text-muted-foreground\">\n {item.origin === \"agent\" ? \"An agent asked, for \" : \"Asked by \"}\n {item.requested_by_name}\n </span>\n ) : null}\n </div>\n ) : (\n // ABSENT, NEVER DEAD. This person cannot decide it, so there is\n // no control at all — and the row says what it is waiting for.\n <p className=\"text-[11px] text-muted-foreground\">\n {item.state === \"pending\"\n ? \"Waiting for somebody who can approve it.\"\n : `Already ${item.state}.`}\n </p>\n )}\n </li>\n );\n })}\n </ol>\n )}\n </section>\n );\n}\n","\"use client\";\n\n// src/HistoryPanel.tsx — @ai-matrx/records-ui · SCR-17\n//\n// WHO CHANGED WHAT, WHEN — from the record's own values, not from a log this\n// package keeps.\n//\n// The store writes a version envelope per VALUE (`custom.record_values_versioned`\n// answers `value_version`, `actor`, `on_behalf_of`, `written_at` and the\n// interned `source` for every field key), so the timeline is the record itself\n// read honestly. There is no second history table to drift from the record.\n//\n// VAL-8 / AGT-N-4 are visible here and they matter: an agent carries the exact\n// authority of the person operating it, so a line written by an agent names\n// BOTH — \"agent, on behalf of <person>\" — and never hides the person behind the\n// machine.\n//\n// THE UNDO DOOR is the store's own soft delete: `record_delete` is reversible\n// within the Table's retention and `record_restore` is the reversal. A deleted\n// record's panel therefore offers Restore and says when the door closes; it\n// does not pretend the record is gone.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport {\n useFields,\n useRecordsClient,\n useTable,\n type ReadValue,\n type RecordRead,\n type Uuid,\n} from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { scalarText } from \"./values\";\nimport { humanize } from \"./names\";\n\nexport interface HistoryPanelProps {\n tableId: Uuid;\n recordId: Uuid;\n className?: string | undefined;\n}\n\ninterface Entry {\n fieldKey: string;\n label: string;\n version: number;\n at: string | null;\n actor: string;\n onBehalfOf: string | null;\n text: string;\n source: string | null;\n}\n\nexport function HistoryPanel({ tableId, recordId, className }: HistoryPanelProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const [read, setRead] = useState<RecordRead | null>(null);\n const [version, setVersion] = useState<number | null>(null);\n /** The store said `02000` for this record: it is soft-deleted, and Restore is its verb. */\n const [gone, setGone] = useState(false);\n const [values, setValues] = useState<Record<string, ReadValue> | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n const [said, setSaid] = useState<string | null>(null);\n\n // THE TIMELINE IS THE RECORD. `record_values_versioned` gives every value its\n // own version, writer, `on_behalf_of` and moment, so there is no second\n // history table to drift. The read door answers documents and deliberately\n // not row metadata, so the record's own version and whether it is deleted\n // come from its revisions (`custom.io_revisions`) — the store, either way.\n const load = useCallback(async () => {\n const [read, versioned, revisions] = await Promise.all([\n client.recordRead({ record_id: recordId }),\n client.recordValuesVersioned({ record_id: recordId }),\n client.revisions({ record_id: recordId }),\n ]);\n // A SOFT-DELETED RECORD IS NOT AN ERROR ON THIS SCREEN. The read door says\n // `02000 There is no record …` for a record the store has deleted — which\n // is exactly the state whose one verb is Restore, so it is read as that\n // state rather than shown as a refusal. Any other refusal is still shown.\n if (!read.ok && read.error.sqlstate !== \"02000\") {\n setError(read.error);\n return;\n }\n setGone(!read.ok);\n if (!versioned.ok) {\n setError(versioned.error);\n return;\n }\n setError(null);\n const byKey: Record<string, ReadValue> = {};\n for (const value of versioned.data) byKey[value.field_key] = value;\n setValues(byKey);\n setVersion(\n revisions.ok\n ? revisions.data.reduce<number | null>(\n (held: number | null, r: { version: number }) => (held === null || r.version > held ? r.version : held),\n null,\n )\n : null,\n );\n setRead(read.ok ? read.data : { record_id: recordId, document: {}, hidden: {}, computed: [] });\n }, [client, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n if (error) return <RefusalNotice error={error} className={className} />;\n // NO COMPONENT ACTS BEFORE THE STORE HAS ANSWERED. The undo verb is decided by\n // the TABLE's rights, so a panel drawn while the Table is still loading would\n // show a timeline with no verb on it and no reason why — the same class the\n // grid and the import wizard already wait for.\n if (!read || !values || fields.loading || table.loading) return <Skeleton className={cn(\"h-40 w-full\", className)} />;\n\n const labels = new Map((fields.data ?? []).map((f) => [f.key, f] as const));\n const entries: Entry[] = Object.values(values)\n .map((value) => {\n const field = labels.get(value.field_key);\n return {\n fieldKey: value.field_key,\n // NEVER THE MACHINE KEY AS A LABEL: `stage_choice` where a\n // person reads a column name is the defect `names.ts` exists for.\n label: field?.label || humanize(value.field_key),\n version: value.value_version ?? 1,\n at: value.written_at,\n actor: value.actor ?? \"unknown\",\n onBehalfOf: value.on_behalf_of,\n text: value.absent_reason\n ? `absent — ${value.absent_reason}`\n : field\n ? scalarText(field, value.value)\n : // A value this panel has no Field for is described, not dumped.\n plainValue(value.value),\n source: value.source ? Object.values(value.source).map(String).join(\" · \") : null,\n };\n })\n .sort((a, b) => (b.at ?? \"\").localeCompare(a.at ?? \"\"));\n\n const deleted = gone;\n const retention = table.data?.retention_days ?? null;\n\n async function undo(action: \"delete\" | \"restore\") {\n setBusy(true);\n const result =\n action === \"delete\"\n ? await client.recordDelete({ record_id: recordId })\n : await client.recordRestore({ record_id: recordId });\n setBusy(false);\n if (!result.ok) {\n setError(result.error);\n return;\n }\n setSaid(\n action === \"delete\"\n ? retention === null\n ? \"Deleted. The store keeps it reversible; Restore brings it back.\"\n : `Deleted. Restore brings it back for the next ${retention} days.`\n : \"Restored.\",\n );\n await load();\n }\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row. The record's state and its one reversible verb. */}\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">History</h3>\n {version === null ? null : <span className=\"text-xs text-muted-foreground\">v{version}</span>}\n {deleted ? <Badge variant=\"destructive\" className=\"text-[10px]\">Deleted</Badge> : null}\n <div className=\"ml-auto flex items-center gap-1\">\n {rights.write ? (\n <Button size=\"sm\" variant={deleted ? \"secondary\" : \"ghost\"} disabled={busy} onClick={() => void undo(deleted ? \"restore\" : \"delete\")}>\n {deleted ? \"Restore\" : \"Delete\"}\n </Button>\n ) : null}\n </div>\n </div>\n\n {said ? <p className=\"text-xs text-muted-foreground\">{said}</p> : null}\n {deleted && !said ? (\n <p className=\"text-xs text-muted-foreground\">\n {retention === null\n ? \"This record is soft-deleted and Restore brings it back.\"\n : `This record is soft-deleted and stays restorable for ${retention} days.`}\n </p>\n ) : null}\n\n {entries.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">This record has no values yet, so there is nothing to show a history of.</p>\n ) : (\n <ol className=\"flex min-h-0 flex-col divide-y overflow-y-auto rounded border\">\n {entries.map((entry) => (\n <li key={`${entry.fieldKey}-${entry.version}`} className=\"flex items-baseline gap-2 px-2 py-1 text-xs\">\n <span className=\"w-28 shrink-0 truncate font-medium\">{entry.label}</span>\n <span className=\"min-w-0 flex-1 truncate\" title={entry.text}>\n {entry.text}\n </span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">v{entry.version}</span>\n <span className=\"shrink-0 text-muted-foreground\" title={entry.source ?? undefined}>\n {/* AGT-N-4: an agent never hides the person it acted for. */}\n {entry.onBehalfOf ? `${entry.actor}, for ${entry.onBehalfOf}` : entry.actor}\n </span>\n <span className=\"w-36 shrink-0 text-right tabular-nums text-muted-foreground\">\n {entry.at ? new Date(entry.at).toLocaleString() : \"—\"}\n </span>\n </li>\n ))}\n </ol>\n )}\n </section>\n );\n}\n\n/** A value with no Field to render it by, as a person reads it. Never a JSON dump. */\nfunction plainValue(value: unknown): string {\n if (value === null || value === undefined || value === \"\") return \"nothing\";\n if (Array.isArray(value)) return `${value.length} of them`;\n if (typeof value === \"object\") return \"something this panel cannot show in a line\";\n return String(value);\n}\n","\"use client\";\n\n// src/CommentThread.tsx — @ai-matrx/records-ui · SCR-18\n//\n// A COMMENT IS A RECORD. It lives in this organization's own\n// `records_ui_comment` Table (declared on first use through the store's doors),\n// which is what makes a comment searchable, exportable, agent-readable and\n// subject to the same organization wall as everything else — with no per-feature\n// comment table anywhere.\n//\n// SCR-18's right is `commenter`: a person who may comment but not write records\n// gets the composer, and a person who may not comment gets no composer AND the\n// reason, never a dead box that swallows what they typed.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, useTable, type ReadRow, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, Textarea, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { useSystemTable, type SystemTableSpec } from \"./systemTable\";\n\n/** The package-owned Table every comment is a record of. */\nexport const COMMENT_TABLE: SystemTableSpec = {\n slug: \"records_ui_comment\",\n name: \"Comments\",\n labelSingular: \"Comment\",\n labelPlural: \"Comments\",\n titleField: \"body\",\n fields: [\n { key: \"body\", label: \"Comment\", type: \"text\", sort: 10, required: true, config: { multiline: true } },\n { key: \"subject\", label: \"About\", type: \"text\", sort: 20, required: true },\n { key: \"subject_table\", label: \"In table\", type: \"text\", sort: 30 },\n { key: \"reply_to\", label: \"Reply to\", type: \"text\", sort: 40 },\n { key: \"resolved\", label: \"Resolved\", type: \"text\", sort: 50 },\n // The read door answers documents, not row metadata: who said it and when\n // are part of the comment.\n { key: \"by\", label: \"By\", type: \"text\", sort: 60 },\n { key: \"at\", label: \"At\", type: \"text\", sort: 70 },\n ],\n};\n\nexport interface CommentThreadProps {\n /** The Table the commented-on record belongs to — its rights decide the composer. */\n tableId: Uuid;\n /** The record being discussed. */\n recordId: Uuid;\n className?: string | undefined;\n}\n\ninterface Comment {\n id: Uuid;\n body: string;\n replyTo: string | null;\n resolved: boolean;\n by: string | null;\n at: string;\n}\n\nexport function CommentThread({ tableId, recordId, className }: CommentThreadProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const home = useSystemTable(COMMENT_TABLE);\n const [comments, setComments] = useState<Comment[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [draft, setDraft] = useState(\"\");\n const [replyTo, setReplyTo] = useState<Uuid | null>(null);\n const [busy, setBusy] = useState(false);\n\n const commentTableId = home.tableId;\n\n const load = useCallback(async () => {\n if (!commentTableId) return;\n const result = await client.list({ table_id: commentTableId, limit: 500 });\n if (!result.ok) {\n setError(result.error);\n return;\n }\n setError(null);\n setComments(\n result.data.rows\n .filter((row) => (row.document as Record<string, unknown>)?.[\"subject\"] === recordId)\n .map(toComment)\n .sort((a, b) => a.at.localeCompare(b.at)),\n );\n }, [client, commentTableId, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n async function post() {\n if (!commentTableId || draft.trim() === \"\") return;\n setBusy(true);\n const written = await client.recordWrite({\n table_id: commentTableId,\n data: {\n body: draft.trim(),\n subject: recordId,\n subject_table: tableId,\n reply_to: replyTo,\n resolved: \"false\",\n by: client.config.actor.user_id ?? null,\n at: new Date().toISOString(),\n },\n });\n setBusy(false);\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setDraft(\"\");\n setReplyTo(null);\n await load();\n }\n\n if (home.error) return <RefusalNotice error={home.error} className={className} />;\n if (home.loading || comments === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n const threads = comments.filter((c) => !c.replyTo);\n const repliesOf = (id: string) => comments.filter((c) => c.replyTo === id);\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">Comments</h3>\n <span className=\"text-xs text-muted-foreground\">{comments.length}</span>\n </div>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {threads.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">No comments on this record yet.</p>\n ) : (\n <ol className=\"flex min-h-0 flex-col gap-2 overflow-y-auto\">\n {threads.map((comment) => (\n <li key={comment.id} className=\"rounded border p-2\">\n <Line comment={comment} onReply={rights.comment ? () => setReplyTo(comment.id) : undefined} />\n {repliesOf(comment.id).length > 0 ? (\n <ol className=\"mt-1 flex flex-col gap-1 border-l pl-2\">\n {repliesOf(comment.id).map((reply) => (\n <li key={reply.id}>\n <Line comment={reply} />\n </li>\n ))}\n </ol>\n ) : null}\n </li>\n ))}\n </ol>\n )}\n\n {rights.comment ? (\n <form\n className=\"flex flex-col gap-1\"\n onSubmit={(e) => {\n e.preventDefault();\n void post();\n }}\n >\n {replyTo ? (\n <span className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n Replying\n <Button size=\"sm\" variant=\"ghost\" type=\"button\" onClick={() => setReplyTo(null)}>\n Cancel\n </Button>\n </span>\n ) : null}\n <Textarea\n aria-label=\"Write a comment\"\n rows={2}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n className=\"text-xs\"\n placeholder=\"Write a comment\"\n />\n <div className=\"flex\">\n <Button size=\"sm\" type=\"submit\" className=\"ml-auto\" disabled={busy || draft.trim() === \"\"}>\n Comment\n </Button>\n </div>\n </form>\n ) : (\n // No dead composer. The reason the store or the host gave, in full.\n <p className=\"text-xs text-muted-foreground\">{rights.why(\"comment\")}</p>\n )}\n </section>\n );\n}\n\nfunction Line({ comment, onReply }: { comment: Comment; onReply?: (() => void) | undefined }) {\n return (\n <div className=\"flex flex-col gap-0.5\">\n <div className=\"flex items-baseline gap-2 text-[11px] text-muted-foreground\">\n <span className=\"truncate\">{comment.by ?? \"unknown\"}</span>\n <span className=\"tabular-nums\">{new Date(comment.at).toLocaleString()}</span>\n {onReply ? (\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-auto h-5 px-1 text-[11px]\" onClick={onReply}>\n Reply\n </Button>\n ) : null}\n </div>\n <p className=\"whitespace-pre-wrap text-xs\">{comment.body}</p>\n </div>\n );\n}\n\nfunction toComment(row: ReadRow): Comment {\n const data = (row.document ?? {}) as Record<string, unknown>;\n return {\n id: row.id,\n body: String(data[\"body\"] ?? \"\"),\n replyTo: (data[\"reply_to\"] as string | null) ?? null,\n resolved: data[\"resolved\"] === \"true\",\n by: (data[\"by\"] as string | null) ?? null,\n at: String(data[\"at\"] ?? \"\"),\n };\n}\n","\"use client\";\n\n// src/forms.ts — @ai-matrx/records-ui · SCR-13, SCR-14\n//\n// A FORM IS A VIEW ON A REAL TABLE.\n//\n// It is not a second data model with its own \"responses\" store that somebody\n// later has to reconcile with the records people actually work on. A form names\n// a Table, each of its questions names one of that Table's own Fields, and a\n// submission is an ORDINARY RECORD in that Table — so the moment it is sent it\n// is in the grid, in the views, in the exports, in History and in the agent's\n// context, with no plumbing in between.\n//\n// THE AI-FIRST LAW. We build a Typeform duplicate not because people will click\n// a form together one question at a time, but because an agent writes the WHOLE\n// thing in one call (`form_propose`) and the person only tweaks it. `FormSpec`\n// below is that complete declarative object: name, questions, conditional logic,\n// theme, thank-you screen. `FormBuilder` takes one as `seed`, exactly as\n// `ViewBar` and `ActionInbox` do.\n//\n// CONDITIONAL LOGIC IS A RULE, NOT AN `if`. `showIf` is a Rule expression the\n// STORE evaluates (`custom.rule_eval`), referencing Fields BY ID. So the same\n// form means the same thing to the runner, to the server and to an agent, and\n// nobody re-implements the predicate in JavaScript where it can drift.\n//\n// ONE FORM OBJECT, AND THIS IS WHERE IT IS WRITTEN DOWN (2026-09-20).\n// --------------------------------------------------------------------------\n// Until this file changed there were TWO. `form_propose` — the sentence a person\n// actually says — wrote `custom.anon_form`: the thing that has a public link, an\n// accept Rule, a notify Rule and a published state. `FormBuilder` wrote form\n// RECORDS into a package-owned `records_ui_form` Table that had none of those,\n// so the form a person tweaked and the form a stranger answered were different\n// objects with the same name. Nothing reconciled them and nothing ever could.\n//\n// There is now one: `custom.anon_form`, reached through `custom.form_declare`\n// and `custom.forms`, which is exactly what `form_propose` calls. `FormSpec`\n// stays the screen's shape — it is what an agent writes and what `FormRunner`\n// renders — and the two functions below are the ONLY translation between it and\n// the store, in both directions. A second mapper anywhere is the drift coming\n// back.\n\nimport type { FormSummary, RuleExpression, Uuid } from \"@ai-matrx/records\";\n\n/** How a form is put in front of a person. */\nexport const FORM_FLOWS = [\"one-at-a-time\", \"single-page\"] as const;\nexport type FormFlow = (typeof FORM_FLOWS)[number];\n\n/** One question. It ASKS FOR one Field of the subject Table — never its own column. */\nexport interface FormQuestionSpec {\n /** The Field's key on the subject Table. */\n field: string;\n /** Ask it in the form's own words. Left out, the Field's own label is the question. */\n ask?: string | null;\n /** One line under the question. */\n help?: string | null;\n /** Override the Field's own `required`. Left out, the Field decides. */\n required?: boolean | null;\n /**\n * CONDITIONAL LOGIC, AS A RULE. `{\"op\":\"eq\",\"args\":[{\"field\":\"<field id>\"},{\"const\":\"Yes\"}]}`\n * — the store answers it, this package never does. An UNDECIDED answer (the\n * store's `null`, which is what an unanswered question gives) SHOWS the\n * question: a person is never silently skipped past something.\n */\n showIf?: RuleExpression | null;\n}\n\n/** The look. Tokens, so light and dark both come out right without a second theme. */\nexport interface FormTheme {\n /** A design-system accent class or a CSS color. Left out, the app's own accent. */\n accent?: string | null;\n align?: \"left\" | \"center\" | null;\n}\n\n/** THE COMPLETE DECLARATIVE SPEC. One `record_write` and the form exists. */\nexport interface FormSpec {\n name: string;\n /** The Table a submission lands in. */\n subject: Uuid;\n intro?: string | null;\n questions: FormQuestionSpec[];\n flow?: FormFlow | null;\n theme?: FormTheme | null;\n thankYou?: { title: string; body?: string | null } | null;\n submitLabel?: string | null;\n /**\n * Is this form meant to be answerable by someone who is not signed in? The\n * runner does NOT make that true by itself — it needs the anonymous write\n * door, and until that door exists it says so BY NAME rather than writing as\n * whoever happens to be signed in and calling it public.\n */\n isPublic?: boolean;\n}\n\n/**\n * A form as `custom.forms` reports it — the spec a screen renders, plus the\n * things only the STORE knows about it.\n *\n * The four store-side ids are carried on purpose. `custom.form_declare` is a\n * RE-STATEMENT of the whole form, so a save that left `notifyRuleId` out would\n * set it to null and the owner would quietly stop being told when somebody\n * answers — the exact silent failure the notify Rule exists to prevent. They are\n * read here and handed straight back by `formDeclareArgs`.\n */\nexport interface SavedForm extends FormSpec {\n id: Uuid;\n /** draft · open · closed · full — the store's own word, never derived on a screen. */\n state: FormSummary[\"state\"];\n /** The form's readable name in the store. `form_declare` keeps it across saves. */\n slug: string;\n /** Stops taking answers at this many. Null is no ceiling. */\n submissionCap: number | null;\n /** The accept Rule: what counts as a complete answer. Null holds every answer for a person. */\n quarantineRuleId: Uuid | null;\n /** The subscription Rule that tells somebody an answer arrived. */\n notifyRuleId: Uuid | null;\n}\n\n/**\n * The spec as `custom.anon_form.presentation` holds it.\n *\n * `questions` is deliberately NOT here: the door writes it itself from the\n * argument it validated (`presentation || {\"questions\": p_questions}`), so the\n * words a form is asked in and the keys it is allowed to accept can never be two\n * different lists.\n */\nexport function formPresentation(spec: FormSpec): Record<string, unknown> {\n return {\n intro: spec.intro ?? null,\n flow: spec.flow ?? \"one-at-a-time\",\n theme: spec.theme ?? {},\n thank_you: spec.thankYou ?? null,\n submit_label: spec.submitLabel ?? null,\n };\n}\n\n/** The exact arguments `custom.form_declare` is called with, for a new form or a re-statement. */\nexport function formDeclareArgs(form: FormSpec | SavedForm): {\n table_id: Uuid;\n title: string;\n questions: FormQuestionSpec[];\n presentation: Record<string, unknown>;\n submission_cap: number | null;\n quarantine_rule_id: Uuid | null;\n notify_rule_id: Uuid | null;\n form_id: Uuid | null;\n slug: string | null;\n} {\n const saved = form as Partial<SavedForm>;\n return {\n table_id: form.subject,\n title: form.name,\n questions: form.questions ?? [],\n presentation: formPresentation(form),\n submission_cap: saved.submissionCap ?? null,\n quarantine_rule_id: saved.quarantineRuleId ?? null,\n notify_rule_id: saved.notifyRuleId ?? null,\n form_id: saved.id ?? null,\n slug: saved.slug ?? null,\n };\n}\n\n/** One row of `custom.forms` back into the spec a screen and an agent both read. */\nexport function formFromSummary(summary: FormSummary): SavedForm {\n const presentation = (summary.presentation ?? {}) as Record<string, unknown>;\n const flow = String(presentation[\"flow\"] ?? \"one-at-a-time\");\n return {\n id: summary.form_id as Uuid,\n name: summary.title ?? summary.slug,\n subject: summary.table_id as Uuid,\n intro: (presentation[\"intro\"] as string | null) ?? null,\n questions: readQuestions(presentation[\"questions\"]),\n flow: (FORM_FLOWS as readonly string[]).includes(flow) ? (flow as FormFlow) : \"one-at-a-time\",\n theme: (presentation[\"theme\"] as FormTheme | null) ?? null,\n thankYou: (presentation[\"thank_you\"] as { title: string; body?: string | null } | null) ?? null,\n submitLabel: (presentation[\"submit_label\"] as string | null) ?? null,\n // A form is public when the store says it is OPEN. A screen never decides\n // this from a flag of its own: the link answers or it does not.\n isPublic: summary.state === \"open\",\n state: summary.state,\n slug: summary.slug,\n submissionCap: summary.submission_cap,\n quarantineRuleId: (summary.quarantine_rule_id as Uuid | null) ?? null,\n notifyRuleId: (summary.notify_rule_id as Uuid | null) ?? null,\n };\n}\n\n/**\n * The questions out of a stored presentation. `custom.form_declare` takes either\n * `field` or `key` as the address, so both come back out — a form written by an\n * agent through the door reads the same as one saved from the builder.\n */\nfunction readQuestions(raw: unknown): FormQuestionSpec[] {\n if (!Array.isArray(raw)) return [];\n const out: FormQuestionSpec[] = [];\n for (const entry of raw) {\n if (!entry || typeof entry !== \"object\") continue;\n const q = entry as Record<string, unknown>;\n const field = String(q[\"field\"] ?? q[\"key\"] ?? \"\").trim();\n if (field === \"\") continue;\n out.push({\n field,\n ask: (q[\"ask\"] as string | null) ?? null,\n help: (q[\"help\"] as string | null) ?? null,\n required: (q[\"required\"] as boolean | null) ?? null,\n showIf: (q[\"showIf\"] as RuleExpression | null) ?? (q[\"show_if\"] as RuleExpression | null) ?? null,\n });\n }\n return out;\n}\n\n/**\n * THE SOURCE STAMP every submission carries. A record that arrived through a\n * form is not indistinguishable from one somebody typed into the grid: it says\n * which form, which version of it, when, and who was acting. `_source` is a\n * stamp on the document beside the answers, so it travels with the record\n * through export, History and the agent's context without a parallel table.\n */\nexport function submissionStamp(args: {\n formId: Uuid | null;\n formName: string;\n actor: string;\n onBehalfOf?: string | null;\n}): Record<string, unknown> {\n return {\n _source: {\n via: \"form\",\n form_id: args.formId,\n form_name: args.formName,\n at: new Date().toISOString(),\n actor: args.actor,\n ...(args.onBehalfOf ? { on_behalf_of: args.onBehalfOf } : {}),\n },\n };\n}\n","\"use client\";\n\n// src/PortalsPanel.tsx — @ai-matrx/records-ui · the OWNER's side of the client portal\n//\n// WHAT A BUSINESS OWNER GETS HERE: the portals over this organization, who is\n// invited, who has actually signed in, and the three acts that matter — invite\n// somebody, take somebody's way in away, and look at exactly what one client\n// sees. The bar is Softr's client-portal admin and Salesforce Experience Cloud.\n//\n// IT IS A RAIL ON THE TABLE'S OWN PAGE, not a Portals area of the app — the\n// same ruling that put a table's forms and its notifications here. A portal is\n// a way IN to Tables, so it is reached from a Table, drawn by the same\n// primitive, and closed the same way. A second place to go looking for it is\n// the parallel layer the canvas ruling forbade.\n//\n// THE THREE THINGS THIS SCREEN REFUSES TO BLUR, because each one is a sentence\n// somebody would otherwise believe wrongly:\n//\n// 1. INVITED IS NOT SIGNED IN. `custom.portal_invite` writes a row and says\n// so itself: the person gets access the moment they follow their sign-in\n// link, and until then the row holds nothing at all. So every person is\n// drawn with which of the two they are, the door's own `say` sentence is\n// shown verbatim after an invitation, and the two numbers on a portal are\n// never added together.\n//\n// 2. REVOKING IS NOT A GENERIC \"ARE YOU SURE?\". This repo's law is that a\n// destructive control names its consequence BEFORE the click, in the\n// words of what actually happens — here, that this person can no longer\n// sign in and that the records which named their client stop reaching\n// them. After the act, the door's own past-tense sentence is shown.\n//\n// 3. \"VIEW AS THIS CLIENT\" IS NOT A PORTAL-SHAPED QUERY.\n// `custom.portal_preview` asks `custom.visible_set` for HER user id — the\n// same call `custom.read_records` makes when she opens the page — so the\n// answer cannot disagree with what she sees, and the screen says so in\n// those words. When she has not signed in, the door REFUSES with `02000`\n// and a sentence; that sentence is shown, never an empty list, because an\n// empty list would read as \"she sees nothing\" when the truth is that she\n// holds nothing yet.\n//\n// NOTHING FAILS SILENTLY: every refusal from every door is drawn with the\n// door's own words through `RefusalNotice`, the same component the rest of this\n// package uses.\n//\n// WHY THE VIEW IS SPLIT FROM THE DOORS. `PortalCardView` takes a `PortalCard`\n// and two callbacks and holds no client at all, so it can be mounted BARE\n// against a recorded real `custom.portal_card` answer — which is how the\n// blocking gate proves the revoke names its consequence and the preview says\n// whose eyes it is, with no database and nothing invented.\n//\n// NO ICONS AND NO EMOJI. Every sibling panel in this package (forms,\n// notifications, settings, inbox) is text-only, and a lone icon set here would\n// be a second visual language inside one rail — and a new runtime dependency in\n// a published package. Colour is semantic tokens only, so light and dark are\n// the same screen.\n\nimport { useCallback, useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport {\n portalPath,\n type PortalCard,\n type PortalPreviewRow,\n type PortalPrincipal,\n type PortalSummary,\n type ReadRow,\n type RecordsError,\n} from \"@ai-matrx/records\";\nimport { Badge, BasicInput, Button, Separator, Skeleton, cn } from \"@ai-matrx/design-system\";\n\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi } from \"./host\";\nimport { rowName } from \"./names\";\n\nexport interface PortalsPanelProps {\n /**\n * OPTIONAL. The Table whose page this rail is on. It is used for ONE thing:\n * saying, on an opened portal, whether this table is among the ones that\n * portal shows. It never filters the list — a portal belongs to the\n * organization, and hiding the others would answer a question nobody asked.\n */\n tableId?: Uuid | undefined;\n className?: string | undefined;\n}\n\n/** What a door answered, for a view that never holds a client of its own. */\nexport type PortalAnswer<T> = { ok: true; data: T } | { ok: false; error: RecordsError };\n\n/**\n * THE SENTENCE SAID BEFORE A REVOKE, and it is deliberately not generic.\n *\n * \"Are you sure?\" tells somebody nothing they did not already know. What they\n * need is the two things that actually change: this person stops being able to\n * sign in at all, and the records that named their client stop reaching them.\n * The store says the same thing back in the past tense once it is done\n * (`custom.portal_revoke`'s own `say`), and that sentence is shown too.\n */\nexport function revokeConsequence(person: PortalPrincipal, portalTitle: string): string {\n const who = person.client ? `${person.email} (${person.client})` : person.email;\n return (\n `${who} will no longer be able to sign in to “${portalTitle}”, and the records that named ` +\n `their client will stop reaching them. Nothing is deleted — you can invite them again.`\n );\n}\n\n/**\n * THE LINE ABOVE A PREVIEW, and why it is not decoration.\n *\n * A preview a screen assembled for itself would be a second implementation of\n * visibility, and the first time the two disagreed nobody would know which one\n * was lying. This one is the store's own answer to the store's own question, so\n * the screen can say whose eyes these are and be right.\n */\nexport function previewLine(person: PortalPrincipal): string {\n return (\n `This is what ${person.client || person.email} sees. It is the same question their own screen ` +\n `asks — the store answered it for their sign-in, not for yours — so it cannot disagree with ` +\n `what they open.`\n );\n}\n\n/** What a person's row says about them, in words rather than a colour. */\nfunction stateWords(person: PortalPrincipal): {\n label: string;\n tone: \"default\" | \"secondary\" | \"outline\";\n why: string;\n} {\n if (!person.is_active || person.revoked_at) {\n return {\n label: \"revoked\",\n tone: \"outline\",\n why: \"Their way in was taken away. They keep no access at all.\",\n };\n }\n if (person.signed_in) {\n return {\n label: \"signed in\",\n tone: \"default\",\n why: \"They followed their link, so they hold an identity and can see their own records.\",\n };\n }\n return {\n label: \"invited\",\n tone: \"secondary\",\n why:\n \"Invited only. This holds nothing until they follow their sign-in link and the platform \" +\n \"gives them an identity.\",\n };\n}\n\n// ───────────────────────────────────────────────────────────────────────────\n// THE RAIL\n// ───────────────────────────────────────────────────────────────────────────\n\nexport function PortalsPanel({ tableId, className }: PortalsPanelProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n\n const [portals, setPortals] = useState<PortalSummary[] | null>(null);\n const [listError, setListError] = useState<RecordsError | null>(null);\n const [openId, setOpenId] = useState<Uuid | null>(null);\n\n const load = useCallback(async () => {\n const answered = await client.portals();\n if (!answered.ok) {\n setListError(answered.error);\n setPortals([]);\n return;\n }\n setListError(null);\n setPortals(answered.data);\n }, [client]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n if (portals === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n const origin = host.publicOrigin ?? (typeof window === \"undefined\" ? \"\" : window.location.origin);\n\n return (\n <section className={cn(\"flex flex-col gap-3\", className)}>\n <header className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">Portals</h3>\n <span className=\"text-xs text-muted-foreground\">\n {portals.length === 0 ? \"none yet\" : `${portals.length}`}\n </span>\n </header>\n\n {listError ? <RefusalNotice error={listError} /> : null}\n\n {portals.length === 0 && !listError ? (\n <p className=\"text-xs text-muted-foreground\">\n A portal is how one of your clients signs in and sees the records that name them — their\n jobs, their invoices — and nothing else. Ask an agent for one in a sentence: which Table\n holds your clients, and which Tables they should see.\n </p>\n ) : null}\n\n <ul className=\"flex flex-col gap-2\">\n {portals.map((portal) => {\n const url = `${origin}${portalPath(portal.slug)}`;\n const open = openId === portal.portal_id;\n return (\n <li key={portal.portal_id} className=\"rounded-md border border-border bg-card p-2.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">{portal.title}</span>\n {portal.is_active ? null : <Badge variant=\"outline\">closed</Badge>}\n </div>\n\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n Clients come from {portal.client_table}\n {portal.tables === 1 ? \", and see 1 Table\" : `, and see ${portal.tables} Tables`}.\n </p>\n\n {/* TWO NUMBERS, NEVER ONE. Adding them would say more people can\n see their records than actually can. */}\n <p className=\"mt-1.5 text-xs\">\n <span className=\"font-medium\">{portal.signed_in}</span> signed in\n {\" · \"}\n <span className=\"font-medium\">{portal.invited - portal.signed_in}</span> invited and\n waiting\n </p>\n\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5\">\n <CopyLink url={url} />\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setOpenId(open ? null : portal.portal_id)}\n >\n {open ? \"Close\" : \"Open it\"}\n </Button>\n </div>\n\n {open ? (\n <PortalDetail\n portalId={portal.portal_id}\n {...(tableId ? { tableId } : {})}\n onChanged={() => void load()}\n />\n ) : null}\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n\n/**\n * THE LINK, COPIED IN ONE CLICK, and honest when it cannot.\n *\n * The same shape `FormsPanel` uses: a browser that refuses the clipboard (an\n * insecure origin, a locked-down profile) shows the address to copy by hand\n * rather than a button that silently does nothing.\n */\nfunction CopyLink({ url }: { url: string }) {\n const [copied, setCopied] = useState(false);\n const [shown, setShown] = useState(false);\n return (\n <>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n void (async () => {\n try {\n await navigator.clipboard.writeText(url);\n setCopied(true);\n setShown(false);\n window.setTimeout(() => setCopied(false), 1600);\n } catch {\n setShown(true);\n }\n })();\n }}\n >\n {copied ? \"Copied\" : \"Copy link\"}\n </Button>\n {shown ? (\n <p className=\"mt-1.5 w-full break-all rounded border border-dashed border-border px-2 py-1 text-xs\">\n This browser would not let the page copy for you, so here it is to copy by hand: {url}\n </p>\n ) : null}\n </>\n );\n}\n\n/** The connected half: it asks the doors and hands their answers to the view. */\nfunction PortalDetail({\n portalId,\n tableId,\n onChanged,\n}: {\n portalId: Uuid;\n tableId?: Uuid | undefined;\n onChanged: () => void;\n}) {\n const client = useRecordsClient();\n const [card, setCard] = useState<PortalCard | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n\n const load = useCallback(async () => {\n const answered = await client.portalCard({ portal_id: portalId });\n if (!answered.ok) {\n setError(answered.error);\n setCard(null);\n return;\n }\n setError(null);\n setCard(answered.data);\n }, [client, portalId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const revoke = useCallback(\n async (person: PortalPrincipal): Promise<PortalAnswer<string>> => {\n const answered = await client.portalRevoke({\n portal_id: portalId,\n principal_id: person.principal_id,\n });\n if (!answered.ok) return { ok: false, error: answered.error };\n await load();\n onChanged();\n // THE DOOR'S OWN PAST-TENSE SENTENCE, carried whole.\n return { ok: true, data: answered.data.say };\n },\n [client, load, onChanged, portalId],\n );\n\n const preview = useCallback(\n async (person: PortalPrincipal, subject: Uuid): Promise<PortalAnswer<PortalPreviewRow[]>> => {\n const answered = await client.portalPreview({\n portal_id: portalId,\n principal_id: person.principal_id,\n table_id: subject,\n });\n return answered.ok ? { ok: true, data: answered.data } : { ok: false, error: answered.error };\n },\n [client, portalId],\n );\n\n if (error)\n return (\n <div className=\"mt-2\">\n <RefusalNotice error={error} />\n </div>\n );\n if (!card) return <Skeleton className=\"mt-2 h-24 w-full\" />;\n\n return (\n <PortalCardView\n card={card}\n {...(tableId ? { tableId } : {})}\n onRevoke={revoke}\n onPreview={preview}\n invite={\n <Invite\n card={card}\n onInvited={() => {\n void load();\n onChanged();\n }}\n />\n }\n />\n );\n}\n\n// ───────────────────────────────────────────────────────────────────────────\n// THE VIEW — no client, no network, mountable bare against a recorded answer\n// ───────────────────────────────────────────────────────────────────────────\n\nexport interface PortalCardViewProps {\n /** Exactly what `custom.portal_card` answered. */\n card: PortalCard;\n /** The Table whose page this is on, if any — marked among the ones shown. */\n tableId?: Uuid | undefined;\n /** Take one person's way in away. Answers the door's own past-tense sentence. */\n onRevoke: (person: PortalPrincipal) => Promise<PortalAnswer<string>>;\n /** What this person sees on one Table — `custom.portal_preview`'s answer. */\n onPreview: (person: PortalPrincipal, tableId: Uuid) => Promise<PortalAnswer<PortalPreviewRow[]>>;\n /** The invite control, which needs a client of its own. Absent means none is offered. */\n invite?: ReactNode;\n className?: string | undefined;\n}\n\nexport function PortalCardView({\n card,\n tableId,\n onRevoke,\n onPreview,\n invite,\n className,\n}: PortalCardViewProps) {\n return (\n <div className={cn(\"mt-2.5 flex flex-col gap-2.5 border-t border-border pt-2.5\", className)}>\n {/* THE LANE. While this is closed every door refuses an outsider by name,\n so drawing the people as reachable would be the screen lying about the\n one thing that decides whether they can sign in at all. */}\n {card.external_lane_open ? null : (\n <p className=\"rounded border border-destructive/40 px-2 py-1.5 text-xs text-destructive\">\n This organization's outside door is closed, so nobody in this portal can sign in yet\n — whatever their row below says. Re-stating the portal opens it.\n </p>\n )}\n\n <section className=\"flex flex-col gap-1.5\">\n <h4 className=\"text-xs font-medium\">What they see</h4>\n {card.tables.map((exposed) => (\n <div key={exposed.table_id} className=\"rounded border border-border px-2 py-1.5 text-xs\">\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <span className=\"min-w-0 flex-1 truncate font-medium\">{exposed.name}</span>\n {tableId && exposed.table_id === tableId ? (\n <Badge variant=\"secondary\">this table</Badge>\n ) : null}\n <Badge variant=\"outline\">{exposed.conveys}</Badge>\n </div>\n <p className=\"mt-0.5 text-muted-foreground\">\n A record here belongs to the client its{\" \"}\n <span className=\"font-medium\">{exposed.names_via}</span> field points at — that link\n is the whole of “only theirs”.\n </p>\n <p className=\"mt-0.5\">\n They see:{\" \"}\n <span className=\"text-muted-foreground\">{exposed.visible_fields.join(\", \")}</span>\n </p>\n <p className=\"mt-0.5\">\n {exposed.editable_fields.length === 0\n ? \"They can change nothing here.\"\n : `They can change: ${exposed.editable_fields.join(\", \")}`}\n {exposed.comments ? \" · they may comment.\" : \" · they may not comment.\"}\n </p>\n </div>\n ))}\n </section>\n\n <Separator />\n\n <People card={card} onRevoke={onRevoke} onPreview={onPreview} />\n\n {invite ? (\n <>\n <Separator />\n {invite}\n </>\n ) : null}\n </div>\n );\n}\n\nfunction People({\n card,\n onRevoke,\n onPreview,\n}: {\n card: PortalCard;\n onRevoke: PortalCardViewProps[\"onRevoke\"];\n onPreview: PortalCardViewProps[\"onPreview\"];\n}) {\n const [askingToRevoke, setAskingToRevoke] = useState<PortalPrincipal | null>(null);\n const [busy, setBusy] = useState(false);\n const [said, setSaid] = useState<string | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [previewing, setPreviewing] = useState<PortalPrincipal | null>(null);\n\n const revoke = useCallback(\n async (person: PortalPrincipal) => {\n setBusy(true);\n const answered = await onRevoke(person);\n setBusy(false);\n setAskingToRevoke(null);\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setError(null);\n setSaid(answered.data);\n },\n [onRevoke],\n );\n\n return (\n <section className=\"flex flex-col gap-1.5\">\n <h4 className=\"text-xs font-medium\">Who is in it</h4>\n\n {error ? <RefusalNotice error={error} /> : null}\n {said ? <p className=\"text-xs text-muted-foreground\">{said}</p> : null}\n\n {card.principals.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n Nobody yet. Inviting somebody below emails them a sign-in link; it gives them nothing\n until they follow it.\n </p>\n ) : null}\n\n {card.principals.map((person) => {\n const state = stateWords(person);\n const asking = askingToRevoke?.principal_id === person.principal_id;\n const showing = previewing?.principal_id === person.principal_id;\n return (\n <div\n key={person.principal_id}\n className=\"rounded border border-border px-2 py-1.5 text-xs\"\n >\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <span className=\"min-w-0 flex-1 truncate font-medium\">\n {person.client || person.email}\n </span>\n <Badge variant={state.tone}>{state.label}</Badge>\n </div>\n <p className=\"mt-0.5 break-all text-muted-foreground\">{person.email}</p>\n <p className=\"mt-0.5 text-muted-foreground\">{state.why}</p>\n\n {person.is_active ? (\n <div className=\"mt-1.5 flex flex-wrap gap-1.5\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setPreviewing(showing ? null : person)}\n >\n {showing ? \"Stop viewing as them\" : \"View as this client\"}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAskingToRevoke(person)}>\n Remove their access\n </Button>\n </div>\n ) : null}\n\n {/* THE CONSEQUENCE, NAMED BEFORE THE CLICK — the same shape the\n table's own delete and the field remove use in this package. */}\n {asking ? (\n <div className=\"mt-1.5 flex flex-col gap-1.5 rounded border border-destructive/40 px-2 py-1.5\">\n <span className=\"text-destructive\">{revokeConsequence(person, card.title)}</span>\n <div className=\"flex flex-wrap gap-1.5\">\n <Button\n size=\"sm\"\n variant=\"destructive\"\n disabled={busy}\n onClick={() => void revoke(person)}\n >\n {busy ? \"Removing…\" : \"Remove their access\"}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setAskingToRevoke(null)}>\n Keep it\n </Button>\n </div>\n </div>\n ) : null}\n\n {showing ? <Preview card={card} person={person} onPreview={onPreview} /> : null}\n </div>\n );\n })}\n </section>\n );\n}\n\n/**\n * VIEW AS THIS CLIENT — the store's answer, not the screen's.\n *\n * One Table at a time, because that is the shape of the door's question. The\n * refusal for somebody who has not signed in is shown in the door's own words:\n * an empty list here would be the screen inventing \"she sees nothing\".\n */\nfunction Preview({\n card,\n person,\n onPreview,\n}: {\n card: PortalCard;\n person: PortalPrincipal;\n onPreview: PortalCardViewProps[\"onPreview\"];\n}) {\n const first = card.tables[0];\n const [which, setWhich] = useState<Uuid | null>((first?.table_id as Uuid | undefined) ?? null);\n const [rows, setRows] = useState<PortalPreviewRow[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n\n useEffect(() => {\n if (!which) return;\n let cancelled = false;\n setRows(null);\n void onPreview(person, which).then((answered) => {\n if (cancelled) return;\n if (!answered.ok) {\n setError(answered.error);\n setRows([]);\n return;\n }\n setError(null);\n setRows(answered.data);\n });\n return () => {\n cancelled = true;\n };\n }, [onPreview, person, which]);\n\n if (!which) return null;\n\n return (\n <div className=\"mt-1.5 rounded border border-border bg-card px-2 py-1.5\">\n <p className=\"text-xs text-muted-foreground\">{previewLine(person)}</p>\n\n {card.tables.length > 1 ? (\n <div className=\"mt-1.5 flex flex-wrap gap-1.5\">\n {card.tables.map((exposed) => (\n <Button\n key={exposed.table_id}\n size=\"sm\"\n variant={exposed.table_id === which ? \"secondary\" : \"ghost\"}\n onClick={() => setWhich(exposed.table_id as Uuid)}\n >\n {exposed.name}\n </Button>\n ))}\n </div>\n ) : null}\n\n {/* THE DOOR'S REFUSAL IN ITS OWN WORDS — never an empty list. */}\n {error ? (\n <div className=\"mt-1.5\">\n <RefusalNotice error={error} />\n </div>\n ) : null}\n\n {rows === null && !error ? <Skeleton className=\"mt-1.5 h-12 w-full\" /> : null}\n\n {rows && !error ? (\n rows.length === 0 ? (\n <p className=\"mt-1.5 text-xs\">\n They can sign in, and right now no record of this Table names them — so this page is\n empty for them.\n </p>\n ) : (\n <ul className=\"mt-1.5 flex flex-col gap-1\">\n {rows.map((row) => (\n <li key={row.record_id} className=\"truncate text-xs\">\n {row.title}\n </li>\n ))}\n </ul>\n )\n ) : null}\n </div>\n );\n}\n\n/**\n * INVITE ONE PERSON — a client record, and an email.\n *\n * The record is not optional and cannot be typed: a portal principal IS a row\n * of the portal's client Table, and that row is the whole of \"only theirs\". So\n * the picker reads that Table through the read door (the same door every other\n * list in this package reads through) and never lets somebody invent a client.\n */\nfunction Invite({ card, onInvited }: { card: PortalCard; onInvited: () => void }) {\n const client = useRecordsClient();\n const [rows, setRows] = useState<ReadRow[] | null>(null);\n const [titleKey, setTitleKey] = useState<string | null>(null);\n const [search, setSearch] = useState(\"\");\n const [picked, setPicked] = useState<Uuid | null>(null);\n const [email, setEmail] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [said, setSaid] = useState<string | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void client.list({ table_id: card.client_table_id as Uuid, limit: 200 }).then((answered) => {\n if (cancelled) return;\n if (answered.ok) setRows(answered.data.rows);\n else {\n setError(answered.error);\n setRows([]);\n }\n });\n void client.tableList().then((answered) => {\n if (cancelled || !answered.ok) return;\n setTitleKey(answered.data.find((t) => t.id === card.client_table_id)?.title_field ?? null);\n });\n return () => {\n cancelled = true;\n };\n }, [client, card.client_table_id]);\n\n const options = useMemo(() => {\n const all = (rows ?? []).map((row) => ({ id: row.id as Uuid, name: rowName(row, titleKey) }));\n const needle = search.trim().toLowerCase();\n return needle === \"\"\n ? all.slice(0, 25)\n : all.filter((o) => o.name.toLowerCase().includes(needle)).slice(0, 25);\n }, [rows, titleKey, search]);\n\n const send = useCallback(async () => {\n if (!picked) return;\n setBusy(true);\n const answered = await client.portalInvite({\n portal_id: card.portal_id,\n client_record_id: picked,\n email: email.trim(),\n });\n setBusy(false);\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setError(null);\n // THE DOOR'S OWN SENTENCE, verbatim — it is the one that says an invitation\n // confers nothing until the link is followed.\n setSaid(answered.data.say);\n setPicked(null);\n setEmail(\"\");\n setSearch(\"\");\n onInvited();\n }, [card.portal_id, client, email, onInvited, picked]);\n\n const pickedName = options.find((o) => o.id === picked)?.name ?? null;\n\n return (\n <section className=\"flex flex-col gap-1.5\">\n <h4 className=\"text-xs font-medium\">Invite somebody</h4>\n <p className=\"text-xs text-muted-foreground\">\n Pick the client they are, and say where to send their sign-in link. They get nothing until\n they follow it.\n </p>\n\n {error ? <RefusalNotice error={error} /> : null}\n {said ? <p className=\"text-xs text-muted-foreground\">{said}</p> : null}\n\n {rows === null ? (\n <Skeleton className=\"h-9 w-full\" />\n ) : (\n <>\n <BasicInput\n className=\"text-base\"\n placeholder=\"Find the client…\"\n value={picked ? (pickedName ?? search) : search}\n onChange={(event) => {\n setPicked(null);\n setSearch(event.target.value);\n }}\n />\n {picked ? null : (\n <ul className=\"flex max-h-40 flex-col gap-0.5 overflow-y-auto\">\n {options.length === 0 ? (\n <li className=\"text-xs text-muted-foreground\">\n No client of this portal's client Table matches that. A portal principal is\n one of those rows — add the client there first.\n </li>\n ) : null}\n {options.map((option) => (\n <li key={option.id}>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"w-full justify-start\"\n onClick={() => {\n setPicked(option.id);\n setSearch(option.name);\n }}\n >\n {option.name}\n </Button>\n </li>\n ))}\n </ul>\n )}\n\n <BasicInput\n className=\"text-base\"\n type=\"email\"\n placeholder=\"their email address\"\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n />\n\n <div>\n <Button\n size=\"sm\"\n disabled={busy || !picked || email.trim() === \"\"}\n onClick={() => void send()}\n >\n {busy ? \"Inviting…\" : \"Send the invitation\"}\n </Button>\n </div>\n </>\n )}\n </section>\n );\n}\n","\"use client\";\n\n// src/SubscriptionsPanel.tsx — @ai-matrx/records-ui · DOOR-18, the owner's side\n//\n// WHAT THIS TABLE IS TELLING YOU ABOUT, AND HOW TO MAKE IT STOP.\n//\n// A subscription is a Rule record carrying a `subscription` block — there is no\n// subscriptions table and no second notifier. That is the right architecture and\n// it had one hole: `custom.agg_subscriptions` is the NOTIFIER's reader and no\n// client may call it, so until `custom.subscriptions` landed there was no way\n// for a person to SEE what they were being told about, and no way at all to\n// switch one off. An agent could turn a notification on — \"tell me when a new\n// patient arrives\" does exactly that — and the person it was telling could not\n// turn it off. A notification nobody can stop is not a feature.\n//\n// IT IS THIS TABLE'S, AND IT IS IN THIS TABLE'S RAIL, for the same reason the\n// forms are: a subscription watches a Table, so it belongs beside that Table's\n// settings and its forms rather than in a separate notifications area of the app\n// that somebody has to know exists.\n//\n// ABSENT, NEVER DEAD. A row the store says this person may not mute (`i_may_mute`)\n// carries no switch at all — not a greyed one — and says whose it is instead.\n// The store answers that question; this screen never works it out.\n//\n// MUTED IS THE STORE'S WORD, NOT A LOCAL ONE. `custom.agg_subscriptions` —\n// the single reader every consumer goes through — already excludes a muted\n// subscription, so \"off\" here and \"does not fire\" are the same fact rather than\n// two that can drift.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { MySubscription, RecordsError } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, Switch, cn } from \"@ai-matrx/design-system\";\n\nimport { RefusalNotice } from \"./Refusal\";\n\nexport interface SubscriptionsPanelProps {\n tableId: Uuid;\n className?: string | undefined;\n}\n\n/** How often, in the words a person uses. The store's cadence, said once. */\nfunction whenItFires(subscription: MySubscription): string {\n if (subscription.cadence === \"immediate\") return \"as it happens\";\n if (subscription.schedule) return `a summary, ${subscription.schedule}`;\n return \"a summary\";\n}\n\n/** Where it arrives, and the one honest thing to say about each channel. */\nconst CHANNEL_WORDS: Record<string, string> = {\n in_app: \"in the app\",\n email: \"by email — only if an address is on the account\",\n sms: \"by text — only if a number is on the account\",\n};\n\nexport function SubscriptionsPanel({ tableId, className }: SubscriptionsPanelProps) {\n const client = useRecordsClient();\n const [rows, setRows] = useState<MySubscription[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n\n const load = useCallback(async () => {\n const answered = await client.subscriptions({ table_id: tableId });\n if (!answered.ok) {\n setError(answered.error);\n setRows([]);\n return;\n }\n setError(null);\n setRows(answered.data);\n }, [client, tableId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const flip = useCallback(\n async (subscription: MySubscription, on: boolean) => {\n setBusy(subscription.rule_id);\n const answered = await client.subscriptionMute({\n rule_id: subscription.rule_id as Uuid,\n muted: !on,\n });\n setBusy(null);\n if (!answered.ok) {\n // The store's own sentence — \"That notification is not addressed to\n // you, so you cannot switch it off.\" — rather than a silent no-op.\n setError(answered.error);\n return;\n }\n await load();\n },\n [client, load],\n );\n\n if (rows === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n return (\n <section className={cn(\"flex flex-col gap-3\", className)}>\n <header className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">Notifications</h3>\n <span className=\"text-xs text-muted-foreground\">\n {rows.length === 0 ? \"none\" : `${rows.filter((r) => !r.muted).length} on`}\n </span>\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {rows.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n Nothing is telling you about this table. A form that says \"tell me when somebody answers\"\n makes one, and it appears here the moment it does.\n </p>\n ) : null}\n\n <ul className=\"flex flex-col gap-2\">\n {rows.map((subscription) => (\n <li key={subscription.rule_id} className=\"rounded-md border p-2.5\">\n <div className=\"flex items-start gap-2\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium\">{subscription.name}</p>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {CHANNEL_WORDS[subscription.channel] ?? `on the ${subscription.channel} channel`}\n {\" · \"}\n {whenItFires(subscription)}\n </p>\n </div>\n {subscription.i_may_mute ? (\n <Switch\n checked={!subscription.muted}\n disabled={busy === subscription.rule_id}\n aria-label={`Tell me about ${subscription.name}`}\n onCheckedChange={(on) => void flip(subscription, on)}\n />\n ) : (\n <Badge variant=\"secondary\">someone else's</Badge>\n )}\n </div>\n <p className=\"mt-1.5 text-xs text-muted-foreground\">\n {subscription.muted\n ? \"Off — it stays here and tells nobody until you switch it back on.\"\n : subscription.mine\n ? \"On, and addressed to you.\"\n : \"On, and addressed to somebody else in this organization.\"}\n </p>\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","\"use client\";\n\n// src/FormBuilder.tsx — @ai-matrx/records-ui · SCR-13\n//\n// THE FORM BUILDER, BUILT FOR THE AGENT FIRST.\n//\n// `seed` takes COMPLETE declarative `FormSpec`s an agent wrote — the whole form\n// in one object, questions, conditions, theme and thank-you screen included —\n// and saves each one that is not there yet as a record. That is the 45 seconds\n// the law is about. Everything else on this screen is the TWEAK: a person\n// changes what the agent got wrong, one control at a time, and never has to\n// assemble a form field by field to have one.\n//\n// The questions a person can add are the subject Table's own Fields, because a\n// form is a view on a real Table — there is no way in this screen to invent a\n// question that lands nowhere, which is why a submission is a record and not a\n// \"response\" in a second store.\n//\n// A condition is written as the store's own Rule expression, pointing at a\n// Field BY ID (REC-17). The builder never writes a field NAME into a rule: the\n// store refuses that by name, and it is right to.\n//\n// IT EDITS THE FORM THAT HAS THE LINK (2026-09-20). This screen used to keep\n// its own form records in a package-owned `records_ui_form` Table — a second\n// form object with no public link, no accept Rule and no notify Rule, sitting\n// beside the `custom.anon_form` one that `form_propose` makes and a stranger\n// actually answers. Two objects, one name, nothing reconciling them. It now\n// reads `custom.forms` and writes `custom.form_declare`: the same two doors the\n// agent uses, so a tweak here changes the form at the link.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, RuleExpression } from \"@ai-matrx/records\";\nimport { publicFormPath } from \"@ai-matrx/records\";\nimport {\n BasicInput,\n BasicTextarea,\n Button,\n Checkbox,\n Label,\n Skeleton,\n cn,\n} from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useSeedGuard } from \"./seedOnce\";\nimport { useRecordsUi, useTableRights } from \"./host\";\nimport { FormRunner } from \"./FormRunner\";\nimport { fieldName } from \"./names\";\nimport {\n FORM_FLOWS,\n formDeclareArgs,\n formFromSummary,\n type FormFlow,\n type FormQuestionSpec,\n type FormSpec,\n type SavedForm,\n} from \"./forms\";\n\nexport interface FormBuilderProps {\n /** The Table this form collects into. A form is a view on a real Table. */\n tableId: Uuid;\n /**\n * COMPLETE DECLARATIVE SPECS an agent wrote. Any of these whose name this\n * table does not have yet is saved as a record the first time the builder\n * loads. A seed whose name exists is LEFT ALONE — an agent re-running never\n * overwrites what a person has since tweaked.\n */\n seed?: FormSpec[] | undefined;\n activeFormId?: Uuid | null | undefined;\n onActiveForm?: ((form: SavedForm) => void) | undefined;\n className?: string | undefined;\n}\n\n/** The comparisons a condition can make. The store's own operator names. */\nconst CONDITION_OPS: Array<{ op: string; label: string }> = [\n { op: \"eq\", label: \"is\" },\n { op: \"ne\", label: \"is not\" },\n { op: \"present\", label: \"has been answered\" },\n { op: \"gt\", label: \"is more than\" },\n { op: \"lt\", label: \"is less than\" },\n];\n\nexport function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }: FormBuilderProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n // One claim per seed name, per mount: a check against the server's list is\n // not a lock, and a loader that re-runs mid-write would write it twice.\n const claimSeed = useSeedGuard();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const fields = useFields(tableId);\n const [forms, setForms] = useState<SavedForm[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [activeId, setActiveId] = useState<Uuid | null>(activeFormId ?? null);\n const [draft, setDraft] = useState<SavedForm | null>(null);\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState<string | null>(null);\n\n const load = useCallback(async () => {\n // `custom.forms` is already scoped to this Table by the door, so there is no\n // client-side filter here that could disagree with the one the store used.\n const answered = await client.forms({ table_id: tableId });\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n let mine = answered.data.map(formFromSummary);\n const missing = (seed ?? []).filter((s) => !mine.some((f) => f.name === s.name));\n if (missing.length > 0) {\n for (const spec of missing) {\n if (!claimSeed(spec.name)) continue;\n const written = await client.formDeclare(formDeclareArgs({ ...spec, subject: tableId }));\n if (!written.ok) {\n setError(written.error);\n return;\n }\n }\n const again = await client.forms({ table_id: tableId });\n if (!again.ok) {\n setError(again.error);\n return;\n }\n mine = again.data.map(formFromSummary);\n }\n setError(null);\n setForms(mine);\n }, [client, tableId, seed, claimSeed]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n useEffect(() => {\n if (!forms || forms.length === 0) return;\n const chosen = forms.find((f) => f.id === (activeFormId ?? activeId)) ?? forms[0]!;\n if (chosen.id !== activeId) setActiveId(chosen.id);\n setDraft(chosen);\n onActiveForm?.(chosen);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [forms, activeFormId]);\n\n const byKey = useMemo(() => new Map((fields.data ?? []).map((f) => [f.key, f])), [fields.data]);\n\n function patch(change: Partial<FormSpec>) {\n setDraft((prev) => (prev ? { ...prev, ...change } : prev));\n setSaved(null);\n }\n\n function patchQuestion(index: number, change: Partial<FormQuestionSpec>) {\n setDraft((prev) => {\n if (!prev) return prev;\n const questions = prev.questions.map((q, i) => (i === index ? { ...q, ...change } : q));\n return { ...prev, questions };\n });\n setSaved(null);\n }\n\n async function save() {\n if (!draft) return;\n setSaving(true);\n // A RE-STATEMENT OF THE WHOLE FORM. `formDeclareArgs` hands back the accept\n // Rule, the notify Rule, the cap and the slug it read, because the door sets\n // every one of them — a save that dropped `notify_rule_id` would silently\n // stop the owner being told that somebody answered.\n const written = await client.formDeclare(formDeclareArgs(draft));\n setSaving(false);\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setSaved(\"Saved.\");\n await load();\n }\n\n async function create(name: string) {\n // The store refuses a form that asks nothing (\"A form has to ask something\"),\n // and it is right to: a form with no questions is a link to an empty page. A\n // new one starts by asking for this Table's first Field, which is the one\n // question a person is certainly going to want and can immediately change.\n const first = (fields.data ?? [])[0];\n if (!first) return;\n const written = await client.formDeclare(\n formDeclareArgs({ name, subject: tableId, questions: [{ field: first.key }] }),\n );\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setActiveId(written.data);\n await load();\n }\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (fields.loading || forms === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (!rights.admin) {\n // SCR-4 again: building a form is administering the table. There is no\n // greyed-out builder — there is no builder, and the reason is readable.\n return <p className={cn(\"text-xs text-muted-foreground\", className)}>{rights.why(\"structure\")}</p>;\n }\n\n return (\n <div className={cn(\"flex min-h-0 gap-3\", className)}>\n <div className=\"flex min-w-0 flex-1 flex-col gap-2 overflow-auto\">\n {/* One row: the forms, the flow, the save. No repeated names. */}\n <div className=\"flex items-center gap-1 overflow-x-auto\" role=\"group\" aria-label=\"Forms\">\n {forms.map((form) => (\n <Button\n key={form.id}\n size=\"sm\"\n variant={form.id === activeId ? \"secondary\" : \"ghost\"}\n aria-pressed={form.id === activeId}\n onClick={() => {\n setActiveId(form.id);\n setDraft(form);\n }}\n >\n {form.name}\n </Button>\n ))}\n {(fields.data ?? []).length > 0 ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void create(`Form ${forms.length + 1}`)}>\n New form\n </Button>\n ) : null}\n <span className=\"ml-auto flex items-center gap-2\">\n {saved ? <span className=\"text-xs text-muted-foreground\">{saved}</span> : null}\n <Button size=\"sm\" disabled={saving || !draft} onClick={() => void save()}>\n {saving ? \"Saving…\" : \"Save\"}\n </Button>\n </span>\n </div>\n\n {!draft ? (\n <p className=\"text-xs text-muted-foreground\">\n {(fields.data ?? []).length === 0\n ? \"This table has no fields yet, so there is nothing a form could ask for. Add a field first — every question is one of this table's own fields.\"\n : 'No form collects into this table yet. \"New form\" makes one, or you ask an agent for the whole thing in a sentence.'}\n </p>\n ) : (\n <>\n {/* WHICH FORM THIS IS, in the store's own words. The builder edits the\n form that has the link, so it says where that link points and\n whether it is answering — never a save into something invisible. */}\n <p className=\"text-xs text-muted-foreground\">\n {draft.state === \"open\"\n ? `Open at ${host.publicOrigin ?? \"\"}${publicFormPath(draft.id)} — changes here change what people answer.`\n : draft.state === \"draft\"\n ? \"Not published yet. It gets a link when somebody opens it in Forms.\"\n : draft.state === \"closed\"\n ? \"Closed. It keeps its answers and takes no more.\"\n : \"Full. It has all the answers it was set up to take.\"}\n </p>\n\n <div className=\"grid grid-cols-2 gap-2\">\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Name</Label>\n <BasicInput value={draft.name} onChange={(e) => patch({ name: e.target.value })} />\n </label>\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Flow</Label>\n <select\n className=\"h-9 rounded border bg-background px-2 text-sm\"\n value={draft.flow ?? \"one-at-a-time\"}\n onChange={(e) => patch({ flow: e.target.value as FormFlow })}\n >\n {FORM_FLOWS.map((flow) => (\n <option key={flow} value={flow}>\n {flow === \"one-at-a-time\" ? \"One question at a time\" : \"All on one page\"}\n </option>\n ))}\n </select>\n </label>\n <label className=\"col-span-2 flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Intro</Label>\n <BasicTextarea\n rows={2}\n value={draft.intro ?? \"\"}\n onChange={(e) => patch({ intro: e.target.value || null })}\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Submit button</Label>\n <BasicInput\n value={draft.submitLabel ?? \"\"}\n placeholder=\"Submit\"\n onChange={(e) => patch({ submitLabel: e.target.value || null })}\n />\n </label>\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Thank-you title</Label>\n <BasicInput\n value={draft.thankYou?.title ?? \"\"}\n placeholder=\"Thank you\"\n onChange={(e) =>\n patch({\n thankYou: e.target.value\n ? { title: e.target.value, body: draft.thankYou?.body ?? null }\n : null,\n })\n }\n />\n </label>\n </div>\n\n {/* The questions. Each one asks for a Field this Table actually has. */}\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Questions</span>\n <span>{draft.questions.length} of this table's {fields.data?.length ?? 0} fields</span>\n </div>\n {(fields.data ?? []).map((field) => {\n const index = draft.questions.findIndex((q) => q.field === field.key);\n const asked = index >= 0;\n const question = asked ? draft.questions[index]! : null;\n return (\n <div key={field.id} className=\"rounded border px-2 py-1.5\">\n <div className=\"flex items-center gap-2\">\n <Checkbox\n checked={asked}\n aria-label={`Ask for ${fieldName(field)}`}\n onCheckedChange={(checked) =>\n patch({\n questions: checked\n ? [...draft.questions, { field: field.key }]\n : draft.questions.filter((q) => q.field !== field.key),\n })\n }\n />\n <span className=\"text-xs font-medium\">{fieldName(field)}</span>\n <span className=\"text-xs text-muted-foreground\">{field.key}</span>\n {field.required ? <span className=\"text-xs text-destructive\">required</span> : null}\n </div>\n {asked && question ? (\n <div className=\"mt-1.5 grid grid-cols-2 gap-2 pl-6\">\n <BasicInput\n className=\"h-8 text-xs\"\n placeholder={fieldName(field)}\n aria-label={`How to ask for ${field.key}`}\n value={question.ask ?? \"\"}\n onChange={(e) => patchQuestion(index, { ask: e.target.value || null })}\n />\n <BasicInput\n className=\"h-8 text-xs\"\n placeholder=\"Help text\"\n aria-label={`Help text for ${field.key}`}\n value={question.help ?? \"\"}\n onChange={(e) => patchQuestion(index, { help: e.target.value || null })}\n />\n <Condition\n question={question}\n fieldKeys={fields.data ?? []}\n onChange={(showIf) => patchQuestion(index, { showIf })}\n />\n </div>\n ) : null}\n </div>\n );\n })}\n {draft.questions\n .filter((q) => !byKey.has(q.field))\n .map((q) => (\n <p key={q.field} className=\"text-xs text-destructive\">\n This form asks for \"{q.field}\" and this table has no such Field. It is shown here rather\n than quietly dropped.\n </p>\n ))}\n </div>\n </>\n )}\n </div>\n\n {/* The preview is the RUNNER, not a picture of it: what a person will actually meet. */}\n {draft ? (\n <aside className=\"w-96 shrink-0 overflow-auto rounded border p-2\">\n {/* The runner no longer prints the form's name — a host that mounts\n one has its own heading, and on the public page two of them sat on\n top of each other. This pane is that heading. */}\n <h4 className=\"px-1 text-sm font-medium\">{draft.name}</h4>\n <FormRunner form={draft} preview />\n </aside>\n ) : null}\n </div>\n );\n}\n\n/** The one condition row. It writes the store's own Rule expression, by Field id. */\nfunction Condition({\n question,\n fieldKeys,\n onChange,\n}: {\n question: FormQuestionSpec;\n fieldKeys: Array<{ id: string; key: string; label: string }>;\n onChange: (showIf: RuleExpression | null) => void;\n}) {\n const expr = question.showIf as { op?: string; args?: Array<{ field?: string; const?: unknown }> } | null;\n const op = expr?.op ?? \"\";\n const onField = expr?.args?.[0]?.field ?? \"\";\n const value = expr?.args?.[1]?.const ?? \"\";\n\n function write(next: { op?: string; field?: string; value?: unknown }) {\n const chosenOp = next.op ?? op;\n const chosenField = next.field ?? onField;\n const chosenValue = next.value ?? value;\n if (!chosenOp || !chosenField) {\n onChange(null);\n return;\n }\n onChange(\n chosenOp === \"present\"\n ? ({ op: \"present\", args: [{ field: chosenField }] } as RuleExpression)\n : ({ op: chosenOp, args: [{ field: chosenField }, { const: chosenValue }] } as RuleExpression),\n );\n }\n\n return (\n <div className=\"col-span-2 flex items-center gap-1 text-xs\">\n <span className=\"text-muted-foreground\">Ask only when</span>\n <select\n aria-label=\"Condition field\"\n className=\"h-8 rounded border bg-background px-1 text-xs\"\n value={onField}\n onChange={(e) => write({ field: e.target.value })}\n >\n <option value=\"\">always</option>\n {fieldKeys.map((f) => (\n <option key={f.id} value={f.id}>\n {f.label || f.key}\n </option>\n ))}\n </select>\n {onField ? (\n <>\n <select\n aria-label=\"Condition comparison\"\n className=\"h-8 rounded border bg-background px-1 text-xs\"\n value={op}\n onChange={(e) => write({ op: e.target.value })}\n >\n {CONDITION_OPS.map((c) => (\n <option key={c.op} value={c.op}>\n {c.label}\n </option>\n ))}\n </select>\n {op !== \"present\" ? (\n <BasicInput\n className=\"h-8 w-28 text-xs\"\n aria-label=\"Condition value\"\n value={String(value ?? \"\")}\n onChange={(e) => write({ value: e.target.value })}\n />\n ) : null}\n </>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/FormRunner.tsx — @ai-matrx/records-ui · SCR-14\n//\n// THE FORM, AS THE PERSON ANSWERING IT SEES IT. One question at a time, a\n// progress line that is honest about how many questions are actually left, the\n// keyboard doing what a keyboard does (Enter goes on, Shift+Enter goes back),\n// and a submission that is an ORDINARY RECORD in a real Table the moment it is\n// sent.\n//\n// TWO ARMS, ONE SCREEN. This file exports ONE component and it runs in two\n// places that could not be more different:\n//\n// · SIGNED IN — mounted inside <RecordsProvider>. It reads the Table's Fields\n// through the read door, asks the store to answer every condition, and\n// writes through `custom.record_write` as the person sitting there.\n// · PUBLIC — served to somebody with NO ACCOUNT, at an unguessable link. There\n// is no session, no organization the caller may name and no read of the\n// table it writes into. The SERVER resolved the form through\n// `custom.form_public` and hands this component `fields` and `onSubmit`, so\n// the identical screen runs with the store nowhere near the browser.\n//\n// The public arm is why `useOptionalRecordsClient` exists in @ai-matrx/records\n// and why the connected half lives in its own component below: React hooks are\n// unconditional, so \"call the store's hooks only sometimes\" has to be a\n// different component, never an `if` around a hook.\n//\n// FIVE THINGS THIS COMPONENT REFUSES TO DO:\n//\n// 1. It never evaluates a condition itself. `showIf` is a Rule and the STORE\n// answers it (`custom.rule_eval`), so the form branches the same way for a\n// person, for the server and for an agent. An UNDECIDED answer — which is\n// what the store returns for a question nobody has answered yet — SHOWS the\n// question. Undecided is not false, and silently skipping a person past\n// something is the exact failure the store's own null-handling avoids. On\n// the public arm there is no evaluator at all, so every conditional question\n// is shown AND the form says so, rather than branching on a guess.\n// 2. It never draws a file chooser with nowhere to put the file. With no\n// `upload` port bound the attachment question says so in one sentence.\n// 3. It never calls itself public on the strength of a flag. `isPublic` needs\n// the anonymous write door; a signed-in mount of a public form says who the\n// record will be stamped as, by name.\n// 4. It never invents its own editors. Every answer is taken with the same\n// `FieldControl` the record form uses, so a currency in a form and a\n// currency in the grid are the same control with the same unit.\n// 5. It never sends the decoy. `honeypotKey` renders an input that no person\n// can see, reach by keyboard or autofill into; its value travels beside the\n// answers and the door decides what to do about it.\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useFields, useOptionalRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { Field, RecordsError } from \"@ai-matrx/records\";\nimport { Button, Progress, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { FieldControl, FieldLabel } from \"./editors\";\nimport { editorKindFor } from \"./parity\";\nimport { NO_UPLOAD_REASON, useRecordsUi } from \"./host\";\nimport { submissionStamp, type FormSpec, type SavedForm } from \"./forms\";\n\n/** What the public arm's `onSubmit` answers. A refusal carries the door's words. */\nexport type FormSubmitOutcome =\n | { ok: true; message?: string | null; recordId?: Uuid | null }\n | { ok: false; message: string };\n\nexport interface FormRunnerProps {\n /** The complete spec. An agent wrote it; `FormBuilder` saved it; this runs it. */\n form: FormSpec | SavedForm;\n /**\n * PUBLIC ARM — the subject Table's Fields, already resolved by the server\n * through `custom.form_public`. Given together with `onSubmit`, this component\n * mounts no store client at all and the browser never touches the store.\n */\n fields?: readonly Field[] | undefined;\n /** PUBLIC ARM — where an answer goes. Server action or route handler. */\n onSubmit?: ((values: Record<string, unknown>) => Promise<FormSubmitOutcome>) | undefined;\n /**\n * PUBLIC ARM — the name of a decoy input. A person never fills it; a script\n * fills everything. The door decides what a filled one means, not this screen.\n */\n honeypotKey?: string | null | undefined;\n /** Preview mode answers the questions but writes nothing, and says so. */\n preview?: boolean | undefined;\n onSubmitted?: ((recordId: Uuid | null) => void) | undefined;\n className?: string | undefined;\n}\n\ntype Answers = Record<string, unknown>;\n\n/** One question resolved against the subject Table's own Fields. */\ninterface ResolvedQuestion {\n key: string;\n ask: string;\n help: string | null;\n required: boolean;\n /** Null when the Table has no such Field — named on screen, never dropped. */\n field: Field | null;\n showIf: unknown;\n}\n\n/**\n * THE ONE ENTRY POINT. It picks the arm and nothing else: a caller that brought\n * the Fields and a place to send the answers gets the stage on its own, and\n * everybody else gets the connected half, which reads both from the store.\n */\nexport function FormRunner(props: FormRunnerProps) {\n if (props.fields && props.onSubmit) {\n return <FormStage {...props} fields={props.fields} onSubmit={props.onSubmit} />;\n }\n return <ConnectedFormRunner {...props} />;\n}\n\n/** The signed-in arm: the Fields from the read door, the answers through the write door. */\nfunction ConnectedFormRunner(props: FormRunnerProps) {\n const client = useOptionalRecordsClient();\n const fields = useFields(props.form.subject);\n const { form, className } = props;\n\n const submit = useCallback(\n async (values: Record<string, unknown>): Promise<FormSubmitOutcome> => {\n if (!client) {\n return {\n ok: false,\n message:\n \"This form has nowhere to send an answer: it is running outside the record store \" +\n \"and nobody gave it a submit port. A public form is served with its questions and \" +\n \"its submit port by the server; a signed-in one needs <RecordsProvider> above it.\",\n };\n }\n const document = {\n ...values,\n ...submissionStamp({\n formId: (form as SavedForm).id ?? null,\n formName: form.name,\n actor: client.config.actor.actor,\n onBehalfOf: client.config.actor.on_behalf_of ?? null,\n }),\n };\n const written = await client.recordWrite({ table_id: form.subject, data: document });\n if (!written.ok) return { ok: false, message: written.error.message };\n return { ok: true, recordId: written.data };\n },\n [client, form],\n );\n\n const evaluate = useCallback(\n async (expr: unknown, values: Answers): Promise<boolean | null> => {\n if (!client) return null;\n const answered = await client.ruleEval({ expr, values });\n if (!answered.ok) throw answered.error;\n // `null` is UNDECIDED. Undecided shows the question.\n return answered.data as boolean | null;\n },\n [client],\n );\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (fields.loading) return <Skeleton className={cn(\"h-40 w-full\", className)} />;\n return (\n <FormStage\n {...props}\n fields={fields.data ?? []}\n onSubmit={props.onSubmit ?? submit}\n evaluate={evaluate}\n connected\n />\n );\n}\n\n/**\n * THE SCREEN. It knows about questions, a keyboard and a thank-you, and nothing\n * whatsoever about a database. Both arms render exactly this.\n */\nfunction FormStage({\n form,\n fields,\n onSubmit,\n evaluate,\n honeypotKey,\n preview = false,\n onSubmitted,\n className,\n connected = false,\n}: FormRunnerProps & {\n fields: readonly Field[];\n onSubmit: (values: Record<string, unknown>) => Promise<FormSubmitOutcome>;\n evaluate?: ((expr: unknown, values: Answers) => Promise<boolean | null>) | undefined;\n connected?: boolean;\n}) {\n const host = useRecordsUi();\n const [answers, setAnswers] = useState<Answers>({});\n const [at, setAt] = useState(0);\n const [error, setError] = useState<RecordsError | null>(null);\n const [refusal, setRefusal] = useState<string | null>(null);\n const [writing, setWriting] = useState(false);\n const [done, setDone] = useState<string | null>(null);\n /** Which conditional questions the STORE said to hide. Keyed by field key. */\n const [hidden, setHidden] = useState<Record<string, boolean>>({});\n const decoy = useRef(\"\");\n const stage = useRef<HTMLDivElement>(null);\n\n const questions: ResolvedQuestion[] = useMemo(() => {\n const byKey = new Map((fields ?? []).map((f) => [f.key, f]));\n return (form.questions ?? []).map((q) => {\n const field = byKey.get(q.field) ?? null;\n return {\n key: q.field,\n ask: q.ask ?? field?.label ?? q.field,\n help: q.help ?? null,\n required: q.required ?? field?.required ?? false,\n field,\n showIf: q.showIf ?? null,\n };\n });\n }, [fields, form.questions]);\n\n // ── the conditions, answered by the STORE ────────────────────────────────\n // Re-asked whenever an answer changes, because that is what a condition is\n // about. One call per conditional question; a form with no conditions makes\n // no calls at all, and a public form makes none because it has no evaluator —\n // see `unanswerable` below, which SAYS that rather than branching on a guess.\n useEffect(() => {\n let cancelled = false;\n const conditional = questions.filter((q) => q.showIf);\n if (conditional.length === 0 || !evaluate) return;\n void (async () => {\n const next: Record<string, boolean> = {};\n for (const q of conditional) {\n try {\n const answered = await evaluate(q.showIf, answers);\n // `null` is UNDECIDED. Undecided shows the question.\n next[q.key] = answered === false;\n } catch (thrown) {\n // A condition the store could not work out is NOT a silent hide: the\n // question stays, and the store's sentence is shown above the form.\n if (!cancelled) setError(thrown as RecordsError);\n next[q.key] = false;\n }\n }\n if (!cancelled) setHidden(next);\n })();\n return () => {\n cancelled = true;\n };\n }, [evaluate, questions, answers]);\n\n const live = questions.filter((q) => !hidden[q.key]);\n const oneAtATime = (form.flow ?? \"one-at-a-time\") === \"one-at-a-time\";\n const index = Math.min(at, Math.max(live.length - 1, 0));\n const current = live[index];\n const centred = (form.theme?.align ?? \"center\") === \"center\";\n\n const answered = live.filter((q) => {\n const v = answers[q.key];\n return v !== undefined && v !== null && v !== \"\";\n }).length;\n\n const missing = live.filter((q) => {\n const v = answers[q.key];\n return q.required && (v === undefined || v === null || v === \"\");\n });\n\n const submit = useCallback(async () => {\n if (preview) {\n setDone(\"preview\");\n return;\n }\n setWriting(true);\n setError(null);\n setRefusal(null);\n const values: Record<string, unknown> = Object.fromEntries(\n live.map((q) => [q.key, answers[q.key] ?? null]),\n );\n if (honeypotKey) values[honeypotKey] = decoy.current;\n const outcome = await onSubmit(values);\n setWriting(false);\n if (!outcome.ok) {\n setRefusal(outcome.message);\n return;\n }\n setDone(outcome.message ?? \"sent\");\n onSubmitted?.(outcome.recordId ?? null);\n }, [answers, form, honeypotKey, live, onSubmit, onSubmitted, preview]);\n\n function advance() {\n if (!oneAtATime) return;\n if (index < live.length - 1) setAt(index + 1);\n else if (missing.length === 0) void submit();\n }\n\n function retreat() {\n if (oneAtATime && index > 0) setAt(index - 1);\n }\n\n // The keyboard flow. Enter goes on, Shift+Enter goes back — except inside a\n // long-text answer, where Enter is a new line and always has been.\n function onKeyDown(event: React.KeyboardEvent) {\n if (event.key !== \"Enter\") return;\n const target = event.target as HTMLElement;\n if (target.tagName === \"TEXTAREA\" && !event.metaKey && !event.ctrlKey) return;\n event.preventDefault();\n if (event.shiftKey) retreat();\n else advance();\n }\n\n useEffect(() => {\n // Moving to a question puts the caret in it: a person who is typing never\n // has to reach for the mouse to answer the next one.\n const input = stage.current?.querySelector<HTMLElement>(\n \"input:not([tabindex='-1']), textarea, select, [role='combobox']\",\n );\n input?.focus();\n }, [index, done]);\n\n // ── the thank-you screen ─────────────────────────────────────────────────\n if (done) {\n return (\n <section className={cn(\"mx-auto max-w-xl py-10\", centred && \"text-center\", className)}>\n <h2 className=\"text-lg font-medium\">{form.thankYou?.title ?? \"Thank you\"}</h2>\n {form.thankYou?.body ? (\n <p className=\"mt-1 text-sm text-muted-foreground\">{form.thankYou.body}</p>\n ) : null}\n <p className=\"mt-3 text-xs text-muted-foreground\">\n {done === \"preview\"\n ? \"This was a preview, so nothing was written.\"\n : done === \"sent\"\n ? `Saved to ${form.name}, with this form stamped on it.`\n : done}\n </p>\n </section>\n );\n }\n\n const unresolved = questions.filter((q) => !q.field);\n // A conditional question with nobody to answer its condition is SHOWN, and\n // that is said out loud. Hiding it would be branching on a guess; showing it\n // silently would leave the form's author believing a condition applied.\n const unanswerable = !evaluate && questions.some((q) => q.showIf);\n // A signed-in mount of a form meant for strangers writes as the person\n // sitting there, and says whose name the record will carry. The public arm\n // has no client at all, so this is only ever about the owner's own preview.\n const signedInPublic = connected && form.isPublic === true;\n\n return (\n <section\n className={cn(\"mx-auto flex max-w-xl flex-col gap-3 py-4\", centred && \"text-center\", className)}\n onKeyDown={onKeyDown}\n >\n {/* THE RUNNER RUNS THE FORM; THE PAGE NAMES IT.\n This row used to start with the form's name, and on the public page\n that printed the title twice — once as the page's own heading and again\n here, three millimetres below it, which is not something Typeform or\n Tally would ever ship. A host that mounts a form has a heading of its\n own (the public page's `h1`, the builder's preview pane); a component\n that repeats it is the \"no repeated names\" rule broken by a component\n that could not see the screen it was on. One row: progress, count. */}\n <header className=\"flex items-center gap-3 text-xs text-muted-foreground\">\n {/* THE BAR AND THE COUNT BESIDE IT SAY THE SAME THING. One question at a\n time, \"1 of 4\" is a POSITION, and a bar measuring answers instead\n sat at zero while the count said one — an empty sliver in a tinted\n track, which reads as either full or broken. Typeform's bar advances\n as you move through the form. On a single page there is no position,\n so it measures what it can: how much is answered. */}\n <Progress\n value={\n live.length === 0\n ? 0\n : ((oneAtATime ? index + 1 : answered) / live.length) * 100\n }\n className=\"h-1 flex-1\"\n />\n <span className=\"tabular-nums\">\n {oneAtATime ? `${index + 1} of ${live.length}` : `${answered} of ${live.length}`}\n </span>\n </header>\n\n {signedInPublic ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-left text-xs text-muted-foreground\">\n You are answering this signed in, so the record will carry your name. A stranger answers the\n same form at its public link, where the answer arrives through the anonymous door instead.\n </p>\n ) : null}\n\n {unanswerable ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-left text-xs text-muted-foreground\">\n This form has questions that only appear in certain cases. Nothing here can work out which\n ones, so all of them are being shown rather than any being skipped.\n </p>\n ) : null}\n\n {unresolved.length > 0 ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-left text-xs text-destructive\">\n {unresolved.map((q) => q.key).join(\", \")} {unresolved.length === 1 ? \"is a question\" : \"are questions\"} this\n form asks for and this table has no such Field. Add the Field, or take the question out — it is\n shown here rather than quietly dropped, because a dropped question is an answer nobody gave.\n </p>\n ) : null}\n\n {form.intro && index === 0 ? <p className=\"text-sm text-muted-foreground\">{form.intro}</p> : null}\n\n {error ? <RefusalNotice error={error} className=\"text-left\" /> : null}\n {refusal ? (\n <p role=\"alert\" className=\"rounded border border-destructive/40 px-2 py-1 text-left text-xs text-destructive\">\n {refusal}\n </p>\n ) : null}\n\n <div ref={stage} className=\"flex flex-col gap-4 text-left\">\n {(oneAtATime ? (current ? [current] : []) : live).map((q) => (\n <Question\n key={q.key}\n question={q}\n value={answers[q.key]}\n onChange={(v) => setAnswers((prev) => ({ ...prev, [q.key]: v }))}\n upload={host.upload}\n />\n ))}\n {live.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n Every question in this form is hidden by its own condition right now, so there is nothing to\n answer yet.\n </p>\n ) : null}\n </div>\n\n {/* THE DECOY. Off-screen, out of the tab order, and told not to be\n autofilled — so no person and no password manager ever touches it. */}\n {honeypotKey ? (\n <div aria-hidden className=\"pointer-events-none absolute left-[-9999px] h-px w-px overflow-hidden\">\n <label htmlFor={`hp-${honeypotKey}`}>Leave this field empty</label>\n <input\n id={`hp-${honeypotKey}`}\n name={honeypotKey}\n type=\"text\"\n tabIndex={-1}\n autoComplete=\"off\"\n defaultValue=\"\"\n onChange={(e) => {\n decoy.current = e.target.value;\n }}\n />\n </div>\n ) : null}\n\n <footer className={cn(\"flex flex-wrap items-center gap-2\", centred && \"justify-center\")}>\n {oneAtATime && index > 0 ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={retreat}>\n Back\n </Button>\n ) : null}\n {oneAtATime && index < live.length - 1 ? (\n <Button size=\"sm\" onClick={advance}>\n Next\n </Button>\n ) : (\n <Button size=\"sm\" disabled={writing || missing.length > 0} onClick={() => void submit()}>\n {writing ? \"Sending…\" : (form.submitLabel ?? \"Submit\")}\n </Button>\n )}\n {missing.length > 0 && (!oneAtATime || index === live.length - 1) ? (\n <span className=\"text-xs text-muted-foreground\">\n {missing.map((q) => q.ask).join(\", \")} still {missing.length === 1 ? \"needs\" : \"need\"} an answer.\n </span>\n ) : null}\n {preview ? <span className=\"text-xs text-muted-foreground\">Preview — nothing is written.</span> : null}\n </footer>\n </section>\n );\n}\n\n/** One question: the Field's own editor, or the honest sentence when it cannot be drawn. */\nfunction Question({\n question,\n value,\n onChange,\n upload,\n}: {\n question: ResolvedQuestion;\n value: unknown;\n onChange: (value: unknown) => void;\n upload: ReturnType<typeof useRecordsUi>[\"upload\"];\n}) {\n const [uploadError, setUploadError] = useState<string | null>(null);\n const field = question.field;\n if (!field) return null;\n\n const id = `form-${field.key}`;\n const isAttachment = editorKindFor(field) === \"attachment\";\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n <FieldLabel field={{ ...field, label: question.ask, required: question.required }} htmlFor={id} />\n {question.help ? <p className=\"text-xs text-muted-foreground\">{question.help}</p> : null}\n {isAttachment && !upload ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{NO_UPLOAD_REASON}</p>\n ) : isAttachment ? (\n <>\n <input\n id={id}\n type=\"file\"\n className=\"text-xs\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (!file) return;\n setUploadError(null);\n void upload?.(file).then((result) => {\n if (!result) return;\n if (result.ok) onChange(result.fileId);\n else setUploadError(result.reason);\n });\n }}\n />\n {uploadError ? <p className=\"text-xs text-destructive\">{uploadError}</p> : null}\n </>\n ) : (\n <FieldControl field={field} value={value} onChange={onChange} id={id} />\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/charts.ts — @ai-matrx/records-ui · SCR-15, SCR-16\n//\n// A CHART IS A QUESTION THE STORE ANSWERS, NOT A PILE OF ROWS A BROWSER SUMS.\n//\n// Every block on a canvas is answered by `custom.dashboard_run`, which walks the\n// dashboard's saved blocks and asks `custom.record_aggregate` for each one UNDER\n// THE CALLER'S OWN PRINCIPAL. The aggregate node sits ABOVE the join to the read\n// door's visibility set, and both consequences are why this file exists:\n//\n// · A chart shows exactly the records this person may see. Rows they may not\n// see are never fetched, so they cannot be summed and then hidden — and a\n// total that quietly included them would be a screen lying in the one place\n// nobody would ever check.\n// · A canvas over a hundred thousand records is ONE round trip, not a hundred\n// thousand rows over the wire and not one call per block.\n//\n// ONE DASHBOARD OBJECT, AND THIS IS WHERE IT IS WRITTEN DOWN (2026-09-20).\n// --------------------------------------------------------------------------\n// Until this file changed there were TWO. `dashboard_propose` — the sentence a\n// person actually says to an agent — writes a dashboard in the presentation\n// kernel: the thing `custom.dashboards` lists, `custom.dashboard_run` runs and\n// the database itself judges block by block on the way in. `DashboardCanvas`\n// wrote dashboard RECORDS into a package-owned `records_ui_dashboard` Table that\n// the agent could not reach and the store never validated. Two objects, one\n// name, nothing reconciling them — the same defect lane FORMS removed for forms\n// on the same day.\n//\n// There is now one. `ChartSpec` stays the SCREEN's shape — the words a person\n// edits — and the four functions below are the ONLY translation between it and\n// `DashboardBlock`, in both directions. A second mapper anywhere is the drift\n// coming back.\n\nimport type {\n AggregateBucket,\n AggregateFilter,\n AggregateMeasure,\n DashboardBlock,\n DashboardBlockKind,\n DashboardSummary,\n Uuid,\n} from \"@ai-matrx/records\";\n\n/**\n * The shapes a block can take. There is exactly ONE closed set and it is the\n * store's — `custom.dashboard_kinds()` answers it and `@ai-matrx/records`\n * carries it. A second copy here would be a list that can disagree with the\n * door, which is how a screen comes to offer a shape the store refuses.\n */\nexport type ChartKind = DashboardBlockKind;\n\nexport const CHART_KIND_LABEL: Record<ChartKind, string> = {\n number: \"Number\",\n bar: \"Bars\",\n column: \"Columns\",\n line: \"Line\",\n donut: \"Donut\",\n table: \"Table\",\n stuck: \"Stuck\",\n};\n\n/**\n * The shapes in the order a person reads them, derived from the labels above —\n * which TypeScript keys exhaustively by the store's own type, so this list can\n * never drift from the closed set.\n */\nexport const CHART_KINDS = Object.keys(CHART_KIND_LABEL) as ChartKind[];\n\n/** What each shape needs before it can draw, in one sentence a block prints. */\nexport const CHART_NEEDS: Record<ChartKind, string | null> = {\n bar: \"A bar chart needs something to group by — pick a Field and the bars appear.\",\n column: \"A column chart needs something to group by — pick a Field and the columns appear.\",\n line: \"A line needs a date Field to run along — pick one and the line appears.\",\n donut: \"A donut needs something to group by — pick a Field and the slices appear.\",\n stuck: \"A stuck block needs a Field to watch — pick the one that moves as work progresses.\",\n number: null,\n table: null,\n};\n\n/** ONE BLOCK, in the words a screen edits. */\nexport interface ChartSpec {\n title: string;\n /** The Table this block asks about. */\n subject: Uuid;\n kind: ChartKind;\n /** Field keys whose values become the groups. */\n groupBy?: string[];\n /** A date Field truncated to a period — what a line runs along. */\n bucket?: { key: string; by: AggregateBucket } | null;\n /** `count` needs no key; every other measure reads one Field. */\n measures?: AggregateMeasure[];\n /** A scalar is an equality; an object is a half-open moment window. */\n filter?: Record<string, AggregateFilter>;\n limit?: number;\n /** How wide this block sits on the canvas, in twelfths. */\n span?: number;\n /** `stuck` only: the Field whose value is watched for a change. */\n stateKey?: string;\n /** `stuck` only: how long a record may sit on the same value. */\n days?: number;\n}\n\n/** A dashboard as `custom.dashboards` reports it, in the screen's own words. */\nexport interface SavedDashboard {\n id: Uuid;\n name: string;\n /** The subject Table: the one a block that names no table of its own reads. */\n subject: Uuid | null;\n blocks: ChartSpec[];\n presentation: Record<string, unknown>;\n /** The store's own version. A save re-states the whole dashboard. */\n version: number;\n}\n\n/** One saved block back into the shape a screen edits. */\nexport function specFromBlock(block: DashboardBlock, subject: Uuid): ChartSpec {\n return {\n title: block.title ?? CHART_KIND_LABEL[block.kind] ?? \"Block\",\n subject: (block.table_id as Uuid | null) ?? subject,\n kind: block.kind,\n ...(block.group_by ? { groupBy: block.group_by } : {}),\n ...(block.bucket === undefined ? {} : { bucket: block.bucket }),\n ...(block.measures ? { measures: block.measures } : {}),\n ...(block.filter ? { filter: block.filter } : {}),\n ...(block.limit === undefined ? {} : { limit: block.limit }),\n ...(block.span === undefined ? {} : { span: block.span }),\n ...(block.state_key === undefined ? {} : { stateKey: block.state_key }),\n ...(block.days === undefined ? {} : { days: block.days }),\n };\n}\n\n/**\n * One block back into the door's own argument. `custom.dashboard_declare` judges\n * every block on the way IN — a block naming a Field this Table does not have is\n * refused BY NAME — so a canvas cannot be saved broken.\n */\nexport function blockFromSpec(spec: ChartSpec, subject: Uuid): DashboardBlock {\n return {\n title: spec.title,\n kind: spec.kind,\n ...(spec.subject && spec.subject !== subject ? { table_id: spec.subject } : {}),\n ...(spec.groupBy ? { group_by: spec.groupBy } : {}),\n ...(spec.bucket === undefined ? {} : { bucket: spec.bucket }),\n ...(spec.measures ? { measures: spec.measures } : {}),\n ...(spec.filter ? { filter: spec.filter } : {}),\n ...(spec.limit === undefined ? {} : { limit: spec.limit }),\n ...(spec.span === undefined ? {} : { span: spec.span }),\n ...(spec.stateKey === undefined ? {} : { state_key: spec.stateKey }),\n ...(spec.days === undefined ? {} : { days: spec.days }),\n };\n}\n\n/** One row of `custom.dashboards` into the shape a screen and an agent both read. */\nexport function dashboardFromSummary(summary: DashboardSummary): SavedDashboard {\n const subject = (summary.table_id as Uuid | null) ?? null;\n return {\n id: summary.dashboard_id as Uuid,\n name: summary.name,\n subject,\n blocks: (summary.blocks ?? []).map((block) => specFromBlock(block, (subject ?? \"\") as Uuid)),\n presentation: summary.presentation ?? {},\n version: summary.version,\n };\n}\n\n/**\n * The exact arguments `custom.dashboard_declare` is called with. A save is a\n * RE-STATEMENT of the whole dashboard, so the presentation goes straight back:\n * a save that dropped it would quietly lose the question the person asked the\n * agent, which is what the canvas is FOR.\n */\nexport function dashboardDeclareArgs(board: SavedDashboard, subject: Uuid): {\n table_id: Uuid;\n name: string;\n blocks: DashboardBlock[];\n presentation: Record<string, unknown>;\n dashboard_id: Uuid | null;\n} {\n const table = (board.subject ?? subject) as Uuid;\n return {\n table_id: table,\n name: board.name,\n blocks: board.blocks.map((spec) => blockFromSpec(spec, table)),\n presentation: board.presentation ?? {},\n dashboard_id: board.id ?? null,\n };\n}\n\n/**\n * The series palette. Six SEMANTIC tokens the design system already flips for\n * dark mode, so a chart is correct in both themes without a second palette and\n * without a hex code anywhere in this package.\n */\nexport const SERIES_COLORS = [\n \"hsl(var(--primary))\",\n \"hsl(var(--info))\",\n \"hsl(var(--success))\",\n \"hsl(var(--warning))\",\n \"hsl(var(--destructive))\",\n \"hsl(var(--accent-foreground))\",\n] as const;\n\n/** The label one aggregate row carries — its groups, joined the way a person reads them. */\nexport function groupLabel(groups: Record<string, string | null>): string {\n const parts = Object.values(groups).map((v) => (v === null || v === \"\" ? \"—\" : v));\n return parts.length === 0 ? \"All records\" : parts.join(\" · \");\n}\n","\"use client\";\n\n// src/chartFrame.tsx — @ai-matrx/records-ui\n//\n// THE APP'S OWN CHART CONVENTIONS, IN THE PACKAGE THAT SHIPS THE SCREENS.\n//\n// AI Matrx draws charts with Recharts through a shadcn-shaped wrapper —\n// `matrx-frontend`'s `components/ui/chart.tsx` — whose whole idea is that a\n// series' colour is a CSS VARIABLE emitted per theme, so one `ChartConfig`\n// comes out right in light and in dark with no second palette and no hex code\n// in a component. `features/cx-dashboard`, `features/marketing/.../performance`\n// and `features/education/study` all draw that way, and a records dashboard\n// that invented its own look would be the one chart in the product that is\n// different.\n//\n// WHY IT IS RE-STATED HERE RATHER THAN IMPORTED. That file lives in the Next.js\n// app; this is a package the app consumes. The conventions are copied — the\n// `--color-<key>` variables, the tooltip's markup and classes, the legend's —\n// and the behaviour is the same. `recharts` itself is a PEER: the host provides\n// the one copy, so nothing is bundled twice.\n//\n// AND THERE IS NO `ResponsiveContainer`. It measures its parent, gets 0 in\n// jsdom, and renders a chart of nothing — which would make every component test\n// over these blocks a green test about an empty SVG. The width is measured with\n// a `ResizeObserver` and falls back to a sane one when there is no measurement\n// (a server render, an old browser, a test), so the chart always has real\n// dimensions and the suite proves what a person sees.\n\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentType,\n type CSSProperties,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport { cn } from \"@ai-matrx/design-system\";\n\n/** The same shape `components/ui/chart.tsx` takes: one entry per series key. */\nexport type ChartConfig = Record<\n string,\n { label?: ReactNode; icon?: ComponentType; color?: string }\n>;\n\n/**\n * MEASURE THE BOX, DO NOT ASK RECHARTS TO. Returns the ref to put on the\n * wrapper and the width to hand the chart. `ResizeObserver` being absent is not\n * an error: the fallback stands and the chart still draws.\n */\nexport function useMeasuredWidth(fallback = 480): [RefObject<HTMLDivElement | null>, number] {\n const ref = useRef<HTMLDivElement | null>(null);\n const [width, setWidth] = useState(fallback);\n useEffect(() => {\n const node = ref.current;\n if (!node) return;\n const apply = () => {\n const measured = Math.round(node.getBoundingClientRect().width);\n if (measured > 0) setWidth(measured);\n };\n apply();\n const Observer = (globalThis as unknown as { ResizeObserver?: typeof ResizeObserver })\n .ResizeObserver;\n if (typeof Observer !== \"function\") return;\n const observer = new Observer(apply);\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n return [ref, width];\n}\n\n/**\n * The colour variables, with the app's own names: `--color-<key>` on the chart's\n * own box, so every series refers to `var(--color-<key>)` exactly as it does in\n * `components/ui/chart.tsx`.\n *\n * The app emits them in a `<style>` block with a `.dark` copy, because its\n * configs carry literal per-theme colours. Ours carry SEMANTIC TOKENS\n * (`hsl(var(--primary))`), which the design system already flips for dark mode —\n * so one definition is right in both themes, and it goes on the element rather\n * than into an injected stylesheet.\n */\nfunction chartVariables(config: ChartConfig): CSSProperties {\n const style: Record<string, string> = {};\n for (const [key, entry] of Object.entries(config)) {\n if (entry.color) style[`--color-${key}`] = entry.color;\n }\n return style as CSSProperties;\n}\n\n/**\n * The box a chart lives in. It carries the app's own Recharts class overrides —\n * axis ticks in `muted-foreground`, the grid and the cursor in `border`, no\n * focus outline on a layer — so the chart sits in the page's own palette.\n */\nexport function ChartFrame({\n config,\n height,\n className,\n children,\n}: {\n config: ChartConfig;\n height: number;\n className?: string | undefined;\n children: (width: number) => ReactNode;\n}) {\n const [ref, width] = useMeasuredWidth();\n const chartId = `records-chart-${useId().replace(/:/g, \"\")}`;\n return (\n <div\n ref={ref}\n data-chart={chartId}\n style={{ height, ...chartVariables(config) }}\n className={cn(\n \"w-full min-w-0 overflow-hidden text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground \" +\n \"[&_.recharts-cartesian-grid_line]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border \" +\n \"[&_.recharts-layer]:outline-none [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted \" +\n \"[&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none\",\n className,\n )}\n >\n {children(width)}\n </div>\n );\n}\n\n/** One payload entry as Recharts injects it into a tooltip's `content` element. */\ninterface TooltipEntry {\n name?: string | number;\n dataKey?: string | number;\n value?: number | string;\n color?: string;\n payload?: Record<string, unknown>;\n}\n\n/**\n * The app's tooltip, with its markup and its classes. Recharts 3 injects\n * `active` / `payload` / `label` into the element it clones, so they are\n * declared optional here exactly as the app declares them.\n */\nexport function ChartTooltipContent({\n active,\n payload,\n label,\n config,\n className,\n}: {\n active?: boolean;\n payload?: ReadonlyArray<TooltipEntry>;\n label?: ReactNode;\n config: ChartConfig;\n className?: string | undefined;\n}) {\n if (!active || !payload || payload.length === 0) return null;\n return (\n <div\n className={cn(\n \"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl\",\n className,\n )}\n >\n {label ? <div className=\"font-medium\">{label}</div> : null}\n <div className=\"grid gap-1.5\">\n {payload.map((entry, index) => {\n const key = String(entry.dataKey ?? entry.name ?? index);\n return (\n <div key={key} className=\"flex w-full items-center gap-2\">\n <span\n className=\"h-2.5 w-2.5 shrink-0 rounded-[2px] bg-[--color-swatch]\"\n style={{ \"--color-swatch\": entry.color } as CSSProperties}\n />\n <span className=\"text-muted-foreground\">{config[key]?.label ?? key}</span>\n <span className=\"ml-auto font-mono font-medium tabular-nums text-foreground\">\n {typeof entry.value === \"number\" ? entry.value.toLocaleString() : entry.value}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\n/** The app's legend, with its markup and its classes. */\nexport function ChartLegendContent({\n payload,\n config,\n className,\n}: {\n payload?: ReadonlyArray<{ value?: string | number; color?: string; dataKey?: string | number }>;\n config: ChartConfig;\n className?: string | undefined;\n}) {\n if (!payload || payload.length === 0) return null;\n return (\n <div className={cn(\"flex flex-wrap items-center justify-center gap-3 pt-2\", className)}>\n {payload.map((entry, index) => {\n const key = String(entry.dataKey ?? entry.value ?? index);\n return (\n <span key={key} className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <span\n className=\"h-2 w-2 shrink-0 rounded-[2px] bg-[--color-swatch]\"\n style={{ \"--color-swatch\": entry.color } as CSSProperties}\n />\n {config[key]?.label ?? key}\n </span>\n );\n })}\n </div>\n );\n}\n","\"use client\";\n\n// src/docs.ts — @ai-matrx/records-ui · SCR-20, SCR-21, SCR-22\n//\n// DOCUMENTS OVER RECORDS. A template is a body whose tokens point at Fields BY\n// ID; a render is written ONCE and frozen with the SHA-256 of its own text; a\n// signature seals that exact version and is immutable once made.\n//\n// Three things this package refuses to re-implement, because the store already\n// does them and doing them twice is how two answers appear:\n// · which tokens a body contains — `custom.doc_tokens`;\n// · which of them this Table cannot answer, and why — `custom.doc_unresolved_tokens`;\n// · whether a signature still holds — `custom.doc_signature_intact`.\n//\n// The token syntax is the store's own: `{{field:<the field's id>}}`. A name\n// would be a token that silently stops resolving the day somebody renames a\n// Field, which is the exact failure REC-17 exists to prevent.\n\nimport type { Field, Uuid } from \"@ai-matrx/records\";\n\n/** The one token form, written the way the store's own pattern reads it. */\nexport function fieldToken(fieldId: Uuid): string {\n return `{{field:${fieldId}}}`;\n}\n\n/** THE DECLARATIVE SPEC an agent writes. One template, whole, in one object. */\nexport interface DocTemplateSpec {\n name: string;\n /** The body, tokens and all. */\n body: string;\n}\n\n/**\n * A template written in terms of Field KEYS — which is how an agent thinks and\n * how a person reads — turned into the store's id-based tokens. The agent writes\n * `{{title}}`; what is stored points at the Field's id, so a rename never\n * silently empties the document.\n *\n * A key this Table does not have is LEFT EXACTLY AS IT IS, so\n * `custom.doc_unresolved_tokens` names it and the screen shows the store's own\n * reason — it is never quietly deleted from the body.\n */\nexport function bodyFromKeys(body: string, fields: Field[]): string {\n const byKey = new Map(fields.map((f) => [f.key, f.id]));\n return body.replace(/\\{\\{\\s*([a-zA-Z0-9_]+)\\s*\\}\\}/g, (whole, key: string) => {\n const id = byKey.get(key);\n return id ? fieldToken(id) : whole;\n });\n}\n\n/** The reverse, for a person reading a stored body: ids shown as the Field's label. */\nexport function bodyForReading(body: string, fields: Field[]): string {\n const byId = new Map(fields.map((f) => [f.id, f.label || f.key]));\n return body.replace(/\\{\\{\\s*field:([0-9a-fA-F-]{36})\\s*\\}\\}/g, (whole, id: string) => {\n const label = byId.get(id);\n return label ? `{{${label}}}` : whole;\n });\n}\n\n/** VAL-10: a signature is a Value on a text Field whose format is `signature`. */\nexport function isSignatureField(field: Field): boolean {\n return field.type === \"text\" && (field.format ?? \"\").toLowerCase() === \"signature\";\n}\n","\"use client\";\n\n// src/DocTemplate.tsx — @ai-matrx/records-ui · SCR-20\n//\n// THE TEMPLATE EDITOR. A body, a palette of this Table's own Fields, and the\n// STORE's verdict on which tokens it cannot answer — never this package's.\n//\n// `custom.doc_unresolved_tokens` is asked on every change and its sentence is\n// shown verbatim beside the token it is about. A template is still saveable\n// with an unresolved token, because half-written is a normal state; what is not\n// allowed is publishing one and letting a token reach a person's document\n// looking like text somebody typed.\n//\n// `seed` is the agent's half, as everywhere: complete templates written in\n// Field KEYS (`{{title}}`), converted to the store's id-based tokens on the way\n// in, so a rename never silently empties a contract.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { DocTemplateRow, DocUnresolvedToken, RecordsError } from \"@ai-matrx/records\";\nimport { BasicInput, BasicTextarea, Button, Label, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useSeedGuard } from \"./seedOnce\";\nimport { useTableRights } from \"./host\";\nimport { bodyFromKeys, fieldToken, type DocTemplateSpec } from \"./docs\";\nimport { fieldName } from \"./names\";\n\nexport interface DocTemplateProps {\n /** The Table these templates render. */\n tableId: Uuid;\n /** COMPLETE templates an agent wrote, in Field keys. Saved once, never overwritten. */\n seed?: DocTemplateSpec[] | undefined;\n activeTemplateId?: Uuid | null | undefined;\n onActiveTemplate?: ((template: DocTemplateRow) => void) | undefined;\n className?: string | undefined;\n}\n\nexport function DocTemplate({ tableId, seed, activeTemplateId, onActiveTemplate, className }: DocTemplateProps) {\n const client = useRecordsClient();\n // One claim per seed name, per mount: a check against the server's list is\n // not a lock, and a loader that re-runs mid-write would write it twice.\n const claimSeed = useSeedGuard();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const fields = useFields(tableId);\n const [templates, setTemplates] = useState<DocTemplateRow[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [activeId, setActiveId] = useState<Uuid | null>(activeTemplateId ?? null);\n const [draftName, setDraftName] = useState(\"\");\n const [draftBody, setDraftBody] = useState(\"\");\n const [unresolved, setUnresolved] = useState<DocUnresolvedToken[]>([]);\n const [saving, setSaving] = useState(false);\n\n const load = useCallback(async () => {\n const held = await client.docTemplates({ table_id: tableId });\n if (!held.ok) {\n setError(held.error);\n return;\n }\n let rows = held.data;\n const missing = (seed ?? []).filter((s) => !rows.some((t) => t.name === s.name));\n if (missing.length > 0 && (fields.data ?? []).length > 0) {\n for (const spec of missing) {\n if (!claimSeed(spec.name)) continue;\n const saved = await client.docTemplateSave({\n table_id: tableId,\n name: spec.name,\n body: bodyFromKeys(spec.body, fields.data ?? []),\n });\n if (!saved.ok) {\n setError(saved.error);\n return;\n }\n }\n const again = await client.docTemplates({ table_id: tableId });\n if (!again.ok) {\n setError(again.error);\n return;\n }\n rows = again.data;\n }\n setError(null);\n setTemplates(rows);\n }, [client, tableId, seed, fields.data]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n useEffect(() => {\n if (!templates || templates.length === 0) return;\n const chosen = templates.find((t) => t.id === (activeTemplateId ?? activeId)) ?? templates[0]!;\n if (chosen.id !== activeId) setActiveId(chosen.id);\n setDraftName(chosen.name);\n setDraftBody(chosen.body);\n onActiveTemplate?.(chosen);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [templates, activeTemplateId]);\n\n // The STORE's verdict on the body, re-asked as it is typed. Never this\n // package's own idea of which token resolves.\n useEffect(() => {\n let cancelled = false;\n if (draftBody.trim() === \"\") {\n setUnresolved([]);\n return;\n }\n void client.docUnresolvedTokens({ table_id: tableId, body: draftBody }).then((answered) => {\n if (cancelled) return;\n if (answered.ok) setUnresolved(answered.data);\n });\n return () => {\n cancelled = true;\n };\n }, [client, tableId, draftBody]);\n\n async function save() {\n setSaving(true);\n const saved = await client.docTemplateSave({\n table_id: tableId,\n name: draftName.trim() || \"Untitled template\",\n body: draftBody,\n template_id: activeId,\n });\n setSaving(false);\n if (!saved.ok) {\n setError(saved.error);\n return;\n }\n setActiveId(saved.data);\n await load();\n }\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (templates === null || fields.loading) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (!rights.admin) {\n return <p className={cn(\"text-xs text-muted-foreground\", className)}>{rights.why(\"structure\")}</p>;\n }\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {/* One row: the templates, the version, the save. */}\n <div className=\"flex items-center gap-1 overflow-x-auto\" role=\"group\" aria-label=\"Templates\">\n {templates.map((t) => (\n <Button\n key={t.id}\n size=\"sm\"\n variant={t.id === activeId ? \"secondary\" : \"ghost\"}\n aria-pressed={t.id === activeId}\n onClick={() => {\n setActiveId(t.id);\n setDraftName(t.name);\n setDraftBody(t.body);\n }}\n >\n {t.name}\n <span className=\"ml-1 text-[10px] text-muted-foreground\">v{t.template_version}</span>\n </Button>\n ))}\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n setActiveId(null);\n setDraftName(\"\");\n setDraftBody(\"\");\n }}\n >\n New template\n </Button>\n <Button size=\"sm\" className=\"ml-auto\" disabled={saving} onClick={() => void save()}>\n {saving ? \"Saving…\" : \"Save\"}\n </Button>\n </div>\n\n <label className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">Name</Label>\n <BasicInput value={draftName} onChange={(e) => setDraftName(e.target.value)} placeholder=\"Agreement\" />\n </label>\n\n {/* The palette: this Table's own Fields, inserted as the store's own token. */}\n <div className=\"flex flex-wrap items-center gap-1\">\n <span className=\"text-xs text-muted-foreground\">Insert</span>\n {(fields.data ?? []).map((field) => (\n <Button\n key={field.id}\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-6 px-1.5 text-xs\"\n onClick={() => setDraftBody((body) => `${body}${fieldToken(field.id)}`)}\n >\n {fieldName(field)}\n </Button>\n ))}\n </div>\n\n <BasicTextarea\n rows={10}\n aria-label=\"Template body\"\n className=\"font-mono text-xs\"\n value={draftBody}\n onChange={(e) => setDraftBody(e.target.value)}\n />\n\n {/* The store's own sentence per token it cannot answer — verbatim. */}\n {unresolved.length > 0 ? (\n <ul className=\"flex flex-col gap-0.5 rounded border border-dashed px-2 py-1 text-xs\">\n {unresolved.map((token) => (\n <li key={token.raw} className=\"text-destructive\">\n <code>{token.raw}</code> — {token.why}\n </li>\n ))}\n </ul>\n ) : draftBody.trim() !== \"\" ? (\n <p className=\"text-xs text-muted-foreground\">\n Every token in this body points at a Field this table can answer.\n </p>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\n// src/DocRender.tsx — @ai-matrx/records-ui · SCR-21\n//\n// ONE TEMPLATE, ONE RECORD, ONE DOCUMENT — and the preview and the frozen\n// version are the SAME bytes, because both come from the store.\n//\n// `custom.doc_render_body` resolves the tokens without writing anything, which\n// is the preview. `custom.doc_render_document` writes the render: the text and\n// the SHA-256 of that text, frozen. Everything downstream — a signature, a PDF,\n// a link somebody sends — is about a VERSION, never about \"the document as it\n// happens to read today\". That is the whole reason a render is a row and not a\n// function call a screen repeats.\n//\n// The PDF is `@ai-matrx/print`'s, not a second renderer: the platform has one\n// answer to \"make this a PDF\" and this screen uses it.\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { DocRenderRow, RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\n\nexport interface DocRenderProps {\n templateId: Uuid;\n recordId: Uuid;\n /** A name for the file when somebody takes the PDF. */\n filename?: string | undefined;\n onRendered?: ((render: DocRenderRow) => void) | undefined;\n className?: string | undefined;\n}\n\nexport function DocRender({ templateId, recordId, filename, onRendered, className }: DocRenderProps) {\n const client = useRecordsClient();\n const [preview, setPreview] = useState<string | null>(null);\n const [renders, setRenders] = useState<DocRenderRow[] | null>(null);\n const [showing, setShowing] = useState<Uuid | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const paper = useRef<HTMLDivElement>(null);\n\n const load = useCallback(async () => {\n const [body, held] = await Promise.all([\n client.docRenderBody({ template_id: templateId, record_id: recordId }),\n client.docRenders({ record_id: recordId }),\n ]);\n if (!body.ok) {\n setError(body.error);\n return;\n }\n if (!held.ok) {\n setError(held.error);\n return;\n }\n setError(null);\n setPreview(body.data);\n setRenders(held.data.filter((r) => r.template_id === templateId));\n }, [client, templateId, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n async function freeze() {\n setBusy(\"freeze\");\n const written = await client.docRenderDocument({ template_id: templateId, record_id: recordId });\n setBusy(null);\n if (!written.ok) {\n setError(written.error);\n return;\n }\n await load();\n setShowing(written.data);\n const made = (await client.docRenders({ record_id: recordId }));\n if (made.ok) {\n const row = made.data.find((r) => r.id === written.data);\n if (row) onRendered?.(row);\n }\n }\n\n async function toPdf() {\n const element = paper.current;\n if (!element) return;\n setBusy(\"pdf\");\n try {\n // The platform's ONE answer to \"make this a PDF\". A second renderer here\n // would produce a document that does not match the printed one.\n const { captureToPDF } = await import(\"@ai-matrx/print/pdf\");\n await captureToPDF(element, { filename: filename ?? \"document\" });\n } catch (thrown) {\n setError({\n code: \"internal\",\n message: \"The PDF could not be made on this screen.\",\n hint: thrown instanceof Error ? thrown.message : String(thrown),\n });\n } finally {\n setBusy(null);\n }\n }\n\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (preview === null || renders === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n const frozen = showing ? (renders.find((r) => r.id === showing) ?? null) : null;\n const text = frozen ? frozen.body : preview;\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {/* One row: which version is on screen, and the two verbs. */}\n <div className=\"flex items-center gap-1 text-xs\">\n <Button\n size=\"sm\"\n variant={frozen ? \"ghost\" : \"secondary\"}\n aria-pressed={!frozen}\n onClick={() => setShowing(null)}\n >\n As it reads now\n </Button>\n {renders.map((render) => (\n <Button\n key={render.id}\n size=\"sm\"\n variant={render.id === showing ? \"secondary\" : \"ghost\"}\n aria-pressed={render.id === showing}\n onClick={() => setShowing(render.id)}\n title={`Template v${render.template_version} · ${render.content_hash.slice(0, 12)}`}\n >\n {new Date(render.rendered_at).toLocaleString()}\n </Button>\n ))}\n <span className=\"ml-auto flex items-center gap-1\">\n <Button size=\"sm\" disabled={busy !== null} onClick={() => void freeze()}>\n {busy === \"freeze\" ? \"Freezing…\" : \"Freeze this version\"}\n </Button>\n <Button size=\"sm\" variant=\"ghost\" disabled={busy !== null} onClick={() => void toPdf()}>\n {busy === \"pdf\" ? \"Making the PDF…\" : \"PDF\"}\n </Button>\n </span>\n </div>\n\n {/* The document. Frozen bytes when a version is chosen, the live resolution\n otherwise — and the screen says which, because they are not the same thing. */}\n <div ref={paper} className=\"whitespace-pre-wrap rounded border bg-background p-4 text-sm text-foreground\">\n {text}\n </div>\n\n <p className=\"text-xs text-muted-foreground\">\n {frozen\n ? `Frozen ${new Date(frozen.rendered_at).toLocaleString()} from template v${frozen.template_version}. Its text and its SHA-256 (${frozen.content_hash.slice(0, 12)}…) are what any signature seals.`\n : \"This is how the template reads against this record right now. Nothing has been frozen, so there is no version for anyone to sign yet.\"}\n </p>\n </div>\n );\n}\n","\"use client\";\n\n// src/SignBlock.tsx — @ai-matrx/records-ui · SCR-22\n//\n// A SIGNATURE IS A VALUE, AND THE STORE DECIDES WHETHER IT STILL HOLDS.\n//\n// VAL-10: a signature is written on a text Field whose format is `signature`,\n// on the record's own Table, through `custom.doc_sign` — which writes it as an\n// ordinary Value with the envelope law's stamp plus the document version and\n// hash it sealed. So a signature is in History, in the export and in the agent's\n// context like any other Value, and there is no signatures feature bolted on.\n//\n// THREE THINGS THIS SCREEN NEVER DOES:\n// · It never checks a seal itself. `custom.doc_signature_intact` answers, and\n// its verdict is shown as the store said it.\n// · It never offers to re-sign. The door refuses a second signature on a Field\n// already signed, and the screen says the same sentence rather than showing a\n// button that will be refused.\n// · It never signs anything unfrozen. A seal is over a document VERSION, so\n// with no render there is no Sign — and the reason is on screen.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useFields, useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { DocRenderRow, DocSignatureRow, Field, RecordsError } from \"@ai-matrx/records\";\nimport { BasicInput, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { useTable } from \"@ai-matrx/records/react\";\nimport { isSignatureField } from \"./docs\";\nimport { fieldName } from \"./names\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface SignBlockProps {\n tableId: Uuid;\n recordId: Uuid;\n /** The frozen version being signed. Without one there is nothing to seal. */\n render: DocRenderRow | null;\n className?: string | undefined;\n}\n\nexport function SignBlock({ tableId, recordId, render, className }: SignBlockProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const fields = useFields(tableId);\n const [signatures, setSignatures] = useState<DocSignatureRow[] | null>(null);\n const [verdicts, setVerdicts] = useState<Record<string, unknown>>({});\n const [error, setError] = useState<RecordsError | null>(null);\n const [name, setName] = useState(\"\");\n const [busy, setBusy] = useState(false);\n\n const load = useCallback(async () => {\n const held = await client.docSignatures({ record_id: recordId });\n if (!held.ok) {\n setError(held.error);\n return;\n }\n setError(null);\n setSignatures(held.data);\n // Whether each seal still holds is the STORE's answer, asked for each one.\n const answers: Record<string, unknown> = {};\n for (const signature of held.data) {\n const intact = await client.docSignatureIntact({ signature_id: signature.id });\n answers[signature.id] = intact.ok ? intact.data : refusalLineForAPerson(intact.error);\n }\n setVerdicts(answers);\n }, [client, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n async function sign(field: Field) {\n if (!render) return;\n setBusy(true);\n const signed = await client.docSign({\n render_id: render.id,\n field_key: field.key,\n signer_name: name.trim(),\n signer_user_id: client.config.actor.user_id ?? null,\n });\n setBusy(false);\n if (!signed.ok) {\n setError(signed.error);\n return;\n }\n setName(\"\");\n await load();\n }\n\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (fields.loading || signatures === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n const signable = (fields.data ?? []).filter(isSignatureField);\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Signatures</span>\n <span>{signatures.length} on this record</span>\n </div>\n\n {signatures.length > 0 ? (\n <ul className=\"flex flex-col gap-1\">\n {signatures.map((signature) => {\n const verdict = verdicts[signature.id];\n const intact = typeof verdict === \"object\" && verdict !== null ? (verdict as { intact?: boolean }).intact : undefined;\n return (\n <li key={signature.id} className=\"rounded border px-2 py-1.5 text-xs\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{signature.signer_name}</span>\n <span className=\"text-muted-foreground\">{signature.field_key}</span>\n <span className=\"text-muted-foreground\">{new Date(signature.signed_at).toLocaleString()}</span>\n <span className=\"ml-auto font-mono text-[10px] text-muted-foreground\">\n v{signature.document_version} · {signature.document_hash.slice(0, 12)}\n </span>\n </div>\n {/* The store's verdict, not a check this screen invented. */}\n <p className={cn(\"mt-0.5\", intact === false ? \"text-destructive\" : \"text-muted-foreground\")}>\n {intact === true\n ? \"The store says what was signed is still exactly what is there.\"\n : intact === false\n ? typeof verdict === \"object\" && verdict !== null && \"reason\" in verdict\n ? String((verdict as { reason?: unknown }).reason)\n : \"The store says what is there no longer matches what was signed.\"\n : String(verdict ?? \"\")}\n </p>\n </li>\n );\n })}\n </ul>\n ) : null}\n\n {/* A seal is over a VERSION, so with nothing frozen there is no Sign at\n all — and the reason is on screen rather than a dead button. */}\n {!render ? (\n <p className=\"text-xs text-muted-foreground\">\n Nothing has been frozen yet, so there is no version to sign. A signature seals one exact document\n version and its hash — \"the document as it reads today\" is not something anyone can agree to.\n </p>\n ) : signable.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n This table has no signature Field, so there is nowhere to write a signature. A signature is a Value\n on a text Field whose format is <code>signature</code> — add one and the signing appears.\n </p>\n ) : !rights.write ? (\n <p className=\"text-xs text-muted-foreground\">{rights.why(\"write\")}</p>\n ) : (\n <div className=\"flex flex-col gap-1\">\n {signable.map((field) => {\n const already = signatures.find((s) => s.field_key === field.key);\n if (already) {\n return (\n <p key={field.id} className=\"text-xs text-muted-foreground\">\n {fieldName(field)} is signed, and a signature is immutable once made. A further\n agreement is a further Field with its own signature, or a further version with its own seal.\n </p>\n );\n }\n return (\n <form\n key={field.id}\n className=\"flex items-center gap-1\"\n onSubmit={(event) => {\n event.preventDefault();\n if (name.trim() !== \"\") void sign(field);\n }}\n >\n <BasicInput\n className=\"h-8 w-56 text-xs\"\n aria-label={`Sign ${fieldName(field)}`}\n placeholder=\"Type your full name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n <Button size=\"sm\" type=\"submit\" disabled={busy || name.trim() === \"\"}>\n Sign\n </Button>\n <span className=\"text-xs text-muted-foreground\">\n seals version {render.template_version} · {render.content_hash.slice(0, 12)}…\n </span>\n </form>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/NotifyRuleEditor.tsx — @ai-matrx/records-ui · SCR-19\n//\n// \"TELL ME WHEN SOMETHING IN THIS VIEW CHANGES\" — and that sentence is a RULE\n// RECORD, not a notifications table.\n//\n// DOOR-18: a subscription is an ordinary Rule carrying a `subscription` block\n// that names a saved view, a cadence, a channel and the person to tell. The\n// store answers `custom.agg_subscriptions`, fires `custom.agg_subscription_fire`\n// and delivers through `communication.notification`. So there is one notifier in\n// this platform, and a subscription is readable, historied, exportable and\n// agent-writable exactly like everything else this package touches.\n//\n// THE PART THAT MATTERS MOST IS NOT ON THIS SCREEN. `custom.agg_view_admits`\n// runs the admission test as the SUBSCRIBER, not as the writer: a change to a\n// record the subscriber may not see is not a notification they are entitled to,\n// because the notification's existence would leak the record. This editor never\n// re-implements that test and never offers to turn it off.\n//\n// `seed` is the agent's half, as everywhere else: complete declarative\n// subscriptions, written once, never overwriting one a person has since changed.\n//\n// WHAT DOES NOT WORK YET, AND WHY IT SAYS SO INSTEAD OF PRETENDING. A\n// subscription is a RULE record, and `custom.record_write` — the one write door\n// — inserts `data_class = 'record'`. A document written that way is not a Rule:\n// `custom.agg_subscriptions` never sees it, so a screen that wrote one and said\n// \"subscribed\" would have subscribed nobody to anything and left a stray record\n// behind. Declaring a Rule needs a door of its own (`custom.rule_declare`,\n// W1-RULE's), so this editor asks for that door BY NAME and shows the store's\n// refusal. Reading, listing and stopping a subscription all work today; the day\n// the door lands, so does subscribing, with no change on this screen.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, Subscription } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { NO_SAVED_VIEWS_REASON, useRecordsUi, useTableRights } from \"./host\";\n\n/** THE DECLARATIVE SPEC an agent writes. One declaration and a person is told. */\nexport interface NotifyRuleSpec {\n name: string;\n savedViewId: Uuid;\n /** `immediate` fires on the change; `digest` is collected and sent on a schedule. */\n cadence?: string;\n /** The digest's schedule, in the store's own words. Meaningless for `immediate`. */\n schedule?: string | null;\n channel?: string;\n /** Who is told. Left out, the person setting it up — \"tell ME\". */\n recipientUserId?: Uuid | null;\n eventKey?: string;\n}\n\nexport interface NotifyRuleEditorProps {\n /** The Table these subscriptions are about — the Rule's scope. */\n tableId: Uuid;\n /** COMPLETE declarative subscriptions an agent wrote. Saved once, never overwritten. */\n seed?: NotifyRuleSpec[] | undefined;\n className?: string | undefined;\n}\n\nexport function NotifyRuleEditor({ tableId, seed, className }: NotifyRuleEditorProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const [subscriptions, setSubscriptions] = useState<Subscription[] | null>(null);\n const [cadences, setCadences] = useState<string[]>([]);\n const [views, setViews] = useState<Array<{ id: Uuid; name: string }> | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n\n const load = useCallback(async () => {\n const [held, offered] = await Promise.all([\n client.aggSubscriptions(),\n // The cadences are ASKED of the store, never a list typed into a picker\n // here that could drift from what the digest runner understands.\n client.aggSubscriptionCadences(),\n ]);\n if (!held.ok) {\n setError(held.error);\n return;\n }\n setError(null);\n setSubscriptions(held.data);\n if (offered.ok) setCadences(offered.data);\n if (host.savedViews) setViews(await host.savedViews());\n else setViews(null);\n }, [client, host]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const write = useCallback(\n async (spec: NotifyRuleSpec) => {\n const declared = await client.ruleDeclare({\n spec: {\n name: spec.name,\n // REC-15: a subscription answers yes-or-no about a record, so it is a\n // predicate, and what it decides is membership of the view.\n kind: \"predicate\",\n uses: [\"membership\"],\n scope_table_id: tableId,\n applies_to_types: [],\n expr: { const: true },\n subscription: {\n saved_view_id: spec.savedViewId,\n cadence: spec.cadence ?? \"immediate\",\n schedule: spec.schedule ?? null,\n channel: spec.channel ?? \"in_app\",\n // \"Tell me\" is the default, and the store fires at nobody when this\n // is null — which it says out loud rather than dropping quietly.\n recipient_user_id: spec.recipientUserId ?? client.config.actor.user_id ?? null,\n event_key: spec.eventKey ?? \"records.changed\",\n },\n },\n });\n if (!declared.ok) {\n setError(declared.error);\n return false;\n }\n return true;\n },\n [client, tableId],\n );\n\n // The agent's specs, saved once. A seed whose name is already subscribed is\n // left alone — an agent re-running never overwrites a person's tweak.\n useEffect(() => {\n if (!subscriptions || !seed || seed.length === 0) return;\n const missing = seed.filter((s) => !subscriptions.some((held) => held.name === s.name));\n if (missing.length === 0) return;\n void (async () => {\n for (const spec of missing) {\n if (!(await write(spec))) return;\n }\n await load();\n })();\n }, [subscriptions, seed, write, load]);\n\n async function subscribe(viewId: Uuid, viewName: string, cadence: string) {\n setBusy(true);\n const ok = await write({ name: `${viewName} — ${cadence}`, savedViewId: viewId, cadence });\n setBusy(false);\n if (ok) await load();\n }\n\n async function unsubscribe(ruleId: Uuid) {\n setBusy(true);\n const deleted = await client.recordDelete({ record_id: ruleId });\n setBusy(false);\n if (!deleted.ok) {\n setError(deleted.error);\n return;\n }\n await load();\n }\n\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (subscriptions === null) return <Skeleton className={cn(\"h-40 w-full\", className)} />;\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {/* One row. What this is, and how many there are — no subtitle repeating it. */}\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Tell me when</span>\n <span>{subscriptions.length} subscription{subscriptions.length === 1 ? \"\" : \"s\"}</span>\n </div>\n\n {subscriptions.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n Nothing is telling anyone about this yet. A subscription is a Rule over a saved view, so what\n you are told about is exactly what that view holds.\n </p>\n ) : (\n <ul className=\"flex flex-col gap-1\">\n {subscriptions.map((held) => (\n <li key={held.rule_id} className=\"flex items-center gap-2 rounded border px-2 py-1.5 text-xs\">\n <span className=\"truncate font-medium\">{held.name}</span>\n <span className=\"text-muted-foreground\">{held.cadence}</span>\n <span className=\"text-muted-foreground\">{held.channel}</span>\n {held.cadence === \"digest\" && held.schedule ? (\n <span className=\"text-muted-foreground\">{held.schedule}</span>\n ) : null}\n {/* Nothing fails silently: a subscription that fires at nobody\n says so, rather than looking like it is working. */}\n {held.recipient_user_id === null ? (\n <span className=\"text-destructive\">\n This one has nobody to tell, so it fires at nobody.\n </span>\n ) : null}\n {held.saved_view_id === null ? (\n <span className=\"text-destructive\">\n This one names no view, so the store never admits a record to it.\n </span>\n ) : null}\n {rights.write ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"ml-auto\"\n disabled={busy}\n onClick={() => void unsubscribe(held.rule_id)}\n >\n Stop telling me\n </Button>\n ) : null}\n </li>\n ))}\n </ul>\n )}\n\n {/* Subscribing to a view needs the views, and the store has no door onto\n them — so with no port bound this says that, rather than showing an\n empty picker that reads like \"you have no views\". */}\n {views === null ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n {NO_SAVED_VIEWS_REASON}\n </p>\n ) : views.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n This organization has no saved views yet, so there is nothing to subscribe to. Save a view first.\n </p>\n ) : rights.write ? (\n <form\n className=\"flex items-center gap-1\"\n onSubmit={(event) => {\n event.preventDefault();\n const form = event.currentTarget;\n const view = (form.elements.namedItem(\"view\") as HTMLSelectElement).value;\n const cadence = (form.elements.namedItem(\"cadence\") as HTMLSelectElement).value;\n const name = views.find((v) => v.id === view)?.name ?? \"View\";\n if (view) void subscribe(view, name, cadence);\n }}\n >\n <select name=\"view\" aria-label=\"View to be told about\" className=\"h-7 rounded border bg-background px-1 text-xs\">\n {views.map((view) => (\n <option key={view.id} value={view.id}>\n {view.name}\n </option>\n ))}\n </select>\n <select name=\"cadence\" aria-label=\"How often\" className=\"h-7 rounded border bg-background px-1 text-xs\">\n {(cadences.length > 0 ? cadences : [\"immediate\"]).map((cadence) => (\n <option key={cadence} value={cadence}>\n {cadence === \"immediate\" ? \"as it happens\" : cadence}\n </option>\n ))}\n </select>\n <Button size=\"sm\" type=\"submit\" disabled={busy}>\n Tell me\n </Button>\n </form>\n ) : (\n <p className=\"text-xs text-muted-foreground\">{rights.why(\"write\")}</p>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/ChartBlock.tsx — @ai-matrx/records-ui · SCR-15\n//\n// ONE BLOCK'S ANSWER, DRAWN. This component does NO arithmetic and opens no\n// door: it is handed one `DashboardBlockResult` out of the single\n// `custom.dashboard_run` the canvas made, and turns the groups and measures the\n// store computed into pixels.\n//\n// WHY NOT ONE CALL PER BLOCK, WHICH IS WHAT THIS FILE USED TO DO: the door\n// answers every block of a canvas in ONE snapshot, taken at one moment, under\n// one principal — so eight blocks cannot disagree with each other about what\n// the last hour did, and eight round trips become one.\n//\n// EVERY NUMBER CLICKS THROUGH TO THE RECORDS IT COUNTS. A bar, a slice, a\n// point, a table row and the big number all ask the host's `openRecords` port\n// for the block's own filter with the clicked group over the top. Unbound, the\n// marks are not clickable and the canvas says so once — never a mark that looks\n// pressable and does nothing.\n//\n// A SHAPE THAT CANNOT BE DRAWN SAYS THE SENTENCE THAT FIXES IT, and a block the\n// store REFUSED says the store's own sentence while its siblings still draw.\n\nimport { useMemo } from \"react\";\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Cell,\n Legend,\n Line,\n LineChart,\n Pie,\n PieChart,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport {\n measureKey,\n type AggregateFilter,\n type AggregateRow,\n type DashboardBlockResult,\n type RecordsError,\n type StuckRow,\n type Uuid,\n} from \"@ai-matrx/records\";\nimport { mapPgError } from \"@ai-matrx/records/core\";\nimport { cn } from \"@ai-matrx/design-system\";\n\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi } from \"./host\";\nimport {\n CHART_KIND_LABEL,\n CHART_NEEDS,\n SERIES_COLORS,\n groupLabel,\n type ChartKind,\n} from \"./charts\";\nimport {\n ChartFrame,\n ChartLegendContent,\n ChartTooltipContent,\n type ChartConfig,\n} from \"./chartFrame\";\n\nexport interface ChartBlockProps {\n /** One block out of the canvas's single run — answered, or refused. */\n block: DashboardBlockResult;\n /** The dashboard's subject Table, for a block that names none of its own. */\n subject: Uuid;\n className?: string | undefined;\n}\n\n/** One point a person can click: the group it stands for and what it measured. */\ninterface Point {\n label: string;\n groups: Record<string, string | null>;\n values: Record<string, number>;\n n: number;\n}\n\nfunction pretty(n: number): string {\n return Number.isInteger(n) ? n.toLocaleString() : n.toLocaleString(undefined, { maximumFractionDigits: 2 });\n}\n\n/**\n * The store's own refusal for one block, put through the SAME classifier every\n * other refusal in this package goes through — the door's SQLSTATE decides what\n * kind of refusal it is, so a person reads it in the same words here as\n * everywhere else and nobody invents a code.\n */\nfunction asRefusal(block: DashboardBlockResult): RecordsError {\n return mapPgError(\n {\n message: block.refused ?? \"\",\n ...(block.sqlstate ? { code: block.sqlstate } : {}),\n } as Parameters<typeof mapPgError>[0],\n \"dashboard_run\",\n );\n}\n\nexport function ChartBlock({ block, subject, className }: ChartBlockProps) {\n const host = useRecordsUi();\n const kind = block.kind as ChartKind;\n const tableId = (block.table_id as Uuid | undefined) ?? subject;\n\n const measures = block.measures && block.measures.length > 0 ? block.measures : [{ op: \"count\" as const }];\n const primary = measureKey(measures[0]!);\n // ONE Y AXIS, SO ONE MEASURE IS DRAWN. Found by looking at the render, not by\n // reading the code: a block measuring `count` AND `sum of amount` drew both as\n // bars on one axis, so the axis scaled to 80,000, the bars were the SUMS — and\n // the block's own header and the value list beneath it both said `count 28`.\n // A person read \"Awaiting parts 28\" beside a bar seventy thousand tall. Two\n // units on one scale is the dual-axis error wearing a single axis: the second\n // series is either invisible or it is the only thing you can see, and either\n // way the picture and the label disagree.\n //\n // The drawing shows the FIRST measure — the one the header names and the one\n // every value under the chart reports — and the rest of the measures are in the\n // block's saved question and in the tooltip's own rows. A second measure that\n // deserves its own picture deserves its own block, which is one dropdown away.\n const series = [primary];\n\n const points = useMemo<Point[]>(() => {\n if (kind === \"stuck\") return [];\n const rows = (block.rows ?? []) as AggregateRow[];\n return rows.map((row) => ({\n label: groupLabel(row.groups ?? {}),\n groups: row.groups ?? {},\n values: Object.fromEntries(\n series.map((key) => [key, typeof row.measures?.[key] === \"number\" ? (row.measures[key] as number) : 0]),\n ),\n n: row.row_count,\n }));\n }, [block.rows, kind, series.join(\"|\")]);\n\n const config = useMemo<ChartConfig>(() => {\n const out: ChartConfig = {};\n series.forEach((key, index) => {\n out[key] = {\n label: key.replace(\"_\", \" of \"),\n color: SERIES_COLORS[index % SERIES_COLORS.length]!,\n };\n });\n points.forEach((point, index) => {\n out[point.label] ??= { label: point.label, color: SERIES_COLORS[index % SERIES_COLORS.length]! };\n });\n return out;\n }, [series.join(\"|\"), points]);\n\n const grouped = (block.group_by ?? []).length > 0 || !!block.bucket;\n const needs = block.refused ? null : grouped || kind === \"number\" || kind === \"table\" || kind === \"stuck\"\n ? null\n : CHART_NEEDS[kind];\n\n /** The records behind one point: the block's own filter, then the group clicked. */\n const drill = host.openRecords\n ? (point: Point) => {\n const filter: Record<string, AggregateFilter> = { ...(block.filter ?? {}) };\n for (const [key, value] of Object.entries(point.groups)) filter[key] = value;\n host.openRecords!({\n tableId,\n filter,\n label: point.label === \"All records\" ? block.title : `${block.title} · ${point.label}`,\n });\n }\n : null;\n\n return (\n <figure className={cn(\"flex min-w-0 flex-col gap-1.5 rounded border p-2\", className)}>\n {/* ONE ROW. The title, what is being measured, and how long the store took. */}\n <figcaption className=\"flex items-baseline gap-2 text-xs\">\n <span className=\"truncate font-medium\">{block.title || CHART_KIND_LABEL[kind]}</span>\n <span className=\"ml-auto shrink-0 text-muted-foreground\">\n {kind === \"stuck\" ? `${block.days ?? 14} days` : primary.replace(\"_\", \" of \")}\n </span>\n {typeof block.ms === \"number\" ? (\n <span className=\"shrink-0 tabular-nums text-muted-foreground/70\" title=\"how long the store took\">\n {pretty(block.ms)} ms\n </span>\n ) : null}\n </figcaption>\n\n {block.refused ? (\n <RefusalNotice error={asRefusal(block)} />\n ) : needs ? (\n <p className=\"px-1 py-3 text-xs text-muted-foreground\">{needs}</p>\n ) : kind === \"stuck\" ? (\n <StuckList rows={(block.rows ?? []) as StuckRow[]} />\n ) : points.length === 0 ? (\n <p className=\"px-1 py-3 text-xs text-muted-foreground\">\n The store answered this question with no groups at all, so there is nothing to draw yet.\n </p>\n ) : (\n <>\n {kind === \"number\" ? (\n <BigNumber points={points} measure={primary} onDrill={drill} />\n ) : kind === \"table\" ? (\n <GroupTable points={points} series={series} onDrill={drill} />\n ) : (\n <>\n <Drawing kind={kind} points={points} series={series} config={config} onDrill={drill} />\n {/* THE VALUES, AS REAL CONTROLS. A chart nobody can reach with a\n keyboard is a chart half the people cannot use, so every group\n is a button here as well as a mark in the drawing. */}\n <Values points={points} measure={primary} config={config} onDrill={drill} />\n </>\n )}\n </>\n )}\n </figure>\n );\n}\n\nfunction BigNumber({\n points,\n measure,\n onDrill,\n}: {\n points: Point[];\n measure: string;\n onDrill: ((point: Point) => void) | null;\n}) {\n const total = points.reduce((sum, p) => sum + (p.values[measure] ?? 0), 0);\n const records = points.reduce((sum, p) => sum + p.n, 0);\n const body = (\n <>\n <span className=\"text-2xl font-semibold tabular-nums\">{pretty(total)}</span>\n <span className=\"text-xs text-muted-foreground\">from {records.toLocaleString()} records</span>\n </>\n );\n if (!onDrill || !points[0]) return <div className=\"flex items-baseline gap-2 px-1 py-2\">{body}</div>;\n return (\n <button\n type=\"button\"\n className=\"flex items-baseline gap-2 rounded px-1 py-2 text-left hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n onClick={() => onDrill(points[0]!)}\n >\n {body}\n </button>\n );\n}\n\nfunction Values({\n points,\n measure,\n config,\n onDrill,\n}: {\n points: Point[];\n measure: string;\n config: ChartConfig;\n onDrill: ((point: Point) => void) | null;\n}) {\n return (\n <ul className=\"flex flex-wrap gap-x-2 gap-y-0.5\">\n {points.map((point) => {\n const text = (\n <>\n <span\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n style={{ background: String(config[point.label]?.color ?? SERIES_COLORS[0]) }}\n />\n <span className=\"truncate\">{point.label}</span>\n <span className=\"tabular-nums text-muted-foreground\">{pretty(point.values[measure] ?? 0)}</span>\n </>\n );\n return (\n <li key={point.label} className=\"min-w-0\">\n {onDrill ? (\n <button\n type=\"button\"\n className=\"flex min-w-0 items-center gap-1.5 rounded px-1 py-0.5 text-xs hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n onClick={() => onDrill(point)}\n >\n {text}\n </button>\n ) : (\n <span className=\"flex min-w-0 items-center gap-1.5 px-1 py-0.5 text-xs\">{text}</span>\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n\nfunction GroupTable({\n points,\n series,\n onDrill,\n}: {\n points: Point[];\n series: string[];\n onDrill: ((point: Point) => void) | null;\n}) {\n return (\n <table className=\"w-full text-xs\">\n <tbody>\n {points.map((point) => (\n <tr key={point.label} className=\"border-t first:border-t-0\">\n <td className=\"min-w-0 truncate py-0.5 pr-2\">\n {onDrill ? (\n <button\n type=\"button\"\n className=\"max-w-full truncate rounded px-1 text-left hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n onClick={() => onDrill(point)}\n >\n {point.label}\n </button>\n ) : (\n point.label\n )}\n </td>\n {series.map((key) => (\n <td key={key} className=\"py-0.5 pl-2 text-right tabular-nums\">\n {pretty(point.values[key] ?? 0)}\n </td>\n ))}\n <td className=\"py-0.5 pl-2 text-right tabular-nums text-muted-foreground\">{point.n}</td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n}\n\nfunction StuckList({ rows }: { rows: StuckRow[] }) {\n if (rows.length === 0) {\n return (\n <p className=\"px-1 py-3 text-xs text-muted-foreground\">\n Nothing has sat still this long. This block goes quiet when the work is moving.\n </p>\n );\n }\n // `table-fixed` AND A `colgroup`, BECAUSE A TABLE CELL SIZES TO ITS CONTENT.\n // `w-full` with automatic layout let a long record title and its stage push the\n // day count off the right edge — at 390 px the first render of this list read\n // \"Job 101 · Scheduled · 3\" with \"1 days\" past the card — and `truncate` on a\n // <td> does nothing about it, because the cell was never the thing being\n // squeezed. The DAY COUNT is the whole point of a stuck list and is the column\n // that must never be the one that goes; the title gives way first.\n return (\n <table className=\"w-full table-fixed text-xs\">\n <colgroup>\n <col className=\"w-[45%]\" />\n <col className=\"w-[33%]\" />\n <col className=\"w-[22%]\" />\n </colgroup>\n <thead className=\"sr-only\">\n <tr>\n <th>Record</th>\n <th>Where it is</th>\n <th>Days unchanged</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.record_id} className=\"border-t first:border-t-0\">\n <td className=\"truncate py-0.5 pr-2\" title={row.title ?? undefined}>\n {row.title ?? row.record_id.slice(0, 8)}\n </td>\n <td className=\"truncate py-0.5 pr-2 text-muted-foreground\" title={row.state ?? undefined}>\n {row.state ?? \"—\"}\n </td>\n <td\n className=\"whitespace-nowrap py-0.5 text-right tabular-nums\"\n title={row.measured_from}\n >\n {row.days_unchanged} days\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n}\n\nconst HEIGHT = 140;\n\n/**\n * ONE TICK, SHORT ENOUGH TO FIT. A category tick is a word and passes through\n * untouched; a number becomes 1.2k / 3.4M / 5.6B, and anything under a thousand\n * keeps every digit because rounding a small count is how a chart starts lying.\n */\nfunction compactTick(value: unknown): string {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return String(value ?? \"\");\n const abs = Math.abs(value);\n if (abs < 1000) return Number.isInteger(value) ? String(value) : value.toFixed(1);\n for (const [size, suffix] of [\n [1e9, \"B\"],\n [1e6, \"M\"],\n [1e3, \"k\"],\n ] as const) {\n if (abs >= size) {\n const scaled = value / size;\n return `${Math.abs(scaled) >= 100 ? Math.round(scaled) : Number(scaled.toFixed(1))}${suffix}`;\n }\n }\n return String(value);\n}\n\nfunction Drawing({\n kind,\n points,\n series,\n config,\n onDrill,\n}: {\n kind: ChartKind;\n points: Point[];\n series: string[];\n config: ChartConfig;\n onDrill: ((point: Point) => void) | null;\n}) {\n const data = points.map((point) => ({ label: point.label, ...point.values }));\n const click = onDrill\n ? (_entry: unknown, index: number) => {\n const point = points[index];\n if (point) onDrill(point);\n }\n : undefined;\n // AN AXIS LABEL THAT DOES NOT FIT IS AN AXIS LABEL THAT LIES. Recharts clips a\n // tick to the axis width rather than growing it, so a sum of 70,198 rendered as\n // \"0000\" in the first screenshot of this canvas — three identical ticks and a\n // zero, on a chart whose whole job is to say how big something is. Money and\n // counts are abbreviated the way every dashboard worth copying abbreviates them,\n // and the exact figure is one hover away in the tooltip.\n const axis = {\n stroke: \"currentColor\",\n fontSize: 10,\n tickLine: false,\n axisLine: false,\n tickFormatter: compactTick,\n } as const;\n const tooltip = <Tooltip content={<ChartTooltipContent config={config} />} cursor={false} />;\n const legend =\n series.length > 1 ? <Legend content={<ChartLegendContent config={config} />} /> : null;\n\n if (kind === \"donut\") {\n return (\n <ChartFrame config={config} height={HEIGHT}>\n {(width) => (\n <PieChart width={width} height={HEIGHT}>\n {tooltip}\n <Pie\n data={data}\n dataKey={series[0]!}\n nameKey=\"label\"\n innerRadius={34}\n outerRadius={58}\n isAnimationActive={false}\n {...(click ? { onClick: click, className: \"cursor-pointer\" } : {})}\n >\n {points.map((point) => (\n <Cell key={point.label} fill={String(config[point.label]?.color ?? SERIES_COLORS[0])} />\n ))}\n </Pie>\n </PieChart>\n )}\n </ChartFrame>\n );\n }\n\n if (kind === \"line\") {\n return (\n <ChartFrame config={config} height={HEIGHT}>\n {(width) => (\n <LineChart width={width} height={HEIGHT} data={data} margin={{ top: 6, right: 6, bottom: 0, left: 0 }}>\n <CartesianGrid vertical={false} />\n <XAxis dataKey=\"label\" {...axis} />\n <YAxis width={44} {...axis} />\n {tooltip}\n {legend}\n {series.map((key) => (\n <Line\n key={key}\n type=\"monotone\"\n dataKey={key}\n stroke={`var(--color-${key})`}\n strokeWidth={2}\n dot={false}\n isAnimationActive={false}\n {...(click ? { className: \"cursor-pointer\" } : {})}\n />\n ))}\n </LineChart>\n )}\n </ChartFrame>\n );\n }\n\n // `bar` runs across, because a category label is words and words read across;\n // `column` stands up, which is what a period or a small set reads as.\n const horizontal = kind === \"bar\";\n return (\n <ChartFrame config={config} height={HEIGHT}>\n {(width) => (\n <BarChart\n width={width}\n height={HEIGHT}\n data={data}\n layout={horizontal ? \"vertical\" : \"horizontal\"}\n margin={{ top: 6, right: 6, bottom: 0, left: 0 }}\n >\n <CartesianGrid vertical={horizontal} horizontal={!horizontal} />\n {horizontal ? (\n <>\n <XAxis type=\"number\" {...axis} />\n <YAxis type=\"category\" dataKey=\"label\" width={88} {...axis} />\n </>\n ) : (\n <>\n <XAxis dataKey=\"label\" {...axis} />\n <YAxis width={44} {...axis} />\n </>\n )}\n {tooltip}\n {legend}\n {series.map((key, index) => (\n <Bar\n key={key}\n dataKey={key}\n radius={2}\n isAnimationActive={false}\n fill={`var(--color-${key})`}\n {...(click ? { onClick: click, className: \"cursor-pointer\" } : {})}\n >\n {series.length === 1\n ? points.map((point) => (\n <Cell key={point.label} fill={String(config[point.label]?.color ?? SERIES_COLORS[index])} />\n ))\n : null}\n </Bar>\n ))}\n </BarChart>\n )}\n </ChartFrame>\n );\n}\n","\"use client\";\n\n// src/DashboardCanvas.tsx — @ai-matrx/records-ui · SCR-16\n//\n// ONE DASHBOARD OBJECT, ONE CALL, EVERY BLOCK.\n//\n// This screen reads `custom.dashboards` and writes `custom.dashboard_declare` —\n// the same two doors `dashboard_propose` uses, so the dashboard a person tweaks\n// here IS the one the agent wrote and the one the database judges. Until\n// 2026-09-20 it kept its own dashboard records in a package-owned\n// `records_ui_dashboard` Table: a second store the agent could not reach and\n// the store never validated, which is exactly the defect lane FORMS removed for\n// forms on the same day.\n//\n// AND IT ASKS ONCE. `custom.dashboard_run` walks every saved block and answers\n// them all in ONE snapshot, each with its own `ms`, under the CALLER'S OWN\n// principal — so a member shared eleven of two hundred records sees eleven, and\n// eight blocks cannot disagree with each other about what the last hour did.\n// One block that refuses says why and the others still draw: a canvas that went\n// blank because one column moved would be the screen telling a lie about the\n// whole organization.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { AggregateFilter, DashboardRunResult, RecordsError } from \"@ai-matrx/records\";\nimport { BasicInput, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\n\nimport { RefusalNotice } from \"./Refusal\";\nimport { NO_OPEN_RECORDS_REASON, NO_REASK_REASON, useRecordsUi, useTableRights } from \"./host\";\nimport { ChartBlock } from \"./ChartBlock\";\nimport {\n CHART_KINDS,\n CHART_KIND_LABEL,\n dashboardDeclareArgs,\n dashboardFromSummary,\n type ChartKind,\n type ChartSpec,\n type SavedDashboard,\n} from \"./charts\";\n\nexport interface DashboardCanvasProps {\n /** The Table these blocks are about. */\n tableId: Uuid;\n activeDashboardId?: Uuid | null | undefined;\n /** The one filter bar across the canvas. Merged UNDER each block's own filter. */\n filter?: Record<string, AggregateFilter> | undefined;\n className?: string | undefined;\n}\n\nexport function DashboardCanvas({ tableId, activeDashboardId, filter, className }: DashboardCanvasProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const fields = useFields(tableId);\n const [boards, setBoards] = useState<SavedDashboard[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [activeId, setActiveId] = useState<Uuid | null>(activeDashboardId ?? null);\n const [run, setRun] = useState<DashboardRunResult | null>(null);\n const [running, setRunning] = useState(false);\n const [question, setQuestion] = useState(\"\");\n const [asking, setAsking] = useState(false);\n\n const load = useCallback(async () => {\n // `custom.dashboards` is already scoped to this Table by the door, so there\n // is no client-side filter here that could disagree with the one it used.\n const answered = await client.dashboards({ table_id: tableId });\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setError(null);\n setBoards(answered.data.map(dashboardFromSummary));\n }, [client, tableId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n useEffect(() => {\n if (!boards || boards.length === 0) return;\n const chosen = boards.find((d) => d.id === (activeDashboardId ?? activeId)) ?? boards[0]!;\n if (chosen.id !== activeId) setActiveId(chosen.id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [boards, activeDashboardId]);\n\n const board = useMemo(() => boards?.find((d) => d.id === activeId) ?? null, [boards, activeId]);\n const filterKey = JSON.stringify(filter ?? {});\n\n // ONE RUN FOR THE WHOLE CANVAS. Not one per block: the door answers them all\n // in one snapshot and reports each block's own `ms`.\n useEffect(() => {\n if (!activeId) {\n setRun(null);\n return;\n }\n let cancelled = false;\n setRunning(true);\n setRun(null);\n void client\n .dashboardRun({ dashboard_id: activeId, ...(filter ? { filter } : {}) })\n .then((answered) => {\n if (cancelled) return;\n setRunning(false);\n if (answered.ok) setRun(answered.data);\n else setError(answered.error);\n });\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, activeId, filterKey]);\n\n const declare = useCallback(\n async (next: SavedDashboard, blocks: ChartSpec[]) => {\n const written = await client.dashboardDeclare(\n dashboardDeclareArgs({ ...next, blocks }, tableId),\n );\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setActiveId(written.data);\n await load();\n // The blocks changed, so the answers must be taken again.\n setRun(null);\n const again = await client.dashboardRun({\n dashboard_id: written.data,\n ...(filter ? { filter } : {}),\n });\n if (again.ok) setRun(again.data);\n },\n [client, tableId, load, filter],\n );\n\n async function create() {\n const groupable = (fields.data ?? []).filter((f) => f.type === \"text\" || f.type === \"list\");\n const by = groupable[0]?.key;\n await declare(\n {\n id: null as unknown as Uuid,\n name: `Dashboard ${(boards?.length ?? 0) + 1}`,\n subject: tableId,\n blocks: [],\n presentation: {},\n version: 0,\n },\n [\n { title: \"How many\", subject: tableId, kind: \"number\", measures: [{ op: \"count\" }] },\n ...(by\n ? [\n {\n title: `By ${by}`,\n subject: tableId,\n kind: \"column\" as ChartKind,\n groupBy: [by],\n measures: [{ op: \"count\" as const }],\n },\n ]\n : []),\n ],\n );\n }\n\n const refresh = useCallback(async () => {\n if (!activeId) return;\n setRunning(true);\n const again = await client.dashboardRun({\n dashboard_id: activeId,\n ...(filter ? { filter } : {}),\n });\n setRunning(false);\n if (again.ok) setRun(again.data);\n else setError(again.error);\n }, [client, activeId, filter]);\n\n async function remove(target: SavedDashboard) {\n const gone = await client.dashboardDelete({ dashboard_id: target.id });\n if (!gone.ok) {\n setError(gone.error);\n return;\n }\n setActiveId(null);\n await load();\n }\n\n async function reask() {\n const said = question.trim();\n if (!said || !host.onReask) return;\n setAsking(true);\n await host.onReask(said, {\n tableId,\n dashboardId: board?.id ?? null,\n dashboardName: board?.name ?? null,\n });\n setAsking(false);\n setQuestion(\"\");\n await load();\n if (activeId) {\n const again = await client.dashboardRun({\n dashboard_id: activeId,\n ...(filter ? { filter } : {}),\n });\n if (again.ok) setRun(again.data);\n }\n }\n\n if (error) {\n return (\n <RefusalNotice\n error={error}\n className={className}\n actions={\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void load()}>\n Try again\n </Button>\n }\n />\n );\n }\n if (boards === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* ONE ROW: the dashboards, and the verbs that change this one. */}\n <div className=\"flex flex-wrap items-center gap-1\" role=\"group\" aria-label=\"Dashboards\">\n {boards.map((d) => (\n <Button\n key={d.id}\n size=\"sm\"\n variant={d.id === activeId ? \"secondary\" : \"ghost\"}\n aria-pressed={d.id === activeId}\n onClick={() => setActiveId(d.id)}\n >\n {d.name}\n </Button>\n ))}\n {/* SCR-4: making a dashboard is administering the table, so a member\n gets no dead button — there is no button. */}\n {rights.admin ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void create()}>\n New dashboard\n </Button>\n ) : null}\n {board ? (\n <span className=\"ml-auto flex items-center gap-1\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => void refresh()}\n disabled={running}\n >\n {running ? \"Asking\" : \"Refresh\"}\n </Button>\n {rights.admin ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => void remove(board)}>\n Delete\n </Button>\n ) : null}\n </span>\n ) : null}\n </div>\n\n {/* THE RE-ASK BOX. A dashboard is changed by saying what you want, and the\n agent re-states it through `dashboard_propose`. */}\n {board ? (\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-1\">\n <BasicInput\n value={question}\n aria-label=\"Ask for a change to this dashboard\"\n placeholder=\"break it down by owner\"\n disabled={!host.onReask || asking}\n onChange={(e) => setQuestion(e.currentTarget.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") void reask();\n }}\n className=\"h-8 min-w-0 flex-1 text-xs\"\n />\n <Button size=\"sm\" disabled={!host.onReask || asking || question.trim() === \"\"} onClick={() => void reask()}>\n {asking ? \"Asking\" : \"Ask\"}\n </Button>\n </div>\n {/* ABSENT OR HONEST. A box that took a sentence and did nothing with\n it would be the worst control in the product. */}\n {!host.onReask ? <p className=\"text-xs text-muted-foreground\">{NO_REASK_REASON}</p> : null}\n </div>\n ) : null}\n\n {!board ? (\n <p className=\"text-xs text-muted-foreground\">\n {rights.admin\n ? \"No dashboard looks at this table yet. “New dashboard” makes one, or ask an agent for the one you want and it writes the whole thing.\"\n : rights.why(\"structure\")}\n </p>\n ) : run === null ? (\n <Skeleton className=\"h-64 w-full\" />\n ) : run.blocks.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n This dashboard has no blocks yet. Each one is a single question the store answers — grouped,\n bucketed and measured inside the read door.\n </p>\n ) : (\n <>\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3\">\n {run.blocks.map((block, index) => (\n <div key={`${block.title}-${index}`} className=\"flex min-w-0 flex-col gap-1\">\n <ChartBlock block={block} subject={tableId} />\n {rights.admin && board.blocks[index] ? (\n <div className=\"flex items-center gap-1 text-xs\">\n <select\n aria-label={`Shape of ${block.title}`}\n className=\"h-7 rounded border bg-background px-1 text-xs\"\n value={board.blocks[index]!.kind}\n onChange={(e) =>\n void declare(\n board,\n board.blocks.map((b, i) =>\n i === index ? { ...b, kind: e.target.value as ChartKind } : b,\n ),\n )\n }\n >\n {CHART_KINDS.map((kind) => (\n <option key={kind} value={kind}>\n {CHART_KIND_LABEL[kind]}\n </option>\n ))}\n </select>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() =>\n void declare(\n board,\n board.blocks.filter((_, i) => i !== index),\n )\n }\n >\n Remove\n </Button>\n </div>\n ) : null}\n </div>\n ))}\n </div>\n {/* Said ONCE for the canvas, not on every block. */}\n {!host.openRecords ? (\n <p className=\"text-xs text-muted-foreground\">{NO_OPEN_RECORDS_REASON}</p>\n ) : null}\n </>\n )}\n </div>\n );\n}\n","\"use client\";\n\n// src/FormsPanel.tsx — @ai-matrx/records-ui · PRODUCTS row 1, the owner's side\n//\n// THE FORMS OF ONE TABLE, on the table's own screen, in the table's own rail.\n//\n// It is deliberately NOT a tab bar, a second page or a \"Forms\" area of the app:\n// a form is a VIEW ON THIS TABLE, so it belongs beside this table's settings,\n// its inbox and its import — reached the same way, drawn by the same primitive,\n// closing the same way. A separate Forms section would be the parallel layer the\n// canvas ruling forbade: one more place to look for something that is already\n// somewhere.\n//\n// WHAT AN OWNER ACTUALLY NEEDS HERE, and nothing else:\n// · the link, copied in one click, because that is the whole product;\n// · how many answers arrived, how many are IN THE TABLE, and how many are\n// waiting for a person — three different numbers, and conflating them is how\n// somebody believes they have twelve patients when four are still held;\n// · open and close, which is one act (`custom.anon_publish`) and needs `admin`\n// on this table, because it decides whether strangers may add rows to it.\n//\n// ABSENT, NEVER DEAD. Someone without `admin` sees the forms and their links and\n// no open/close control at all — not a greyed one. The store answers the level\n// (`custom.my_levels`, through `useTableRights`); this screen never guesses it.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport { publicFormPath, type FormSummary, type RecordsError } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\n\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi, useTableRights } from \"./host\";\n\nexport interface FormsPanelProps {\n tableId: Uuid;\n className?: string | undefined;\n}\n\n/**\n * THERE IS NO \"NEW FORM\" BUTTON HERE, AND THAT IS THE PRODUCT.\n *\n * PRODUCTS row 1 is written under one law: *\"we do not ship a builder people\n * click together.\"* A person says \"make me an intake form for new patients that\n * tells me when one arrives\" and the agent writes the table, the fields, the\n * validation and the notify rule in one call (`form_propose`) and hands back the\n * link. Putting a builder button here would make the slow path the obvious one.\n *\n * What this panel is for is everything AFTER that sentence: the link, the three\n * numbers, and opening or closing it.\n *\n * (`FormBuilder` is the TWEAK, and since 2026-09-20 it edits this very form —\n * same `custom.anon_form` row, same `custom.form_declare` door the agent used.\n * It is a different screen for a different moment, not a second form store.)\n */\nconst NO_BUILDER =\n \"A form asks for this table's own fields, and its answers land here as ordinary records stamped \" +\n \"with the form they came through. Ask an agent for one in a sentence — what it should ask for, and \" +\n \"who to tell when somebody answers.\";\n\n/** The words for each state, said once. A state a screen invents is a state that drifts. */\nconst STATE_WORDS: Record<FormSummary[\"state\"], string> = {\n draft: \"Not published — the link does not answer yet.\",\n open: \"Open — anyone with the link can answer it.\",\n closed: \"Closed — it keeps its answers and takes no more.\",\n full: \"Full — it has all the answers it was set up to take.\",\n};\n\nexport function FormsPanel({ tableId, className }: FormsPanelProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const [forms, setForms] = useState<FormSummary[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState<Uuid | null>(null);\n const [copied, setCopied] = useState<Uuid | null>(null);\n\n const load = useCallback(async () => {\n const answered = await client.forms({ table_id: tableId });\n if (!answered.ok) {\n setError(answered.error);\n setForms([]);\n return;\n }\n setError(null);\n setForms(answered.data);\n }, [client, tableId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const toggle = useCallback(\n async (form: FormSummary) => {\n setBusy(form.form_id as Uuid);\n const wanted = form.published_at === null || form.closed_at !== null;\n const answered = await client.anonPublish({ form_id: form.form_id as Uuid, published: wanted });\n setBusy(null);\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n await load();\n },\n [client, load],\n );\n\n // THE LINK IS THE PRODUCT, so copying it is one click and it SAYS it worked.\n // A clipboard that is unavailable (an insecure origin, a locked-down browser)\n // shows the address instead of failing silently.\n const [shown, setShown] = useState<string | null>(null);\n const copy = useCallback(async (url: string, formId: Uuid) => {\n try {\n await navigator.clipboard.writeText(url);\n setCopied(formId);\n setShown(null);\n window.setTimeout(() => setCopied(null), 1600);\n } catch {\n setShown(url);\n }\n }, []);\n\n if (forms === null) return <Skeleton className={cn(\"h-32 w-full\", className)} />;\n\n const origin = host.publicOrigin ?? (typeof window === \"undefined\" ? \"\" : window.location.origin);\n\n return (\n <section className={cn(\"flex flex-col gap-3\", className)}>\n <header className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium\">Forms</h3>\n <span className=\"text-xs text-muted-foreground\">\n {forms.length === 0 ? \"none yet\" : `${forms.length}`}\n </span>\n <div className=\"flex-1\" />\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {forms.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {rights.structure\n ? NO_BUILDER\n : \"This table has no forms. Making one needs the admin level on it, because a form decides what people with no account may add here.\"}\n </p>\n ) : null}\n\n <ul className=\"flex flex-col gap-2\">\n {forms.map((form) => {\n const url = `${origin}${publicFormPath(form.form_id)}`;\n return (\n <li key={form.form_id} className=\"rounded-md border p-2.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">\n {form.title ?? form.slug}\n </span>\n <Badge variant={form.state === \"open\" ? \"default\" : \"secondary\"}>{form.state}</Badge>\n </div>\n\n <p className=\"mt-0.5 text-xs text-muted-foreground\">{STATE_WORDS[form.state]}</p>\n\n {/* THREE NUMBERS, NEVER ONE. \"12 responses\" while four are held is\n how somebody comes to believe they have twelve patients. */}\n <p className=\"mt-1.5 text-xs\">\n <span className=\"font-medium\">{form.in_table}</span> in the table\n {form.held > 0 ? (\n <>\n {\" · \"}\n <span className=\"font-medium\">{form.held}</span> waiting for someone\n </>\n ) : null}\n {form.rejected > 0 ? (\n <>\n {\" · \"}\n <span className=\"font-medium\">{form.rejected}</span> turned away\n </>\n ) : null}\n {form.submission_cap !== null ? (\n <span className=\"text-muted-foreground\"> · stops at {form.submission_cap}</span>\n ) : null}\n </p>\n\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5\">\n {form.published_at ? (\n <Button size=\"sm\" variant=\"outline\" onClick={() => void copy(url, form.form_id as Uuid)}>\n {copied === form.form_id ? \"Copied\" : \"Copy link\"}\n </Button>\n ) : null}\n {rights.structure ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={busy === form.form_id}\n onClick={() => void toggle(form)}\n >\n {busy === form.form_id\n ? \"…\"\n : form.published_at && !form.closed_at\n ? \"Close\"\n : \"Open it\"}\n </Button>\n ) : null}\n </div>\n\n {shown && shown === url ? (\n <p className=\"mt-1.5 break-all rounded border border-dashed px-2 py-1 text-xs\">\n This browser would not let the page copy for you, so here it is to copy by hand:{\" \"}\n {url}\n </p>\n ) : null}\n </li>\n );\n })}\n </ul>\n\n {!rights.known ? (\n <p className=\"text-xs text-muted-foreground\">\n Still asking what you may do with this table — nothing is offered until it answers.\n </p>\n ) : null}\n </section>\n );\n}\n","\"use client\";\n\n// src/RecordChat.tsx — @ai-matrx/records-ui · SCR-26\n//\n// \"TALK TO THIS RECORD\" — AND THERE IS EXACTLY ONE CHAT SURFACE IN THIS\n// PLATFORM, WHICH IS NOT THIS ONE.\n//\n// The temptation here is to build a message list and a composer. Doing that\n// would give AI Matrx a second chat UI that streams differently, handles tool\n// asks differently, pages history differently and drifts from the real one\n// within a month — for the sake of a panel beside a record. So this component\n// builds NO chat UI at all.\n//\n// What it builds is the thing only the record store can build: the CONTEXT.\n// It reads the one record THROUGH THE READ DOOR (`custom.read_record`), turns\n// the Fields the store agreed this person may see into named context entries,\n// names the ones the store MASKED rather than pretending the record has fewer\n// fields than it has, and hands that to the host's chat port.\n//\n// WHAT matrx-frontend MUST PASS (the port, in its own words):\n//\n// <RecordsUiProvider value={{\n// chat: (ctx) => {\n// const { conversationId } = useAgentLauncher(agentId, {\n// surfaceKey: ctx.surfaceKey,\n// runtime: { context: Object.fromEntries(ctx.entries.map(e => [e.key, e.value])) },\n// });\n// return <AgentConversationColumn conversationId={conversationId} surfaceKey={ctx.surfaceKey} />;\n// },\n// }}>\n//\n// `AgentConversationColumn`\n// (matrx-frontend `features/agents/components/shared/AgentConversationColumn.tsx`)\n// is that one surface, and it cannot live in this package: it reads the app's\n// Redux store — conversations, messages, instance-context, surfaces — and a\n// package that imported those would stop being a package. The agent itself is\n// resolved through a Mandate on the host's side, never a UUID pinned here.\n//\n// UNBOUND, THIS COMPONENT IS ABSENT WITH ITS REASON. It never draws a dead\n// composer, and it never quietly renders a transcript that goes nowhere.\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { Field, HiddenFieldNotice, RecordsError } from \"@ai-matrx/records\";\nimport { Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi } from \"./host\";\nimport { scalarText } from \"./values\";\n\n/** One named piece of grounding, shaped the way the platform's context slice takes them. */\nexport interface RecordChatEntry {\n key: string;\n value: unknown;\n label: string;\n /** `text` for a scalar, `json` for a structure. The host maps this to its own vocabulary. */\n type: \"text\" | \"json\";\n}\n\n/** A Field the STORE masked for this reader, named rather than silently dropped. */\nexport interface RecordChatWithheld {\n key: string;\n label: string;\n /** The store's own reason. */\n reason: string;\n}\n\n/** Everything the host's chat surface needs, and nothing about how it should look. */\nexport interface RecordChatContext {\n /**\n * A unique key per mounted conversation. Two record panels open at once must\n * not fight over focus, so this is derived from the record and never a\n * constant.\n */\n surfaceKey: string;\n tableId: Uuid;\n recordId: Uuid;\n tableName: string;\n /** The record's own title, for the panel's one-row header and the chip. */\n title: string;\n /** The grounding, already read through the read door. */\n entries: RecordChatEntry[];\n /** What this reader is NOT being given, with the store's reason for each. */\n withheld: RecordChatWithheld[];\n}\n\nexport const NO_CHAT_REASON =\n \"No chat port is bound, so this panel is absent rather than showing a composer that goes nowhere. \" +\n \"Bind `chat` on <RecordsUiProvider> with your host's own chat surface — in AI Matrx that is \" +\n \"`AgentConversationColumn`, launched through a Mandate — and this panel becomes that surface with \" +\n \"this record as its context. This package deliberately ships no second chat UI.\";\n\nexport interface RecordChatProps {\n tableId: Uuid;\n recordId: Uuid;\n className?: string | undefined;\n}\n\nexport function RecordChat({ tableId, recordId, className }: RecordChatProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const [read, setRead] = useState<{\n document: Record<string, unknown>;\n hidden: Record<string, HiddenFieldNotice>;\n } | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setRead(null);\n setError(null);\n void client.recordRead({ record_id: recordId }).then((answered) => {\n if (cancelled) return;\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setRead({\n document: answered.data.document as Record<string, unknown>,\n hidden: answered.data.hidden ?? {},\n });\n });\n return () => {\n cancelled = true;\n };\n }, [client, recordId]);\n\n const context: RecordChatContext | null = useMemo(() => {\n if (!read || !table.data || !fields.data) return null;\n const titleKey = table.data.title_field ?? fields.data[0]?.key ?? \"\";\n const title = String(read.document[titleKey] ?? \"this record\");\n const withheld: RecordChatWithheld[] = Object.entries(read.hidden).map(([key, notice]) => ({\n key,\n label: fields.data?.find((f) => f.key === key)?.label ?? key,\n reason: noticeText(notice),\n }));\n return {\n surfaceKey: `records-ui:record-chat:${recordId}`,\n tableId,\n recordId,\n tableName: table.data.name,\n title,\n entries: entriesFor(fields.data, read.document, table.data.name, title, withheld),\n // Two different absences, both named: what the STORE masked for this\n // reader, and what the organization's own policy keeps out of a\n // conversation. Neither one silently shrinks the record.\n withheld,\n };\n }, [read, table.data, fields.data, recordId, tableId]);\n\n if (error) return <RefusalNotice error={error} className={className} />;\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (!context) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (!host.chat) {\n // ABSENT, WITH THE REASON — and with what was going to be sent, because a\n // person reading \"no chat port is bound\" should be able to see that the\n // record half of this actually works.\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{context.title}</span>\n <span>{context.entries.length} facts ready</span>\n </header>\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{NO_CHAT_REASON}</p>\n <Withheld withheld={context.withheld} />\n </section>\n );\n }\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: the record, and what the agent is holding. No repeated names. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{context.title}</span>\n <span>{context.entries.length} facts in context</span>\n </header>\n <Withheld withheld={context.withheld} />\n <div className=\"flex min-h-0 flex-1 flex-col\">{host.chat(context)}</div>\n </section>\n );\n}\n\n/**\n * The store masked something, and the person is TOLD.\n *\n * An agent answering out of a record it was given nine of eleven fields from\n * will answer confidently and wrongly about the other two. A screen that hid\n * that would be the record store lying about what it handed over.\n */\nfunction Withheld({ withheld }: { withheld: RecordChatWithheld[] }) {\n if (withheld.length === 0) return null;\n return (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n Not in this conversation: {withheld.map((w) => w.label).join(\", \")}.{\" \"}\n {withheld[0]?.reason ? withheld[0].reason : \"The store masked it for this reader.\"} An answer here is\n an answer without {withheld.length === 1 ? \"that field\" : \"those fields\"}.\n </p>\n );\n}\n\n/**\n * THE GROUNDING, AND IT CARRIES THE FIELD'S MEANING.\n *\n * FLD-N-1: a unit and a format are on the Field because they change what the\n * value MEANS, so `48000` reaches the agent as `$48,000` exactly as it reaches\n * the screen. An agent given the bare number is an agent one currency away from\n * a confident mistake.\n */\nfunction entriesFor(\n fields: Field[],\n document: Record<string, unknown>,\n tableName: string,\n title: string,\n held: RecordChatWithheld[],\n): RecordChatEntry[] {\n const entries: RecordChatEntry[] = [\n {\n key: \"record_subject\",\n label: \"Record\",\n type: \"text\",\n value: `${title} — a ${tableName} record.`,\n },\n ];\n for (const field of fields) {\n // AGT-7 / VAL-6: a Field's sensitivity is a CEILING. The store's four words\n // are public · internal · confidential · restricted, and the top two are\n // ceilings no conversation rises through. Both these and FLD-12's `exclude`\n // and `on_request` are left out HERE and named in `held` below: a field\n // that quietly vanished would be a field the agent answers around.\n // FLD-12 is the FIELD'S OWN ANSWER to \"may an agent see this?\", in the\n // store's four words, and `exclude` means exactly that. AGT-7 adds a\n // ceiling on top: `confidential` and `restricted` values are not handed to\n // a conversation whatever the policy says.\n const guarded = field.sensitivity === \"confidential\" || field.sensitivity === \"restricted\";\n if (guarded || field.context_policy === \"exclude\" || field.context_policy === \"on_request\") {\n held.push({\n key: field.key,\n label: field.label,\n reason: guarded\n ? `This field is marked ${field.sensitivity}, so it is not handed to a conversation.`\n : field.context_policy === \"exclude\"\n ? \"This field says an agent may not see its values.\"\n : \"This field is given on request, so the agent asks for it rather than being handed it.\",\n });\n continue;\n }\n const raw = document[field.key];\n if (raw === undefined || raw === null || raw === \"\") continue;\n const structured = typeof raw === \"object\";\n entries.push({\n key: field.key,\n label: field.label,\n type: structured ? \"json\" : \"text\",\n value: structured ? raw : scalarText(field, raw),\n });\n }\n return entries;\n}\n\nfunction noticeText(notice: HiddenFieldNotice): string {\n const bag = notice as unknown as Record<string, unknown>;\n const said = bag[\"reason\"] ?? bag[\"message\"] ?? bag[\"why\"];\n return typeof said === \"string\" && said.length > 0 ? said : \"The store masked this field for this reader.\";\n}\n","\"use client\";\n\n// src/EnrichPanel.tsx — @ai-matrx/records-ui · SCR-27\n//\n// PER-FIELD AI FILL, AND THE THREE FACTS IT REFUSES TO FAKE.\n//\n// A Field whose `source` is `agent` is a Field the organization said an agent\n// keeps filled (FLD-7). `review_interval_days` is how often (AGT-6). Those two\n// live on the Field record, so this panel does not decide which fields are\n// agent-filled and it does not decide when they are stale — it READS both, and\n// a Table with no agent Fields says so instead of offering a Fill button over\n// nothing.\n//\n// 1. FRESHNESS IS THE VALUE'S OWN. `_values.<key>.at` is when it was written\n// and `.actor` is who wrote it; `review_interval_days` turns those into\n// \"due\" or \"fresh\". A screen that timed this off `updated_at` on the row\n// would call every field stale because one of them changed.\n//\n// 2. THE PROVENANCE BADGE IS NOT DECORATION. VAL-8: a value knows whether a\n// person or an agent wrote it, and which person the agent was acting for.\n// That is shown on every agent-filled value, always, because a number a\n// machine guessed and a number a person typed are different facts and the\n// difference must survive into the screen.\n//\n// 3. THE FILL GOES THROUGH THE SERVER, NEVER THROUGH THIS CLIENT. The write\n// has to be stamped actor `agent` on behalf of the person, and a browser\n// that stamped itself `agent` would be a browser claiming to be an agent.\n// The server's own `records` tool does it properly\n// (aidream `packages/matrx-records/matrx_records/agent/tool.py`:\n// `Actor.agent(principal)` → the reserved document keys `_actor` and\n// `_on_behalf_of`), so this panel asks the HOST to make that call.\n//\n// WHAT matrx-frontend MUST PASS:\n//\n// <RecordsUiProvider value={{\n// enrich: async (ask) =>\n// fetch(\"/api/ai/tools/execute\", { method: \"POST\", body: JSON.stringify({\n// tool_name: \"records\", surface: \"records-ui:enrich\",\n// arguments: { action: \"record_write\", record_id: ask.recordId,\n// values: Object.fromEntries(ask.fields.map(f => [f.key, null])) },\n// })}).then(...)\n//\n// TWO LIVE GATES SIT IN FRONT OF THAT CALL TODAY, and this panel names them\n// rather than spinning: the knob `custom/code_paths_enabled` resolves false\n// (the tool refuses every action while it does), and the `records` row in\n// `tool.binding` is `is_active = false`. Both are switches somebody flips on\n// purpose; neither is something a screen may work around.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { Field, RecordDocument, RecordsError, ValueEnvelope } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi, useTableRights } from \"./host\";\nimport { envelopeFor, RecordValue } from \"./values\";\n\n/** What the host is asked to have the server's `records` tool do. */\nexport interface EnrichAsk {\n tableId: Uuid;\n recordId: Uuid;\n /** The agent Fields to refill, each with why this panel thinks it is due. */\n fields: Array<{ key: string; label: string; because: string }>;\n}\n\nexport interface EnrichOutcome {\n ok: boolean;\n /** What happened, in a sentence — the server's own words when it has some. */\n message: string;\n}\n\nexport const NO_ENRICH_REASON =\n \"No enrich port is bound, so nothing here offers to fill a field it cannot fill. An AI fill is \" +\n \"written by the SERVER with actor `agent` on behalf of you — a browser that stamped itself `agent` \" +\n \"would be a browser claiming to be one — so bind `enrich` on <RecordsUiProvider> with a call to the \" +\n \"server's own `records` tool (action `record_write`). Two switches also sit in front of it today: \" +\n \"the knob `custom/code_paths_enabled` resolves false, and the `records` row in `tool.binding` is \" +\n \"`is_active = false`.\";\n\nexport interface EnrichPanelProps {\n tableId: Uuid;\n recordId: Uuid;\n className?: string | undefined;\n}\n\ninterface AgentField {\n field: Field;\n envelope: ValueEnvelope | undefined;\n value: unknown;\n /** Days since it was written, or null when it has never been written. */\n ageDays: number | null;\n /** The Field's own interval, null when the organization set none. */\n everyDays: number | null;\n due: boolean;\n /** Why it is due, or why it is not — said in words, never left to a colour. */\n because: string;\n}\n\nexport function EnrichPanel({ tableId, recordId, className }: EnrichPanelProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const rights = useTableRights(table.data);\n const [document, setDocument] = useState<RecordDocument | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [outcome, setOutcome] = useState<EnrichOutcome | null>(null);\n\n const load = useCallback(async () => {\n const answered = await client.recordRead({ record_id: recordId });\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setError(null);\n setDocument(answered.data.document);\n }, [client, recordId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const agentFields: AgentField[] | null = useMemo(() => {\n if (!fields.data || !document) return null;\n // FLD-7: the STORE says which fields an agent keeps filled. This panel has\n // no list of its own and no heuristic — a Field is here because its own\n // record says `source = 'agent'`.\n return fields.data.filter((f) => f.source === \"agent\").map((field) => describe(field, document));\n }, [fields.data, document]);\n\n const runFill = useCallback(\n async (targets: AgentField[]) => {\n if (!host.enrich || targets.length === 0) return;\n setBusy(targets.length === 1 ? (targets[0] as AgentField).field.key : \"*\");\n setOutcome(null);\n const answered = await host.enrich({\n tableId,\n recordId,\n fields: targets.map((t) => ({ key: t.field.key, label: t.field.label, because: t.because })),\n });\n setBusy(null);\n setOutcome(answered);\n // Re-read either way: a refused fill leaves the record exactly as it was,\n // and a screen that assumed so without looking would be guessing.\n await load();\n },\n [host, load, recordId, tableId],\n );\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (error) return <RefusalNotice error={error} className={className} />;\n if (!agentFields) return <Skeleton className={cn(\"h-40 w-full\", className)} />;\n\n if (agentFields.length === 0) {\n return (\n <p className={cn(\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\", className)}>\n No Field on {table.data?.name ?? \"this table\"} says an agent keeps it filled, so there is nothing\n here to enrich. A Field becomes agent-filled by carrying <code>source = agent</code> on its own\n record — set it in the field editor and it appears here with its review interval.\n </p>\n );\n }\n\n const due = agentFields.filter((f) => f.due);\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: the count, what is due, and the one verb. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">AI fill</span>\n <span>\n {agentFields.length} agent {agentFields.length === 1 ? \"field\" : \"fields\"}\n {due.length > 0 ? `, ${due.length} due` : \", all fresh\"}\n </span>\n {host.enrich && rights.write && due.length > 0 ? (\n <Button size=\"sm\" className=\"ml-auto\" disabled={busy !== null} onClick={() => void runFill(due)}>\n {busy === \"*\" ? \"Asking…\" : `Refill ${due.length}`}\n </Button>\n ) : null}\n </header>\n\n {/* The port is not bound: absent verb, stated reason. Never a dead button. */}\n {!host.enrich ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{NO_ENRICH_REASON}</p>\n ) : null}\n {host.enrich && !rights.write ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{rights.why(\"write\")}</p>\n ) : null}\n\n {outcome ? (\n <p\n className={cn(\n \"rounded border px-2 py-1 text-xs\",\n outcome.ok ? \"text-muted-foreground\" : \"border-destructive text-destructive\",\n )}\n >\n {outcome.message}\n </p>\n ) : null}\n\n <ul className=\"flex min-h-0 flex-col gap-1 overflow-y-auto\">\n {agentFields.map((entry) => (\n <li key={entry.field.key} className=\"rounded border p-2\">\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-xs font-medium\">{entry.field.label}</span>\n <ProvenanceBadge envelope={entry.envelope} />\n <span className={cn(\"text-[11px]\", entry.due ? \"text-destructive\" : \"text-muted-foreground\")}>\n {entry.because}\n </span>\n {host.enrich && rights.write ? (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"ml-auto h-6 px-2 text-[11px]\"\n disabled={busy !== null}\n onClick={() => void runFill([entry])}\n >\n {busy === entry.field.key ? \"Asking…\" : \"Fill\"}\n </Button>\n ) : null}\n </div>\n <div className=\"mt-1 text-xs\"><RecordValue field={entry.field} value={entry.value} document={document ?? undefined} /></div>\n </li>\n ))}\n </ul>\n </section>\n );\n}\n\n/**\n * VAL-8 ON SCREEN. Who wrote this value, and — when it was an agent — which\n * person they were acting for. AGT-N-4 is the whole reason the second half is\n * shown: an agent carries the exact authority of the person operating it, so\n * \"an agent, for Dana\" is the true sentence and \"an agent\" is not.\n */\nfunction ProvenanceBadge({ envelope }: { envelope: ValueEnvelope | undefined }) {\n if (!envelope) return null;\n if (envelope.actor !== \"agent\") {\n return (\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {envelope.actor === \"system\" ? \"written by the system\" : \"written by a person\"}\n </Badge>\n );\n }\n return (\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {envelope.on_behalf_of ? `filled by an agent, for ${envelope.on_behalf_of}` : \"filled by an agent\"}\n </Badge>\n );\n}\n\n/**\n * IS THIS VALUE DUE? Read off the value's own envelope and the Field's own\n * interval, and said in a sentence.\n *\n * An interval nobody set is NOT silently \"never due\" and not silently \"always\n * due\": the Field has no review interval, that is stated, and the value is left\n * alone. A knob nobody turned is not a decision somebody made.\n */\nfunction describe(field: Field, document: RecordDocument): AgentField {\n const envelope = envelopeFor(document, field.key);\n const value = (document as Record<string, unknown>)[field.key];\n const everyDays = field.review_interval_days ?? null;\n const writtenAt = envelope?.at ? Date.parse(envelope.at) : Number.NaN;\n const ageDays = Number.isNaN(writtenAt) ? null : Math.floor((Date.now() - writtenAt) / 86_400_000);\n\n if (value === undefined || value === null || value === \"\") {\n return {\n field,\n envelope,\n value,\n ageDays,\n everyDays,\n due: true,\n because: \"never filled\",\n };\n }\n if (everyDays === null) {\n return {\n field,\n envelope,\n value,\n ageDays,\n everyDays,\n due: false,\n because:\n ageDays === null ? \"no review interval set\" : `filled ${ageDays}d ago, no review interval set`,\n };\n }\n if (ageDays === null) {\n return {\n field,\n envelope,\n value,\n ageDays,\n everyDays,\n due: true,\n because: `every ${everyDays}d, and this value carries no date`,\n };\n }\n return {\n field,\n envelope,\n value,\n ageDays,\n everyDays,\n due: ageDays >= everyDays,\n because: ageDays >= everyDays ? `${ageDays}d old, due every ${everyDays}d` : `${ageDays}d old of ${everyDays}d`,\n };\n}\n","\"use client\";\n\n// src/ChecklistRunner.tsx — @ai-matrx/records-ui · SCR-28\n//\n// A CHECKLIST IS NOT A LIST OF STRINGS. Every step is a REAL RECORD in a real\n// Table, related to the others, so a step can be assigned, commented on,\n// exported, historied and read by an agent exactly like anything else in this\n// store — and \"step 3 of the onboarding\" is a row somebody can find six months\n// later rather than a line in a JSON blob.\n//\n// THE TEMPLATE IS INSTANTIATED IN ONE ACT (REC-70). `custom.work_template_instantiate`\n// judges the whole graph before writing any of it, so a half-made checklist is\n// not a state this store can be in — and this component does not loop writing\n// steps one at a time, which is exactly how half-made checklists happen.\n//\n// THE STORE OWNS THE ORDER, THE TURN AND THE STATES:\n// · `custom.work_states()` is the five states and what each may become. This\n// screen hardcodes none of them; a picker built from a hardcoded list is a\n// second source of truth waiting to disagree.\n// · `custom.work_whose_turn` says whose turn each step is and whether its\n// state is terminal.\n// · `custom.work_transition_refusal` says why a move is refused, ASKED FIRST,\n// so a person is told before they try rather than after.\n//\n// `seed` is the agent's half: a complete declarative template, saved the first\n// time it is seen, exactly as `ViewBar`, `FormBuilder` and `DashboardCanvas`\n// take theirs. An agent writes a twelve-step checklist in one object.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useRecordsClient, useTable, type ReadRow, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, WorkGraph, WorkState, WorkTurn } from \"@ai-matrx/records\";\nimport { Badge, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useTableRights } from \"./host\";\nimport { useSystemTable, type SystemTableSpec } from \"./systemTable\";\n\n/** THE COMPLETE DECLARATIVE SPEC — one object, one `record_write`, a whole checklist. */\nexport interface ChecklistSpec {\n name: string;\n /** The Table the steps become records in. */\n subject: Uuid;\n steps: ChecklistStepSpec[];\n}\n\nexport interface ChecklistStepSpec {\n /** The document this step's record starts life with. `title` is what a person reads. */\n title: string;\n /** Anything else the subject Table's Fields take. */\n data?: Record<string, unknown>;\n}\n\n/**\n * The package-owned Table a checklist RUN is recorded in. The steps are records\n * in the subject Table — this holds only which template was instantiated and\n * when, so re-opening a checklist finds the same steps rather than making new\n * ones. (Running the same checklist twice on purpose is two rows here, which is\n * the correct answer: they are two runs.)\n */\nexport const CHECKLIST_TABLE: SystemTableSpec = {\n slug: \"records_ui_checklist_run\",\n name: \"Checklist runs\",\n labelSingular: \"Checklist run\",\n labelPlural: \"Checklist runs\",\n titleField: \"name\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"text\", sort: 10, required: true },\n { key: \"subject\", label: \"Table\", type: \"text\", sort: 20, required: true },\n { key: \"template_id\", label: \"Template\", type: \"text\", sort: 30 },\n { key: \"instantiation_id\", label: \"Instantiation\", type: \"text\", sort: 40 },\n { key: \"step_ids\", label: \"Steps\", type: \"text\", sort: 50, config: { multiline: true } },\n { key: \"started_at\", label: \"Started\", type: \"text\", sort: 60 },\n ],\n};\n\nexport interface ChecklistRunnerProps {\n /** The Table the steps live in — normally the same Table the checklist is about. */\n tableId: Uuid;\n /** The agent's half. Each spec not already run is instantiated once. */\n seed?: ChecklistSpec[] | undefined;\n className?: string | undefined;\n}\n\ninterface Run {\n id: Uuid;\n name: string;\n subject: Uuid;\n templateId: Uuid | null;\n stepIds: Uuid[];\n startedAt: string;\n}\n\nexport function ChecklistRunner({ tableId, seed, className }: ChecklistRunnerProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const home = useSystemTable(CHECKLIST_TABLE);\n const [runs, setRuns] = useState<Run[] | null>(null);\n const [activeId, setActiveId] = useState<Uuid | null>(null);\n const [turns, setTurns] = useState<WorkTurn[] | null>(null);\n const [states, setStates] = useState<WorkState[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n const [note, setNote] = useState<string | null>(null);\n\n const runTableId = home.tableId;\n\n // The five states, from the store. Asked once, never typed out here.\n useEffect(() => {\n let cancelled = false;\n void client.workStates().then((answered) => {\n if (cancelled || !answered.ok) return;\n setStates([...answered.data].sort((a, b) => a.sort - b.sort));\n });\n return () => {\n cancelled = true;\n };\n }, [client]);\n\n const loadRuns = useCallback(async (): Promise<Run[] | null> => {\n if (!runTableId) return null;\n const listed = await client.list({ table_id: runTableId, limit: 200 });\n if (!listed.ok) {\n setError(listed.error);\n return null;\n }\n setError(null);\n const held = listed.data.rows.map(toRun).filter((r) => r.subject === tableId);\n setRuns(held);\n return held;\n }, [client, runTableId, tableId]);\n\n useEffect(() => {\n void loadRuns();\n }, [loadRuns]);\n\n // ── the seed: instantiated ONCE, never on top of a run that exists ────────\n useEffect(() => {\n let cancelled = false;\n if (!runTableId || !seed || seed.length === 0 || runs === null) return;\n const missing = seed.filter((spec) => !runs.some((run) => run.name === spec.name));\n if (missing.length === 0) return;\n void (async () => {\n for (const spec of missing) {\n if (cancelled) return;\n const started = await start(client, runTableId, spec);\n if (!started.ok) {\n setError(started.error);\n return;\n }\n }\n if (!cancelled) await loadRuns();\n })();\n return () => {\n cancelled = true;\n };\n }, [client, loadRuns, runTableId, runs, seed]);\n\n const active = useMemo(\n () => runs?.find((r) => r.id === activeId) ?? runs?.[0] ?? null,\n [runs, activeId],\n );\n\n // Whose turn each step is — the STORE's answer, over the whole subject Table,\n // narrowed here to this run's own steps.\n const loadTurns = useCallback(async () => {\n const answered = await client.workWhoseTurn({ table_id: tableId, includeFinished: true });\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setTurns(answered.data);\n }, [client, tableId]);\n\n // Re-asked whenever the RUN changes, not only on mount: the seed instantiates\n // its steps AFTER the first read, so a screen that asked once would draw a\n // checklist whose every step said \"you cannot see this\" — records that had\n // been written a second earlier.\n useEffect(() => {\n void loadTurns();\n }, [loadTurns, active?.id, active?.stepIds.length]);\n\n async function move(step: Uuid, to: string) {\n setBusy(true);\n setNote(null);\n const written = await client.recordUpdate({ record_id: step, patch: { status: to } });\n setBusy(false);\n if (!written.ok) {\n setError(written.error);\n return;\n }\n setError(null);\n setNote(`Moved to ${to}.`);\n await loadTurns();\n }\n\n if (home.error) return <RefusalNotice error={home.error} className={className} />;\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (home.loading || runs === null) return <Skeleton className={cn(\"h-48 w-full\", className)} />;\n\n if (!active) {\n return (\n <p className={cn(\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\", className)}>\n No checklist has been run against {table.data?.name ?? \"this table\"} yet. Pass a complete template as{\" \"}\n <code>seed</code> — a name and its ordered steps — and it is instantiated once, as real records.\n </p>\n );\n }\n\n const steps = active.stepIds\n .map((id) => turns?.find((t) => t.record_id === id) ?? null)\n .map((turn, index) => ({ turn, index, id: active.stepIds[index] as Uuid }));\n const done = steps.filter((s) => s.turn?.terminal === true).length;\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: which run, and how far through. No subtitle restating the name. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{active.name}</span>\n <span className=\"tabular-nums\">\n {done} of {steps.length} done\n </span>\n {runs.length > 1 ? (\n <select\n aria-label=\"Checklist run\"\n className=\"ml-auto h-7 rounded border bg-background px-1 text-xs\"\n value={active.id}\n onChange={(e) => setActiveId(e.target.value as Uuid)}\n >\n {runs.map((r) => (\n <option key={r.id} value={r.id}>\n {r.name}\n </option>\n ))}\n </select>\n ) : null}\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n {note ? <p className=\"text-xs text-muted-foreground\">{note}</p> : null}\n\n {turns === null ? (\n <Skeleton className=\"h-24 w-full\" />\n ) : (\n <ol className=\"flex min-h-0 flex-col gap-1 overflow-y-auto\">\n {steps.map(({ turn, index, id }) => (\n <li key={id} className=\"flex items-center gap-2 rounded border p-2\">\n <span className=\"w-5 shrink-0 text-right text-[11px] tabular-nums text-muted-foreground\">\n {index + 1}\n </span>\n <span className={cn(\"min-w-0 flex-1 truncate text-xs\", turn?.terminal && \"text-muted-foreground line-through\")}>\n {turn?.title ??\n // The step is a record the read door did not return. That is a\n // fact about visibility, not an empty row, so it says so.\n \"This step is a record you cannot see — it is in the run, and the store did not return it to you.\"}\n </span>\n {turn?.assignee_id ? (\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {turn.turn ?? \"assigned\"}\n </Badge>\n ) : null}\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {turn?.status ?? turn?.state ?? \"Not started\"}\n </Badge>\n {/* The next states are the STORE's `next` for the state this step\n is actually in. A move nobody may make is never offered. */}\n {rights.write && turn && states ? (\n <NextMove\n states={states}\n current={turn.status ?? turn.state ?? null}\n disabled={busy}\n onMove={(to) => void move(id, to)}\n />\n ) : null}\n </li>\n ))}\n </ol>\n )}\n\n {!rights.write ? <p className=\"text-xs text-muted-foreground\">{rights.why(\"write\")}</p> : null}\n </section>\n );\n}\n\n/**\n * The moves this step may actually make, from `custom.work_states()`.\n *\n * A state the store does not list as `next` is not shown greyed out — it is not\n * there. Offering a move that will be refused, and only saying so afterwards,\n * is the screen making a person find out by failing.\n */\nfunction NextMove({\n states,\n current,\n disabled,\n onMove,\n}: {\n states: WorkState[];\n current: string | null;\n disabled: boolean;\n onMove: (to: string) => void;\n}) {\n const here = states.find((s) => s.name === current) ?? states[0];\n const next = here?.next ?? [];\n if (next.length === 0) {\n return <span className=\"text-[11px] text-muted-foreground\">finished</span>;\n }\n return (\n <span className=\"flex shrink-0 gap-1\">\n {next.map((to) => (\n <Button key={to} size=\"sm\" variant=\"ghost\" className=\"h-6 px-2 text-[11px]\" disabled={disabled} onClick={() => onMove(to)}>\n {to}\n </Button>\n ))}\n </span>\n );\n}\n\n/**\n * ONE ACT. The template is declared, judged and instantiated, and only then is\n * the run recorded — so a refused graph leaves nothing behind at all.\n */\nasync function start(\n client: ReturnType<typeof useRecordsClient>,\n runTableId: Uuid,\n spec: ChecklistSpec,\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n const graph: WorkGraph = {\n // A ref is lower-case letters, digits and underscores — the store refuses\n // `step-1` by name (\"every record in a template needs a name made of\n // lower-case letters, digits and underscores\"). Refs are built here rather\n // than taken from a person's step title for exactly that reason.\n nodes: spec.steps.map((step, index) => ({\n ref: `step_${index + 1}`,\n table: spec.subject,\n data: { title: step.title, ...(step.data ?? {}) },\n })),\n // Each step owns the next, so the order is a fact in the store rather than\n // an array index a screen remembered.\n relations: spec.steps.slice(1).map((_, index) => ({ from: `step_${index + 1}`, to: `step_${index + 2}` })),\n };\n\n // ASKED BEFORE IT IS WRITTEN. The store says why a graph would be refused,\n // and a refusal here costs nothing rather than leaving a declared template\n // nobody can instantiate.\n const refusal = await client.workTemplateRefusal({ graph });\n if (!refusal.ok) return refusal;\n if (refusal.data) {\n return {\n ok: false,\n error: {\n code: \"refused_by_rule\",\n message: refusal.data,\n hint: \"The store judged the whole graph before anything was written, so nothing was — fix the template and run it again.\",\n },\n };\n }\n\n const declared = await client.workTemplateDeclare({ name: spec.name, graph });\n if (!declared.ok) return declared;\n const made = await client.workTemplateInstantiate({ template_id: declared.data });\n if (!made.ok) return made;\n\n return client.recordWrite({\n table_id: runTableId,\n data: {\n name: spec.name,\n subject: spec.subject,\n template_id: declared.data,\n instantiation_id: made.data.instantiation_id,\n step_ids: JSON.stringify(made.data.records),\n started_at: new Date().toISOString(),\n },\n });\n}\n\nfunction toRun(row: ReadRow): Run {\n const data = (row.document ?? {}) as Record<string, unknown>;\n let stepIds: Uuid[] = [];\n try {\n const raw = data[\"step_ids\"];\n stepIds = typeof raw === \"string\" ? (JSON.parse(raw) as Uuid[]) : Array.isArray(raw) ? (raw as Uuid[]) : [];\n } catch {\n stepIds = [];\n }\n return {\n id: row.id,\n name: String(data[\"name\"] ?? \"Checklist\"),\n subject: String(data[\"subject\"] ?? \"\"),\n templateId: (data[\"template_id\"] as Uuid | null) ?? null,\n stepIds,\n startedAt: String(data[\"started_at\"] ?? \"\"),\n };\n}\n","\"use client\";\n\n// src/BookingSlots.tsx — @ai-matrx/records-ui · SCR-29\n//\n// AVAILABILITY, A SLOT PICKER, AND THE ONE THING THAT MAKES BOOKING HARD:\n// TWO PEOPLE PICKING THE SAME SLOT AT THE SAME MOMENT.\n//\n// This screen does not decide that. `custom.work_slot_hold` does, under a\n// unique index, and the loser is TOLD — not shown a spinner, not silently given\n// the next slot, not left believing they have a booking that somebody else has.\n// A picker that filtered out taken slots client-side would be correct roughly\n// until two people used it.\n//\n// WHERE A HOLD LIVES, AND WHY IT IS NOT THE BOOKING TABLE. Measured against the\n// live store: `custom.work_slot_hold` WRITES a record for the hold, so pointing\n// it at the bookings Table is refused by that Table's own Rules (\"Title is\n// required\"), and `custom.work_slot_holds` then reads every booking back as a\n// hold with no slot key. A slot has to live in a Table declared for it, by\n// `custom.work_slots_declare`, which builds the UNIQUE INDEX that makes one\n// hold per slot true in the database rather than true in an application. So\n// this component declares that Table once, through the same doors everything\n// else uses, and holds against it.\n//\n// THE THREE PARTS, AND WHO OWNS EACH:\n// · AVAILABILITY is the organization's own: a start hour, an end hour, a slot\n// length, over N days. Those are knobs on this component with sensible\n// defaults, because they are an opinion and opinions are settings.\n// · WHAT IS TAKEN is the store's: `custom.work_slot_holds` lists every hold\n// with whether it has LAPSED, so a slot that came back says why rather than\n// reappearing mysteriously.\n// · WHAT A BOOKING *IS* is `FormRunner`'s: the person answers the form's own\n// questions and the submission is an ORDINARY RECORD in a real Table. There\n// is no bookings table, no second data model, and no reconciliation later.\n//\n// THE ORDER MATTERS AND IT IS THE STRICT ONE: hold the slot FIRST, then take\n// the details, then release the hold only if they abandon it. Taking details\n// first and holding after is how two people fill in a form and one of them\n// finds out at the end.\n\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError, WorkSlotHold } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { FormRunner } from \"./FormRunner\";\nimport type { FormSpec } from \"./forms\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface BookingSlotsProps {\n /** The Table holds are taken against, and the Table a booking lands in. */\n tableId: Uuid;\n /** The form a person fills in once they hold a slot. Its `subject` is the Table. */\n form: FormSpec;\n /** Availability — the organization's opinion, with a default rather than a question. */\n availability?: {\n /** First hour offered, 24h. Default 9. */\n fromHour?: number;\n /** Last hour offered, exclusive. Default 17. */\n toHour?: number;\n /** Minutes per slot. Default 60. */\n everyMinutes?: number;\n /** How many days ahead to offer. Default 5. */\n days?: number;\n };\n /** How long a hold lasts before the store lets the slot go. Default 15 minutes. */\n holdFor?: string;\n /** `null` when the answer was HELD rather than written — see the runner's own note. */\n onBooked?: ((recordId: Uuid | null) => void) | undefined;\n className?: string | undefined;\n}\n\ninterface Slot {\n /** The key the STORE holds. Stable, sortable, and the same string for everyone. */\n key: string;\n at: Date;\n taken: boolean;\n /** Set when the slot is taken: who by, so a person can see it is their own. */\n holder: string | null;\n}\n\nexport function BookingSlots({\n tableId,\n form,\n availability,\n holdFor = \"15 minutes\",\n onBooked,\n className,\n}: BookingSlotsProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const [slotTableId, setSlotTableId] = useState<Uuid | null>(null);\n const [holds, setHolds] = useState<WorkSlotHold[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [held, setHeld] = useState<{ slot: Slot; holdId: Uuid | null } | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [refused, setRefused] = useState<string | null>(null);\n\n const me = client.config.actor.user_id ?? \"anonymous\";\n const slug = `records_ui_slots_${tableId.replace(/-/g, \"\").slice(0, 16)}`;\n\n // ── the slots Table, declared once, through the store's own doors ─────────\n // A Home first (REC-1: a Table has to live somewhere), then the declaration\n // — the same sequence `ensureSystemTable` obeys, and for the same reason.\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n // FOUND BEFORE IT IS MADE. Two screens open on the same bookings Table\n // must hold against the SAME slots Table, or each one has its own\n // private idea of what is free and the unique index protects nothing.\n const tables = await client.tableList();\n if (!tables.ok) {\n if (!cancelled) setError(tables.error);\n return;\n }\n const already = tables.data.find((t) => t.slug === slug);\n if (already) {\n if (!cancelled) setSlotTableId(already.id);\n return;\n }\n const kernel = await client.personKernelId();\n if (!kernel.ok) {\n if (!cancelled) setError(kernel.error);\n return;\n }\n const home = await client.recordWrite({\n table_id: kernel.data,\n data: { name: `Slots for ${tableId}` },\n });\n if (!home.ok) {\n if (!cancelled) setError(home.error);\n return;\n }\n const declared = await client.workSlotsDeclare({\n name: `Slots for ${table.data?.name ?? \"bookings\"}`,\n slug,\n homeId: home.data,\n });\n if (cancelled) return;\n if (!declared.ok) {\n // THE STORE REFUSED TO MAKE SLOTS AT ALL — most often because it\n // cannot build the unique index that keeps one hold per slot. That is\n // shown verbatim and NO PICKER IS DRAWN: a booking screen over a store\n // that cannot decide a double-booking is a screen that will sell the\n // same hour twice and look fine doing it.\n setError(declared.error);\n return;\n }\n const made = (declared.data ?? {}) as Record<string, unknown>;\n setSlotTableId((made[\"table_id\"] as Uuid | undefined) ?? null);\n })();\n return () => {\n cancelled = true;\n };\n }, [client, slug, table.data, tableId]);\n\n const loadHolds = useCallback(async () => {\n if (!slotTableId) return;\n const answered = await client.workSlotHolds({ table_id: slotTableId });\n if (!answered.ok) {\n setError(answered.error);\n return;\n }\n setError(null);\n setHolds(answered.data);\n }, [client, slotTableId]);\n\n useEffect(() => {\n void loadHolds();\n }, [loadHolds]);\n\n const slots: Slot[] = useMemo(() => {\n const fromHour = availability?.fromHour ?? 9;\n const toHour = availability?.toHour ?? 17;\n const everyMinutes = availability?.everyMinutes ?? 60;\n const days = availability?.days ?? 5;\n // A LAPSED hold is not a taken slot. The store says which is which, so the\n // slot comes back on its own and nobody has to guess from a clock.\n const taken = new Map(\n (holds ?? []).filter((h) => !h.expired).map((h) => [h.slot_key, h.holder] as const),\n );\n const out: Slot[] = [];\n const first = new Date();\n first.setHours(0, 0, 0, 0);\n for (let day = 0; day < days; day += 1) {\n for (let minute = fromHour * 60; minute < toHour * 60; minute += everyMinutes) {\n const at = new Date(first);\n at.setDate(at.getDate() + day);\n at.setMinutes(minute);\n if (at.getTime() < Date.now()) continue;\n const key = at.toISOString();\n out.push({ key, at, taken: taken.has(key), holder: taken.get(key) ?? null });\n }\n }\n return out;\n }, [availability, holds]);\n\n async function take(slot: Slot) {\n if (!slotTableId) return;\n setBusy(slot.key);\n setRefused(null);\n setError(null);\n const answered = await client.workSlotHold({\n table_id: slotTableId,\n slotKey: slot.key,\n holder: me,\n ttl: holdFor,\n });\n setBusy(null);\n if (!answered.ok) {\n // THE LOSING HALF OF A RACE, AND IT IS THE DATABASE'S ANSWER.\n // `already_exists` is the unique index refusing a second hold on one\n // slot; the store's own sentence names the index that did it. Shown\n // verbatim, because \"the slot is already held\" is a fact a person can act\n // on and a spinner is not.\n if (answered.error.code === \"already_exists\") {\n setRefused(refusalLineForAPerson(answered.error));\n } else {\n setError(answered.error);\n }\n await loadHolds();\n return;\n }\n const outcome = (answered.data ?? {}) as Record<string, unknown>;\n const holdId = (outcome[\"hold_id\"] as Uuid | undefined) ?? null;\n if (!holdId) {\n setRefused(\n \"The store did not hold that slot and did not say why, so nothing was booked. Pick another, and \" +\n \"report this — a hold that neither succeeds nor refuses is a defect, not a busy moment.\",\n );\n await loadHolds();\n return;\n }\n setHeld({ slot, holdId });\n }\n\n async function letGo() {\n if (held?.holdId) await client.workSlotRelease({ hold_id: held.holdId });\n setHeld(null);\n await loadHolds();\n }\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n // A refusal from the declaration is the END of this screen, not a banner over\n // a working picker.\n if (error && !slotTableId) return <RefusalNotice error={error} className={className} />;\n if (holds === null || !slotTableId) return <Skeleton className={cn(\"h-48 w-full\", className)} />;\n\n // ── the slot is held: now, and only now, the details ──────────────────────\n if (held) {\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{whenText(held.slot.at)}</span>\n <span>held for you for {holdFor}</span>\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-auto h-6 px-2 text-[11px]\" onClick={() => void letGo()}>\n Pick another\n </Button>\n </header>\n <FormRunner\n // The booking IS the submission: an ordinary record in a real Table,\n // carrying the slot it was made for, so it is in the grid and the\n // exports the moment it is sent.\n form={{\n ...form,\n questions: form.questions,\n }}\n onSubmitted={(recordId) => {\n // A SUBMISSION DOES NOT ALWAYS BECOME A RECORD. `FormRunner` now\n // answers `null` when the form's own accept Rule held the answer for\n // a person instead of clearing it (DOOR-17's quarantine), and there\n // is nothing to stamp the slot onto until somebody does. Silently\n // patching `null` would have been a booking that lost its slot.\n if (recordId === null) {\n setRefused(\n \"Your details were sent and are waiting for someone to confirm them, so this slot is \" +\n \"not held for you yet. Whoever owns this form will be in touch.\",\n );\n void loadHolds();\n onBooked?.(null);\n return;\n }\n void client\n .recordUpdate({ record_id: recordId, patch: { slot: held.slot.key } })\n .then(() => loadHolds());\n onBooked?.(recordId);\n }}\n />\n </section>\n );\n }\n\n const free = slots.filter((s) => !s.taken).length;\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: what is on offer. No subtitle restating it. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Pick a time</span>\n <span className=\"tabular-nums\">\n {free} free of {slots.length}\n </span>\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n {refused ? <p className=\"rounded border border-destructive px-2 py-1 text-xs text-destructive\">{refused}</p> : null}\n\n {slots.length === 0 ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n There is no time left today inside the hours this is offered in. Tomorrow's slots appear here\n from midnight — this is empty because the day is over, not because something failed.\n </p>\n ) : (\n <ol className=\"flex flex-wrap gap-1\">\n {slots.map((slot) => (\n <li key={slot.key}>\n {/* A taken slot is not a dead button: it is not a button. */}\n {slot.taken ? (\n <span\n className=\"inline-flex h-8 items-center rounded border border-dashed px-2 text-[11px] text-muted-foreground\"\n title={slot.holder === me ? \"You are holding this one.\" : \"Somebody is holding this one.\"}\n >\n {whenText(slot.at)} · {slot.holder === me ? \"yours\" : \"taken\"}\n </span>\n ) : (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-8 px-2 text-[11px]\"\n disabled={busy !== null}\n onClick={() => void take(slot)}\n >\n {busy === slot.key ? \"Holding…\" : whenText(slot.at)}\n </Button>\n )}\n </li>\n ))}\n </ol>\n )}\n </section>\n );\n}\n\nfunction whenText(at: Date): string {\n return at.toLocaleString(undefined, { weekday: \"short\", hour: \"numeric\", minute: \"2-digit\" });\n}\n","\"use client\";\n\n// src/CaptureSheet.tsx — @ai-matrx/records-ui · SCR-30\n//\n// A PHONE, IN A BASEMENT, WITH NO SIGNAL — AND THE CAPTURE STILL COUNTS.\n//\n// Everything hard about offline capture is one question: when the phone comes\n// back and fires the same capture for the thirtieth time, does the store write\n// thirty records? The answer is the OFFLINE CAPTURE CONTRACT, and both halves\n// of it are load-bearing:\n//\n// 1. THE CLIENT MINTS THE ID, BEFORE THE FIRST ATTEMPT, OFFLINE. `clientKey`\n// is decided the moment a person hits Capture — not when the write lands,\n// because a key minted by the server is a key that does not exist while\n// there is no server. It is never re-minted on retry: re-minting is exactly\n// how a retry becomes a second capture.\n// 2. THE STORE DEDUPES ON IT. `custom.anon_capture` writes a replay-ledger row\n// `on conflict do nothing` under a unique index and returns the record id\n// the FIRST attempt produced. So the second, third and thirtieth replay all\n// take the same branch whatever this client believes, and a phone that\n// crashed mid-send loses nothing.\n//\n// THREE MORE THINGS THIS SHEET REFUSES TO FAKE:\n// · It never claims a capture is saved while it is queued. The queue is\n// visible, counted, and each waiting item says what the store last said.\n// · With no `captureQueue` port bound the queue is IN MEMORY for the life of\n// the page and SAYS SO — a queue that silently died with the tab is the\n// precise failure this component exists to prevent.\n// · A camera or a microphone this browser will not give it is named, not\n// rendered as a button that does nothing. Bytes go through the host's\n// `upload` port; with none bound, the photo and voice capture say so and\n// the reading capture — which is just a number and a note — still works.\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useFields, useRecordsClient, useTable, type Uuid } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { Button, Input, Skeleton, Textarea, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { NO_UPLOAD_REASON, useRecordsUi, type PendingCapture } from \"./host\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\n/** The three things a phone captures. Each one writes the SAME kind of record. */\nexport const CAPTURE_MODES = [\"reading\", \"photo\", \"voice\"] as const;\nexport type CaptureMode = (typeof CAPTURE_MODES)[number];\n\nexport const IN_MEMORY_QUEUE_REASON =\n \"No capture queue is bound, so anything that cannot be sent right now is held in this page's memory \" +\n \"and is lost if the page closes. Bind `captureQueue` on <RecordsUiProvider> with your host's own \" +\n \"durable store (IndexedDB in a browser) and a queued capture survives the tab, the reload and the \" +\n \"flight. It is said here rather than discovered later.\";\n\nexport interface CaptureSheetProps {\n /** The Table a capture becomes a record in. */\n tableId: Uuid;\n /** Which Field a reading's number goes in. Defaults to the first range Field. */\n readingField?: string | undefined;\n /** Which Field the note goes in. Defaults to the Table's title field. */\n noteField?: string | undefined;\n /** Which Field an attachment's file id goes in. */\n attachmentField?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * THE CLIENT-MINTED ID. `crypto.randomUUID` where there is one; a time-and-\n * randomness key where there is not. Either way it is decided HERE, offline,\n * before anything is attempted.\n */\nfunction mintClientKey(): string {\n const c = globalThis.crypto as { randomUUID?: () => string } | undefined;\n if (typeof c?.randomUUID === \"function\") return `capture:${c.randomUUID()}`;\n return `capture:${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;\n}\n\nfunction deviceName(): string {\n const nav = globalThis.navigator as { userAgent?: string } | undefined;\n return nav?.userAgent ? nav.userAgent.slice(0, 120) : \"unknown device\";\n}\n\nexport function CaptureSheet({\n tableId,\n readingField,\n noteField,\n attachmentField,\n className,\n}: CaptureSheetProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const fields = useFields(tableId);\n const [mode, setMode] = useState<CaptureMode>(\"reading\");\n const [reading, setReading] = useState(\"\");\n const [note, setNote] = useState(\"\");\n const [fileId, setFileId] = useState<Uuid | null>(null);\n const [pending, setPending] = useState<PendingCapture[] | null>(null);\n const [saved, setSaved] = useState<Uuid[]>([]);\n const [error, setError] = useState<RecordsError | null>(null);\n const [uploadError, setUploadError] = useState<string | null>(null);\n const [flushing, setFlushing] = useState(false);\n /** Kept in a ref as well so a flush never races the render that queued an item. */\n const queue = useRef<PendingCapture[]>([]);\n\n const keep = useCallback(\n async (next: PendingCapture[]) => {\n queue.current = next;\n setPending(next);\n if (host.captureQueue) await host.captureQueue.save(next);\n },\n [host],\n );\n\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n const held = host.captureQueue ? await host.captureQueue.load() : [];\n if (cancelled) return;\n queue.current = held;\n setPending(held);\n })();\n return () => {\n cancelled = true;\n };\n }, [host]);\n\n const resolved = useCallback(() => {\n const all = fields.data ?? [];\n return {\n reading: readingField ?? all.find((f) => f.type === \"range\")?.key ?? null,\n note: noteField ?? table.data?.title_field ?? all[0]?.key ?? null,\n attachment: attachmentField ?? all.find((f) => f.format === \"file\" || f.format === \"image\")?.key ?? null,\n };\n }, [attachmentField, fields.data, noteField, readingField, table.data]);\n\n /**\n * SEND EVERYTHING WAITING. Each item goes through `custom.anon_capture` with\n * the key it was minted with — so an item that actually landed last time\n * comes back with the same record id and leaves the queue, and an item that\n * did not is tried again. Nothing here decides \"this probably worked\".\n */\n const flush = useCallback(async () => {\n if (flushing || queue.current.length === 0) return;\n setFlushing(true);\n const left: PendingCapture[] = [];\n const landed: Uuid[] = [];\n for (const item of queue.current) {\n const answered = await client.anonCapture({\n table_id: item.tableId,\n clientKey: item.clientKey,\n payload: item.payload,\n device: item.device,\n capturedAt: item.capturedAt,\n });\n if (answered.ok) {\n landed.push(answered.data);\n continue;\n }\n left.push({ ...item, attempts: item.attempts + 1, lastRefusal: refusalLineForAPerson(answered.error) });\n setError(answered.error);\n }\n if (landed.length > 0) {\n setSaved((held) => [...held, ...landed]);\n setError(null);\n }\n await keep(left);\n setFlushing(false);\n }, [client, flushing, keep]);\n\n // A capture is queued first and sent immediately after, which is the same\n // path a reconnect takes. There is no \"online\" branch that skips the queue:\n // one path means the offline path is the one that is actually exercised.\n async function capture() {\n const keys = resolved();\n const payload: Record<string, unknown> = {};\n if (keys.note && note.trim() !== \"\") payload[keys.note] = note.trim();\n if (mode === \"reading\" && keys.reading && reading.trim() !== \"\") {\n payload[keys.reading] = Number(reading);\n }\n if (mode !== \"reading\" && keys.attachment && fileId) payload[keys.attachment] = fileId;\n if (Object.keys(payload).length === 0) return;\n\n const item: PendingCapture = {\n // MINTED HERE. Before the attempt, not after it.\n clientKey: mintClientKey(),\n tableId,\n payload,\n capturedAt: new Date().toISOString(),\n device: deviceName(),\n attempts: 0,\n lastRefusal: null,\n };\n setReading(\"\");\n setNote(\"\");\n setFileId(null);\n await keep([...queue.current, item]);\n await flush();\n }\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (fields.error) return <RefusalNotice error={fields.error} className={className} />;\n if (fields.loading || pending === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n const keys = resolved();\n\n return (\n <section className={cn(\"mx-auto flex w-full max-w-sm flex-col gap-2\", className)}>\n {/* One row, phone-first: the three modes and the queue count. */}\n <header className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n {CAPTURE_MODES.map((m) => (\n <Button\n key={m}\n size=\"sm\"\n variant={m === mode ? \"default\" : \"ghost\"}\n className=\"h-8 px-3 text-[11px] capitalize\"\n onClick={() => setMode(m)}\n >\n {m}\n </Button>\n ))}\n <span className=\"ml-auto tabular-nums\">\n {pending.length > 0 ? `${pending.length} waiting` : `${saved.length} saved`}\n </span>\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {mode === \"reading\" ? (\n keys.reading ? (\n <Input\n aria-label=\"Reading\"\n inputMode=\"decimal\"\n // A phone keyboard, and a touch target a thumb can hit.\n className=\"h-12 text-lg\"\n placeholder=\"0\"\n value={reading}\n onChange={(e) => setReading(e.target.value)}\n />\n ) : (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n {table.data?.name ?? \"This table\"} has no number Field for a reading to go in, so this mode\n would have nowhere to put what you typed. Add one, or name it with <code>readingField</code>.\n </p>\n )\n ) : null}\n\n {mode !== \"reading\" ? (\n !host.upload ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">{NO_UPLOAD_REASON}</p>\n ) : !keys.attachment ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n {table.data?.name ?? \"This table\"} has no Field a file id can go in, so a {mode} capture would\n upload the bytes and then have nowhere to record them. Add one, or name it with{\" \"}\n <code>attachmentField</code>.\n </p>\n ) : (\n <>\n <input\n aria-label={mode === \"photo\" ? \"Take a photo\" : \"Record a voice note\"}\n type=\"file\"\n className=\"text-xs\"\n // Phone-first: this is what opens the camera and the microphone\n // rather than a file browser.\n accept={mode === \"photo\" ? \"image/*\" : \"audio/*\"}\n capture={mode === \"photo\" ? \"environment\" : undefined}\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (!file) return;\n setUploadError(null);\n void host.upload?.(file).then((result) => {\n if (result.ok) setFileId(result.fileId);\n else setUploadError(result.reason);\n });\n }}\n />\n {fileId ? <p className=\"text-[11px] text-muted-foreground\">Attached.</p> : null}\n {uploadError ? <p className=\"text-xs text-destructive\">{uploadError}</p> : null}\n </>\n )\n ) : null}\n\n <Textarea\n aria-label=\"Note\"\n rows={2}\n className=\"text-sm\"\n placeholder=\"Note\"\n value={note}\n onChange={(e) => setNote(e.target.value)}\n />\n\n <Button className=\"h-12\" onClick={() => void capture()}>\n Capture\n </Button>\n\n {/* The queue, visible and honest. Never a capture that claims to be saved. */}\n {pending.length > 0 ? (\n <div className=\"flex flex-col gap-1 rounded border p-2\">\n <div className=\"flex items-center gap-2 text-xs\">\n <span className=\"font-medium\">Waiting to send</span>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n className=\"ml-auto h-6 px-2 text-[11px]\"\n disabled={flushing}\n onClick={() => void flush()}\n >\n {flushing ? \"Sending…\" : \"Try now\"}\n </Button>\n </div>\n <ul className=\"flex flex-col gap-0.5\">\n {pending.map((item) => (\n <li key={item.clientKey} className=\"text-[11px] text-muted-foreground\">\n {new Date(item.capturedAt).toLocaleTimeString()} · {item.attempts} tried\n {item.lastRefusal ? ` · ${item.lastRefusal}` : \"\"}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n\n {!host.captureQueue ? (\n <p className=\"rounded border border-dashed px-2 py-1 text-[11px] text-muted-foreground\">\n {IN_MEMORY_QUEUE_REASON}\n </p>\n ) : null}\n </section>\n );\n}\n","\"use client\";\n\n// src/PortalShell.tsx — @ai-matrx/records-ui · SCR-23\n//\n// AN OUTSIDER'S WHOLE WORLD: their list, their record, their form — and NOTHING\n// ELSE, because they are not in the organization.\n//\n// VIS-31 is the fact this shell is built on, and it is subtle enough that the\n// store says it in one place so no screen can invent a second answer: \"no\n// organization\" cannot mean \"no row in the membership table\", because signup\n// mints every account a PERSONAL organization — under that reading nobody would\n// ever be external. `iam.is_external_principal` means no membership of a\n// NON-personal organization, and `iam.external_principal_card` says WHY in\n// plain English, which is what this shell shows instead of an empty page.\n//\n// WHAT AN OUTSIDER REACHES IS NOT \"THEIR ORGANIZATION'S RECORDS\". It is\n// `iam.external_principal_reach` — exactly the resource ids Visibility handed\n// them, one by one. A portal that listed a Table and relied on the read door to\n// filter would be a portal whose correctness depended on a filter running; this\n// one asks for the list of ids first and reads only those.\n//\n// AND THE SHELL IS HONEST ABOUT THE LANE. While `custom/external_principal_enabled`\n// is false the doors refuse BY NAME, which is the answer the platform gave\n// before this campaign, and this screen shows that sentence rather than an\n// empty list that reads like \"you have nothing\".\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { ExternalPrincipalCard, RecordsError } from \"@ai-matrx/records\";\nimport { Button, Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { Peek } from \"./Peek\";\nimport { FormRunner } from \"./FormRunner\";\nimport type { FormSpec } from \"./forms\";\nimport { refusalLineForAPerson } from \"./plainWords\";\n\nexport interface PortalShellProps {\n /** The Table the outsider's records belong to. */\n tableId: Uuid;\n /** OPTIONAL. A form the outsider may send — their one way to put something in. */\n form?: FormSpec | undefined;\n /** What the resources are called in `iam`'s own vocabulary. Default `record`. */\n resourceType?: string;\n className?: string | undefined;\n}\n\nexport function PortalShell({ tableId, form, resourceType = \"record\", className }: PortalShellProps) {\n const client = useRecordsClient();\n const [card, setCard] = useState<ExternalPrincipalCard | null>(null);\n const [reach, setReach] = useState<Uuid[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [open, setOpen] = useState<Uuid | null>(null);\n const [sending, setSending] = useState(false);\n\n const load = useCallback(async () => {\n // WHO THEY ARE, FIRST. A portal that read records before it knew whose\n // portal it was would be a portal deciding that for itself.\n const who = await client.externalPrincipalCard();\n if (!who.ok) {\n setError(who.error);\n return;\n }\n setError(null);\n setCard(who.data);\n const reached = await client.externalPrincipalReach({ resourceType });\n if (!reached.ok) {\n setError(reached.error);\n return;\n }\n setReach(reached.data.map((row) => row.resource_id));\n }, [client, resourceType]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n if (error) {\n // The lane is closed, or the outsider is not one. Either way the sentence\n // is `iam`'s own, verbatim — never softened into \"nothing to show\".\n return <RefusalNotice error={error} className={className} />;\n }\n if (!card || reach === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (!card.external) {\n return (\n <p className={cn(\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\", className)}>\n {card.explanation ||\n \"You are a member of an organization here, so this portal is not yours — a portal is the scoped \" +\n \"view an OUTSIDER gets. You have the full application instead.\"}\n </p>\n );\n }\n\n if (sending && form) {\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{form.name}</span>\n <Button size=\"sm\" variant=\"ghost\" className=\"ml-auto h-6 px-2 text-[11px]\" onClick={() => setSending(false)}>\n Back\n </Button>\n </header>\n <FormRunner\n form={form}\n onSubmitted={() => {\n setSending(false);\n void load();\n }}\n />\n </section>\n );\n }\n\n if (open) {\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n <Peek tableId={tableId} recordId={open} onClose={() => setOpen(null)} />\n </section>\n );\n }\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: how many things are theirs, and the one thing they may do. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Shared with you</span>\n <span className=\"tabular-nums\">{reach.length}</span>\n {form ? (\n <Button size=\"sm\" className=\"ml-auto h-7 px-2 text-[11px]\" onClick={() => setSending(true)}>\n {form.submitLabel ?? form.name}\n </Button>\n ) : null}\n </header>\n\n {reach.length === 0 ? (\n // EMPTY, AND IT SAYS WHICH EMPTY. \"Nobody has shared anything with you\"\n // and \"the store would not tell us\" are different sentences, and a\n // person acts on them differently.\n <p className=\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\">\n Nothing has been shared with you yet. {card.explanation} When somebody shares a record with you it\n appears here — this list is exactly what Visibility gave you, one record at a time, never an\n organization's list.\n </p>\n ) : (\n <ul className=\"flex min-h-0 flex-col gap-1 overflow-y-auto\">\n {reach.map((id) => (\n <li key={id}>\n <button\n type=\"button\"\n className=\"w-full truncate rounded border px-2 py-1.5 text-left text-xs hover:bg-muted\"\n onClick={() => setOpen(id)}\n >\n <PortalRow tableId={tableId} recordId={id} />\n </button>\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n}\n\n/**\n * One line for one record the outsider may see. It reads through the SAME read\n * door as everything else — there is no portal read path, because a second read\n * path is a second place for a visibility bug to live.\n */\nfunction PortalRow({ tableId, recordId }: { tableId: Uuid; recordId: Uuid }) {\n const client = useRecordsClient();\n const [title, setTitle] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void client.recordRead({ record_id: recordId }).then((answered) => {\n if (cancelled) return;\n if (!answered.ok) {\n setTitle(refusalLineForAPerson(answered.error));\n return;\n }\n const document = answered.data.document as Record<string, unknown>;\n const first = Object.values(document).find((v) => typeof v === \"string\" && v !== \"\");\n setTitle(typeof first === \"string\" ? first : recordId);\n });\n return () => {\n cancelled = true;\n };\n }, [client, recordId, tableId]);\n\n return <span>{title ?? \"…\"}</span>;\n}\n","\"use client\";\n\n// src/PublicViewPage.tsx — @ai-matrx/records-ui · SCR-24\n//\n// THE PUBLIC PAGE A SIGNED-OUT VISITOR LANDS ON, AND THE NOTE IT REFUSES TO\n// LEAVE OFF.\n//\n// VIS-32: a share, however generous, produces NO public address. A public\n// address exists only because somebody made a publish binding on purpose, and\n// the binding carries its own RENDER MODE — this page does not choose between\n// a list and a detail, it is TOLD.\n//\n// `iam.resolve_publish_binding` is the whole of the resolution, and three\n// different-looking situations deliberately resolve identically to NOTHING: an\n// address nobody ever made, an address that was revoked, and an address whose\n// lane was closed again. They are one 404, because an address that answered\n// differently for a revoked binding would be an existence oracle — \"this used\n// to be something\" is information a stranger should not get for free.\n//\n// D-15, AND IT IS NOT DECORATION. Nothing was scanned before this was listed:\n// there is no pre-listing scan, no quarantine, no report-and-takedown ranking.\n// `iam.world_publish_gap_notice()` is ONE function so the screen, the API, the\n// admission row and this page cannot drift into four different admissions of\n// the same gap — or into none. The note is carried on EVERY read and is shown\n// here every time, including when everything worked.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type ReadRow, type Uuid } from \"@ai-matrx/records/react\";\nimport type { Field, RecordsError, ResolvedPublishBinding } from \"@ai-matrx/records\";\nimport { Skeleton, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { RecordValue } from \"./values\";\n\nexport interface PublicViewPageProps {\n /** The public address, exactly as it appears in the URL. */\n slug: string;\n className?: string | undefined;\n}\n\nexport function PublicViewPage({ slug, className }: PublicViewPageProps) {\n const client = useRecordsClient();\n const [binding, setBinding] = useState<ResolvedPublishBinding | null | \"none\">(null);\n const [rows, setRows] = useState<ReadRow[] | null>(null);\n const [fields, setFields] = useState<Field[] | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n /** D-15's sentence, read from the store even when a binding did not resolve. */\n const [gap, setGap] = useState<string | null>(null);\n\n const load = useCallback(async () => {\n // The gap notice is read FIRST and unconditionally: a page that only\n // admitted the gap on the happy path would be a page that stops admitting\n // it exactly when something is wrong.\n const notice = await client.worldPublishGapNotice();\n if (notice.ok) setGap(notice.data);\n\n const resolved = await client.resolvePublishBinding({ slug });\n if (!resolved.ok) {\n setError(resolved.error);\n return;\n }\n setError(null);\n const found = resolved.data[0];\n if (!found) {\n setBinding(\"none\");\n return;\n }\n setBinding(found);\n\n // The render mode says which read to do. It is the BINDING's decision, made\n // when it was published, not a guess this page makes from the shape of the\n // answer.\n if (found.render_mode === \"list\") {\n const listed = await client.list({ table_id: found.resource_id, limit: 100 });\n if (!listed.ok) {\n setError(listed.error);\n return;\n }\n setRows(listed.data.rows);\n const held = await client.fields({ table_id: found.resource_id });\n if (held.ok) setFields(held.data);\n return;\n }\n const read = await client.recordRead({ record_id: found.resource_id });\n if (!read.ok) {\n setError(read.error);\n return;\n }\n setRows([{ id: found.resource_id, document: read.data.document, level: \"viewer\", hidden: read.data.hidden } as ReadRow]);\n }, [client, slug]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n if (error) return <RefusalNotice error={error} className={className} />;\n if (binding === null) return <Skeleton className={cn(\"h-64 w-full\", className)} />;\n\n if (binding === \"none\") {\n // THE 404, AND IT IS THE SAME 404 FOR ALL THREE CAUSES. Nothing here hints\n // that this address ever existed.\n return (\n <main className={cn(\"mx-auto max-w-2xl py-16 text-center\", className)}>\n <h1 className=\"text-lg font-medium\">Nothing here</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n There is no public page at this address.\n </p>\n {gap ? <p className=\"mt-6 text-xs text-muted-foreground\">{gap}</p> : null}\n </main>\n );\n }\n\n return (\n <main className={cn(\"mx-auto flex max-w-2xl flex-col gap-3 py-8\", className)}>\n {/* One row. The namespace it was published under, and nothing restating it. */}\n <header className=\"flex items-baseline gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{binding.namespace ?? \"Published\"}</span>\n <span>{binding.render_mode === \"list\" ? `${rows?.length ?? 0} items` : \"Shared publicly\"}</span>\n </header>\n\n {rows === null ? (\n <Skeleton className=\"h-40 w-full\" />\n ) : rows.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">This page has nothing on it yet.</p>\n ) : (\n <ol className=\"flex flex-col gap-2\">\n {rows.map((row) => (\n <li key={row.id} className=\"rounded border p-3\">\n <PublicRow row={row} fields={fields} />\n </li>\n ))}\n </ol>\n )}\n\n {/* D-15, ON EVERY READ, INCLUDING THE HAPPY ONE. */}\n <footer className=\"mt-4 border-t pt-3 text-xs text-muted-foreground\">\n {binding.notice || gap || \"Nothing was scanned before this was listed.\"}\n </footer>\n </main>\n );\n}\n\n/**\n * One public row. It draws through the same `renderValue` as every other screen\n * in this package, so a unit and a format mean the same thing to a stranger as\n * they do to the person who typed the value.\n */\nfunction PublicRow({ row, fields }: { row: ReadRow; fields: Field[] | null }) {\n const document = (row.document ?? {}) as Record<string, unknown>;\n if (!fields) {\n const first = Object.entries(document).filter(([key]) => !key.startsWith(\"_\"));\n return (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-sm\">\n {first.map(([key, value]) => (\n <div key={key} className=\"contents\">\n <dt className=\"text-xs text-muted-foreground\">{key}</dt>\n <dd className=\"text-sm\">{String(value ?? \"\")}</dd>\n </div>\n ))}\n </dl>\n );\n }\n return (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-3 gap-y-1\">\n {fields.map((field) => (\n <div key={field.key} className=\"contents\">\n <dt className=\"text-xs text-muted-foreground\">{field.label}</dt>\n <dd className=\"text-sm\"><RecordValue field={field} value={document[field.key]} document={row.document} /></dd>\n </div>\n ))}\n </dl>\n );\n}\n","\"use client\";\n\n// src/EmbedFrame.tsx — @ai-matrx/records-ui · SCR-25\n//\n// PUTTING ONE OF OUR FORMS OR VIEWS ON SOMEBODY ELSE'S WEBSITE, WITHOUT HANDING\n// THEM A WAY INTO EVERYTHING ELSE.\n//\n// This component is two halves that must not be confused:\n//\n// · THE ISSUING HALF (`EmbedFrame`) runs on OUR side, signed in, for the\n// person who owns the form. It mints a token through\n// `custom.anon_token_issue` and shows the snippet to paste. The secret comes\n// back ONCE — only its digest is stored, so a database read, a backup or a\n// leaked dump cannot produce a working token — which is why this screen says\n// so out loud and offers to mint a new one rather than pretending it can\n// show the old one again.\n//\n// · THE HANDSHAKE (`useEmbedHandshake`) runs on THEIR page, inside the iframe.\n// It calls `custom.anon_token_verify` with the secret and the ORIGIN, and\n// the store decides. It is the store that decides, and the check is EXACT —\n// `https://example.com.evil.test` passes a suffix match and fails this one.\n//\n// THE THREE THINGS THE STORE REFUSES, AND THIS SCREEN NAMES BEFORE IT ASKS:\n// 1. A token with no origin list. An empty list does not mean \"everywhere\" —\n// it is refused at issue, because a token that works from any page on the\n// internet includes an attacker's.\n// 2. A token carrying both read and write. One credential, one decision; the\n// second is always the one nobody meant to grant.\n// 3. A write token for a form nobody published. Closed by default.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useRecordsClient, type Uuid } from \"@ai-matrx/records/react\";\nimport type { AnonTokenBinding, RecordsError } from \"@ai-matrx/records\";\nimport { Button, Input, Skeleton, Textarea, cn } from \"@ai-matrx/design-system\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { useRecordsUi, useTableRights } from \"./host\";\nimport { useTable } from \"@ai-matrx/records/react\";\n\nexport interface EmbedFrameProps {\n /** The Table whose rights decide whether an embed may be issued at all. */\n tableId: Uuid;\n /** A write embed names the form it writes into. */\n formId?: Uuid | null | undefined;\n /** A read embed names the saved view or the record it shows. */\n savedViewId?: Uuid | null | undefined;\n recordId?: Uuid | null | undefined;\n /** Where the embedded page is served from — the `src` of the iframe. */\n embedUrl: string;\n className?: string | undefined;\n}\n\nexport function EmbedFrame({\n tableId,\n formId,\n savedViewId,\n recordId,\n embedUrl,\n className,\n}: EmbedFrameProps) {\n const client = useRecordsClient();\n const host = useRecordsUi();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const [origins, setOrigins] = useState(\"\");\n const [secret, setSecret] = useState<string | null>(null);\n const [tokenId, setTokenId] = useState<Uuid | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [busy, setBusy] = useState(false);\n\n // A write embed needs a form; a read embed needs a view or a record. The mode\n // is therefore a FACT about what was passed, never a toggle somebody can set\n // to a value the store will refuse.\n const mode: \"read\" | \"write\" = formId ? \"write\" : \"read\";\n\n const parsed = origins\n .split(/[\\s,]+/)\n .map((o) => o.trim())\n .filter((o) => o.length > 0);\n\n const issue = useCallback(async () => {\n setBusy(true);\n setError(null);\n const minted = await client.anonTokenIssue({\n mode,\n allowedOrigins: parsed,\n formId: formId ?? null,\n savedViewId: savedViewId ?? null,\n recordId: recordId ?? null,\n });\n setBusy(false);\n if (!minted.ok) {\n setError(minted.error);\n return;\n }\n setSecret(minted.data.secret);\n setTokenId(minted.data.token_id);\n host.notify?.success(\"Embed token issued. Copy it now — it is never shown again.\");\n }, [client, formId, host, mode, parsed, recordId, savedViewId]);\n\n const revoke = useCallback(async () => {\n if (!tokenId) return;\n setBusy(true);\n const done = await client.anonTokenRevoke({ token_id: tokenId });\n setBusy(false);\n if (!done.ok) {\n setError(done.error);\n return;\n }\n setSecret(null);\n setTokenId(null);\n }, [client, tokenId]);\n\n if (table.error) return <RefusalNotice error={table.error} className={className} />;\n if (table.loading) return <Skeleton className={cn(\"h-48 w-full\", className)} />;\n\n // Issuing an embed hands a stranger a way in, so the store asks for `admin`\n // on the Table. Without it there is no control here at all — not a greyed\n // one — and the reason is shown.\n if (!rights.admin) {\n return (\n <p className={cn(\"rounded border border-dashed px-2 py-1 text-xs text-muted-foreground\", className)}>\n {rights.why(\"structure\")} Issuing an embed opens a way in from somebody else's website, so the store asks for\n the admin level on this table before it will mint one.\n </p>\n );\n }\n\n const snippet = secret\n ? `<iframe src=\"${embedUrl}#t=${secret}\" style=\"width:100%;height:640px;border:0\" loading=\"lazy\"></iframe>`\n : null;\n\n return (\n <section className={cn(\"flex min-h-0 flex-col gap-2\", className)}>\n {/* One row: what kind of embed this is, and where it may run. */}\n <header className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Embed</span>\n <span>{mode === \"write\" ? \"a form people can send\" : \"a read-only view\"}</span>\n </header>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n <label className=\"flex flex-col gap-1 text-xs\">\n <span className=\"text-muted-foreground\">Sites this embed works on</span>\n <Input\n aria-label=\"Allowed origins\"\n className=\"h-8 text-xs\"\n placeholder=\"https://example.com\"\n value={origins}\n onChange={(e) => setOrigins(e.target.value)}\n />\n {/* Said BEFORE the refusal, because a person should not have to be\n refused to learn the rule. */}\n <span className=\"text-[11px] text-muted-foreground\">\n Name every site, scheme and host and port. An empty list is refused rather than quietly meaning\n \"anywhere\": a token that works from any page on the internet includes an attacker's. The match is\n exact, so <code>example.com.evil.test</code> will not pass.\n </span>\n </label>\n\n {!secret ? (\n <Button size=\"sm\" className=\"self-start\" disabled={busy || parsed.length === 0} onClick={() => void issue()}>\n {busy ? \"Issuing…\" : \"Issue embed\"}\n </Button>\n ) : (\n <>\n <p className=\"rounded border px-2 py-1 text-xs text-muted-foreground\">\n Copy this now. Only its digest is stored, so nobody — including us — can show it to you again;\n if it is lost, issue a new one and replace the old.\n </p>\n <Textarea aria-label=\"Embed snippet\" readOnly rows={3} className=\"font-mono text-[11px]\" value={snippet ?? \"\"} />\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => void navigator.clipboard?.writeText(snippet ?? \"\")}\n >\n Copy\n </Button>\n <Button size=\"sm\" variant=\"ghost\" disabled={busy} onClick={() => void revoke()}>\n Revoke\n </Button>\n </div>\n </>\n )}\n </section>\n );\n}\n\n/**\n * THE OTHER HALF, RUNNING INSIDE THE IFRAME ON SOMEBODY ELSE'S PAGE.\n *\n * It hands the secret and this page's own origin to the store and uses whatever\n * comes back. It decides nothing itself: a handshake that checked the origin in\n * JavaScript would be a handshake an attacker can edit.\n *\n * `origin` is taken from `window.location.origin` by default rather than from a\n * prop, because a prop is a value the embedding page controls and the origin\n * must not be.\n */\nexport function useEmbedHandshake(args: { secret: string; requiredMode?: \"read\" | \"write\"; origin?: string }): {\n binding: AnonTokenBinding | null;\n error: RecordsError | null;\n loading: boolean;\n} {\n const client = useRecordsClient();\n const [binding, setBinding] = useState<AnonTokenBinding | null>(null);\n const [error, setError] = useState<RecordsError | null>(null);\n const [loading, setLoading] = useState(true);\n const origin = args.origin ?? (typeof location === \"undefined\" ? \"\" : location.origin);\n const { secret, requiredMode } = args;\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n setError(null);\n void client\n .anonTokenVerify({ secret, origin, requiredMode: requiredMode ?? null })\n .then((answered) => {\n if (cancelled) return;\n setLoading(false);\n if (!answered.ok) {\n setError(answered.error);\n setBinding(null);\n return;\n }\n setBinding(answered.data);\n });\n return () => {\n cancelled = true;\n };\n }, [client, origin, requiredMode, secret]);\n\n return { binding, error, loading };\n}\n","\"use client\";\n\n// src/RecordsMount.tsx — @ai-matrx/records-ui\n//\n// THE ONE LINE A HOST ROUTE WRITES. `<RecordsProvider>` from @ai-matrx/records\n// and `<RecordsUiProvider>` from this package are two providers that must be\n// nested in one order, every time — so a route that got the order wrong would\n// fail with \"useRecordsClient was called outside <RecordsProvider>\" at the\n// bottom of a screen nobody was looking at. This mounts both, in the one order\n// that is correct, so a route file stays a mount and nothing more.\n//\n// THE RIGHTS QUESTION — AND THE ANSWER THAT USED TO BE HERE.\n//\n// `storeDecidesRights` returned `{admin: true, comment: true, write: true}` for\n// every non-kernel table, for everybody, on the reasoning that the doors are\n// the authority and a refusal would be shown verbatim when it came. The\n// sixth-pass verdict measured the cost of that reasoning: a colleague at viewer\n// double-clicked a cell, got a live editor, typed a value, pressed Enter, and\n// was told only then that she may not write. \"The permission is right; the\n// screen told her she could.\"\n//\n// It is not a guess any more. The read door has always answered the reader's\n// level on the table and the client now carries it (`Table.your_level`), so\n// this function ASKS instead of assuming, `letTheStoreDecideRights` still means\n// what it says, and a host that binds nothing gets the same honest answer\n// rather than every control absent. Kernel Tables (REC-27) keep their own\n// exclusion: the nine Tables the platform ships are not administered from a\n// person's screen at any level.\n\nimport type { ReactNode } from \"react\";\nimport type { RecordsActor, RecordsConfig, RecordsDataSource, Table, Uuid } from \"@ai-matrx/records\";\nimport { RecordsProvider } from \"@ai-matrx/records/react\";\nimport { RecordLabelProvider } from \"./labels\";\n\nimport { NO_RIGHTS, RecordsUiProvider, type RecordsUiHost, type TableRights } from \"./host\";\n\nexport const STORE_DECIDES_REASON =\n \"This host offers exactly what the record store says this person may do: the level comes back with \" +\n \"the table on the read door, so a control they cannot use is never drawn in the first place.\";\n\nexport { KERNEL_REASON } from \"./rights\";\n\n/**\n * DEPRECATED, and kept only so a host that imported it still compiles.\n *\n * It used to answer yes to everything for every non-kernel table. It cannot\n * answer honestly at all, because the honest answer needs a door call and this\n * signature is synchronous — which is exactly why the guess was here. Binding\n * it now would be binding a port that OVERRIDES the store's real answer, so it\n * returns the not-yet-answered set and every caller should simply stop passing\n * a `rights` port: unbound is the honest path (`useTableRights`).\n */\nexport function storeDecidesRights(_table: Table): TableRights {\n return NO_RIGHTS;\n}\n\nexport interface RecordsMountProps {\n /** The store config: the host's session-carrying client, the actor, the organization. */\n config: RecordsConfig;\n /** What this host binds on top — links, toasts, uploads, rights. */\n host?: RecordsUiHost | undefined;\n /**\n * Use `storeDecidesRights` when the host binds no `rights` of its own. Left\n * off, an unbound host gets `NO_RIGHTS` and every administering control is\n * absent with its reason.\n */\n letTheStoreDecideRights?: boolean | undefined;\n children: ReactNode;\n}\n\nexport function RecordsMount({\n config,\n host,\n letTheStoreDecideRights,\n children,\n}: RecordsMountProps) {\n // `letTheStoreDecideRights` means what it says and now needs no port at all:\n // with nothing bound, `useTableRights` asks `custom.my_levels` and draws what\n // the answer allows. A port bound here would OVERRIDE that answer.\n const bound: RecordsUiHost = { ...(host ?? {}) };\n void letTheStoreDecideRights;\n return (\n <RecordsProvider config={config}>\n <RecordsUiProvider value={bound}>\n {/* WHAT AN ID IS CALLED. A choice and a relation are stored as the id of\n another record, so every read-only surface needs the same answer to\n \"what is that record called\" — resolved once here rather than once\n per cell, and never drawn as the id itself. */}\n <RecordLabelProvider>{children}</RecordLabelProvider>\n </RecordsUiProvider>\n </RecordsProvider>\n );\n}\n\n/**\n * The actor a signed-in person is. `user` is the store's own word (the closed\n * ACTOR_VOCABULARY is `user` · `agent` · `system`), and AGT-N-4 means an agent\n * acting for this person carries exactly this authority and no other.\n */\nexport function personActor(userId: Uuid | null | undefined): RecordsActor {\n return userId ? { actor: \"user\", user_id: userId } : { actor: \"user\" };\n}\n\n/**\n * A supabase-js client AS this package's data seam.\n *\n * `RecordsDataSource` is deliberately a small structural subset of\n * `SupabaseClient` — the package holds no key and opens no connection, the host\n * hands it a client that already carries the person's session.\n *\n * IT IS NOT AN IDENTITY CAST, and it cost a live screen to learn why\n * (2026-09-19, /data-v2's first load): the port's `rpc(fn, args, { schema })`\n * says the schema OUT LOUD, because every door of this store is `custom.<name>`\n * and every door of the trust layer is `iam.<name>`. supabase-js's own\n * `rpc(fn, args, options)` has no `schema` option at all — its third argument is\n * `{ head, get, count }` — so a client passed straight through silently asked\n * its default PostgREST profile and the store answered, correctly and uselessly,\n * \"Could not find the function public.table_kernel_id ... PGRST202\". The schema\n * is chosen the one way supabase-js offers: `client.schema(name).rpc(...)`.\n *\n * `schema(name).from(table)` already agrees structurally and is passed through.\n *\n * `fallbackSchema` is the profile a call that says NOTHING is sent to. No caller\n * in `@ai-matrx/records` omits the option — `callDoor` always says `custom` and\n * `trustDoor` always says `iam` — so it never fires today; it exists so that a\n * call which one day forgets lands on the store rather than silently on\n * `public`. It is a FALLBACK and not the answer: a version of this adapter that\n * sent EVERY door to one fixed schema would route the `iam` trust doors (the\n * external principal, the publish binding) into `custom` and get a PGRST202\n * naming the wrong schema.\n *\n * The cast itself stays HERE, once, where it is explained: a generated\n * `Database` type makes `schema().from().select()` enormous, and a host app that\n * passes its client straight into `config` gets `TS2589: Type instantiation is\n * excessively deep and possibly infinite` in its own build (matrx-frontend,\n * 2026-09-18, on all three campaign routes at once).\n */\nexport function recordsDataSource(client: object, fallbackSchema = \"custom\"): RecordsDataSource {\n const supabase = client as unknown as {\n rpc: (fn: string, args: Record<string, unknown>) => PromiseLike<unknown>;\n schema: (name: string) => {\n rpc: (fn: string, args: Record<string, unknown>) => PromiseLike<unknown>;\n from: (table: string) => unknown;\n };\n };\n return {\n rpc(fn, args, options) {\n const on = supabase.schema(options?.schema ?? fallbackSchema);\n return on.rpc(fn, args) as ReturnType<RecordsDataSource[\"rpc\"]>;\n },\n schema(name) {\n return supabase.schema(name) as ReturnType<RecordsDataSource[\"schema\"]>;\n },\n };\n}\n","\"use client\";\n\n// src/TablesHome.tsx — @ai-matrx/records-ui\n//\n// THE LIST OF A PERSON'S TABLES — AND IT IS NEVER A FLAT PILE.\n//\n// Four lanes, always, in this order: mine · my organization · system ·\n// community. The lane a Table is in is read off the Table record itself and is\n// not a guess:\n//\n// · mine — `visibility = 'personal'` (the store's own enum word)\n// · organization — `visibility = 'internal'`\n// · system — `is_kernel` (REC-27: the Tables the platform ships)\n// · community — `visibility` is `link` or `public`\n//\n// A lane with nothing in it SAYS SO in one sentence that tells a person how it\n// fills up. An empty heading with nothing under it reads as \"broken\"; this\n// reads as \"nothing here yet, and here is what puts something here\".\n//\n// Creating and importing are both here, because both make a Table, and they go\n// through the store's own doors — `declareTable` walks Home → table_declare →\n// Fields, and the import mounts `ImportWizard` on the Table it just declared.\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { DashboardSummary, Table, Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient, useTables } from \"@ai-matrx/records/react\";\nimport type { RecordsError } from \"@ai-matrx/records\";\nimport { BasicInput, Button, Skeleton, cn } from \"@ai-matrx/design-system\";\n\nimport { RefusalNotice } from \"./Refusal\";\nimport { ImportWizard } from \"./ImportWizard\";\nimport { declareTable, tokenFor } from \"./createTable\";\nimport { tableName } from \"./names\";\n\nexport type TableLane = \"mine\" | \"organization\" | \"system\" | \"community\" | \"app\";\n\n/** The five lanes, in the order a person reads them. Never a flat list. */\nexport const TABLE_LANES: readonly TableLane[] = [\"mine\", \"organization\", \"system\", \"community\", \"app\"];\n\nexport const LANE_TITLE: Record<TableLane, string> = {\n mine: \"Mine\",\n organization: \"My organization\",\n system: \"System\",\n community: \"Community\",\n app: \"Kept by the app\",\n};\n\n/**\n * THE APP'S OWN BOOKKEEPING, MARKED AS SUCH.\n *\n * A saved view, a comment, a queued action and a form are records in Tables\n * this package declares in the organization's own store (`systemTable.ts`) —\n * which is what makes them shareable, historied and agent-writable. The price\n * is that using the product creates Tables in the person's own list: the\n * verdict of 19 September watched \"Saved views · 9 fields · records_ui_view\"\n * appear among somebody's data, and then \"Comments\" appear beside it the\n * moment a record was opened.\n *\n * They are not hidden — hiding a real Table from the person who owns it is its\n * own lie, and they hold that person's comments. They get their own lane,\n * last, with a sentence that says what they are.\n */\nconst APP_TABLE_PREFIX = \"records_ui_\";\n\n/** What fills an empty lane. A heading with nothing under it must still teach. */\nexport const LANE_EMPTY: Record<TableLane, string> = {\n mine: \"Nothing of your own yet. New table makes one that only you can see.\",\n organization:\n \"No tables shared across your organization yet. A table you make is yours until you change its visibility to internal.\",\n system: \"The platform's own tables are not in this organization's store.\",\n community: \"Nothing shared beyond your organization. A table published by link or to the world lands here.\",\n app:\n \"The app has not needed a table of its own in this organization yet. Saving a view, writing a \" +\n \"comment or building a form makes one, and it appears here rather than among your own data.\",\n};\n\n/** Which lane one Table belongs to, from the record's own columns. */\nexport function laneFor(table: Table): TableLane {\n if (table.is_kernel) return \"system\";\n if ((table.slug ?? \"\").startsWith(APP_TABLE_PREFIX)) return \"app\";\n if (table.visibility === \"public\" || table.visibility === \"link\") return \"community\";\n if (table.visibility === \"personal\") return \"mine\";\n return \"organization\";\n}\n\nexport interface TablesHomeProps {\n /** Where a table opens. Absent and the card is a plain row with no pretend link. */\n /**\n * Opening a Table, and — with a second argument — opening it ON one of its\n * dashboards. The second argument is optional so every existing caller is\n * unchanged; a host that ignores it lands on the records, which is what it\n * did before, rather than on a screen it does not know how to address.\n */\n onOpenTable?: ((tableId: Uuid, dashboardId?: Uuid) => void) | undefined;\n className?: string | undefined;\n}\n\nexport function TablesHome({ onOpenTable, className }: TablesHomeProps) {\n const client = useRecordsClient();\n const tables = useTables();\n const [creating, setCreating] = useState(false);\n const [name, setName] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<RecordsError | null>(null);\n const [importInto, setImportInto] = useState<Uuid | null>(null);\n // SCR-16. THE ORGANIZATION'S DASHBOARDS, ON THE RECORDS HOME.\n //\n // A dashboard is about ONE Table, so it lives on that Table's page — but a\n // person who wants to know how the work is going does not start by\n // remembering which Table the answer is in. `custom.dashboards` with no\n // table id answers the whole organization, narrowed to the Tables this\n // person can already open, so this list can never reveal a Table.\n const [boards, setBoards] = useState<DashboardSummary[] | null>(null);\n useEffect(() => {\n let cancelled = false;\n void client.dashboards({}).then((result) => {\n if (cancelled) return;\n // A REFUSAL HERE IS NOT THE PAGE'S REFUSAL. The Tables are what this\n // screen is for; a store with no dashboards door yet simply has no\n // section, and the Tables below are untouched.\n setBoards(result.ok ? result.data : []);\n });\n return () => {\n cancelled = true;\n };\n }, [client]);\n\n const create = useCallback(\n async (mode: \"open\" | \"import\") => {\n const trimmed = name.trim();\n if (!trimmed) return;\n setBusy(true);\n setError(null);\n const result = await declareTable(client, { name: trimmed, slug: tokenFor(trimmed) });\n setBusy(false);\n if (!result.ok) {\n setError(result.error);\n return;\n }\n setName(\"\");\n setCreating(false);\n tables.reload();\n if (mode === \"import\") setImportInto(result.data);\n else onOpenTable?.(result.data);\n },\n [client, name, onOpenTable, tables],\n );\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-4\", className)}>\n {/* One row. The page's own header already says where you are. */}\n <div className=\"flex items-center gap-2\">\n {creating ? (\n <>\n <BasicInput\n autoFocus\n value={name}\n placeholder=\"Table name\"\n onChange={(e) => setName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") void create(\"open\");\n if (e.key === \"Escape\") setCreating(false);\n }}\n className=\"h-8 max-w-xs\"\n />\n <Button size=\"sm\" disabled={busy || name.trim().length === 0} onClick={() => void create(\"open\")}>\n {busy ? \"Declaring…\" : \"Create\"}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled={busy || name.trim().length === 0}\n onClick={() => void create(\"import\")}\n >\n Create and import a file\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setCreating(false)}>\n Cancel\n </Button>\n </>\n ) : (\n <Button size=\"sm\" onClick={() => setCreating(true)}>\n New table\n </Button>\n )}\n </div>\n\n {error ? <RefusalNotice error={error} /> : null}\n\n {importInto ? (\n <div className=\"rounded-md border p-3\">\n <ImportWizard tableId={importInto} onDone={() => setImportInto(null)} />\n <Button size=\"sm\" variant=\"ghost\" className=\"mt-2\" onClick={() => onOpenTable?.(importInto)}>\n Open the table\n </Button>\n </div>\n ) : null}\n\n {tables.error ? <RefusalNotice error={tables.error} /> : null}\n {tables.loading && !tables.data ? (\n <div className=\"space-y-2\">\n <Skeleton className=\"h-6 w-40\" />\n <Skeleton className=\"h-16 w-full\" />\n </div>\n ) : null}\n\n {boards && boards.length > 0 ? (\n <section className=\"space-y-1.5\">\n <div className=\"flex items-baseline gap-2\">\n <h2 className=\"text-sm font-medium\">Dashboards</h2>\n <span className=\"text-xs opacity-60\">{boards.length}</span>\n </div>\n <ul className=\"grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3\">\n {boards.map((board) => (\n <li key={board.dashboard_id}>\n <button\n type=\"button\"\n disabled={!board.table_id}\n onClick={() =>\n board.table_id ? onOpenTable?.(board.table_id, board.dashboard_id) : undefined\n }\n className={cn(\n \"w-full rounded-md border px-3 py-2 text-left transition-colors\",\n onOpenTable && board.table_id ? \"hover:bg-accent\" : \"cursor-default\",\n )}\n >\n <span className=\"block truncate text-sm\">{board.name}</span>\n <span className=\"block truncate text-xs opacity-60\">\n {board.block_count} block{board.block_count === 1 ? \"\" : \"s\"}\n {\" · \"}\n {(() => {\n const owner = tables.data?.find((t) => t.id === board.table_id);\n return owner ? tableName(owner) : \"its table\";\n })()}\n </span>\n </button>\n </li>\n ))}\n </ul>\n </section>\n ) : null}\n\n {tables.data\n ? TABLE_LANES.map((lane) => {\n const rows = tables.data!.filter((t) => laneFor(t) === lane);\n return (\n <section key={lane} className=\"space-y-1.5\">\n <div className=\"flex items-baseline gap-2\">\n <h2 className=\"text-sm font-medium\">{LANE_TITLE[lane]}</h2>\n <span className=\"text-xs opacity-60\">{rows.length}</span>\n </div>\n {rows.length === 0 ? (\n <p className=\"text-xs opacity-70\">{LANE_EMPTY[lane]}</p>\n ) : (\n <ul className=\"grid gap-1.5 sm:grid-cols-2 lg:grid-cols-3\">\n {rows.map((table) => (\n <li key={table.id}>\n <button\n type=\"button\"\n onClick={() => onOpenTable?.(table.id)}\n className={cn(\n \"w-full rounded-md border px-3 py-2 text-left transition-colors\",\n onOpenTable ? \"hover:bg-accent\" : \"cursor-default\",\n )}\n >\n {/* The Table's NAME, never its token: `records_ui_view`\n and `v78_widget2` are machine names and no product\n a person judges puts one on a card. */}\n <span className=\"block truncate text-sm\">{tableName(table)}</span>\n <span className=\"block truncate text-xs opacity-60\">\n {table.fields.length} field{table.fields.length === 1 ? \"\" : \"s\"}\n {table.label_plural && table.label_plural !== table.name\n ? ` · ${table.label_plural}`\n : \"\"}\n </span>\n </button>\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n })\n : null}\n </div>\n );\n}\n","// src/createTable.ts — @ai-matrx/records-ui\n//\n// DECLARING A TABLE, THROUGH THE DOORS THAT DECLARE ONE.\n//\n// REC-1: a Table has to live somewhere. `custom._table_shape_guard` refuses a\n// Table with no Home in those words (\"a table has to live somewhere - give it a\n// home\"), so the sequence is fixed and this module is the one place that walks\n// it for a person-made table:\n//\n// 1. `personKernelId()` — the kernel Table a Home record lives in.\n// 2. `record_write` — the Home record. (A Home is an ORDINARY record: it is\n// not a Table, not a Field, not a View, and the write door is its door.)\n// 3. `table_declare` — the Table, under that Home.\n// 4. `field_declare` — ONE per column.\n//\n// STEP 4 USED TO BE `record_write` INTO THE FIELD KERNEL, AND THAT IS WHY\n// NOBODY COULD MAKE A TABLE. A Field is a record (REC-25), so this walked in\n// through the ordinary write door — and that door writes exactly one row with\n// `data_class = 'record'`. Since `custom._field_class_guard` landed it refuses\n// that row outright (23514 / FLD-13, \"a column of a table is stored as a field,\n// and this one says record\"), and before the guard it wrote a Field that no\n// reader asking for a Field by class could see. Either way the column was never\n// really made — and because `table_declare` runs FIRST and succeeds, every\n// \"Create table\" showed a red refusal AND left a table behind it. Measured on\n// the published screens (records-ui 0.16.0) on 2026-09-20: four tables in one\n// organization, each declaring a column name, none of them with a Field row.\n//\n// So the column goes through `custom.field_declare`, which is the door built\n// for exactly this: it takes what a PERSON knows — a name, a type, and for a\n// list the choices themselves — tells the Table first, stamps\n// `data_class = 'field'`, and fills in a name the Table declared and never\n// defined. And a table that could not take all of its columns is UNDONE, so a\n// person sees either a table or a refusal and never both.\n\nimport type { RecordsClient } from \"@ai-matrx/records/core\";\nimport type {\n FieldTypeWord,\n NewFieldDeclaration,\n ParityFieldType,\n RecordsError,\n Uuid,\n} from \"@ai-matrx/records\";\n\n/** One Field a person asked for, in the words a person uses (FLD-1 / FLD-11). */\nexport interface NewFieldSpec {\n key: string;\n label: string;\n /**\n * The word for what this column holds. One of the thirteen parity types, one\n * of the five behaviours, or a plain synonym (`text`, `long_text`, `number`)\n * — `custom._field_document_for` resolves all three and refuses a word that\n * means nothing, by name, with the list.\n */\n type: FieldTypeWord;\n sort?: number;\n required?: boolean;\n multi?: boolean;\n config?: Record<string, unknown>;\n /** A choice list's choices, as words. The store keeps them as a Table (FLD-5). */\n options?: string[];\n /** A column that points at another Table of this organization (FLD-11 / REL-8). */\n relationTarget?: Uuid;\n /** A currency column's symbol; a date column's day-or-day-and-time. */\n unit?: string;\n kind?: \"date\" | \"datetime\";\n}\n\nexport interface NewTableSpec {\n name: string;\n /** The token the Table is addressed by. Derived from the name when absent. */\n slug?: string;\n labelSingular?: string;\n labelPlural?: string;\n /** The Field whose value is the record's title (REC-2). Defaults to the first Field. */\n titleField?: string;\n fields?: NewFieldSpec[];\n}\n\nexport type DeclareResult =\n /**\n * The Table's id — and its HOME's, because REC-14 gives the Table exactly one\n * and the caller that made it is the only one that can tidy it up again. A\n * caller reading `data` alone is unaffected.\n */\n | { ok: true; data: Uuid; homeId: Uuid }\n | { ok: false; error: RecordsError };\n\n/** `My Sales Pipeline` → `my_sales_pipeline`. A token, never a sentence. */\nexport function tokenFor(name: string): string {\n return (\n name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 48) || \"table\"\n );\n}\n\n/** The one Field a Table cannot be declared without: something to call a record. */\n/**\n * WHY THE FIRST FIELD IS NOT REQUIRED.\n *\n * It was, and the cost showed up the moment the grid could add a row: \"New\n * record\" writes an empty record and puts you in the first cell, and the store\n * correctly refused every one of them — `REC-51: Title is required` — so the\n * one gesture that makes a grid feel like a grid never worked on a table a\n * person had just made. A title is what makes a record a CHIP (REC-2), which is\n * a fact about how it is shown, not a promise it can never be written without;\n * an organization that wants it demanded says so in the field editor, and the\n * store then enforces it for everyone.\n */\nexport const DEFAULT_FIELDS: NewFieldSpec[] = [\n { key: \"title\", label: \"Title\", type: \"text\", sort: 10, required: false },\n];\n\n/**\n * One column, in the shape `custom.field_declare` takes — and EVERYTHING a\n * person said about it. The keys after the type are not decoration: without\n * `options` the door refuses a choice list outright (\"A list of choices needs\n * its choices\"), without `unit` a money column is dollars whatever the person\n * picked, and without `relation_target` a column that points at another of this\n * organization's own tables cannot be declared at all.\n */\nexport function fieldDeclarationFor(field: NewFieldSpec): NewFieldDeclaration {\n return {\n key: field.key,\n label: field.label,\n sort: field.sort ?? 100,\n required: field.required ?? false,\n multi: field.multi ?? false,\n ...declaredType(field),\n ...(field.config ? { config: field.config } : {}),\n ...(field.options ? { options: field.options } : {}),\n ...(field.relationTarget ? { relation_target: field.relationTarget } : {}),\n ...(field.unit ? { unit: field.unit } : {}),\n ...(field.kind ? { kind: field.kind } : {}),\n };\n}\n\nexport async function declareTable(\n client: RecordsClient,\n spec: NewTableSpec,\n): Promise<DeclareResult> {\n const fields = spec.fields && spec.fields.length > 0 ? spec.fields : DEFAULT_FIELDS;\n const slug = spec.slug ?? tokenFor(spec.name);\n const titleField = spec.titleField ?? fields[0]!.key;\n\n const personKernel = await client.personKernelId();\n if (!personKernel.ok) return personKernel;\n\n const home = await client.recordWrite({\n table_id: personKernel.data,\n data: { name: `${spec.name} Home` },\n });\n if (!home.ok) return home;\n\n const table = await client.tableDeclare({\n homeId: home.data,\n spec: {\n name: spec.name,\n slug,\n type: \"entity\",\n label_singular: spec.labelSingular ?? spec.name,\n label_plural: spec.labelPlural ?? spec.name,\n display: \"list\",\n weight: \"light\",\n ordered: false,\n row_order: \"manual\",\n title_field: titleField,\n retention_days: 365,\n // AGT-1: a table a person made is agent-writable by declaration; the\n // organization turns it off, never this package.\n agent_writable: true,\n default_sort: [{ field: titleField, direction: \"asc\" }],\n fields: fields.map((f) => ({ name: f.key })),\n },\n });\n if (!table.ok) {\n // The Home is this table's and nothing else's, so it goes with it.\n await client.recordDelete({ record_id: home.data });\n return table;\n }\n\n const written = await addFields(client, table.data, fields);\n if (!written.ok) return undo(client, table.data, home.data, spec.name, written.error);\n return { ok: true, data: table.data, homeId: home.data };\n}\n\n/**\n * ONE ACT, FROM THE PERSON'S SIDE.\n *\n * The store has no transaction a client can hold across four calls, so the\n * three doors are three acts — and for two months the middle one failing left\n * a table nobody asked for beside a red sentence saying it had failed. Both\n * halves were true and together they were a lie.\n *\n * What is made is therefore taken back, newest first, and what that leaves is\n * reported. A take-back that itself fails is NOT swallowed: the person is told\n * the table is there and what to do with it, because a leftover nobody\n * mentioned is the silent failure this package exists to refuse.\n */\nasync function undo(\n client: RecordsClient,\n tableId: Uuid,\n homeId: Uuid,\n name: string,\n refusal: RecordsError,\n): Promise<DeclareResult> {\n const removed = await client.recordDelete({ record_id: tableId });\n if (removed.ok) {\n await client.recordDelete({ record_id: homeId });\n return { ok: false, error: refusal };\n }\n return {\n ok: false,\n error: {\n ...refusal,\n hint:\n `${refusal.hint ? `${refusal.hint} ` : \"\"}\"${name}\" was created before this happened and ` +\n `could not be removed again, so it is in your tables with no columns — open it and add ` +\n `the first column, or delete it from its own Settings.`,\n },\n };\n}\n\n/**\n * Columns for an existing Table, through the door that declares one. Used by\n * the create path and by import.\n *\n * A column the store refused STOPS the sequence and hands back the store's own\n * sentence: a Table that quietly lost a column is the silent failure this\n * package exists to prevent.\n */\nexport async function addFields(\n client: RecordsClient,\n tableId: Uuid,\n fields: NewFieldSpec[],\n): Promise<{ ok: true; data: Uuid } | { ok: false; error: RecordsError }> {\n /*\n * A COLUMN GOES THROUGH THE COLUMN DOOR (FLD-13).\n *\n * This wrote each Field as a plain record into the Field kernel Table, and\n * the store now refuses it out loud: `custom.record_write` stores a record\n * whose class defaults to \"record\", \"which makes the column invisible to\n * every reader that asks for a Field by class — including the duplicate check\n * that stops one table having the same column twice\" (`23514`,\n * `refused_by_rule`). Measured 2026-09-20: this is why `demo/live-smoke`\n * could not declare a table at all.\n *\n * `custom.field_declare` is the door that exists for this. It is also the one\n * that derives a parity type, creates a choice Table for a list column and\n * stamps the auto Rules a url or a percent carries — none of which a hand-\n * written record ever got, so every column made this way was thinner than one\n * made through the field panel.\n */\n for (const field of fields) {\n const result = await client.fieldDeclare({\n table_id: tableId,\n spec: fieldDeclarationFor(field),\n });\n if (!result.ok) return result;\n }\n return { ok: true, data: tableId };\n}\n\n/**\n * `NewFieldSpec.type` is the word a caller writes — one of the thirteen parity\n * types, or a plain behaviour — and `custom.field_declare` takes those as two\n * DIFFERENT keys: `parity_type` for the thirteen, `plain` for the three that\n * have none. The mapping is here rather than pushed onto every caller, and it\n * carries the one config a plain long text needs.\n *\n * An unrecognized word is passed through as a parity type rather than quietly\n * turned into text: the store keeps the closed list and its refusal names every\n * word it would have accepted, which is a better answer than a column that\n * silently came out as text.\n */\nconst PLAIN_WORDS: Record<string, \"text\" | \"long_text\" | \"number\"> = {\n text: \"text\",\n string: \"text\",\n long_text: \"long_text\",\n longtext: \"long_text\",\n paragraph: \"long_text\",\n number: \"number\",\n range: \"number\",\n integer: \"number\",\n decimal: \"number\",\n float: \"number\",\n};\n\nfunction declaredType(\n field: NewFieldSpec,\n): { plain: \"text\" | \"long_text\" | \"number\" } | { parity_type: ParityFieldType } {\n const word = (field.type ?? \"text\").toLowerCase();\n const plain = PLAIN_WORDS[word];\n if (plain) {\n // A caller that asked for multiline text gets long text, which is what the\n // store stores `config.multiline` for.\n return { plain: plain === \"text\" && field.config?.[\"multiline\"] === true ? \"long_text\" : plain };\n }\n return { parity_type: word as ParityFieldType };\n}\n","\"use client\";\n\n// src/TablePage.tsx — @ai-matrx/records-ui\n//\n// ONE TABLE'S WHOLE PAGE, assembled from this package's own components and\n// nothing else. A host route mounts this and passes the table token; every\n// screen below it is the canonical one, so a table reached from /data, from a\n// portal or from an agent's link looks and behaves identically.\n//\n// WHAT IS ON IT, and which contract row each part answers:\n// ViewBar (SCR-7) the saved views, and saving a new one\n// ViewSwitcher (SCR-6) grid · kanban · calendar · gallery over the SAME records\n// RecordForm (SCR-N-1) adding a record\n// FieldEditor (SCR-9) adding or retyping a field\n// TableSettings (SCR-3/4/5) rename, reorder, retype, delete, proposals\n// ActionInbox (SCR-11) approvals, assignments and agent proposals\n// Peek (SCR-N-3) a record, opened in place\n// HistoryPanel (SCR-17) that record's own versioned timeline\n// CommentThread (SCR-18) that record's comments\n// ExportMenu (SCR-31) the same bytes a script would produce\n// ImportWizard (SCR-10) rows in through the one write door\n// DashboardCanvas (SCR-16) the same records, counted\n// PortalsPanel (VIS-31) who signs in from outside, and exactly what they see\n//\n// ONE PANEL AT A TIME. The right-hand rail shows exactly one of settings,\n// inbox, import, the new-field editor or the opened record — a page that opens\n// four rails at once is a page nobody can read.\n\nimport { useCallback, useState } from \"react\";\nimport { viewPatchDocument, type SavedView, type SavedViewSpec } from \"./views\";\nimport type { Uuid } from \"@ai-matrx/records\";\nimport { useRecordsClient, useTable } from \"@ai-matrx/records/react\";\nimport { Button, Separator, Skeleton, cn } from \"@ai-matrx/design-system\";\n\nimport { ActionInbox } from \"./ActionInbox\";\nimport { DashboardCanvas } from \"./DashboardCanvas\";\nimport { CommentThread } from \"./CommentThread\";\nimport { ExportMenu } from \"./ExportMenu\";\nimport { FieldEditor } from \"./FieldEditor\";\nimport { HistoryPanel } from \"./HistoryPanel\";\nimport { ImportWizard } from \"./ImportWizard\";\nimport { Peek } from \"./Peek\";\nimport { RecordForm } from \"./RecordForm\";\nimport { FormsPanel } from \"./FormsPanel\";\nimport { PortalsPanel } from \"./PortalsPanel\";\nimport { SubscriptionsPanel } from \"./SubscriptionsPanel\";\nimport { RefusalNotice } from \"./Refusal\";\nimport { ShareControl } from \"./ShareControl\";\nimport { TableSettings } from \"./TableSettings\";\nimport { ViewBar } from \"./ViewBar\";\nimport { ViewSwitcher } from \"./ViewSwitcher\";\nimport { useTableRights } from \"./host\";\nimport { useRecordVersion } from \"./systemTable\";\n\ntype Rail =\n | \"none\"\n | \"settings\"\n | \"inbox\"\n | \"import\"\n | \"field\"\n | \"record\"\n | \"new-record\"\n | \"forms\"\n | \"notifications\"\n | \"portals\";\n\nexport interface TablePageProps {\n tableId: Uuid;\n /** Rows per page for every layout. */\n pageSize?: number | undefined;\n /**\n * The views this table should have. Each one whose NAME the table does not\n * hold yet is saved the first time the bar loads, and a name a person has\n * since tweaked is never overwritten. Left out, `DEFAULT_VIEW_NAME` below is\n * used — see why that default is not optional.\n */\n seedViews?: SavedViewSpec[] | undefined;\n /**\n * What a person does when the table is not theirs to see — switch\n * organization, go back to the list. Absent, the screen still SAYS what\n * happened; it just has no button to offer, which is honest and is never a\n * blank frame.\n */\n onLeave?: (() => void) | undefined;\n /** The word on that button. Defaults to \"Back to your tables\". */\n leaveLabel?: string | undefined;\n /**\n * OPEN ON ONE DASHBOARD, because an agent's answer ends in a LINK.\n *\n * `dashboard_propose` makes the whole canvas in one call and hands back an\n * address. A link that landed on the records and left the person to find the\n * Dashboards button, and then the right dashboard among several, is a link\n * that did not finish the sentence the agent started. Present, this opens the\n * canvas on that dashboard; absent, the page opens on the records exactly as\n * it always has.\n */\n activeDashboardId?: Uuid | null | undefined;\n className?: string | undefined;\n}\n\n/**\n * THE SENTENCE A TABLE YOU CANNOT SEE SAYS.\n *\n * Measured on the real screen (independent verdict, 19 September): opening a\n * table's page while another organization was active left the main area's text\n * \"literally the empty string\" after eighteen seconds — no sentence, no\n * spinner, no console error. A made-up id did the same. The cause is exactly\n * one line of this file: `custom.table_list` correctly answers the tables this\n * person can see in THIS organization, the table is not among them, so\n * `useTable` answers `{ data: null, error: null }` — not a refusal, just\n * absence — and the page rendered a skeleton for ever.\n *\n * Absence is an ANSWER and it gets a sentence. It deliberately does not say\n * whether the table exists: this person cannot see it, and which of the two it\n * is is not theirs to learn.\n */\nexport const TABLE_NOT_REACHABLE =\n \"This table is not in the organization you are working in, so there is nothing here to show. \" +\n \"Switch to the organization that owns it and open it again — or it may have been deleted.\";\n\n/**\n * THE VIEW EVERY TABLE HAS, AND WHY IT IS NOT OPTIONAL.\n *\n * A view is a record, so a table nobody has saved a view for has none — and\n * this page then renders its own honest sentence (\"Waiting for this table's\n * views\") and NO RECORDS AT ALL. Measured on 2026-09-19 by walking the real\n * product: declare a table, write a record, open the table — and the record is\n * not on the screen, with the only remedy being a control the person has no\n * reason to press. That is a dead end on the first table anybody makes.\n *\n * So the page seeds one: every record, newest work first, as a grid. It is an\n * ordinary saved view record like any other — renamable, re-sortable,\n * deletable — not a hidden built-in mode, because a \"special\" default view is a\n * second kind of view that every feature after it has to know about.\n */\nexport const DEFAULT_VIEW_NAME = \"All records\";\n\n/**\n * What the page says while it is running on the unsaved default. It is a\n * STAND-IN and it announces itself, with the one thing a person can do about\n * it: the bar above saves a view, and from then on the layout is remembered.\n */\nexport const VIEW_NOT_SAVED_YET =\n \"This table has no saved view yet, so the layout you pick here is not being kept. \" +\n \"Save one from the bar above and it is remembered.\";\n\nfunction defaultView(tableId: Uuid): SavedViewSpec {\n return { name: DEFAULT_VIEW_NAME, subject: tableId, layout: \"grid\", isDefault: true };\n}\n\n/**\n * THE TWO WAYS TO LOOK AT ONE TABLE'S RECORDS, and they are not two places in\n * the app. The views show the records; the canvas counts them — same table,\n * same door, same page, one control between them. A dashboard that lived\n * somewhere else in the product would be a second answer to \"how is the work\n * going\", reached by knowing where to click.\n */\ntype MainView = \"records\" | \"dashboards\";\n\nexport function TablePage({\n tableId,\n pageSize = 100,\n seedViews,\n onLeave,\n leaveLabel = \"Back to your tables\",\n activeDashboardId,\n className,\n}: TablePageProps) {\n const client = useRecordsClient();\n const table = useTable(tableId);\n const rights = useTableRights(table.data);\n const organizationId = useRecordsClient().config.organizationId;\n const [view, setView] = useState<SavedView | null>(null);\n const [rail, setRail] = useState<Rail>(\"none\");\n // An agent's link names a dashboard, so the page OPENS on the canvas rather\n // than making the person find it. Without one, nothing changes.\n const [main, setMain] = useState<MainView>(activeDashboardId ? \"dashboards\" : \"records\");\n const [openRecord, setOpenRecord] = useState<Uuid | null>(null);\n // The view record's own version at load, so two tabs tweaking one view are\n // TOLD — and moved forward after every save, so ONE person switching layout\n // twice is not told they conflicted with themselves.\n const viewVersion = useRecordVersion(view?.id ?? null);\n\n const show = (next: Rail) => setRail((current) => (current === next ? \"none\" : next));\n\n /**\n * A change the switcher made — the layout, the kanban's grouping Field, the\n * calendar's date Field — saved onto the VIEW RECORD, which is what makes it\n * remembered per saved view rather than per page load. The local copy moves\n * first so the board redraws at once; the store is the one that keeps it.\n */\n const patchView = useCallback(\n async (patch: Partial<SavedViewSpec>) => {\n const current = view;\n if (!current) return;\n setView({ ...current, ...patch });\n const document = viewPatchDocument(patch);\n if (Object.keys(document).length === 0) return;\n const written = await client.recordUpdate({\n record_id: current.id,\n patch: document,\n ...(viewVersion.version === null ? {} : { expectedVersion: viewVersion.version }),\n });\n if (written.ok) viewVersion.note(written.data);\n },\n [client, view, viewVersion],\n );\n\n if (table.error) return <RefusalNotice error={table.error} />;\n if (table.loading) return <Skeleton className=\"h-40 w-full\" />;\n if (!table.data) {\n // NOT a blank frame, and not a spinner that never ends.\n return (\n <div className={cn(\"flex flex-col items-start gap-2 rounded-md border border-dashed p-6\", className)}>\n <p className=\"text-sm font-medium\">This table is not here</p>\n <p className=\"max-w-prose text-xs text-muted-foreground\">{TABLE_NOT_REACHABLE}</p>\n {onLeave ? (\n <Button size=\"sm\" variant=\"outline\" onClick={onLeave}>\n {leaveLabel}\n </Button>\n ) : null}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex min-h-0 gap-4\", className)}>\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n {/* One row of controls. The route's own header already carries the name. */}\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <ViewBar\n tableId={tableId}\n onActiveView={setView}\n seed={seedViews ?? [defaultView(tableId)]}\n className=\"min-w-0 flex-1\"\n />\n {/* ONE \"New record\" ON SCREEN, EVER. The grid carries its own — it\n adds a row and puts you straight into the first cell, which is the\n gesture a person expects — so this page's button would be a second\n control for one thing (and was: the walk found two buttons of the\n same name in one header). It exists for the layouts that have no\n cells to type into. */}\n {rights.write && view && view.layout !== \"grid\" ? (\n <Button size=\"sm\" onClick={() => show(\"new-record\")}>\n New record\n </Button>\n ) : null}\n {rights.structure ? (\n <>\n <Button size=\"sm\" variant=\"outline\" onClick={() => show(\"field\")}>\n Add field\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"settings\")}>\n Settings\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"import\")}>\n Import\n </Button>\n </>\n ) : null}\n {/* PRODUCTS row 1. A form is a view on THIS table, so it opens in this\n table's own rail beside its settings and its inbox — never a\n second place in the app to go looking for it. */}\n {/* SCR-16. The counts over THESE records, beside the views of them —\n one control, and the main area is the dashboard rather than a\n second screen somewhere else in the app. */}\n <Button\n size=\"sm\"\n variant={main === \"dashboards\" ? \"secondary\" : \"ghost\"}\n aria-pressed={main === \"dashboards\"}\n onClick={() => setMain((v) => (v === \"dashboards\" ? \"records\" : \"dashboards\"))}\n >\n Dashboards\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"forms\")}>\n Forms\n </Button>\n {/* DOOR-18. A subscription watches a TABLE, so switching one off\n belongs beside that table's forms — not in a notifications area of\n the app somebody has to know exists. An agent can turn a\n notification on; this is where a person turns it off. */}\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"notifications\")}>\n Notifications\n </Button>\n {/* VIS-31 / PORTAL. A portal is a way IN to this table, so who may\n sign in and what they see belongs on the table's own page beside\n its forms — never a Portals area of the app somebody has to find. */}\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"portals\")}>\n Portals\n </Button>\n <Button size=\"sm\" variant=\"ghost\" onClick={() => show(\"inbox\")}>\n Inbox\n </Button>\n {/* SCR-N-5. A Table is a record, so the table screen shares through the\n same door and the same dialog a record does. */}\n <ShareControl\n kind=\"table\"\n organizationId={organizationId}\n subjectId={tableId}\n name={table.data?.name}\n may={rights.share}\n />\n <ExportMenu tableId={tableId} />\n </div>\n\n {main === \"dashboards\" ? (\n <DashboardCanvas tableId={tableId} activeDashboardId={activeDashboardId ?? null} />\n ) : (\n <>\n {/* THE RECORDS ARE NEVER HELD BACK BY THE BOOKKEEPING.\n\n A saved view is a record in this organization's own `records_ui_view`\n Table, and until it exists this page drew its own sentence and NO\n RECORDS AT ALL. That made one table's plumbing decide whether another\n table's data could be seen: when `records_ui_view` could not be\n declared — every one of its nine columns refused by FLD-13 — every\n table in the organization opened as \"Waiting for <name>'s views\" over\n an empty frame, with nothing on screen about the real reason and no\n control that could fix it. Measured on the published screens\n 2026-09-20.\n\n So the page always has a view. `ViewBar` hands over the saved one as\n soon as it has it; until then the grid runs on the unsaved default,\n which is the same spec `seedViews` would have written. A stand-in\n announces itself: the line below says the layout is not being kept\n yet, and `ViewSwitcher` already says the same of its own pickers\n because nothing is bound to save them. */}\n <ViewSwitcher\n view={view ?? defaultView(tableId)}\n pageSize={pageSize}\n {...(view ? { onViewChange: (patch: Partial<SavedViewSpec>) => void patchView(patch) } : {})}\n {...(rights.write ? { onNewRecordForm: () => setRail(\"new-record\") } : {})}\n onOpenRecord={(recordId) => {\n setOpenRecord(recordId);\n setRail(\"record\");\n }}\n />\n {view ? null : (\n <p className=\"text-xs text-muted-foreground\">{VIEW_NOT_SAVED_YET}</p>\n )}\n </>\n )}\n </div>\n\n {rail === \"none\" ? null : (\n <aside className=\"w-[26rem] shrink-0 overflow-y-auto rounded-md border p-3\">\n {rail === \"settings\" ? (\n <TableSettings\n tableId={tableId}\n {...(onLeave ? { onDeleted: onLeave } : {})}\n />\n ) : null}\n {rail === \"inbox\" ? (\n <ActionInbox\n tableId={tableId}\n onOpenRecord={(recordId) => {\n setOpenRecord(recordId);\n setRail(\"record\");\n }}\n />\n ) : null}\n {rail === \"forms\" ? <FormsPanel tableId={tableId} /> : null}\n {rail === \"notifications\" ? <SubscriptionsPanel tableId={tableId} /> : null}\n {rail === \"portals\" ? <PortalsPanel tableId={tableId} /> : null}\n {rail === \"import\" ? <ImportWizard tableId={tableId} onDone={() => setRail(\"none\")} /> : null}\n {rail === \"field\" ? (\n <FieldEditor tableId={tableId} onSaved={() => setRail(\"none\")} onCancel={() => setRail(\"none\")} />\n ) : null}\n {rail === \"new-record\" ? (\n <RecordForm\n tableId={tableId}\n onSaved={(recordId) => {\n setOpenRecord(recordId);\n setRail(\"record\");\n }}\n onCancel={() => setRail(\"none\")}\n />\n ) : null}\n {rail === \"record\" && openRecord ? (\n <div className=\"space-y-3\">\n <Peek tableId={tableId} recordId={openRecord} onClose={() => setRail(\"none\")} />\n <Separator />\n <HistoryPanel tableId={tableId} recordId={openRecord} />\n <Separator />\n <CommentThread tableId={tableId} recordId={openRecord} />\n </div>\n ) : null}\n </aside>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","document","import_react","import_design_system","import_react","import_records","import_design_system","import_records","import_records","import_react","import_jsx_runtime","id","import_jsx_runtime","import_jsx_runtime","id","import_react","import_design_system","import_design_system","import_jsx_runtime","import_design_system","import_react","import_jsx_runtime","import_jsx_runtime","document","import_jsx_runtime","inFlight","import_react","import_data_table","import_data_table","import_design_system","import_jsx_runtime","import_react","import_core","import_design_system","import_jsx_runtime","document","import_react","import_core","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","written","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_react","import_core","import_design_system","import_react","import_jsx_runtime","document","import_react","import_design_system","import_jsx_runtime","import_jsx_runtime","document","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_react","import_react","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","read","undo","import_react","import_design_system","import_jsx_runtime","import_react","import_records","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_records","import_design_system","import_react","import_design_system","import_jsx_runtime","document","answered","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_react","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_records","import_core","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","declare","import_react","import_records","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","document","tableName","import_react","import_design_system","import_jsx_runtime","document","ProvenanceBadge","import_react","import_design_system","import_jsx_runtime","step","import_react","import_design_system","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","keys","import_react","import_design_system","import_jsx_runtime","document","import_react","import_design_system","import_jsx_runtime","document","import_react","import_design_system","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_design_system","import_jsx_runtime","import_react","import_react","import_design_system","import_jsx_runtime","document"]}
|