@ai-matrx/records-ui 0.85.7 → 0.85.9

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 CHANGED
@@ -1,5 +1,48 @@
1
1
  # Changelog — @ai-matrx/records-ui
2
2
 
3
+ ## 0.85.9
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/records-ui/v0.85.7..npm/records-ui/v0.85.9 -- apps/shared/records-ui`).
7
+ No source changes intended and no consumer action required.
8
+
9
+ ## Unreleased
10
+
11
+ ### Lane MOVE-AND-OUTSIDER (2026-09-24)
12
+
13
+ * **A refused move stays on the confirm and says why, with the store's remedy.** `WhereItLives`
14
+ dropped the confirm on a refusal and drew only the message, then re-read the table (the panel
15
+ flipped to "Asking…"); the store's hint was never shown, and on production the panel closed with
16
+ nothing on the screen (VERIFIER-19 #1). Now the refusal is drawn inside the confirm as
17
+ "Nothing moved. <the store's sentence> <its hint>", the button reads **Try again**, **Cancel**
18
+ goes back to the list and re-reads, and a focus shift outside the panel (a toast, the error pill)
19
+ never closes it — only the person does. The success answer is unchanged. Suite
20
+ `a-refused-move-keeps-the-panel-open.test.tsx`: RED on the prior bytes (hint missing, confirm
21
+ gone), GREEN. The store half (`custom.table_move` now finds or makes the destination's home) is
22
+ on production. **Consumer action:** none.
23
+
24
+ ### Lane UI-FIX-19 (2026-09-24)
25
+
26
+ * **An inbox kind is a noun.** `WORK_INBOX_KIND_LABEL` (and `ActionInbox.KIND_WORD`) read
27
+ `Approve` / `Yours` / `Agent`; the bordered kind badge at the left of every row therefore read as
28
+ a live **Approve** control on each withdrawn and decided item (VERIFIER-19 #6 — the closed row
29
+ already drew no Approve button). Now `Approval` / `Assigned` / `Agent proposal`. Suite
30
+ `inbox-groups-and-closed-items.test.tsx` gains "no element that reads as a decision on a closed
31
+ item": RED on the prior bytes, GREEN 7/7. **Consumer action:** none, unless a host matched the
32
+ old words.
33
+ * **A dashboard save is judged by value.** `whatTheStoreDidNotKeep` compared canonical strings, so
34
+ a target the store kept and filled with its own defaults (`per: "period"`, `measure`) was
35
+ reported as "The store did not keep its target" right above *Target 150,000* (VERIFIER-19 #7).
36
+ Every key that was SENT must be held at the same value; a key the store added is not a loss; a
37
+ setting removed must be held as nothing. Suite `a-dashboard-save-says-what-the-store-did-not-keep`:
38
+ RED 1 on the prior bytes, GREEN 7/7.
39
+
40
+ ## 0.85.8
41
+
42
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
43
+ `git diff npm/records-ui/v0.85.7..npm/records-ui/v0.85.8 -- apps/shared/records-ui`).
44
+ No source changes intended and no consumer action required.
45
+
3
46
  ## 0.85.7 (2026-09-24 — published by PUBLISH-SWEEP-5)
4
47
 
5
48
  **Needs `@ai-matrx/records` 0.58.6** (the inbox doors: `inboxSnooze`, `inboxClear`, `inboxCounts`,
package/dist/index.cjs CHANGED
@@ -2535,9 +2535,9 @@ var DUE_STATE_LABEL = {
2535
2535
  };
2536
2536
  var WORK_INBOX_KINDS = exhaustiveValuesOf()(["assignment", "approval", "proposal"]);
2537
2537
  var WORK_INBOX_KIND_LABEL = {
2538
- assignment: "Yours",
2539
- approval: "Approve",
2540
- proposal: "Agent"
2538
+ assignment: "Assigned",
2539
+ approval: "Approval",
2540
+ proposal: "Agent proposal"
2541
2541
  };
2542
2542
  var WORK_INBOX_KIND_GROUP_LABEL = {
2543
2543
  approval: "Approvals",
@@ -19236,14 +19236,20 @@ var COMPARE_LABEL = {
19236
19236
  function compareKey(block, fields) {
19237
19237
  return block.bucket?.key ?? block.compare?.key ?? offerableFields(onePerKey(fields), "date")[0]?.key ?? null;
19238
19238
  }
19239
- function canonical(value) {
19240
- if (value === void 0 || value === null) return "null";
19241
- if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
19242
- if (typeof value === "object") {
19243
- const entries = Object.entries(value).filter(([, v]) => v !== void 0 && v !== null).sort(([a], [b]) => a.localeCompare(b));
19244
- return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(",")}}`;
19239
+ function holds(sent, stored) {
19240
+ const absent = (v) => v === void 0 || v === null;
19241
+ if (absent(sent)) return absent(stored);
19242
+ if (absent(stored)) return false;
19243
+ if (Array.isArray(sent)) {
19244
+ return Array.isArray(stored) && stored.length === sent.length && sent.every((v, i) => holds(v, stored[i]));
19245
19245
  }
19246
- return JSON.stringify(value);
19246
+ if (typeof sent === "object") {
19247
+ if (typeof stored !== "object" || Array.isArray(stored)) return false;
19248
+ return Object.entries(sent).every(
19249
+ ([k, v]) => absent(v) || holds(v, stored[k])
19250
+ );
19251
+ }
19252
+ return Object.is(sent, stored);
19247
19253
  }
