You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ai/research/data-sync/plan.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -199,6 +199,14 @@ Notes:
199
199
-`pruneChildPaths` yields the changed path set — value-less and index-addressed (the reactivity review's finding), so the wire write picks values via `get` per path, and array segments translate to id-addressed form for schema-declared keyed arrays before send (see Repeating groups)
200
200
- Clone cost is a non-goal: Meteor-era apps cloned liberally and stayed fast where it mattered. The place it would compound — per-inbound-delta apply — is avoided by field swaps incidentally, not as a crusade
201
201
202
+
### Write capture — `trackWrites`
203
+
204
+
`trackWrites(doc, fn, opts)` is the layer's write-capture primitive, lifted from its first consumer (`Signal.mutate`). It runs the mutator body and reports `{ changed, result, paths }` — `paths` only when `returnPaths: true`. The data layer always passes `returnPaths: true`, and `onWrite` for the per-write streaming path (outbox append, optimistic dep fires); a signal passes `returnPaths: false` because a signal's reactive granularity is the whole cell, so a path has nowhere to route — `returnPaths: false` is the floor, the data layer lives above it. The body runs synchronously: the tracked proxy expires at callback return, which is the root of the sync-only mutator constraint, not a separate rule.
205
+
206
+
The contract the layer relies on is that `paths` is deliberately thin — value-less, kind-less, positional (see the Write Path note above on `pruneChildPaths`, and Repeating groups for id-addressing). Richness is reconstructed by the consumer at the point it is needed, not carried in the capture: new values read via `get(doc, path)` against the post-apply doc, op-kind inferred from value-presence (undefined means cleared) plus channel-membership re-match, base values taken from the rebase shadow — never the proxy trap, whose intermediate value is a partially-rebased replay artifact — and id-addressed array paths translated by schema-aware lookup at commit. The capture stays a position log because every richer datum has a more authoritative downstream source; widening the return would only manufacture a second, staler one.
207
+
208
+
`trackWrites` is the owned-write engine — a mutation the layer performs and watches, both the client optimistic apply and the server authoritative apply. Its twin is `detectChanges(before, after)`, which diffs two finished images rather than watching a mutation, and is the external-write engine behind `watch()` CDC (External Writers). Owned writes capture, external writes diff — the dual-stream router's two capture engines, not redundant paths.
209
+
202
210
## Execution Without Fibers
203
211
204
212
Meteor's server-side sync CRUD was fibers suspending the stack during I/O. Node removed that, Meteor 3 paid with `insertAsync` everywhere. This design splits the problem by what actually blocks:
Copy file name to clipboardExpand all lines: ai/skills/authoring/component-css.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ type: skill
11
11
12
12
> **Skill:**`component-css`
13
13
> **Purpose:** Canonical patterns for writing CSS inside a component's shadow DOM — nesting, container queries, responsive design, state management, theming, and design token usage.
14
-
> **Last Updated:** 2026-03-04
14
+
> **Last Updated:** 2026-06-16
15
15
16
16
---
17
17
@@ -46,16 +46,16 @@ Write minimal, maintainable CSS that leverages the design token system and mirro
46
46
47
47
.header {
48
48
font-weight: var(--bold);
49
-
margin-bottom: var(--compact-spacing);
49
+
margin-bottom: var(--spacing-xs);
50
50
}
51
51
52
52
.items {
53
53
display: flex;
54
54
flex-direction: column;
55
-
gap: var(--compact-spacing);
55
+
gap: var(--gap-xs);
56
56
57
57
.item {
58
-
padding: var(--compact-spacing);
58
+
padding: var(--padding-xs);
59
59
cursor: pointer;
60
60
61
61
&:hover {
@@ -84,7 +84,7 @@ Write minimal, maintainable CSS that leverages the design token system and mirro
84
84
85
85
.actions {
86
86
display: flex;
87
-
gap: var(--compact-spacing);
87
+
gap: var(--gap-xs);
88
88
}
89
89
}
90
90
}
@@ -371,7 +371,7 @@ Semantic UI uses a sophisticated theme system where CSS variables automatically
Copy file name to clipboardExpand all lines: ai/skills/authoring/component-patterns.md
+11-19Lines changed: 11 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ type: skill
11
11
12
12
> **Skill:**`component-patterns`
13
13
> **Purpose:** Decision trees and production patterns for component communication, DOM querying, race condition prevention, resource cleanup, async reactions, lazy loading, scroll handling, and key anti-patterns.
14
-
> **Last Updated:** 2026-03-04
14
+
> **Last Updated:** 2026-06-16
15
15
16
16
---
17
17
@@ -46,30 +46,22 @@ How should component A talk to component B?
46
46
Use when a child needs to read or mutate parent state. The child knows about the parent by name.
The argument to `findParent` is the **camelCase component name**, not the tag name. `findParent('uiPanels')` finds `<ui-panels>`, not `findParent('ui-panels')`.
63
64
64
-
```javascript
65
-
// panel.js — child accesses parent coordinator
66
-
getPanels() {
67
-
constpanels=findParent('uiPanels');
68
-
return panels;
69
-
},
70
-
```
71
-
*Source: `src/components/panels/panel.js`*
72
-
73
65
### Pattern 2: Parent listens to child via event delegation
74
66
75
67
Use when the parent needs to react to child lifecycle or user actions without the child needing a reference to the parent.
Copy file name to clipboardExpand all lines: ai/skills/authoring/component-specs.md
+14-10Lines changed: 14 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ type: skill
11
11
12
12
> **Skill:**`component-specs`
13
13
> **Purpose:** Guide to the @semantic-ui/specs package — declarative component metadata, spec file format, SpecReader API, shared terms system, and build pipeline integration for spec-driven web components.
@@ -198,7 +198,7 @@ Tiers are cumulative: `standard` ⊂ `extended` ⊂ `full`. The value is the **l
198
198
At build time, these are aggregated into `dist/presets.json` which the CDN upload script reads and publishes to R2. The CDN Worker uses presets to resolve URLs like `/core@canary/standard` into the correct set of component imports.
199
199
200
200
Tiers:
201
-
-**`standard`**(~40-50 components) — General-purpose UI for building typical apps. The "don't think about it" default.
201
+
-**`standard`** — General-purpose UI for building typical apps. The "don't think about it" default.
202
202
-**`extended`** — Standard + specialized components (rich form inputs, data viz, niche patterns).
Copy file name to clipboardExpand all lines: ai/skills/authoring/example-curriculum.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@ The first 7 carry the core argument. The rest fill pattern gaps. Each entry list
24
24
25
25
### 1. `minimal` — The Floor
26
26
27
-
A complete component in 6 lines. Inline template and CSS as strings. This is the absolute minimum — proof that the simplest case is trivially simple before any complexity is introduced.
27
+
A complete component in a few lines. Inline template and CSS as strings. This is the absolute minimum — proof that the simplest case is trivially simple before any complexity is introduced.
Copy file name to clipboardExpand all lines: ai/skills/authoring/reactive-state.md
+3-2Lines changed: 3 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ type: skill
11
11
12
12
> **Skill:**`reactive-state`
13
13
> **Purpose:** Comprehensive guide to the @semantic-ui/reactivity package — a standalone signals-based reactive system with automatic dependency tracking for state management.
14
-
> **Last Updated:** 2026-03-04
14
+
> **Last Updated:** 2026-06-16
15
15
16
16
---
17
17
@@ -158,7 +158,8 @@ const users = signal([
158
158
]);
159
159
160
160
// Find by ID (supports id, _id, hash, key properties)
161
-
constindex=users.getItem(1); // Returns index of item with id=1
161
+
constuser=users.getItem(1); // Returns the item with id=1
162
+
constuserIndex=users.getItemIndex(1); // Returns its index (-1 if absent)
162
163
users.setItemProperty(1, 'name', 'Alice2'); // Set property on item with id=1
163
164
users.replaceItem(1, newUserObject); // Replace entire item with id=1
Copy file name to clipboardExpand all lines: ai/skills/authoring/ssr-hydration.md
+3-2Lines changed: 3 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -391,7 +391,7 @@ For each marker:
391
391
392
392
### The skipFirstWrite contract
393
393
394
-
When debugging "my signal mutation doesn't update the DOM after hydration," name `skipFirstWrite:true` explicitly — it's the grep-able load-bearing mechanism in `packages/renderer/src/engines/native/reactive-data.js` and surfacing it lets the reader navigate the code path directly.
394
+
When debugging "my signal mutation doesn't update the DOM after hydration," name `skipFirstWrite:true` explicitly — it's the grep-able load-bearing mechanism in `packages/renderer/src/engines/native/attribute-binding.js` and surfacing it lets the reader navigate the code path directly.
395
395
396
396
Per-binding Reactions wired during hydration use `skipFirstWrite:true`:
0 commit comments