stylegallery 0.1.6 → 0.1.8

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 (97) hide show
  1. package/AGENTS.md +13 -1
  2. package/DOMAINS.md +10 -6
  3. package/GOVERNANCE.md +14 -12
  4. package/LICENSE +28 -0
  5. package/LICENSE-DOCS +42 -0
  6. package/NOTICE +38 -0
  7. package/README.md +47 -15
  8. package/consumer-reference/agent-native/README.md +7 -7
  9. package/consumer-reference/agent-native/v2/admission-policy.json +196 -31
  10. package/consumer-reference/agent-native/v2/material-registry.json +1 -1
  11. package/consumer-reference/agent-native/v2/schema/admission-policy.schema.json +3 -3
  12. package/consumer-reference/agent-native/v2/schema/material-record.schema.json +1 -1
  13. package/design-engineering/component-contract.md +19 -3
  14. package/design-engineering/decision-tree.md +1 -0
  15. package/design-engineering/index.md +48 -0
  16. package/design-engineering/loading-and-feedback.md +91 -0
  17. package/design-engineering/native-interaction-contracts.md +94 -0
  18. package/design-engineering/state-management/decision-tree.md +60 -0
  19. package/design-engineering/state-management/index.md +61 -0
  20. package/design-engineering/state-management/patterns/derived-state.md +85 -0
  21. package/design-engineering/state-management/patterns/draft-and-baseline.md +86 -0
  22. package/design-engineering/state-management/patterns/id-selection.md +85 -0
  23. package/design-engineering/state-management/patterns/identity-reset.md +89 -0
  24. package/design-engineering/state-management/patterns/latest-request-wins.md +94 -0
  25. package/design-engineering/state-management/patterns/optimistic-overlay.md +98 -0
  26. package/design-engineering/state-management/patterns/single-flight.md +92 -0
  27. package/design-engineering/state-management/patterns/single-owner.md +89 -0
  28. package/design-engineering/state-management/patterns/submitted-snapshot.md +107 -0
  29. package/design-engineering/state-management/patterns/unsaved-navigation.md +100 -0
  30. package/design-engineering/state-management/patterns/url-state.md +96 -0
  31. package/design-engineering/state-management/patterns/versioned-restore.md +95 -0
  32. package/design-engineering/state-management/recipes/delete-undo.md +65 -0
  33. package/design-engineering/state-management/recipes/index.md +64 -0
  34. package/design-engineering/state-management/recipes/multi-step-form.md +65 -0
  35. package/design-engineering/state-management/recipes/search-detail.md +65 -0
  36. package/design-engineering/state-management/recipes/settings-save.md +64 -0
  37. package/design-engineering/state-management/state-brief.md +83 -0
  38. package/design-engineering/state-management/verification.md +65 -0
  39. package/design-engineering/text-input-and-internationalization.md +91 -0
  40. package/design-engineering/worked-examples.md +2 -0
  41. package/design-terminology/conflict-cases.md +51 -8
  42. package/design-terminology/index.md +6 -0
  43. package/design-terminology/interaction-semantics.md +87 -0
  44. package/design-terminology/source-kinds.md +1 -1
  45. package/design-terminology/source-vocabularies.md +17 -1
  46. package/design-terminology/token-semantics.md +90 -0
  47. package/design-terminology/typography-semantics.md +86 -0
  48. package/expression/brand-studies.md +50 -0
  49. package/expression/direction-brief.md +71 -0
  50. package/expression/directions/nocturne-editorial.md +80 -0
  51. package/expression/directions/warm-print.md +73 -0
  52. package/expression/index.md +40 -0
  53. package/expression/techniques/gradient-atmosphere.md +107 -0
  54. package/expression/techniques/grain-and-texture.md +83 -0
  55. package/expression/techniques/webgl-hero.md +123 -0
  56. package/guides/vocabulary.md +1 -1
  57. package/index.md +3 -3
  58. package/log.md +64 -0
  59. package/motion/accessible-motion.md +90 -0
  60. package/motion/index.md +9 -0
  61. package/motion/interaction-recipes.md +8 -2
  62. package/motion/interruption-and-retargeting.md +90 -0
  63. package/motion/observed-choreography.md +73 -0
  64. package/motion/rendering-and-performance.md +89 -0
  65. package/motion/techniques/kinetic-type.md +145 -0
  66. package/motion/techniques/scroll-choreography.md +154 -0
  67. package/package.json +76 -21
  68. package/platform-guides/adaptive-navigation.md +85 -0
  69. package/platform-guides/compatibility-matrix.md +1 -1
  70. package/platform-guides/index.md +6 -0
  71. package/platform-guides/input-and-focus.md +91 -0
  72. package/platform-guides/preferences-and-accessibility.md +90 -0
  73. package/quality/claim-records/stylegallery-multidomain-scope.md +2 -2
  74. package/quality/evidence/executable-evidence.md +1 -1
  75. package/quality/index.md +1 -2
  76. package/scripts/agent-native/v2/material-admission.mjs +1 -1
  77. package/scripts/agent-native/v2/material-identity.mjs +2 -2
  78. package/scripts/compiler/README.md +112 -0
  79. package/scripts/compiler/cli.mjs +51 -0
  80. package/scripts/compiler/mcp.mjs +53 -0
  81. package/scripts/compiler/operations.mjs +70 -0
  82. package/scripts/compiler/runtime.mjs +156 -0
  83. package/scripts/sg-entry.mjs +20 -0
  84. package/scripts/sg-server.mjs +20 -0
  85. package/showcase/README.md +113 -0
  86. package/game-ui/classification.md +0 -82
  87. package/game-ui/decision-tree.md +0 -81
  88. package/game-ui/index.md +0 -45
  89. package/game-ui/reference-record.md +0 -62
  90. package/game-ui/screen-hierarchy.md +0 -107
  91. package/game-ui/screen-recipes.md +0 -101
  92. package/game-ui/unity/architecture.md +0 -166
  93. package/game-ui/unity/cli-loop.md +0 -84
  94. package/game-ui/unity/org-wiki.md +0 -146
  95. package/game-ui/unity/repository-map.md +0 -102
  96. package/game-ui/unity/ui-systems.md +0 -85
  97. package/game-ui/verification-workflow.md +0 -100
