@happyvertical/smrt-fields 0.40.61 → 0.40.62

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.
Files changed (68) hide show
  1. package/README.md +125 -112
  2. package/dist/chunks/FieldPolicyCollection--RxukfCX.js +1218 -0
  3. package/dist/chunks/FieldPolicyCollection--RxukfCX.js.map +1 -0
  4. package/dist/collections/FieldPolicySuggestionCollection.d.ts +160 -0
  5. package/dist/collections/FieldPolicySuggestionCollection.d.ts.map +1 -0
  6. package/dist/collections/FieldUsageCounterCollection.d.ts +143 -0
  7. package/dist/collections/FieldUsageCounterCollection.d.ts.map +1 -0
  8. package/dist/deterministic-id.d.ts +18 -0
  9. package/dist/deterministic-id.d.ts.map +1 -0
  10. package/dist/field-definitions.d.ts +8 -0
  11. package/dist/field-definitions.d.ts.map +1 -1
  12. package/dist/index.d.ts +8 -2
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1565 -1077
  15. package/dist/index.js.map +1 -1
  16. package/dist/manifest.json +1442 -188
  17. package/dist/models/FieldPolicySuggestion.d.ts +132 -0
  18. package/dist/models/FieldPolicySuggestion.d.ts.map +1 -0
  19. package/dist/models/FieldUsageCounter.d.ts +178 -0
  20. package/dist/models/FieldUsageCounter.d.ts.map +1 -0
  21. package/dist/models/FieldUsageReportReceipt.d.ts +25 -0
  22. package/dist/models/FieldUsageReportReceipt.d.ts.map +1 -0
  23. package/dist/smrt-knowledge.json +402 -5
  24. package/dist/svelte/__tests__/FieldPolicyControlPanel.test.js +54 -0
  25. package/dist/svelte/__tests__/ObjectForm.test.js +131 -0
  26. package/dist/svelte/__tests__/UsageLearning.test.js +140 -0
  27. package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte +21 -4
  28. package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts +5 -1
  29. package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts.map +1 -1
  30. package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte +23 -0
  31. package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte.d.ts +10 -0
  32. package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte.d.ts.map +1 -0
  33. package/dist/svelte/components/FieldPolicyControlPanel.svelte +28 -1
  34. package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts +3 -0
  35. package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts.map +1 -1
  36. package/dist/svelte/components/FieldPolicyGearButton.svelte +8 -1
  37. package/dist/svelte/components/FieldPolicyGearButton.svelte.d.ts.map +1 -1
  38. package/dist/svelte/components/FieldPolicyGearProvider.svelte +34 -0
  39. package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts +3 -0
  40. package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts.map +1 -1
  41. package/dist/svelte/components/FieldPolicySuggestionQueue.svelte +135 -0
  42. package/dist/svelte/components/FieldPolicySuggestionQueue.svelte.d.ts +11 -0
  43. package/dist/svelte/components/FieldPolicySuggestionQueue.svelte.d.ts.map +1 -0
  44. package/dist/svelte/components/ObjectForm.svelte +91 -2
  45. package/dist/svelte/components/ObjectForm.svelte.d.ts +11 -1
  46. package/dist/svelte/components/ObjectForm.svelte.d.ts.map +1 -1
  47. package/dist/svelte/gear-context.svelte.d.ts +2 -0
  48. package/dist/svelte/gear-context.svelte.d.ts.map +1 -1
  49. package/dist/svelte/index.d.ts +6 -1
  50. package/dist/svelte/index.d.ts.map +1 -1
  51. package/dist/svelte/index.js +4 -1
  52. package/dist/svelte/suggestions.d.ts +38 -0
  53. package/dist/svelte/suggestions.d.ts.map +1 -0
  54. package/dist/svelte/suggestions.js +68 -0
  55. package/dist/svelte/usage-capture.d.ts +63 -0
  56. package/dist/svelte/usage-capture.d.ts.map +1 -0
  57. package/dist/svelte/usage-capture.js +61 -0
  58. package/dist/types.d.ts +40 -0
  59. package/dist/types.d.ts.map +1 -1
  60. package/dist/types.js +7 -1
  61. package/dist/types.js.map +1 -1
  62. package/dist/usage-learning.d.ts +201 -0
  63. package/dist/usage-learning.d.ts.map +1 -0
  64. package/dist/usage-schedules.d.ts +110 -0
  65. package/dist/usage-schedules.d.ts.map +1 -0
  66. package/dist/users-module.d.ts +30 -0
  67. package/dist/users-module.d.ts.map +1 -0
  68. package/package.json +8 -8
