@ai-matrx/content-ir-react 0.24.5 → 0.25.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/dist/index.d.cts CHANGED
@@ -386,6 +386,15 @@ interface ItemChangesOptions {
386
386
  valueWord?: DirectiveValueWord | null;
387
387
  }
388
388
  declare function itemChanges(item: Record<string, unknown>, current?: Record<string, unknown> | null, options?: ItemChangesOptions): ItemChange[];
389
+ /**
390
+ * 🚨 AN UPDATE THAT WOULD CHANGE NOTHING SAYS SO (G11B review, 2026-10-07: the
391
+ * confirm listed every field "(no change)", Apply stayed full-weight, and the
392
+ * run ended "Updated task. Ran 2 times"). True when the item sets no field, or
393
+ * when the record was read and EVERY field already holds its new value. A field
394
+ * whose current value is unknown counts as a change — doubt never mutes Apply.
395
+ * ONE rule for the card and the host's confirm.
396
+ */
397
+ declare function changesNothing(changes: ReadonlyArray<ItemChange>): boolean;
389
398
 
390
399
  interface SideEffectDirectiveCardProps {
391
400
  directive: DecodedDirective;
@@ -756,4 +765,4 @@ declare class DbKindComponentErrorBoundary extends react.Component<DbKindCompone
756
765
  render(): react.ReactNode;
757
766
  }
758
767
 
759
- export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveHost, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type DirectiveValueWord, EMPTY_VALUE_WORD, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NO_TITLE_WORD, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, directiveFieldLabel, directiveValueWord, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemOwnName, itemRecordId, kindIsRoutable, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordRevision, useRecordValues };
768
+ export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveHost, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type DirectiveValueWord, EMPTY_VALUE_WORD, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NO_TITLE_WORD, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, changesNothing, createDbKindComponentCache, defaultFailureWords, describeChangeValue, directiveFieldLabel, directiveValueWord, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemOwnName, itemRecordId, kindIsRoutable, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordRevision, useRecordValues };
package/dist/index.d.ts CHANGED
@@ -386,6 +386,15 @@ interface ItemChangesOptions {
386
386
  valueWord?: DirectiveValueWord | null;
387
387
  }
388
388
  declare function itemChanges(item: Record<string, unknown>, current?: Record<string, unknown> | null, options?: ItemChangesOptions): ItemChange[];
389
+ /**
390
+ * 🚨 AN UPDATE THAT WOULD CHANGE NOTHING SAYS SO (G11B review, 2026-10-07: the
391
+ * confirm listed every field "(no change)", Apply stayed full-weight, and the
392
+ * run ended "Updated task. Ran 2 times"). True when the item sets no field, or
393
+ * when the record was read and EVERY field already holds its new value. A field
394
+ * whose current value is unknown counts as a change — doubt never mutes Apply.
395
+ * ONE rule for the card and the host's confirm.
396
+ */
397
+ declare function changesNothing(changes: ReadonlyArray<ItemChange>): boolean;
389
398
 
390
399
  interface SideEffectDirectiveCardProps {
391
400
  directive: DecodedDirective;
@@ -756,4 +765,4 @@ declare class DbKindComponentErrorBoundary extends react.Component<DbKindCompone
756
765
  render(): react.ReactNode;
757
766
  }
758
767
 
759
- export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveHost, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type DirectiveValueWord, EMPTY_VALUE_WORD, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NO_TITLE_WORD, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, directiveFieldLabel, directiveValueWord, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemOwnName, itemRecordId, kindIsRoutable, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordRevision, useRecordValues };
768
+ export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveHost, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type DirectiveValueWord, EMPTY_VALUE_WORD, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NO_TITLE_WORD, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, changesNothing, createDbKindComponentCache, defaultFailureWords, describeChangeValue, directiveFieldLabel, directiveValueWord, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemOwnName, itemRecordId, kindIsRoutable, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordRevision, useRecordValues };
package/dist/index.js CHANGED
@@ -739,7 +739,7 @@ function useContentIrKindVersion(kind, sources) {
739
739
  }
740
740
 
741
741
  // react/KindInstanceRender.tsx
