stylegallery 0.1.4 → 0.1.7

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 (80) hide show
  1. package/DOMAINS.md +11 -9
  2. package/GOVERNANCE.md +8 -2
  3. package/LICENSE +28 -0
  4. package/LICENSE-DOCS +42 -0
  5. package/NOTICE +38 -0
  6. package/README.md +43 -6
  7. package/consumer-reference/agent-native/README.md +7 -7
  8. package/consumer-reference/agent-native/v2/admission-policy.json +241 -1
  9. package/consumer-reference/agent-native/v2/material-registry.json +1 -1
  10. package/consumer-reference/agent-native/v2/schema/admission-policy.schema.json +2 -2
  11. package/design-engineering/component-contract.md +114 -0
  12. package/design-engineering/decision-tree.md +70 -0
  13. package/design-engineering/index.md +60 -2
  14. package/design-engineering/loading-and-feedback.md +91 -0
  15. package/design-engineering/native-interaction-contracts.md +94 -0
  16. package/design-engineering/state-management/decision-tree.md +60 -0
  17. package/design-engineering/state-management/index.md +61 -0
  18. package/design-engineering/state-management/patterns/derived-state.md +85 -0
  19. package/design-engineering/state-management/patterns/draft-and-baseline.md +86 -0
  20. package/design-engineering/state-management/patterns/id-selection.md +85 -0
  21. package/design-engineering/state-management/patterns/identity-reset.md +89 -0
  22. package/design-engineering/state-management/patterns/latest-request-wins.md +94 -0
  23. package/design-engineering/state-management/patterns/optimistic-overlay.md +98 -0
  24. package/design-engineering/state-management/patterns/single-flight.md +92 -0
  25. package/design-engineering/state-management/patterns/single-owner.md +89 -0
  26. package/design-engineering/state-management/patterns/submitted-snapshot.md +107 -0
  27. package/design-engineering/state-management/patterns/unsaved-navigation.md +100 -0
  28. package/design-engineering/state-management/patterns/url-state.md +96 -0
  29. package/design-engineering/state-management/patterns/versioned-restore.md +95 -0
  30. package/design-engineering/state-management/recipes/delete-undo.md +65 -0
  31. package/design-engineering/state-management/recipes/index.md +64 -0
  32. package/design-engineering/state-management/recipes/multi-step-form.md +65 -0
  33. package/design-engineering/state-management/recipes/search-detail.md +65 -0
  34. package/design-engineering/state-management/recipes/settings-save.md +64 -0
  35. package/design-engineering/state-management/state-brief.md +83 -0
  36. package/design-engineering/state-management/verification.md +65 -0
  37. package/design-engineering/text-input-and-internationalization.md +91 -0
  38. package/design-engineering/worked-examples.md +129 -0
  39. package/design-terminology/comparison-workflow.md +98 -0
  40. package/design-terminology/conflict-cases.md +87 -55
  41. package/design-terminology/index.md +19 -5
  42. package/design-terminology/interaction-semantics.md +87 -0
  43. package/design-terminology/relation-types.md +12 -6
  44. package/design-terminology/source-vocabularies.md +33 -3
  45. package/design-terminology/token-semantics.md +90 -0
  46. package/design-terminology/typography-semantics.md +86 -0
  47. package/game-ui/decision-tree.md +81 -0
  48. package/game-ui/index.md +11 -1
  49. package/game-ui/screen-recipes.md +101 -0
  50. package/game-ui/verification-workflow.md +100 -0
  51. package/index.md +8 -0
  52. package/log.md +67 -0
  53. package/motion/accessible-motion.md +90 -0
  54. package/motion/decision-tree.md +70 -0
  55. package/motion/index.md +21 -2
  56. package/motion/interaction-recipes.md +170 -0
  57. package/motion/interruption-and-retargeting.md +90 -0
  58. package/motion/motion-brief.md +125 -0
  59. package/motion/observed-choreography.md +73 -0
  60. package/motion/rendering-and-performance.md +89 -0
  61. package/motion/review-workflow.md +8 -0
  62. package/motion/vocabulary.md +2 -2
  63. package/package.json +74 -8
  64. package/platform-guides/adaptation-workflow.md +76 -0
  65. package/platform-guides/adaptive-navigation.md +85 -0
  66. package/platform-guides/android-interaction.md +74 -0
  67. package/platform-guides/apple-interaction.md +9 -1
  68. package/platform-guides/compatibility-matrix.md +97 -0
  69. package/platform-guides/index.md +19 -2
  70. package/platform-guides/input-and-focus.md +91 -0
  71. package/platform-guides/preferences-and-accessibility.md +90 -0
  72. package/platform-guides/windows-interaction.md +75 -0
  73. package/recipes/homepage.md +8 -0
  74. package/scripts/compiler/README.md +112 -0
  75. package/scripts/compiler/cli.mjs +51 -0
  76. package/scripts/compiler/mcp.mjs +53 -0
  77. package/scripts/compiler/operations.mjs +70 -0
  78. package/scripts/compiler/runtime.mjs +156 -0
  79. package/scripts/sg-entry.mjs +20 -0
  80. package/scripts/sg-server.mjs +20 -0