19248
19254
  var KEPT_SETTINGS = [
19249
19255
  ["kind", "its shape"],
@@ -19260,7 +19266,7 @@ function whatTheStoreDidNotKeep(sent, stored) {
19260
19266
  lost.push(`\u201C${block.title}\u201D`);
19261
19267
  return;
19262
19268
  }
19263
- const what = KEPT_SETTINGS.filter(([key]) => canonical(block[key]) !== canonical(kept[key])).map(([, words]) => words);
19269
+ const what = KEPT_SETTINGS.filter(([key]) => !holds(block[key], kept[key])).map(([, words]) => words);
19264
19270
  if (what.length) lost.push(`${what.join(" and ")} for \u201C${block.title}\u201D`);
19265
19271
  });
19266
19272
  if (lost.length === 0) return null;
@@ -21262,12 +21268,15 @@ function WhereItLives({ tableId, knownOrganizationName, onMoved, variant = "head
21262
21268
  expected_version: home.table.version
21263
21269
  });
21264
21270
  setMoving(false);
21265
- setChoosing(null);
21266
21271
  if (!moved.ok) {
21267
- setSaid({ tone: "refused", text: `Nothing moved. ${moved.error.message}` });
21268
- setAttempt((n) => n + 1);
21272
+ const hint = moved.error.hint?.trim();
21273
+ setSaid({
21274
+ tone: "refused",
21275
+ text: `Nothing moved. ${moved.error.message}${hint && !moved.error.message.includes(hint) ? ` ${hint}` : ""}`
21276
+ });
21269
21277
  return;
21270
21278
  }
21279
+ setChoosing(null);
21271
21280
  setSaid({ tone: "done", text: `${moved.data.tableName} now lives in ${moved.data.to.name}.` });
21272
21281
  setAttempt((n) => n + 1);
21273
21282
  onMoved?.(moved.data.to);
@@ -21303,65 +21312,90 @@ function WhereItLives({ tableId, knownOrganizationName, onMoved, variant = "head
21303
21312
  ]
21304
21313
  }
21305
21314
  ) }),