@@ -0,0 +1,135 @@
1
+ <script lang="ts">
2
+ /** Accessible, host-transport-neutral review queue for pending suggestions. */
3
+ import { Button } from '@happyvertical/smrt-ui/ui';
4
+ import {
5
+ type FieldPolicySuggestion,
6
+ type FieldPolicySuggestionAdapter,
7
+ fieldPolicySuggestionEvidence,
8
+ parsePendingFieldPolicySuggestions,
9
+ } from '../suggestions.js';
10
+
11
+ export interface FieldPolicySuggestionQueueProps {
12
+ adapter: FieldPolicySuggestionAdapter;
13
+ objectRefs?: readonly string[];
14
+ heading?: string;
15
+ onchanged?: () => void;
16
+ }
17
+
18
+ let {
19
+ adapter,
20
+ objectRefs,
21
+ heading = 'Pending field suggestions',
22
+ onchanged,
23
+ }: FieldPolicySuggestionQueueProps = $props();
24
+
25
+ let suggestions = $state<FieldPolicySuggestion[]>([]);
26
+ let total = $state(0);
27
+ let loading = $state(false);
28
+ let busyId = $state<string | null>(null);
29
+ let error = $state<string | null>(null);
30
+ let generation = 0;
31
+
32
+ async function load(): Promise<void> {
33
+ const token = ++generation;
34
+ loading = true;
35
+ error = null;
36
+ try {
37
+ const result = parsePendingFieldPolicySuggestions(
38
+ await adapter.pendingSuggestions(
39
+ objectRefs?.length ? { objectRefs } : undefined,
40
+ ),
41
+ );
42
+ if (token !== generation) return;
43
+ suggestions = result.suggestions;
44
+ total = result.total;
45
+ } catch (cause) {
46
+ if (token !== generation) return;
47
+ suggestions = [];
48
+ total = 0;
49
+ error =
50
+ cause instanceof Error
51
+ ? cause.message
52
+ : 'Unable to load pending field suggestions.';
53
+ } finally {
54
+ if (token === generation) loading = false;
55
+ }
56
+ }
57
+
58
+ async function decide(
59
+ suggestion: FieldPolicySuggestion,
60
+ decision: 'approve' | 'dismiss',
61
+ ): Promise<void> {
62
+ if (busyId) return;
63
+ busyId = suggestion.id;
64
+ error = null;
65
+ try {
66
+ if (decision === 'approve') {
67
+ await adapter.acceptSuggestion({ id: suggestion.id });
68
+ } else {
69
+ await adapter.dismissSuggestion({ id: suggestion.id });
70
+ }
71
+ await load();
72
+ onchanged?.();
73
+ } catch (cause) {
74
+ error =
75
+ cause instanceof Error
76
+ ? cause.message
77
+ : 'Unable to update this field suggestion.';
78
+ } finally {
79
+ busyId = null;
80
+ }
81
+ }
82
+
83
+ $effect(() => {
84
+ adapter;
85
+ objectRefs;
86
+ void load();
87
+ });
88
+
89
+ function description(suggestion: FieldPolicySuggestion): string {
90
+ return suggestion.kind === 'promote'
91
+ ? `Promote ${suggestion.fieldName} to the basic form.`
92
+ : `Set an organization default for ${suggestion.fieldName}.`;
93
+ }
94
+ </script>
95
+
96
+ <section class="field-policy-suggestion-queue" aria-label={heading}>
97
+ <header>
98
+ <h2>{heading}</h2>
99
+ {#if !loading}<span class="field-policy-suggestion-queue__count">{total}</span>{/if}
100
+ </header>
101
+ {#if loading}
102
+ <p role="status" aria-live="polite">Loading pending suggestions…</p>
103
+ {:else if error}
104
+ <p role="alert">{error}</p>
105
+ {:else if suggestions.length === 0}
106
+ <p>No pending field suggestions.</p>
107
+ {:else}
108
+ <ul>
109
+ {#each suggestions as suggestion (suggestion.id)}
110
+ <li>
111
+ <article>
112
+ <h3>{suggestion.objectRef} · {suggestion.fieldName}</h3>
113
+ <p>{description(suggestion)}</p>
114
+ <p>{fieldPolicySuggestionEvidence(suggestion)}</p>
115
+ <div class="field-policy-suggestion-queue__actions">
116
+ <Button type="button" disabled={busyId !== null} onclick={() => decide(suggestion, 'approve')}>Approve</Button>
117
+ <Button type="button" variant="ghost" disabled={busyId !== null} onclick={() => decide(suggestion, 'dismiss')}>Dismiss</Button>
118
+ </div>
119
+ </article>
120
+ </li>
121
+ {/each}
122
+ </ul>
123
+ {/if}
124
+ </section>
125
+
126
+ <style>
127
+ .field-policy-suggestion-queue { display: grid; gap: var(--smrt-spacing-3, 0.75rem); }
128
+ .field-policy-suggestion-queue header { align-items: center; display: flex; gap: var(--smrt-spacing-2, 0.5rem); }
129
+ .field-policy-suggestion-queue h2, .field-policy-suggestion-queue h3 { margin: 0; }
130
+ .field-policy-suggestion-queue__count { border-radius: 999px; background: var(--smrt-color-secondary-container, #e8def8); min-inline-size: 1.5rem; padding: 0.125rem 0.4rem; text-align: center; }
131
+ .field-policy-suggestion-queue ul { display: grid; gap: var(--smrt-spacing-3, 0.75rem); list-style: none; margin: 0; padding: 0; }
132
+ .field-policy-suggestion-queue article { border: 1px solid var(--smrt-color-outline-variant, currentColor); border-radius: var(--smrt-radius-small, 0.25rem); display: grid; gap: var(--smrt-spacing-2, 0.5rem); padding: var(--smrt-spacing-3, 0.75rem); }
133
+ .field-policy-suggestion-queue article p { margin: 0; }
134
+ .field-policy-suggestion-queue__actions { display: flex; flex-wrap: wrap; gap: var(--smrt-spacing-2, 0.5rem); }
135
+ </style>
@@ -0,0 +1,11 @@
1
+ import { type FieldPolicySuggestionAdapter } from '../suggestions.js';
2
+ export interface FieldPolicySuggestionQueueProps {
3
+ adapter: FieldPolicySuggestionAdapter;
4
+ objectRefs?: readonly string[];
5
+ heading?: string;
6
+ onchanged?: () => void;
7
+ }
8
+ declare const FieldPolicySuggestionQueue: import("svelte").Component<FieldPolicySuggestionQueueProps, {}, "">;
9
+ type FieldPolicySuggestionQueue = ReturnType<typeof FieldPolicySuggestionQueue>;
10
+ export default FieldPolicySuggestionQueue;
11
+ //# sourceMappingURL=FieldPolicySuggestionQueue.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FieldPolicySuggestionQueue.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldPolicySuggestionQueue.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,4BAA4B,EAGlC,MAAM,mBAAmB,CAAC;AAG3B,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,4BAA4B,CAAC;IACtC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAuHD,QAAA,MAAM,0BAA0B,qEAAwC,CAAC;AACzE,KAAK,0BAA0B,GAAG,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAChF,eAAe,0BAA0B,CAAC"}
@@ -21,6 +21,11 @@ import {
21
21
  type ObjectFormFieldDefinition,
22
22
  type ObjectFormFieldSnippetProps,
23
23
  } from '../types.js';
24
+ import {
25
+ collectFieldUsageEntries,
26
+ type FieldUsageReporter,
27
+ reportFieldUsage,
28
+ } from '../usage-capture.js';
24
29
  import AdvancedFields from './AdvancedFields.svelte';
25
30
  import FieldInput from './FieldInput.svelte';
26
31
  import FieldPolicyGearButton from './FieldPolicyGearButton.svelte';
@@ -57,10 +62,23 @@ export interface ObjectFormProps {
57
62
  renderers?: Readonly<Record<string, Snippet<[ObjectFormFieldSnippetProps]>>>;
58
63
  /** Optional controls rendered after the policy-ordered fields inside the form. */
59
64
  actions?: Snippet;
65
+ /**
66
+ * Optional telemetry transport. It runs only when `onsubmit` explicitly
67
+ * resolves `true` after persistence; identity and field sensitivity remain
68
+ * server-derived.
69
+ */
70
+ usageReporter?: FieldUsageReporter;
60
71
  class?: string;
61
- onsubmit?: (event: SubmitEvent) => void;
72
+ /** Return true only after the host has persisted this record successfully. */
73
+ onsubmit?: ObjectFormSubmitHandler;
62
74
  }
63
75
 
76
+ // biome-ignore lint/suspicious/noConfusingVoidType: void handlers remain a supported legacy integration and never acknowledge persistence.
77
+ export type ObjectFormSubmitAcknowledgement = boolean | void;
78
+ export type ObjectFormSubmitHandler = (
79
+ event: SubmitEvent,
80
+ ) => ObjectFormSubmitAcknowledgement | Promise<ObjectFormSubmitAcknowledgement>;
81
+
64
82
  let {
65
83
  objectRef,
66
84
  fields = undefined,
@@ -74,6 +92,7 @@ let {
74
92
  inputRegistry,
75
93
  renderers = {},
76
94
  actions,
95
+ usageReporter,
77
96
  class: className = '',
78
97
  onsubmit,
79
98
  }: ObjectFormProps = $props();
@@ -201,6 +220,76 @@ function fieldId(name: string): string {
201
220
  return `${formInstanceId}-${name}`;
202
221
  }
203
222
 
223
+ function captureUsage(values: Readonly<Record<string, unknown>>): void {
224
+ if (!resolvedPolicy) return;
225
+ reportFieldUsage(
226
+ usageReporter,
227
+ collectFieldUsageEntries({
228
+ objectRef,
229
+ values,
230
+ // Hidden fields are not submitted user inputs. Basic and advanced fields
231
+ // are included even when a value matches the default so the server's
232
+ // dominance calculation has a complete denominator.
233
+ fields: Object.fromEntries(
234
+ formFields
235
+ .filter(
236
+ (field) =>
237
+ resolvedPolicy.fields[field.name].visibility !== 'hidden',
238
+ )
239
+ .map((field) => [field.name, field.definition.type]),
240
+ ),
241
+ defaults: Object.fromEntries(
242
+ formFields
243
+ .filter(
244
+ (field) =>
245
+ resolvedPolicy.fields[field.name].visibility !== 'hidden',
246
+ )
247
+ .map((field) => {
248
+ const resolved = resolvedPolicy.fields[field.name];
249
+ return [
250
+ field.name,
251
+ {
252
+ hasDefault: resolved.hasDefault,
253
+ defaultValue: resolved.defaultValue,
254
+ },
255
+ ];
256
+ }),
257
+ ),
258
+ }),
259
+ );
260
+ }
261
+
262
+ async function handleSubmit(event: SubmitEvent): Promise<void> {
263
+ if (invalidFields.size > 0) {
264
+ event.preventDefault();
265
+ return;
266
+ }
267
+ if (!onsubmit) return;
268
+ // A successful create commonly replaces the bound record before its
269
+ // persistence promise resolves. Snapshot before awaiting so usage describes
270
+ // the fields that were submitted, not the newly cleared next-record state.
271
+ const submittedValues = snapshotUsageValues(value);
272
+ try {
273
+ // Form prevents native navigation itself, so persistence acknowledgement
274
+ // must be explicit rather than inferred from event.defaultPrevented.
275
+ if ((await onsubmit(event)) === true) captureUsage(submittedValues);
276
+ } catch {
277
+ // The host owns persistence errors; rejected submissions never emit usage.
278
+ }
279
+ }
280
+
281
+ function snapshotUsageValues(
282
+ record: Readonly<Record<string, unknown>>,
283
+ ): Record<string, unknown> {
284
+ try {
285
+ return structuredClone(record);
286
+ } catch {
287
+ // Generated form values are wire-safe, but retain a shallow fallback for
288
+ // host extensions that add an uncloneable value outside telemetry fields.
289
+ return { ...record };
290
+ }
291
+ }
292
+
204
293
  // Apply policy defaults to a create record once, before a user can interact
205
294
  // with any control. This preserves JSON and boolean defaults (which cannot be
206
295
  // faithfully inferred from generic DOM string assignment) and means callers
@@ -330,7 +419,7 @@ function inputFor(field: ObjectFormField): FieldInputComponent {
330
419
  <div class="object-form__gear"><FieldPolicyGearButton /></div>
331
420
  {/if}
332
421
  {/if}
333
- <Form class="object-form {className}" onsubmit={(event) => { if (invalidFields.size > 0) { event.preventDefault(); return; } onsubmit?.(event); }}>
422
+ <Form class="object-form {className}" onsubmit={handleSubmit}>
334
423
  {@render renderGroups(basicGroups)}
335
424
  {#if advancedGroups.length > 0}
336
425
  <AdvancedFields open>
@@ -2,6 +2,9 @@ import type { Component, Snippet } from 'svelte';
2
2
  import type { ResolvedObjectFieldPolicy } from '../../types.js';
3
3
  import type { FieldInputRegistry } from '../input-registry.js';
4
4
  import { type ObjectFormFieldDefinition, type ObjectFormFieldSnippetProps } from '../types.js';
5
+ import { type FieldUsageReporter } from '../usage-capture.js';
6
+ export type ObjectFormSubmitAcknowledgement = boolean | void;
7
+ export type ObjectFormSubmitHandler = (event: SubmitEvent) => ObjectFormSubmitAcknowledgement | Promise<ObjectFormSubmitAcknowledgement>;
5
8
  export interface ObjectFormProps {
6
9
  objectRef: string;
7
10
  /**
@@ -31,8 +34,15 @@ export interface ObjectFormProps {
31
34
  renderers?: Readonly<Record<string, Snippet<[ObjectFormFieldSnippetProps]>>>;
32
35
  /** Optional controls rendered after the policy-ordered fields inside the form. */
33
36
  actions?: Snippet;
37
+ /**
38
+ * Optional telemetry transport. It runs only when `onsubmit` explicitly
39
+ * resolves `true` after persistence; identity and field sensitivity remain
40
+ * server-derived.
41
+ */
42
+ usageReporter?: FieldUsageReporter;
34
43
  class?: string;
35
- onsubmit?: (event: SubmitEvent) => void;
44
+ /** Return true only after the host has persisted this record successfully. */
45
+ onsubmit?: ObjectFormSubmitHandler;
36
46
  }
37
47
  declare const ObjectForm: Component<ObjectFormProps, {}, "value">;
38
48
  type ObjectForm = ReturnType<typeof ObjectForm>;
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ObjectForm.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAGL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EACjC,MAAM,aAAa,CAAC;AASrB,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAC7D,mFAAmF;IACnF,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,6DAA6D;IAC7D,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CACzC;AAsSD,QAAA,MAAM,UAAU,yCAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ObjectForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ObjectForm.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAGL,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EACjC,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,qBAAqB,CAAC;AAU7B,MAAM,MAAM,+BAA+B,GAAG,OAAO,GAAG,IAAI,CAAC;AAC7D,MAAM,MAAM,uBAAuB,GAAG,CACpC,KAAK,EAAE,WAAW,KACf,+BAA+B,GAAG,OAAO,CAAC,+BAA+B,CAAC,CAAC;AAEhF,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAC7D,mFAAmF;IACnF,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,uEAAuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,6DAA6D;IAC7D,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CACpC;AAgXD,QAAA,MAAM,UAAU,yCAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -4,6 +4,8 @@ export interface FieldPolicyGearController {
4
4
  readonly error: string | null;
5
5
  readonly open: boolean;
6
6
  readonly canEdit: boolean;
7
+ /** Pending reviewed suggestions for this form's object, when configured. */
8
+ readonly pendingSuggestionCount: number;
7
9
  show(): void;
8
10
  hide(): void;
9
11
  reload(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"gear-context.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/gear-context.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,IAAI,IAAI,CAAC;IACb,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAID,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,yBAAyB,GACpC,IAAI,CAEN;AAED,wBAAgB,yBAAyB,IAAI,yBAAyB,CAQrE;AAED,wBAAgB,4BAA4B,IACxC,yBAAyB,GACzB,SAAS,CAIZ"}
1
+ {"version":3,"file":"gear-context.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/gear-context.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,IAAI,IAAI,CAAC;IACb,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAID,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,yBAAyB,GACpC,IAAI,CAEN;AAED,wBAAgB,yBAAyB,IAAI,yBAAyB,CAQrE;AAED,wBAAgB,4BAA4B,IACxC,yBAAyB,GACzB,SAAS,CAIZ"}
@@ -21,22 +21,25 @@ import FieldPolicyEditor from './components/FieldPolicyEditor.svelte';
21
21
  import FieldPolicyGearButton from './components/FieldPolicyGearButton.svelte';
22
22
  import FieldPolicyGearProvider from './components/FieldPolicyGearProvider.svelte';
23
23
  import FieldPolicyProvider from './components/FieldPolicyProvider.svelte';
24
+ import FieldPolicySuggestionQueue from './components/FieldPolicySuggestionQueue.svelte';
24
25
  import FormHelp from './components/FormHelp.svelte';
25
26
  import ModeSwitch from './components/ModeSwitch.svelte';
26
27
  import ObjectForm from './components/ObjectForm.svelte';
27
28
  import ObjectFormSourceProvider from './components/ObjectFormSourceProvider.svelte';
28
29
  import PolicyField from './components/PolicyField.svelte';
29
- export { AdvancedFields, FieldPolicyControlPanel, FieldPolicyEditor, FieldPolicyGearButton, FieldPolicyGearProvider, FieldPolicyProvider, FormHelp, ModeSwitch, ObjectForm, ObjectFormSourceProvider, PolicyField, };
30
+ export { AdvancedFields, FieldPolicyControlPanel, FieldPolicyEditor, FieldPolicyGearButton, FieldPolicyGearProvider, FieldPolicyProvider, FieldPolicySuggestionQueue, FormHelp, ModeSwitch, ObjectForm, ObjectFormSourceProvider, PolicyField, };
30
31
  export type AdvancedFieldsProps = ComponentProps<typeof AdvancedFields>;
31
32
  export type FieldPolicyProviderProps = ComponentProps<typeof FieldPolicyProvider>;
32
33
  export type FormHelpProps = ComponentProps<typeof FormHelp>;
33
34
  export type ModeSwitchProps = ComponentProps<typeof ModeSwitch>;
34
35
  export type ObjectFormProps = ComponentProps<typeof ObjectForm>;
36
+ export type { ObjectFormSubmitAcknowledgement, ObjectFormSubmitHandler, } from './components/ObjectForm.svelte';
35
37
  export type ObjectFormSourceProviderProps = ComponentProps<typeof ObjectFormSourceProvider>;
36
38
  export type FieldPolicyEditorProps = ComponentProps<typeof FieldPolicyEditor>;
37
39
  export type FieldPolicyControlPanelProps = ComponentProps<typeof FieldPolicyControlPanel>;
38
40
  export type FieldPolicyGearButtonProps = ComponentProps<typeof FieldPolicyGearButton>;
39
41
  export type FieldPolicyGearProviderProps = ComponentProps<typeof FieldPolicyGearProvider>;
42
+ export type FieldPolicySuggestionQueueProps = ComponentProps<typeof FieldPolicySuggestionQueue>;
40
43
  export type PolicyFieldProps = ComponentProps<typeof PolicyField>;
41
44
  export type { FieldPolicyCatalogObjectSummary, FieldPolicyDetailItem, FieldPolicySettingsCatalogData, FieldPolicySettingsCatalogPage, FieldPolicySummaryItem, } from '../settings-catalog.js';
42
45
  export type { ResolvedFieldPolicy, ResolvedObjectFieldPolicy, } from '../types.js';
@@ -54,5 +57,7 @@ export { resolveObjectFormFields } from './object-form.js';
54
57
  export { assertObjectFormCollectionDefinition, ObjectFormSourceRegistry, } from './object-form-source.svelte.js';
55
58
  export type { FieldPolicyControlPanelAdapter, FieldPolicyFieldRollup, FieldPolicyLayerCell, } from './settings-catalog.js';
56
59
  export { auditObjectRefs, decorateCatalogItem, decorateCatalogPage, fieldPolicyControlPanelNavItem, fieldPolicyRollup, MAX_FIELD_POLICY_AUDIT_OBJECT_REFS, orgRowIdsForObject, prunableDriftRows, } from './settings-catalog.js';
60
+ export { type FieldPolicySuggestion, type FieldPolicySuggestionAdapter, type FieldPolicySuggestionKind, fieldPolicySuggestionEvidence, parsePendingFieldPolicySuggestions, } from './suggestions.js';
57
61
  export type { FieldInputProps, ObjectFormCollectionDefinition, ObjectFormField, ObjectFormFieldDefinition, ObjectFormFieldSnippetProps, ObjectFormPolicyClient, ObjectFormResolvedSource, ObjectFormSource, ObjectFormWireType, PolicyFieldSnippetProps, } from './types.js';
62
+ export { type CollectFieldUsageEntriesOptions, canCaptureFieldUsageValue, collectFieldUsageEntries, type FieldUsageDefault, type FieldUsageEntry, type FieldUsageReporter, type FieldUsageWireType, fieldUsageValuesEqual, isBlankFieldValue, reportFieldUsage, } from './usage-capture.js';
58
63
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"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"}
@@ -20,13 +20,14 @@ import FieldPolicyEditor from './components/FieldPolicyEditor.svelte';
20
20
  import FieldPolicyGearButton from './components/FieldPolicyGearButton.svelte';
21
21
  import FieldPolicyGearProvider from './components/FieldPolicyGearProvider.svelte';
22
22
  import FieldPolicyProvider from './components/FieldPolicyProvider.svelte';
23
+ import FieldPolicySuggestionQueue from './components/FieldPolicySuggestionQueue.svelte';
23
24
  import FormHelp from './components/FormHelp.svelte';
24
25
  import ModeSwitch from './components/ModeSwitch.svelte';
25
26
  import ObjectForm from './components/ObjectForm.svelte';
26
27
  import ObjectFormSourceProvider from './components/ObjectFormSourceProvider.svelte';
27
28
  import PolicyField from './components/PolicyField.svelte';
28
29
  // Components
29
- export { AdvancedFields, FieldPolicyControlPanel, FieldPolicyEditor, FieldPolicyGearButton, FieldPolicyGearProvider, FieldPolicyProvider, FormHelp, ModeSwitch, ObjectForm, ObjectFormSourceProvider, PolicyField, };
30
+ export { AdvancedFields, FieldPolicyControlPanel, FieldPolicyEditor, FieldPolicyGearButton, FieldPolicyGearProvider, FieldPolicyProvider, FieldPolicySuggestionQueue, FormHelp, ModeSwitch, ObjectForm, ObjectFormSourceProvider, PolicyField, };
30
31
  // Context types and accessors
31
32
  export { getFieldPolicyContext, setFieldPolicyContext, tryGetFieldPolicyContext, } from './context.svelte.js';
32
33
  export { policyToVisibleColumnIds } from './data-table.js';
@@ -36,3 +37,5 @@ export { createFieldInputRegistry, FieldInputRegistry, } from './input-registry.
36
37
  export { resolveObjectFormFields } from './object-form.js';
37
38
  export { assertObjectFormCollectionDefinition, ObjectFormSourceRegistry, } from './object-form-source.svelte.js';
38
39
  export { auditObjectRefs, decorateCatalogItem, decorateCatalogPage, fieldPolicyControlPanelNavItem, fieldPolicyRollup, MAX_FIELD_POLICY_AUDIT_OBJECT_REFS, orgRowIdsForObject, prunableDriftRows, } from './settings-catalog.js';
40
+ export { fieldPolicySuggestionEvidence, parsePendingFieldPolicySuggestions, } from './suggestions.js';
41
+ export { canCaptureFieldUsageValue, collectFieldUsageEntries, fieldUsageValuesEqual, isBlankFieldValue, reportFieldUsage, } from './usage-capture.js';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Structural browser contracts for field-policy suggestion review.
3
+ *
4
+ * These types intentionally omit tenant, user, authorization, and field
5
+ * sensitivity data. Hosts bind methods to authenticated generated clients;
6
+ * the server derives identity and validates every action.
7
+ */
8
+ export type FieldPolicySuggestionKind = 'promote' | 'default';
9
+ export interface FieldPolicySuggestion {
10
+ id: string;
11
+ objectRef: string;
12
+ fieldName: string;
13
+ kind: FieldPolicySuggestionKind;
14
+ proposedValue: string | null;
15
+ evidence: Readonly<Record<string, unknown>>;
16
+ }
17
+ export interface FieldPolicySuggestionAdapter {
18
+ pendingSuggestions(input?: {
19
+ objectRefs?: readonly string[];
20
+ }): Promise<unknown>;
21
+ acceptSuggestion(input: {
22
+ id: string;
23
+ }): Promise<unknown>;
24
+ dismissSuggestion(input: {
25
+ id: string;
26
+ }): Promise<unknown>;
27
+ }
28
+ /**
29
+ * Validate generated custom-action output at the browser boundary. A malformed
30
+ * response is an error, never an empty queue that could conceal work.
31
+ */
32
+ export declare function parsePendingFieldPolicySuggestions(value: unknown): {
33
+ suggestions: FieldPolicySuggestion[];
34
+ total: number;
35
+ };
36
+ /** Human-readable evidence without assuming a server-side evidence schema. */
37
+ export declare function fieldPolicySuggestionEvidence(suggestion: FieldPolicySuggestion): string;
38
+ //# sourceMappingURL=suggestions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggestions.d.ts","sourceRoot":"","sources":["../../src/svelte/suggestions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9D,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,yBAAyB,CAAC;IAChC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,4BAA4B;IAC3C,kBAAkB,CAAC,KAAK,CAAC,EAAE;QACzB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrB,gBAAgB,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,iBAAiB,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5D;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,OAAO,GAAG;IAClE,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;CACf,CAsBA;AAmCD,8EAA8E;AAC9E,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,qBAAqB,GAChC,MAAM,CASR"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Structural browser contracts for field-policy suggestion review.
3
+ *
4
+ * These types intentionally omit tenant, user, authorization, and field
5
+ * sensitivity data. Hosts bind methods to authenticated generated clients;
6
+ * the server derives identity and validates every action.
7
+ */
8
+ /**
9
+ * Validate generated custom-action output at the browser boundary. A malformed
10
+ * response is an error, never an empty queue that could conceal work.
11
+ */
12
+ export function parsePendingFieldPolicySuggestions(value) {
13
+ if (!value || typeof value !== 'object') {
14
+ throw new Error('Unable to load pending field suggestions.');
15
+ }
16
+ const candidate = value;
17
+ const total = candidate.total;
18
+ if (!Array.isArray(candidate.suggestions) ||
19
+ typeof total !== 'number' ||
20
+ !Number.isSafeInteger(total) ||
21
+ total < 0) {
22
+ throw new Error('Unable to load pending field suggestions.');
23
+ }
24
+ const suggestions = candidate.suggestions.map(parseSuggestion);
25
+ if (total < suggestions.length) {
26
+ throw new Error('Unable to load pending field suggestions.');
27
+ }
28
+ return { suggestions, total };
29
+ }
30
+ function parseSuggestion(value) {
31
+ if (!value || typeof value !== 'object') {
32
+ throw new Error('Unable to load pending field suggestions.');
33
+ }
34
+ const candidate = value;
35
+ if (typeof candidate.id !== 'string' ||
36
+ typeof candidate.objectRef !== 'string' ||
37
+ typeof candidate.fieldName !== 'string' ||
38
+ (candidate.kind !== 'promote' && candidate.kind !== 'default') ||
39
+ (candidate.proposedValue !== null &&
40
+ typeof candidate.proposedValue !== 'string') ||
41
+ !isRecord(candidate.evidence) ||
42
+ (candidate.status !== undefined && candidate.status !== 'pending')) {
43
+ throw new Error('Unable to load pending field suggestions.');
44
+ }
45
+ return {
46
+ id: candidate.id,
47
+ objectRef: candidate.objectRef,
48
+ fieldName: candidate.fieldName,
49
+ kind: candidate.kind,
50
+ proposedValue: candidate.proposedValue,
51
+ evidence: candidate.evidence,
52
+ };
53
+ }
54
+ function isRecord(value) {
55
+ return !!value && typeof value === 'object' && !Array.isArray(value);
56
+ }
57
+ /** Human-readable evidence without assuming a server-side evidence schema. */
58
+ export function fieldPolicySuggestionEvidence(suggestion) {
59
+ const summary = suggestion.evidence.summary;
60
+ if (typeof summary === 'string' && summary.trim())
61
+ return summary;
62
+ const distinctUsers = suggestion.evidence.distinctUsers;
63
+ const setCount = suggestion.evidence.setCount;
64
+ if (typeof distinctUsers === 'number' && typeof setCount === 'number') {
65
+ return `${distinctUsers} users set this field ${setCount} times.`;
66
+ }
67
+ return 'Based on recent organization field usage.';
68
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Browser-safe usage capture primitives for the field-policy learning loop.
3
+ *
4
+ * Hosts own the authenticated transport. This module deliberately carries no
5
+ * tenant, user, permission, or field-sensitivity information: the server
6
+ * derives all of that from its ambient context and live object registry.
7
+ */
8
+ /** One submitted field value sent to the host's usage transport. */
9
+ export interface FieldUsageEntry {
10
+ objectRef: string;
11
+ fieldName: string;
12
+ value?: unknown;
13
+ /** Optional value-less hint; normal ObjectForm capture sends the value. */
14
+ matchedDefault?: boolean;
15
+ }
16
+ /** Resolved default metadata used only for a value-less count signal. */
17
+ export interface FieldUsageDefault {
18
+ hasDefault: boolean;
19
+ defaultValue: unknown;
20
+ }
21
+ /**
22
+ * Structural host transport for the counters collection's batched action.
23
+ * A reporter must never be allowed to affect a successful form submission.
24
+ */
25
+ export interface FieldUsageReporter {
26
+ reportUsage(input: {
27
+ entries: readonly FieldUsageEntry[];
28
+ }): unknown;
29
+ }
30
+ export interface CollectFieldUsageEntriesOptions {
31
+ objectRef: string;
32
+ values: Readonly<Record<string, unknown>>;
33
+ /**
34
+ * Rendered field names and their persisted browser wire type. The type is
35
+ * used only to minimize value transit — it is never a sensitivity or
36
+ * authorization decision.
37
+ */
38
+ fields?: Readonly<Record<string, FieldUsageWireType>>;
39
+ /**
40
+ * Resolved defaults for rendered fields. For count-only values, a matching
41
+ * default is sent as a positive hint so the server does not treat it as a
42
+ * deviation. Absent or non-matching defaults deliberately send no hint.
43
+ */
44
+ defaults?: Readonly<Record<string, FieldUsageDefault>>;
45
+ }
46
+ export type FieldUsageWireType = 'text' | 'integer' | 'decimal' | 'boolean' | 'datetime' | 'json' | 'foreignKey' | 'crossPackageRef';
47
+ /** Values may transit only for bounded, identifier-like wire types. */
48
+ export declare function canCaptureFieldUsageValue(type: FieldUsageWireType | undefined): boolean;
49
+ /**
50
+ * Collect every non-blank submitted field, including values matching a
51
+ * resolved default. Values transit only for bounded boolean/reference fields;
52
+ * free text, numbers, dates, and JSON emit count-only signals. Capturing only
53
+ * deviations would make the default's dominance denominator disappear. The
54
+ * server still derives eligibility, sensitivity, and every aggregate.
55
+ */
56
+ export declare function collectFieldUsageEntries(options: CollectFieldUsageEntriesOptions): FieldUsageEntry[];
57
+ /** Zero and false are submissions; only absent/null/empty-string values are not. */
58
+ export declare function isBlankFieldValue(value: unknown): boolean;
59
+ /** JSON-safe equality for the count-only default-match hint. */
60
+ export declare function fieldUsageValuesEqual(left: unknown, right: unknown): boolean;
61
+ /** Fire-and-forget by design: metrics transport failures never reject submit. */
62
+ export declare function reportFieldUsage(reporter: FieldUsageReporter | undefined, entries: readonly FieldUsageEntry[]): void;
63
+ //# sourceMappingURL=usage-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-capture.d.ts","sourceRoot":"","sources":["../../src/svelte/usage-capture.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,SAAS,eAAe,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC;CACtE;AAED,MAAM,WAAW,+BAA+B;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1C;;;;OAIG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACtD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;CACxD;AAED,MAAM,MAAM,kBAAkB,GAC1B,MAAM,GACN,SAAS,GACT,SAAS,GACT,SAAS,GACT,UAAU,GACV,MAAM,GACN,YAAY,GACZ,iBAAiB,CAAC;AAEtB,uEAAuE;AACvE,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,kBAAkB,GAAG,SAAS,GACnC,OAAO,CAIT;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,eAAe,EAAE,CAyBnB;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED,gEAAgE;AAChE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAO5E;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,kBAAkB,GAAG,SAAS,EACxC,OAAO,EAAE,SAAS,eAAe,EAAE,GAClC,IAAI,CASN"}
@@ -0,0 +1,61 @@
1
+ /** Values may transit only for bounded, identifier-like wire types. */
2
+ export function canCaptureFieldUsageValue(type) {
3
+ return (type === 'boolean' || type === 'foreignKey' || type === 'crossPackageRef');
4
+ }
5
+ /**
6
+ * Collect every non-blank submitted field, including values matching a
7
+ * resolved default. Values transit only for bounded boolean/reference fields;
8
+ * free text, numbers, dates, and JSON emit count-only signals. Capturing only
9
+ * deviations would make the default's dominance denominator disappear. The
10
+ * server still derives eligibility, sensitivity, and every aggregate.
11
+ */
12
+ export function collectFieldUsageEntries(options) {
13
+ const fields = options.fields ??
14
+ Object.fromEntries(Object.keys(options.values).map((fieldName) => [fieldName, undefined]));
15
+ const entries = [];
16
+ for (const [fieldName, type] of Object.entries(fields)) {
17
+ const value = options.values[fieldName];
18
+ if (isBlankFieldValue(value))
19
+ continue;
20
+ if (canCaptureFieldUsageValue(type)) {
21
+ entries.push({ objectRef: options.objectRef, fieldName, value });
22
+ continue;
23
+ }
24
+ const fieldDefault = options.defaults?.[fieldName];
25
+ entries.push({
26
+ objectRef: options.objectRef,
27
+ fieldName,
28
+ ...(fieldDefault?.hasDefault &&
29
+ fieldUsageValuesEqual(value, fieldDefault.defaultValue)
30
+ ? { matchedDefault: true }
31
+ : {}),
32
+ });
33
+ }
34
+ return entries;
35
+ }
36
+ /** Zero and false are submissions; only absent/null/empty-string values are not. */
37
+ export function isBlankFieldValue(value) {
38
+ return value === undefined || value === null || value === '';
39
+ }
40
+ /** JSON-safe equality for the count-only default-match hint. */
41
+ export function fieldUsageValuesEqual(left, right) {
42
+ if (left === right)
43
+ return true;
44
+ try {
45
+ return JSON.stringify(left) === JSON.stringify(right);
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ }
51
+ /** Fire-and-forget by design: metrics transport failures never reject submit. */
52
+ export function reportFieldUsage(reporter, entries) {
53
+ if (!reporter || entries.length === 0)
54
+ return;
55
+ try {
56
+ void Promise.resolve(reporter.reportUsage({ entries })).catch(() => undefined);
57
+ }
58
+ catch {
59
+ // A synchronous host adapter failure is non-fatal by the same contract.
60
+ }
61
+ }