@@ -0,0 +1,85 @@
1
+ ---
2
+ type: Domain Guide
3
+ title: Derived State From Authoritative Inputs
4
+ description: Prevent totals, filtered lists, and dirty flags from drifting away from their inputs.
5
+ domain: design-engineering
6
+ lifecycle: experimental
7
+ provenance_kind: local
8
+ ---
9
+
10
+ # Derived State From Authoritative Inputs
11
+
12
+ ## Repository Boundary
13
+
14
+ Prevent totals, filtered lists, and dirty flags from drifting away from their inputs. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
15
+
16
+ ## Reusable Method
17
+
18
+ Use when a value is a deterministic projection of current inputs. Store historical snapshots when the task explicitly needs what was true at a previous event; those are not redundant current projections.
19
+
20
+ ### State Model And Ownership
21
+
22
+ Only source items and filter are writable. Visible items and total are computed. Memoization is optional and must include every dependency; its lifetime cannot change meaning.
23
+
24
+ ### Transitions
25
+
26
+ | Event and precondition | Next state | Effect or invariant |
27
+ | --- | --- | --- |
28
+ | Items change | New items | Recompute projection from current inputs |
29
+ | Filter changes | New filter | Project without mutating items |
30
+ | No matching items | Empty projection | Total is zero, not a separate empty flag |
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 `npm 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 items = [{ id: "a", price: 5 }, { id: "b", price: 12 }];
39
+ let minimum = 10;
40
+ const visible = () => items.filter(item => item.price >= minimum);
41
+ const total = () => visible().reduce((sum, item) => sum + item.price, 0);
42
+ assert.equal(total(), 12);
43
+ items = items.map(item => item.id === "b" ? { ...item, price: 7 } : item);
44
+ assert.deepEqual(visible(), []);
45
+ assert.equal(total(), 0);
46
+ minimum = 0;
47
+ assert.equal(total(), 12);
48
+ ```
49
+
50
+ ### What Breaks If Removed
51
+
52
+ An independently updated total can miss a deletion, filter change, or remote refresh. A memo keyed only by items stays stale after changing the filter.
53
+
54
+ ### Composition And Substitution
55
+
56
+ Combine with [ID selection](id-selection.md); derive the selected object from the current collection. Keep [submitted snapshots](submitted-snapshot.md) because they represent a past event.
57
+
58
+ ## Opinionated Guidance
59
+
60
+ Write down the projection before introducing another writable field. Define domain equality explicitly for dirty checks involving normalized dates, numbers, or nested data.
61
+
62
+ ## Platform-Specific Guidance
63
+
64
+ Framework memo and selector APIs have different invalidation rules. Verify dependency coverage and immutable update assumptions in the chosen adapter.
65
+
66
+ ## Unsupported Absolutes
67
+
68
+ Recomputing every projection is not always cheap; storing a cache can be valid if its invalidation contract is explicit.
69
+
70
+ ## Verification Contract
71
+
72
+ - Change each dependency independently and inspect the projection.
73
+ - Delete the final matching item and verify the empty result and zero total.
74
+ - If memoized, repeat with unchanged references and changed filter inputs.
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,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 `npm 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 `npm 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 `npm 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 `npm 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 `npm 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 `npm 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).