21306
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.PopoverContent, { align: "start", className: "w-80 p-3 text-xs", onClick: (e) => e.stopPropagation(), children: answer === null ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: "Asking the record store where this table lives\u2026" }) : answer.state === "not-given" ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: "This table has not been shared with you, so where it lives is not yours to see." }) : answer.state === "door-absent" || answer.state === "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-2", children: [
21307
- knownOrganizationName ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("p", { children: [
21308
- "Lives in ",
21309
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "font-medium text-foreground", children: knownOrganizationName }),
21310
- "."
21311
- ] }) : null,
21312
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: answer.state === "door-absent" ? "Moving it to another organization is not available on this database yet." : `The record store could not be asked where this lives, so nothing here is an answer about your access. ${answer.why}` }),
21313
- answer.state === "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", variant: "outline", className: "h-7 text-xs", onClick: () => setAttempt((n) => n + 1), children: "Ask again" }) : null
21314
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-2", "data-where-it-lives-panel": answer.home.table.id, children: [
21315
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("p", { children: [
21316
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "text-muted-foreground", children: [
21317
- answer.home.table.name,
21318
- " lives in "
21319
- ] }),
21320
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "font-medium text-foreground", children: answer.home.organization.name }),
21321
- "."
21322
- ] }),
21323
- said ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { "data-where-it-lives-said": said.tone, className: said.tone === "refused" ? "text-destructive" : "text-foreground", children: said.text }) : null,
21324
- choosing ? (
21325
- // THE CONSEQUENCE, SAID BEFORE THE MOVE, in the same panel — no second dialog.
21326
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-2", "data-where-it-lives-confirm": choosing.id, children: [
21327
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("p", { className: "font-medium text-foreground", children: [
21328
- "Move ",
21329
- answer.home.table.name,
21330
- " to ",
21331
- choosing.name,
21332
- "?"
21315
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
21316
+ import_design_system67.PopoverContent,
21317
+ {
21318
+ align: "start",
21319
+ className: "w-80 p-3 text-xs",
21320
+ onClick: (e) => e.stopPropagation(),
21321
+ onFocusOutside: (e) => e.preventDefault(),
21322
+ children: answer === null ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: "Asking the record store where this table lives\u2026" }) : answer.state === "not-given" ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: "This table has not been shared with you, so where it lives is not yours to see." }) : answer.state === "door-absent" || answer.state === "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-2", children: [
21323
+ knownOrganizationName ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("p", { children: [
21324
+ "Lives in ",
21325
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "font-medium text-foreground", children: knownOrganizationName }),
21326
+ "."
21327
+ ] }) : null,
21328
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: answer.state === "door-absent" ? "Moving it to another organization is not available on this database yet." : `The record store could not be asked where this lives, so nothing here is an answer about your access. ${answer.why}` }),
21329
+ answer.state === "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", variant: "outline", className: "h-7 text-xs", onClick: () => setAttempt((n) => n + 1), children: "Ask again" }) : null
21330
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-2", "data-where-it-lives-panel": answer.home.table.id, children: [
21331
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("p", { children: [
21332
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "text-muted-foreground", children: [
21333
+ answer.home.table.name,
21334
+ " lives in "
21335
+ ] }),
21336
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "font-medium text-foreground", children: answer.home.organization.name }),
21337
+ "."
21333
21338
  ] }),