742
- import { useEffect as useEffect3, useState as useState4 } from "react";
742
+ import { useEffect as useEffect4, useState as useState4 } from "react";
743
743
  import {
744
744
  envelopeFromCompleteValue as envelopeFromCompleteValue3,
745
745
  IR_ENVELOPE_KEY as IR_ENVELOPE_KEY2,
@@ -844,6 +844,9 @@ function itemChanges(item, current, options = {}) {
844
844
  }
845
845
  return out;
846
846
  }
847
+ function changesNothing(changes) {
848
+ return changes.every((change) => change.same === true);
849
+ }
847
850
 
848
851
  // directives/record-values.ts
849
852
  import { useEffect, useState, useSyncExternalStore as useSyncExternalStore2 } from "react";
@@ -1352,7 +1355,7 @@ function ApplyDirectiveButton({
1352
1355
  onFocus: warm,
1353
1356
  disabled: view.status === "applying" || view.status === "asking" || items.length === 0,
1354
1357
  "data-apply-tone": muted ? "muted" : destructive ? "destructive" : "default",
1355
- title: muted ? "It sets no fields, so applying it changes nothing." : void 0,
1358
+ title: muted ? "Applying it changes nothing." : void 0,
1356
1359
  className: `inline-flex shrink-0 items-center gap-1 whitespace-nowrap rounded-md border px-2 py-1 text-xs font-medium disabled:opacity-50 ${muted ? "border-border/60 bg-background text-muted-foreground hover:bg-accent" : destructive ? "border-destructive/50 bg-background text-destructive hover:bg-destructive/10" : "border-border bg-background hover:bg-accent"}`,
1357
1360
  children: [
1358
1361
  view.status === "applying" ? /* @__PURE__ */ jsx4(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx4(PlayIcon, { className: "h-3.5 w-3.5" }),
@@ -1510,7 +1513,7 @@ function resetDirectiveRenderers() {
1510
1513
  }
1511
1514
 
1512
1515
  // directives/SideEffectDirectiveCard.tsx
1513
- import { useState as useState3 } from "react";
1516
+ import { useEffect as useEffect3, useState as useState3 } from "react";
1514
1517
  import {
1515
1518
  asKindInstance,
1516
1519
  directiveDisplay as directiveDisplay3,
@@ -1534,12 +1537,23 @@ function ItemRow({
1534
1537
  item,
1535
1538
  index,
1536
1539
  total,
1537
- phase
1540
+ phase,
1541
+ onNothing
1538
1542
  }) {
1539
1543
  const host = useDirectiveHost();
1540
1544
  const recordId = TARGETING_CLASSES.has(directive.directiveClass) ? itemRecordId(item) : null;
1541
1545
  if (recordId) {
1542
- return /* @__PURE__ */ jsx7(TargetRow, { directive, item, recordId, index, phase });
1546
+ return /* @__PURE__ */ jsx7(
1547
+ TargetRow,
1548
+ {
1549
+ directive,
1550
+ item,
1551
+ recordId,
1552
+ index,
1553
+ phase,
1554
+ onNothing
1555
+ }
1556
+ );
1543
1557
  }
1544
1558
  const titleColumn = nounTitleColumn(directive.noun, host.nouns);
1545
1559
  const ownName = itemOwnName(item, titleColumn);
@@ -1558,7 +1572,8 @@ function ItemRow({
1558
1572
  /* @__PURE__ */ jsx7(
1559
1573
  "span",
1560
1574
  {
1561
- className: `min-w-0 shrink-0 truncate font-medium ${ownName ? "text-foreground" : "italic text-muted-foreground"}`,
1575
+ className: `min-w-0 line-clamp-2 font-medium [overflow-wrap:anywhere] sm:shrink-0 sm:truncate ${ownName ? "text-foreground" : "italic text-muted-foreground"}`,
1576
+ "data-item-name": "",
1562
1577
  "data-item-untitled": ownName ? void 0 : "",
1563
1578
  children: title
1564
1579
  }
@@ -1647,7 +1662,8 @@ function TargetRow({
1647
1662
  item,
1648
1663
  recordId,
1649
1664
  index,
1650
- phase
1665
+ phase,
1666
+ onNothing
1651
1667
  }) {
1652
1668
  const host = useDirectiveHost();
1653
1669
  const fallback = recordFallbackName(nounLabel2(directive.noun, host.nouns));
@@ -1662,7 +1678,11 @@ function TargetRow({
1662
1678
  titleColumn: nounTitleColumn(directive.noun, host.nouns),
1663
1679
  valueWord: directiveValueWord(host, directive.noun)
1664
1680
  }) : [];
1665
- const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ jsx7("span", { className: "truncate font-medium text-foreground", children: fallback });
1681
+ const nothing = readsLive && live.values !== null && changesNothing(changes);
1682
+ useEffect3(() => {
1683
+ onNothing?.(index, nothing);
1684
+ }, [onNothing, index, nothing]);
1685
+ const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ jsx7("span", { className: "line-clamp-2 min-w-0 font-medium text-foreground [overflow-wrap:anywhere]", children: fallback });
1666
1686
  return /* @__PURE__ */ jsxs5("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
1667
1687
  /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 items-center gap-2", children: [
1668
1688
  /* @__PURE__ */ jsx7("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
@@ -1686,7 +1706,9 @@ function SideEffectDirectiveCard({ directive }) {
1686
1706
  const [phase, setPhase] = useState3(
1687
1707
  () => readsApplyLedger(host, directive) ? { phase: "pending" } : { phase: "open" }
1688
1708
  );
1689
- const nothingToChange = directive.directiveClass === "update" && total > 0 && items.every((item) => itemChanges(item).length === 0);
1709
+ const [nothingAt, setNothingAt] = useState3({});
1710
+ const noteNothing = (index, nothing) => setNothingAt((prev) => prev[index] === nothing ? prev : { ...prev, [index]: nothing });
1711
+ const nothingToChange = directive.directiveClass === "update" && total > 0 && items.every((item, index) => itemChanges(item).length === 0 || nothingAt[index] === true);
1690
1712
  const shown = expanded ? items : items.slice(0, ROWS_BEFORE_FOLD);
1691
1713
  const hidden = total - shown.length;
1692
1714
  return /* @__PURE__ */ jsxs5("div", { className: "my-3 rounded-md border border-border bg-card px-2.5 py-1.5", "data-directive": directive.slug, children: [
@@ -1715,7 +1737,18 @@ function SideEffectDirectiveCard({ directive }) {
1715
1737
  total === 0 ? (
1716
1738
  // Stated, never silent: an empty batch is a real (and suspicious) state.
1717
1739
  /* @__PURE__ */ jsx7("p", { className: "mt-1 text-xs text-muted-foreground", children: "No items \u2014 nothing would be written." })
1718
- ) : /* @__PURE__ */ jsx7("div", { className: "mt-0.5 divide-y divide-border/60", children: shown.map((item, i) => /* @__PURE__ */ jsx7(ItemRow, { directive, item, index: i, total, phase }, i)) }),
1740
+ ) : /* @__PURE__ */ jsx7("div", { className: "mt-0.5 divide-y divide-border/60", children: shown.map((item, i) => /* @__PURE__ */ jsx7(
1741
+ ItemRow,
1742
+ {
1743
+ directive,
1744
+ item,
1745
+ index: i,
1746
+ total,
1747
+ phase,
1748
+ onNothing: noteNothing
1749
+ },
1750
+ i
1751
+ )) }),
1719
1752
  hidden > 0 || expanded ? /* @__PURE__ */ jsxs5(
1720
1753
  "button",
1721
1754
  {
@@ -1807,7 +1840,7 @@ function KindInstanceRenderInner({
1807
1840
  const [routingStatus, setRoutingStatus] = useState4(
1808
1841
  () => kindIsRoutable(kind, host) ? "routable" : "checking"
1809
1842
  );
1810
- useEffect3(() => {
1843
+ useEffect4(() => {
1811
1844
  let cancelled = false;
1812
1845
  let warmed = false;
1813
1846
  const syncRoutingStatus = () => {
@@ -2225,6 +2258,7 @@ export {
2225
2258
  SideEffectDirectiveCard,
2226
2259
  TARGETING_CLASSES,
2227
2260
  applyIrKindRoute,
2261
+ changesNothing,
2228
2262
  consoleErrorReporter,
2229
2263
  createDbKindComponentCache,
2230
2264
  createKindRouteBinding,