@@ -0,0 +1,86 @@
1
+ ---
2
+ type: Domain Guide
3
+ title: Draft And Persisted Baseline
4
+ description: Preserve editable work while distinguishing it from the last acknowledged saved value.
5
+ domain: design-engineering
6
+ lifecycle: experimental
7
+ provenance_kind: local
8
+ ---
9
+
10
+ # Draft And Persisted Baseline
11
+
12
+ ## Repository Boundary
13
+
14
+ Preserve editable work while distinguishing it from the last acknowledged saved value. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
15
+
16
+ ## Reusable Method
17
+
18
+ Use for explicit Save/Cancel forms. For immediate committed toggles, use an operation contract instead of inventing a long-lived draft.
19
+
20
+ ### State Model And Ownership
21
+
22
+ The form owns a draft, persistence supplies the baseline, and dirty is derived using domain equality. This example uses a single string. A remote update while dirty needs merge, conflict, or reload policy; never silently replace the draft.
23
+
24
+ ### Transitions
25
+
26
+ | Event and precondition | Next state | Effect or invariant |
27
+ | --- | --- | --- |
28
+ | Edit | Draft changes | Baseline stays acknowledged |
29
+ | Discard | Draft becomes baseline | No persistence request |
30
+ | Remote update while dirty | Conflict retained | Keep draft until the user resolves it |
31
+
32
+ ### Minimal Executable Example
33
+
34
+ Run this standalone JavaScript block with Node.js 22 or newer, or run all pattern examples from a repository checkout with `bun run test:state-management`. The assertions exercise the local model, not a browser or backend.
35
+
36
+ ```js
37
+ import assert from "node:assert/strict";
38
+ let baseline = "Original";
39
+ let draft = baseline;
40
+ const dirty = () => draft !== baseline;
41
+ draft = "Edited";
42
+ assert.equal(dirty(), true);
43
+ const remote = "Remote edit";
44
+ const conflict = dirty() && remote !== baseline;
45
+ assert.equal(conflict, true);
46
+ assert.equal(draft, "Edited");
47
+ draft = baseline; // Explicit discard, not an automatic refresh.
48
+ assert.equal(dirty(), false);
49
+ ```
50
+
51
+ ### What Breaks If Removed
52
+
53
+ Binding fields directly to the cached saved object makes Cancel impossible and may tell other readers that unsaved edits are persisted. An independent dirty boolean can remain true after editing back to the baseline.
54
+
55
+ ### Composition And Substitution
56
+
57
+ [Submitted snapshot](submitted-snapshot.md) owns save acknowledgement. [Unsaved navigation](unsaved-navigation.md) uses dirty as an input. Do not let the router own a second draft.
58
+
59
+ ## Opinionated Guidance
60
+
61
+ Choose baseline equality and server normalization rules before wiring a generic deep comparison. For nested drafts, prevent shared mutable references to the baseline.
62
+
63
+ ## Platform-Specific Guidance
64
+
65
+ Use native form labels and validation relationships. Route-level forms may outlive individual fields; unmounting a field should not implicitly discard the form.
66
+
67
+ ## Unsupported Absolutes
68
+
69
+ A baseline is an acknowledged observation, not a guarantee that nobody else edited the server since then.
70
+
71
+ ## Verification Contract
72
+
73
+ - Edit then restore the original value; dirty must become false.
74
+ - Receive a remote update while dirty; preserve entered values.
75
+ - Discard explicitly; restore the acknowledged baseline without sending a save.
76
+
77
+ Record actual outcomes separately using the [verification matrix](../verification.md).
78
+
79
+ ## Source, License, And Attribution
80
+
81
+ Locally authored synthesis and examples. No upstream implementation is copied. These experimental contracts describe consumer-owned behavior; review when a failure, ownership change, or platform change invalidates an assumption.
82
+
83
+ ## IA Navigation
84
+
85
+ Parent: [State Management](../index.md).
86
+ Next: [Continue the state management route](../recipes/index.md).
@@ -0,0 +1,85 @@
1
+ ---
2
+ type: Domain Guide
3
+ title: Selection By Stable Identity
4
+ description: Keep selection attached to an entity while a collection reorders or refreshes.
5
+ domain: design-engineering
6
+ lifecycle: experimental
7
+ provenance_kind: local
8
+ ---
9
+
10
+ # Selection By Stable Identity
11
+
12
+ ## Repository Boundary
13
+
14
+ Keep selection attached to an entity while a collection reorders or refreshes. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
15
+
16
+ ## Reusable Method
17
+
18
+ Use for lists, tables, and detail views with stable IDs. Index selection is sufficient only for immutable position-based options whose identity truly is their position.
19
+
20
+ ### State Model And Ownership
21
+
22
+ The screen owns `selectedId`; the data owner supplies current entities. Detail is derived by ID. Missing from a filtered page does not imply deletion: choose a retained-detail fetch or an unavailable state based on actual knowledge.
23
+
24
+ ### Transitions
25
+
26
+ | Event and precondition | Next state | Effect or invariant |
27
+ | --- | --- | --- |
28
+ | Select an available ID | ID selected | Resolve current entity by identity |
29
+ | Collection reorders | Same ID | Detail still belongs to the same entity |
30
+ | Authoritative deletion removes ID | Null or unavailable | Apply the declared fallback and recover focus |
31
+
32
+ ### Minimal Executable Example
33
+
34
+ Run this standalone JavaScript block with Node.js 22 or newer, or run all pattern examples from a repository checkout with `bun run test:state-management`. The assertions exercise the local model, not a browser or backend.
35
+
36
+ ```js
37
+ import assert from "node:assert/strict";
38
+ let rows = [{ id: "a", name: "Alpha" }, { id: "b", name: "Beta" }];
39
+ let selectedId = "b";
40
+ const selected = () => rows.find(row => row.id === selectedId) ?? null;
41
+ rows = [...rows].reverse();
42
+ assert.equal(selected().name, "Beta");
43
+ rows = rows.map(row => row.id === "b" ? { ...row, name: "Updated" } : row);
44
+ assert.equal(selected().name, "Updated");
45
+ rows = rows.filter(row => row.id !== "b");
46
+ if (!selected()) selectedId = null; // This collection is authoritative and complete.
47
+ assert.equal(selected(), null);
48
+ ```
49
+
50
+ ### What Breaks If Removed
51
+
52
+ Keep row index 1, reverse the array, and the detail silently changes to another entity. Keep a copied selected object and a refresh can leave its fields stale.
53
+
54
+ ### Composition And Substitution
55
+
56
+ Use [URL state](url-state.md) when selection should survive links and history. Use [latest request wins](latest-request-wins.md) for separately fetched detail; key requests by selected ID.
57
+
58
+ ## Opinionated Guidance
59
+
60
+ Choose an explicit missing-item policy. Never infer remote deletion solely from pagination or filtering.
61
+
62
+ ## Platform-Specific Guidance
63
+
64
+ After deleting a focused row, move focus to a logical neighbor or heading. A selected state and keyboard focus are separate responsibilities.
65
+
66
+ ## Unsupported Absolutes
67
+
68
+ Stable keys do not prove stable identity if the server recycles identifiers across tenants or revisions.
69
+
70
+ ## Verification Contract
71
+
72
+ - Reorder and update the selected row; detail must preserve ID and refresh fields.
73
+ - Filter it out without deleting it; apply the declared retained-detail policy.
74
+ - Delete the final item; verify empty detail and focus recovery in the UI.
75
+
76
+ Record actual outcomes separately using the [verification matrix](../verification.md).
77
+
78
+ ## Source, License, And Attribution
79
+
80
+ Locally authored synthesis and examples. No upstream implementation is copied. These experimental contracts describe consumer-owned behavior; review when a failure, ownership change, or platform change invalidates an assumption.
81
+
82
+ ## IA Navigation
83
+
84
+ Parent: [State Management](../index.md).
85
+ Next: [Continue the state management route](../recipes/index.md).
@@ -0,0 +1,89 @@
1
+ ---
2
+ type: Domain Guide
3
+ title: Identity Boundary And Reset
4
+ description: Prevent temporary state and pending outcomes from leaking across entity or account changes.
5
+ domain: design-engineering
6
+ lifecycle: experimental
7
+ provenance_kind: local
8
+ ---
9
+
10
+ # Identity Boundary And Reset
11
+
12
+ ## Repository Boundary
13
+
14
+ Prevent temporary state and pending outcomes from leaking across entity or account changes. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
15
+
16
+ ## Reusable Method
17
+
18
+ Use when a mounted editor is reused for a different document, tenant, or account. Preserve drafts per identity only when that is an explicit product feature.
19
+
20
+ ### State Model And Ownership
21
+
22
+ The screen owner stores identity and generation. Entering a new identity clears identity-local values and invalidates previous operations. Generation matters even when the user goes A → B → A.
23
+
24
+ ### Transitions
25
+
26
+ | Event and precondition | Next state | Effect or invariant |
27
+ | --- | --- | --- |
28
+ | Enter identity | Fresh generation and local state | Invalidate earlier callbacks |
29
+ | Matching-generation completion | Apply within current identity | Accept only live work |
30
+ | Old-generation completion | Unchanged | Reject even if the entity ID matches again |
31
+
32
+ ### Minimal Executable Example
33
+
34
+ Run this standalone JavaScript block with Node.js 22 or newer, or run all pattern examples from a repository checkout with `bun run test:state-management`. The assertions exercise the local model, not a browser or backend.
35
+
36
+ ```js
37
+ import assert from "node:assert/strict";
38
+ let generation = 0, identity = null, draft = "";
39
+ function enter(id) { identity = id; generation++; draft = ""; }
40
+ function ticket() { return { identity, generation }; }
41
+ function receive(t, value) {
42
+ if (t.identity === identity && t.generation === generation) draft = value;
43
+ }
44
+ enter("A");
45
+ const oldA = ticket();
46
+ enter("B");
47
+ enter("A");
48
+ receive(oldA, "stale A");
49
+ assert.equal(draft, "");
50
+ receive(ticket(), "current A");
51
+ assert.equal(draft, "current A");
52
+ ```
53
+
54
+ ### What Breaks If Removed
55
+
56
+ Checking entity ID alone accepts the old A request after returning from B to A. Resetting the draft without invalidating requests lets a late response repopulate it.
57
+
58
+ ### Composition And Substitution
59
+
60
+ Combine [latest request wins](latest-request-wins.md) within each generation and [versioned restore](versioned-restore.md) for explicit per-identity persistence. Apply [unsaved navigation](unsaved-navigation.md) before abandoning dirty work.
61
+
62
+ ## Opinionated Guidance
63
+
64
+ Define the identity tuple, including tenant when needed. Clear sensitive caches at the session boundary rather than relying solely on component unmount.
65
+
66
+ ## Platform-Specific Guidance
67
+
68
+ Framework keys can recreate components, but external listeners, caches, timers, and requests still need explicit cleanup. Router reuse may preserve component instances.
69
+
70
+ ## Unsupported Absolutes
71
+
72
+ A UI reset is not an authorization or secure data-erasure mechanism.
73
+
74
+ ## Verification Contract
75
+
76
+ - Switch A → B while a read is pending; no A result appears in B.
77
+ - Switch A → B → A; reject the first generation's callback.
78
+ - Inspect focus, local errors, draft, and subscriptions after switching.
79
+
80
+ Record actual outcomes separately using the [verification matrix](../verification.md).
81
+
82
+ ## Source, License, And Attribution
83
+
84
+ Locally authored synthesis and examples. No upstream implementation is copied. These experimental contracts describe consumer-owned behavior; review when a failure, ownership change, or platform change invalidates an assumption.
85
+
86
+ ## IA Navigation
87
+
88
+ Parent: [State Management](../index.md).
89
+ Next: [Continue the state management route](../recipes/index.md).
@@ -0,0 +1,94 @@
1
+ ---
2
+ type: Domain Guide
3
+ title: Latest Request Wins
4
+ description: Prevent an older read response from replacing the result of a newer user intent.
5
+ domain: design-engineering
6
+ lifecycle: experimental
7
+ provenance_kind: local
8
+ ---
9
+
10
+ # Latest Request Wins
11
+
12
+ ## Repository Boundary
13
+
14
+ Prevent an older read response from replacing the result of a newer user intent. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
15
+
16
+ ## Reusable Method
17
+
18
+ Use for replaceable reads such as search and selected-item detail. Do not use this policy to discard the outcomes of independent writes that all matter.
19
+
20
+ ### State Model And Ownership
21
+
22
+ The read owner stores a monotonically increasing identity, status, and last accepted result. Both success and failure must match the current request. Cancellation is an optional resource optimization; identity decides acceptance.
23
+
24
+ ### Transitions
25
+
26
+ | Event and precondition | Next state | Effect or invariant |
27
+ | --- | --- | --- |
28
+ | Start read | Pending with new ID | Previous IDs lose authority |
29
+ | Matching success | Ready with results | Accept only current intent |
30
+ | Matching failure | Error | Preserve or clear old results under explicit policy |
31
+ | Stale success or failure | Unchanged | No status, result, or error mutation |
32
+ | Dispose | Disposed and invalidated | Ignore all pending outcomes |
33
+
34
+ ### Minimal Executable Example
35
+
36
+ Run this standalone JavaScript block with Node.js 22 or newer, or run all pattern examples from a repository checkout with `bun run test:state-management`. The assertions exercise the local model, not a browser or backend.
37
+
38
+ ```js
39
+ import assert from "node:assert/strict";
40
+ let serial = 0, active = 0, status = "idle", result = null;
41
+ const begin = () => { active = ++serial; status = "pending"; return active; };
42
+ function settle(id, ok, value) {
43
+ if (id !== active) return;
44
+ status = ok ? "ready" : "error";
45
+ if (ok) result = value;
46
+ }
47
+ const a = begin(), b = begin();
48
+ settle(b, true, "B");
49
+ settle(a, true, "A");
50
+ settle(a, false, "old failure");
51
+ assert.equal(result, "B");
52
+ assert.equal(status, "ready");
53
+ const c = begin();
54
+ active = ++serial; status = "disposed";
55
+ settle(c, true, "C");
56
+ assert.equal(status, "disposed");
57
+ ```
58
+
59
+ ### What Breaks If Removed
60
+
61
+ Remove the ID check: resolve B then A and the screen displays A under B's query. Guarding success only still allows A's error or finally handler to clear B's pending status.
62
+
63
+ ### Composition And Substitution
64
+
65
+ Combine [URL state](url-state.md) for committed query inputs and [ID selection](id-selection.md) for detail. Use [single flight](single-flight.md) for duplicate writes rather than silently discarding their acknowledgements.
66
+
67
+ ## Opinionated Guidance
68
+
69
+ Choose whether old results stay visible while refreshing and label their query identity. Debouncing reduces starts but does not establish response ordering.
70
+
71
+ ## Platform-Specific Guidance
72
+
73
+ Check identity after each awaited stage, including body decoding or transformations. Dispose invalidation and listener cleanup belong to the framework adapter.
74
+
75
+ ## Unsupported Absolutes
76
+
77
+ Latest-wins prevents this local overwrite; it does not guarantee fresh server data, cache coherence, or distributed consistency.
78
+
79
+ ## Verification Contract
80
+
81
+ - Start A then B; resolve B then A, including an A failure.
82
+ - Start B while A is pending; A completion must not clear B's pending indicator.
83
+ - Dispose before completion; no displayed state may update.
84
+
85
+ Record actual outcomes separately using the [verification matrix](../verification.md).
86
+
87
+ ## Source, License, And Attribution
88
+
89
+ Locally authored synthesis and examples. No upstream implementation is copied. These experimental contracts describe consumer-owned behavior; review when a failure, ownership change, or platform change invalidates an assumption.
90
+
91
+ ## IA Navigation
92
+
93
+ Parent: [State Management](../index.md).
94
+ Next: [Continue the state management route](../recipes/index.md).
@@ -0,0 +1,98 @@
1
+ ---
2
+ type: Domain Guide
3
+ title: Optimistic Overlay And Recovery
4
+ description: Show a speculative change while preserving an authoritative base for recovery.
5
+ domain: design-engineering
6
+ lifecycle: experimental
7
+ provenance_kind: local
8
+ ---
9
+
10
+ # Optimistic Overlay And Recovery
11
+
12
+ ## Repository Boundary
13
+
14
+ Show a speculative change while preserving an authoritative base for recovery. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
15
+
16
+ ## Reusable Method
17
+
18
+ Use for a bounded reversible presentation change when failure is recoverable. Prefer pending-until-confirmed behavior for irreversible or high-consequence actions.
19
+
20
+ ### State Model And Ownership
21
+
22
+ The cache owns base; the operation owns an overlay and ID. The displayed value is base plus overlay. This minimal example permits one edit at a time; concurrent mutations require ordered overlays or per-entity serialization.
23
+
24
+ ### Transitions
25
+
26
+ | Event and precondition | Next state | Effect or invariant |
27
+ | --- | --- | --- |
28
+ | Begin mutation while idle | Overlay pending | Display prediction without rewriting base |
29
+ | Matching rejection | Overlay removed | Reveal current base, not an old whole-cache snapshot |
30
+ | Matching acknowledgement | Base becomes server value | Remove overlay atomically |
31
+ | Uncertain outcome | Reconciliation required | Do not announce rollback of the server |
32
+
33
+ ### Minimal Executable Example
34
+
35
+ Run this standalone JavaScript block with Node.js 22 or newer, or run all pattern examples from a repository checkout with `bun run test:state-management`. The assertions exercise the local model, not a browser or backend.
36
+
37
+ ```js
38
+ import assert from "node:assert/strict";
39
+ let base = { name: "Before", revision: 1 }, overlay = null, serial = 0;
40
+ const view = () => overlay ? { ...base, name: overlay.name } : base;
41
+ function begin(name) {
42
+ if (overlay) return null;
43
+ overlay = { id: ++serial, name };
44
+ return overlay.id;
45
+ }
46
+ function settle(id, accepted) {
47
+ if (overlay?.id !== id) return;
48
+ if (accepted) base = accepted;
49
+ overlay = null;
50
+ }
51
+ const a = begin("Predicted");
52
+ assert.equal(view().name, "Predicted");
53
+ base = { name: "Remote", revision: 2 }; // A newer authoritative observation.
54
+ settle(a, null); // Definitive rejection, not an ambiguous timeout.
55
+ assert.equal(view().name, "Remote");
56
+ const b = begin("Next");
57
+ settle(a, null);
58
+ assert.equal(view().name, "Next");
59
+ settle(b, { name: "Normalized", revision: 3 });
60
+ assert.equal(view().name, "Normalized");
61
+ ```
62
+
63
+ ### What Breaks If Removed
64
+
65
+ Restoring a whole-cache snapshot on failure can erase unrelated or newer remote changes. Without correlation, an old failure can remove a newer optimistic operation.
66
+
67
+ ### Composition And Substitution
68
+
69
+ Compose with [single flight](single-flight.md) for this serialized model. Use [ID selection](id-selection.md) for row mutations. Define version ordering before admitting concurrent acknowledgements into a shared cache.
70
+
71
+ ## Opinionated Guidance
72
+
73
+ Separate a definitive rejection from a lost response: a timeout may have committed remotely. Reconcile uncertain results before promising the change was undone.
74
+
75
+ ## Platform-Specific Guidance
76
+
77
+ Keep pending and error information available beyond color or animation. A disappearance animation must not decide whether the underlying entity exists.
78
+
79
+ ## Unsupported Absolutes
80
+
81
+ An inverse UI patch is not a backend undo protocol. The sample does not implement concurrent multi-writer revision arbitration.
82
+
83
+ ## Verification Contract
84
+
85
+ - Reject a speculative edit after a newer base arrives; preserve the newer base.
86
+ - Deliver an old failure during a new edit; retain the new overlay.
87
+ - Return a normalized server value and verify it replaces the prediction.
88
+
89
+ Record actual outcomes separately using the [verification matrix](../verification.md).
90
+
91
+ ## Source, License, And Attribution
92
+
93
+ Locally authored synthesis and examples. No upstream implementation is copied. These experimental contracts describe consumer-owned behavior; review when a failure, ownership change, or platform change invalidates an assumption.
94
+
95
+ ## IA Navigation
96
+
97
+ Parent: [State Management](../index.md).
98
+ Next: [Continue the state management route](../recipes/index.md).
@@ -0,0 +1,92 @@
1
+ ---
2
+ type: Domain Guide
3
+ title: Single Flight And Duplicate Submission
4
+ description: Apply an explicit policy to repeated activation of one pending operation.
5
+ domain: design-engineering
6
+ lifecycle: experimental
7
+ provenance_kind: local
8
+ ---
9
+
10
+ # Single Flight And Duplicate Submission
11
+
12
+ ## Repository Boundary
13
+
14
+ Apply an explicit policy to repeated activation of one pending operation. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
15
+
16
+ ## Reusable Method
17
+
18
+ Use when a duplicate Save or Delete should share or ignore the active attempt. Independent entities may need separate flight keys. A queue is preferable when every intent must execute.
19
+
20
+ ### State Model And Ownership
21
+
22
+ The operation owner holds one pending promise per declared scope. This example shares it. The guard is set before the effect begins and clears on success or failure.
23
+
24
+ ### Transitions
25
+
26
+ | Event and precondition | Next state | Effect or invariant |
27
+ | --- | --- | --- |
28
+ | Activate while idle | One pending operation | Run effect once |
29
+ | Activate while pending | Same pending operation | Return same promise |
30
+ | Settle | Idle | Release guard on success and failure |
31
+
32
+ ### Minimal Executable Example
33
+
34
+ Run this standalone JavaScript block with Node.js 22 or newer, or run all pattern examples from a repository checkout with `bun run test:state-management`. The assertions exercise the local model, not a browser or backend.
35
+
36
+ ```js
37
+ import assert from "node:assert/strict";
38
+ let pending = null, calls = 0;
39
+ function run(effect) {
40
+ if (pending) return pending;
41
+ pending = Promise.resolve().then(effect).finally(() => { pending = null; });
42
+ return pending;
43
+ }
44
+ let release;
45
+ const effect = () => { calls++; return new Promise(resolve => { release = resolve; }); };
46
+ const a = run(effect), b = run(effect);
47
+ assert.equal(a, b);
48
+ await Promise.resolve();
49
+ assert.equal(calls, 1);
50
+ release("saved");
51
+ await a;
52
+ await assert.rejects(run(() => { throw new Error("offline"); }));
53
+ assert.equal(pending, null);
54
+ assert.equal(await run(() => "retry"), "retry");
55
+ ```
56
+
57
+ ### What Breaks If Removed
58
+
59
+ Disabling only the visible button misses keyboard submission or another caller. Setting pending after awaiting the effect permits two operations. Clearing only on success locks the action after a failure.
60
+
61
+ ### Composition And Substitution
62
+
63
+ Use with [submitted snapshot](submitted-snapshot.md); duplicate activation must not silently replace the captured snapshot. For separate rows, scope the guard by stable entity ID.
64
+
65
+ ## Opinionated Guidance
66
+
67
+ Pick ignore, share, queue, or replace deliberately. This example shares a result and does not implement queuing. After an ambiguous write failure, reconcile or use server-supported idempotency before retrying.
68
+
69
+ ## Platform-Specific Guidance
70
+
71
+ Handle every caller's rejection and expose progress through accessible status. UI disabled semantics do not replace the operation guard.
72
+
73
+ ## Unsupported Absolutes
74
+
75
+ One client promise cannot prevent another tab, device, or retry from executing the same server command.
76
+
77
+ ## Verification Contract
78
+
79
+ - Activate from two entry points in the same turn; effect count remains one.
80
+ - Fail the operation; a subsequent explicit attempt can start.
81
+ - For per-entity scope, verify different entities do not block each other.
82
+
83
+ Record actual outcomes separately using the [verification matrix](../verification.md).
84
+
85
+ ## Source, License, And Attribution
86
+
87
+ Locally authored synthesis and examples. No upstream implementation is copied. These experimental contracts describe consumer-owned behavior; review when a failure, ownership change, or platform change invalidates an assumption.
88
+
89
+ ## IA Navigation
90
+
91
+ Parent: [State Management](../index.md).
92
+ Next: [Continue the state management route](../recipes/index.md).
@@ -0,0 +1,89 @@
1
+ ---
2
+ type: Domain Guide
3
+ title: Single Owner And Controlled Inputs
4
+ description: Keep one authoritative value when several controls edit the same setting.
5
+ domain: design-engineering
6
+ lifecycle: experimental
7
+ provenance_kind: local
8
+ ---
9
+
10
+ # Single Owner And Controlled Inputs
11
+
12
+ ## Repository Boundary
13
+
14
+ Keep one authoritative value when several controls edit the same setting. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
15
+
16
+ ## Reusable Method
17
+
18
+ Use when sibling or nested controls must agree immediately. Keep a private disclosure local when no other surface needs its value. Choose the nearest owner that survives every participating control.
19
+
20
+ ### State Model And Ownership
21
+
22
+ The owner stores `value`; controls receive it and emit an intent. Temporary text composition may stay local, but must have an explicit commit/reset boundary. Owner validation can reject an intent without creating a second accepted value.
23
+
24
+ ### Transitions
25
+
26
+ | Event and precondition | Next state | Effect or invariant |
27
+ | --- | --- | --- |
28
+ | Control proposes an allowed value | Owner replaces value | All readers observe the same accepted value |
29
+ | Control proposes an invalid value | Unchanged | Return rejection; do not pretend the value committed |
30
+ | Owner resets externally | New owner value | Every controlled reader reflects reset |
31
+
32
+ ### Minimal Executable Example
33
+
34
+ Run this standalone JavaScript block with Node.js 22 or newer, or run all pattern examples from a repository checkout with `bun run test:state-management`. The assertions exercise the local model, not a browser or backend.
35
+
36
+ ```js
37
+ import assert from "node:assert/strict";
38
+ let value = "compact";
39
+ function propose(next) {
40
+ if (!["compact", "comfortable"].includes(next)) return false;
41
+ value = next;
42
+ return true;
43
+ }
44
+ const toolbar = { read: () => value, change: propose };
45
+ const settings = { read: () => value, change: propose };
46
+ assert.equal(toolbar.change("comfortable"), true);
47
+ assert.equal(settings.read(), "comfortable");
48
+ assert.equal(settings.change("invalid"), false);
49
+ assert.equal(toolbar.read(), "comfortable");
50
+ value = "compact";
51
+ assert.equal(settings.read(), "compact");
52
+ ```
53
+
54
+ ### What Breaks If Removed
55
+
56
+ If each control copies the initial value into its own accepted state, changing the toolbar leaves settings stale. Synchronizing both copies with reciprocal callbacks introduces a second ordering problem.
57
+
58
+ ### Composition And Substitution
59
+
60
+ Compose with [derived state](derived-state.md) for summaries and [identity reset](identity-reset.md) for account changes. A framework context or store can transport this owner; it does not decide who owns the value.
61
+
62
+ ## Opinionated Guidance
63
+
64
+ Name the write API as an intent when the owner may reject or normalize it. Distinguish a local editing buffer from the accepted value in component inputs.
65
+
66
+ ## Platform-Specific Guidance
67
+
68
+ Native controls still need accessible names and correct value semantics. Preserve IME composition when adapting text inputs; do not normalize every keystroke without an input contract.
69
+
70
+ ## Unsupported Absolutes
71
+
72
+ A shared owner does not require an application-wide store or prove efficient subscriptions.
73
+
74
+ ## Verification Contract
75
+
76
+ - Edit from either control, then reset from the parent; both readers must agree.
77
+ - Reject an invalid intent and verify the UI exposes the rejection.
78
+ - Remove and recreate one reader; it must receive the current value.
79
+
80
+ Record actual outcomes separately using the [verification matrix](../verification.md).
81
+
82
+ ## Source, License, And Attribution
83
+
84
+ Locally authored synthesis and examples. No upstream implementation is copied. These experimental contracts describe consumer-owned behavior; review when a failure, ownership change, or platform change invalidates an assumption.
85
+
86
+ ## IA Navigation
87
+
88
+ Parent: [State Management](../index.md).
89
+ Next: [Continue the state management route](../recipes/index.md).