21334
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: (0, import_records23.moveConsequence)(answer.home, choosing) }),
21335
- /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "flex gap-2", children: [
21336
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", className: "h-7 text-xs", disabled: moving, onClick: () => void move(choosing), children: moving ? `Moving to ${choosing.name}\u2026` : "Move it" }),
21337
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", variant: "ghost", className: "h-7 text-xs", disabled: moving, onClick: () => setChoosing(null), children: "Cancel" })
21339
+ said && !(said.tone === "refused" && choosing) ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { "data-where-it-lives-said": said.tone, className: said.tone === "refused" ? "text-destructive" : "text-foreground", children: said.text }) : null,
21340
+ choosing ? (
21341
+ // THE CONSEQUENCE, SAID BEFORE THE MOVE, in the same panel — no second dialog.
21342
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-2", "data-where-it-lives-confirm": choosing.id, children: [
21343
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("p", { className: "font-medium text-foreground", children: [
21344
+ "Move ",
21345
+ answer.home.table.name,
21346
+ " to ",
21347
+ choosing.name,
21348
+ "?"
21349
+ ] }),
21350
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: (0, import_records23.moveConsequence)(answer.home, choosing) }),
21351
+ said?.tone === "refused" ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { "data-where-it-lives-said": "refused", role: "alert", className: "text-destructive", children: said.text }) : null,
21352
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "flex gap-2", children: [
21353
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(import_design_system67.Button, { size: "sm", className: "h-7 text-xs", disabled: moving, onClick: () => void move(choosing), children: moving ? `Moving to ${choosing.name}\u2026` : said?.tone === "refused" ? "Try again" : "Move it" }),
21354
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
21355
+ import_design_system67.Button,
21356
+ {
21357
+ size: "sm",
21358
+ variant: "ghost",
21359
+ className: "h-7 text-xs",
21360
+ disabled: moving,
21361
+ onClick: () => {
21362
+ const wasRefused = said?.tone === "refused";
21363
+ setChoosing(null);
21364
+ setSaid(null);
21365
+ if (wasRefused) setAttempt((n) => n + 1);
21366
+ },
21367
+ children: "Cancel"
21368
+ }
21369
+ )
21370
+ ] })
21371
+ ] })
21372
+ ) : !answer.home.mayMove ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: answer.home.whyNot }) : answer.home.heldBy.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-1", children: [
21373
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "font-medium text-foreground", children: "It cannot move yet:" }),
21374
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ul", { className: "list-disc space-y-1 pl-4 text-muted-foreground", children: answer.home.heldBy.map((line) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("li", { children: line }, line)) })
21375
+ ] }) : answer.home.destinations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: "You are not a member of any other organization, so there is nowhere else to move it." }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-1", children: [
21376
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "font-medium text-foreground", children: "Move it to" }),
21377
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ul", { className: "max-h-64 space-y-1 overflow-y-auto pr-1", children: answer.home.destinations.map((to) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("li", { children: to.ok ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
21378
+ import_design_system67.Button,
21379
+ {
21380
+ size: "sm",
21381
+ variant: "outline",
21382
+ className: "h-7 w-full justify-start text-xs",
21383
+ "data-where-it-lives-move": to.id,
21384
+ onClick: () => {
21385
+ setSaid(null);
21386
+ setChoosing(to);
21387
+ },
21388
+ children: to.name
21389
+ }
21390
+ ) : /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("p", { className: "text-muted-foreground", children: [
21391
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "text-foreground", children: to.name }),
21392
+ " \u2014 ",
21393
+ to.why
21394
+ ] }) }, to.id)) })
21338
21395
  ] })
21339
21396
  ] })
21340
- ) : !answer.home.mayMove ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: answer.home.whyNot }) : answer.home.heldBy.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-1", children: [
21341
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "font-medium text-foreground", children: "It cannot move yet:" }),
21342
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ul", { className: "list-disc space-y-1 pl-4 text-muted-foreground", children: answer.home.heldBy.map((line) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("li", { children: line }, line)) })
21343
- ] }) : answer.home.destinations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-muted-foreground", children: "You are not a member of any other organization, so there is nowhere else to move it." }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "space-y-1", children: [
21344
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "font-medium text-foreground", children: "Move it to" }),
21345
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ul", { className: "max-h-64 space-y-1 overflow-y-auto pr-1", children: answer.home.destinations.map((to) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("li", { children: to.ok ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
21346
- import_design_system67.Button,
21347
- {
21348
- size: "sm",
21349
- variant: "outline",
21350
- className: "h-7 w-full justify-start text-xs",
21351
- "data-where-it-lives-move": to.id,
21352
- onClick: () => {
21353
- setSaid(null);
21354
- setChoosing(to);
21355
- },
21356
- children: to.name
21357
- }
21358
- ) : /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("p", { className: "text-muted-foreground", children: [
21359
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "text-foreground", children: to.name }),
21360
- " \u2014 ",
21361
- to.why
21362
- ] }) }, to.id)) })
21363
- ] })
21364
- ] }) })
21397
+ }
21398
+ )
21365
21399
  ]
21366
21400
  }
21367
21401
  );