solid2-agent-kit 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/baseline.mjs
CHANGED
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
// pulls them in — so doctor also checks an undeclared install of any package
|
|
20
20
|
// here, which is where a lockfile holds an older compiler.
|
|
21
21
|
export const BASELINE = {
|
|
22
|
-
'solid-js': { line: 2, baseline: '2.0.0-rc.
|
|
23
|
-
'@solidjs/web': { line: 2, baseline: '2.0.0-rc.
|
|
24
|
-
'@solidjs/signals': { line: 2, baseline: '2.0.0-rc.
|
|
25
|
-
'@solidjs/diagnostics': { line: 2, baseline: '2.0.0-rc.
|
|
26
|
-
'@solidjs/compiler': { line: 2, baseline: '2.0.0-rc.
|
|
27
|
-
'@solidjs/babel-plugin': { line: 2, baseline: '2.0.0-rc.
|
|
28
|
-
'@solidjs/router': { line: 2, baseline: '2.0.0-next.
|
|
29
|
-
'@solidjs/vite-plugin': { line: 3, baseline: '3.0.0-next.
|
|
22
|
+
'solid-js': { line: 2, baseline: '2.0.0-rc.19' },
|
|
23
|
+
'@solidjs/web': { line: 2, baseline: '2.0.0-rc.19' },
|
|
24
|
+
'@solidjs/signals': { line: 2, baseline: '2.0.0-rc.19' },
|
|
25
|
+
'@solidjs/diagnostics': { line: 2, baseline: '2.0.0-rc.19' },
|
|
26
|
+
'@solidjs/compiler': { line: 2, baseline: '2.0.0-rc.19' },
|
|
27
|
+
'@solidjs/babel-plugin': { line: 2, baseline: '2.0.0-rc.19' },
|
|
28
|
+
'@solidjs/router': { line: 2, baseline: '2.0.0-next.43' },
|
|
29
|
+
'@solidjs/vite-plugin': { line: 3, baseline: '3.0.0-next.52' },
|
|
30
30
|
'@solidjs/testing-library': { line: 1, baseline: '1.0.0-rc.2' },
|
|
31
31
|
};
|
|
32
32
|
|
package/bin/solid2-kit.mjs
CHANGED
|
@@ -849,12 +849,13 @@ const CHECKS = [
|
|
|
849
849
|
},
|
|
850
850
|
];
|
|
851
851
|
|
|
852
|
-
// Named imports from "@solidjs/router"
|
|
853
|
-
//
|
|
854
|
-
// `formAction as action` (the local
|
|
852
|
+
// Named imports (and re-exports) from "@solidjs/router" or its `/data` subpath
|
|
853
|
+
// among `names`, located at the name inside the import list. Only the imported
|
|
854
|
+
// name counts: `action as save` is flagged, `formAction as action` (the local
|
|
855
|
+
// name) is not.
|
|
855
856
|
function routerImportFindings(content, names) {
|
|
856
857
|
const findings = [];
|
|
857
|
-
for (const statement of content.matchAll(/import\s
|
|
858
|
+
for (const statement of content.matchAll(/(?:import|export)\s*(?:type\s+)?\{([^}]*)\}\s*from\s*['"]@solidjs\/router(?:\/data)?['"]/g)) {
|
|
858
859
|
const list = statement[1];
|
|
859
860
|
const offset = statement.index + statement[0].indexOf(list);
|
|
860
861
|
for (const name of names) {
|
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
- After editing TSX, run the `solid2-kit check` mechanical gate — it fails on React/Solid 1.x tokens and props destructuring. Use the project's `lint:solid` script if one exists; otherwise `npx solid2-agent-kit check` (with the kit as a devDependency) or `npx github:lightsound/solid2-agent-kit check`. An edit-time hook may also run this gate automatically after each file edit — treat its findings as errors to fix immediately, not warnings. Do not install `eslint-plugin-solid` (built for Solid 1.x; misreads Solid 2 idioms).
|
|
6
6
|
- After editing `package.json`, `tsconfig*.json`, or root config files (Vite, ESLint), run `solid2-kit doctor` — it fails on React/Solid 1.x wiring: `react`/`vite-plugin-solid`/`eslint-plugin-solid`/SolidStart dependencies, 1.x `solid-js` ranges, and `jsx`/`jsxImportSource` values other than `preserve`/`@solidjs/web`.
|
|
7
7
|
- The kit's guidance and gate files (`.cursor/rules/solid-2.mdc`, the `solid-2` skill directories, hook entries, managed blocks in this file and `CLAUDE.md`) are guardrails, not obstacles. Never edit, weaken, bypass, or delete them to make a failure go away — fix the flagged code. If a guardrail seems wrong, stop and tell the user.
|
|
8
|
-
- Solid 2.0 shipped recently and breaks with 1.x — never trust pre-2.0 Solid docs, tutorials, or training knowledge. Verify APIs against https://v2-rebuild--solid-docs-v2.netlify.app/llms.txt (markdown mirror of https://v2.solidjs.com/, which blocks non-browser fetchers). If the project has `@solidjs/router`, server functions, or `@solidjs/meta`, use those official pages (see the skill's official-docs index) — not React Router, Next.js, SolidStart 1.x, or Solid Router 0.x/1.x JSX `<Route>`/`<A>`. Core `action` from `solid-js` is a generator transaction; router `formAction`/`query` from `@solidjs/router` are POST forms and a read cache (router `action` is a deprecated alias of `formAction`, and `useAction` is deprecated: call the server function directly — a mounted router applies its revalidation and redirect on any call <!-- upstream:router-action-deprecated -->). React `useDeferredValue` is `createDeferred(fn)`: an async memo that lags but never leads <!-- upstream:create-deferred-export -->. Core `refresh(source)`, router `revalidate(key)`, and server-function `return reload(...)` are three different APIs. Pass the accessor to `isPending(user)`, not `isPending(user())`. Pass async values as values (`user={user()}`) — JSX props are lazy; types stay `User`, not `Promise<User>`. `<Loading>` wraps the read, not the memo. Nested fetches run in parallel (components do not suspend). `isPending` is a per-expression question (`isPending(() => props.story)` / `isPending(selectedId)`), not a global spinner; `latest(selectedId)` is opt-in so highlight and content stay consistent by default. `<Errored>` heals when the source succeeds. Pass a function to `render`/`hydrate`: `render(() => <App />, root)`. Component teardown is `onSettled`, not `onCleanup` — return the cleanup; `onCleanup`, memo/effect creation, and `flush()` throw inside the `onSettled` callback in dev. Creating a memo/effect/root inside an effect's `apply` callback throws in dev too (`[PRIMITIVE_IN_EFFECT_CALLBACK]`) — create it in the body or compute phase. <!-- upstream:primitive-in-effect-callback --> Effect `apply` functions use block bodies (`(t) => { document.title = t; }`): any return value other than a cleanup function halts reactivity. Stores are written only through the setter's draft — writes to the store itself are ignored (dev warns `[STORE_WRITE_OUTSIDE_SETTER]` <!-- upstream:store-write-outside-setter -->), and `Map`/`Set`/`Date` inside a store are not tracked. Shared state, app-wide included, is created in a provider at the root of `App` (`createContext<T>()` + `useX()`), never a module-level signal/store (one instance serves every SSR request). Errors thrown out of an `action` never reach `<Errored>` — catch them in the action or `.catch` the call. One router instance; in-app navigation is `useNavigate` / `<a href>`, not `window.location`. Types: `solid-js` exports no `JSX` namespace — markup types are `JSX.Element` from `@solidjs/web` or `Element` from `solid-js` (alias it `SolidElement` next to DOM code) <!-- upstream:jsx-namespace-absent -->. Reset-a-signal-on-change is a writable derivation (`createSignal(() => { source(); return initial; })`), never an effect calling the setter. Client mode mounts with `render()` into an empty body — no hydration mismatch exists, so never defer initial values to post-mount React-style (that can overwrite persisted state). Client → server is additive (same setters + `action` + server functions): do not rewrite App with loading/error branches, disable optimistic rows until ack, invent tRPC, or refetch in `hydrate`/`onSettled`. The graph continues across the wire (`live()` owns the client connection; `<Reveal>` not a delayed stream). A server bundle uses `handleRequest` / Fetchable `fetch`; client-only start is static `dist/client`. One browser-only value takes `ssrSource: "client"` on the memo/signal/derived store, not a `clientOnly` component split. Router link state is `aria-current`/`data-active` + CSS (`data-pending` is opt-in via `createRouter({ links: pendingLinks })`; `useLinkState`/`useIsRouting` in JSX) <!-- upstream:pending-links-opt-in -->; link preloading is opt-in too (`preloadLinks: intentPreload()` for hover/focus/touch; none by default; opt one link out with the string `preload="false"`) <!-- upstream:preload-links-opt-in -->; search params via `useSearchParams`; router forms validate on the server (`throw respond({issues},{400})`) with inline errors from `useSubmissions`. Confirmations on another channel — fire-and-forget sends, and mutations whose result is read through `live()` — wait with `yield until(predicate, {timeout})`, not `refresh()`. Declare live reads `live(fn)` — it implies `GET` (`live(GET(fn))` is the same) <!-- upstream:live-implies-get -->. Debounce at the handler; inputs feeding a request bind `latest(query)`. Dev diagnostics are errors: `[STRICT_READ_UNTRACKED]` means a read outside a tracking scope, `[ASYNC_STORE_SETTER]` means a store setter callback awaited (the draft is a synchronous transaction — await first, then write) <!-- upstream:async-store-setter-throws -->, a held write needs `isPending`/`latest`/optimistic/`affects` feedback or dev + attribution reports `[SILENT_HOLD]
|
|
8
|
+
- Solid 2.0 shipped recently and breaks with 1.x — never trust pre-2.0 Solid docs, tutorials, or training knowledge. Verify APIs against https://v2-rebuild--solid-docs-v2.netlify.app/llms.txt (markdown mirror of https://v2.solidjs.com/, which blocks non-browser fetchers). If the project has `@solidjs/router`, server functions, or `@solidjs/meta`, use those official pages (see the skill's official-docs index) — not React Router, Next.js, SolidStart 1.x, or Solid Router 0.x/1.x JSX `<Route>`/`<A>`. Core `action` from `solid-js` is a generator transaction; router `formAction`/`query` from `@solidjs/router` are POST forms and a read cache (router `action` is a deprecated alias of `formAction`, and `useAction` is deprecated: call the server function directly — a mounted router applies its revalidation and redirect on any call <!-- upstream:router-action-deprecated -->). React `useDeferredValue` is `createDeferred(fn)`: an async memo that lags but never leads <!-- upstream:create-deferred-export -->. Core `refresh(source)`, router `revalidate(key)`, and server-function `return reload(...)` are three different APIs. Pass the accessor to `isPending(user)`, not `isPending(user())`. Pass async values as values (`user={user()}`) — JSX props are lazy; types stay `User`, not `Promise<User>`. `<Loading>` wraps the read, not the memo. Nested fetches run in parallel (components do not suspend). `isPending` is a per-expression question (`isPending(() => props.story)` / `isPending(selectedId)`), not a global spinner; `latest(selectedId)` is opt-in so highlight and content stay consistent by default. `<Errored>` heals when the source succeeds. Pass a function to `render`/`hydrate`: `render(() => <App />, root)`. Component teardown is `onSettled`, not `onCleanup` — return the cleanup; `onCleanup`, memo/effect creation, and `flush()` throw inside the `onSettled` callback in dev. Creating a memo/effect/root inside an effect's `apply` callback throws in dev too (`[PRIMITIVE_IN_EFFECT_CALLBACK]`) — create it in the body or compute phase. <!-- upstream:primitive-in-effect-callback --> Effect `apply` functions use block bodies (`(t) => { document.title = t; }`): any return value other than a cleanup function halts reactivity. Stores are written only through the setter's draft — writes to the store itself are ignored (dev warns `[STORE_WRITE_OUTSIDE_SETTER]` <!-- upstream:store-write-outside-setter -->), and `Map`/`Set`/`Date` inside a store are not tracked. Shared state, app-wide included, is created in a provider at the root of `App` (`createContext<T>()` + `useX()`), never a module-level signal/store (one instance serves every SSR request). Errors thrown out of an `action` never reach `<Errored>` — catch them in the action or `.catch` the call. One router instance; in-app navigation is `useNavigate` / `<a href>`, not `window.location`. Types: `solid-js` exports no `JSX` namespace — markup types are `JSX.Element` from `@solidjs/web` or `Element` from `solid-js` (alias it `SolidElement` next to DOM code) <!-- upstream:jsx-namespace-absent -->. Reset-a-signal-on-change is a writable derivation (`createSignal(() => { source(); return initial; })`), never an effect calling the setter. Client mode mounts with `render()` into an empty body — no hydration mismatch exists, so never defer initial values to post-mount React-style (that can overwrite persisted state). Client → server is additive (same setters + `action` + server functions): do not rewrite App with loading/error branches, disable optimistic rows until ack, invent tRPC, or refetch in `hydrate`/`onSettled`. The graph continues across the wire (`live()` owns the client connection; `<Reveal>` not a delayed stream). A server bundle uses `handleRequest` / Fetchable `fetch`; client-only start is static `dist/client`. One browser-only value takes `ssrSource: "client"` on the memo/signal/derived store, not a `clientOnly` component split. Router link state is `aria-current`/`data-active` + CSS (`data-pending` is opt-in via `createRouter({ links: pendingLinks })`; `useLinkState`/`useIsRouting` in JSX) <!-- upstream:pending-links-opt-in -->; link preloading is opt-in too (`preloadLinks: intentPreload()` for hover/focus/touch; none by default; opt one link out with the string `preload="false"`) <!-- upstream:preload-links-opt-in -->; search params via `useSearchParams`; router forms validate on the server (`throw respond({issues},{400})`) with inline errors from `useSubmissions`. Confirmations on another channel — fire-and-forget sends, and mutations whose result is read through `live()` — wait with `yield until(predicate, {timeout})`, not `refresh()`. Declare live reads `live(fn)` — it implies `GET` (`live(GET(fn))` is the same) <!-- upstream:live-implies-get -->. Debounce at the handler; inputs feeding a request bind `latest(query)`. Dev diagnostics are errors: `[STRICT_READ_UNTRACKED]` means a read outside a tracking scope, `[ASYNC_STORE_SETTER]` means a store setter callback awaited (the draft is a synchronous transaction — await first, then write) <!-- upstream:async-store-setter-throws -->, a held write needs `isPending`/`latest`/optimistic/`affects` feedback or dev + attribution reports `[SILENT_HOLD]` (a write that must not join another update's hold goes in `onFlush(...)` <!-- upstream:on-flush -->), and `[UNCOMMITTED_INPUT_OVERWRITTEN]` means a `value`/`checked` binding re-wrote the bound value over text the user typed but never committed (`value={props.name} onChange={commit}` with no draft signal) — bind a draft signal written from `onInput`, or `defaultValue` <!-- upstream:uncommitted-input-overwritten -->. Error monitoring is `configureClientErrors` / `configureServerErrors` (or per root `render(fn, root, undefined, { onError })` — options are the 4th argument), not a side effect inside `<Errored fallback>`; the server hook must return a reference or nothing, never the error itself. `<Dynamic>` is deprecated — use `dynamic()`. <!-- upstream:dynamic-deprecated --> Observability is on by default in development: whenever a change touches stores, lists, async, actions, or effects, keep the dev console free of `[CODE]` findings and run an attribution session (`/__solid/diagnostics` `begin` → interact → `whyDidRun` / `costs` → `end` with `@solidjs/diagnostics` installed, otherwise `isDev`-guarded `attribution.enable({ log: false })` + `why()` / `costs()`) before finishing. `vite dev` is always the dev build; `solid({ observe: true })` is a production opt-in.
|
|
@@ -316,7 +316,8 @@ Claude Code) for full patterns, decision tables, and official documentation URLs
|
|
|
316
316
|
<!-- upstream:uncommitted-input-overwritten -->. Bind a draft signal written from
|
|
317
317
|
`onInput` (`createSignal(() => props.name)` resets it when the prop changes), use
|
|
318
318
|
`defaultValue` for an uncontrolled field, or write the next value back explicitly;
|
|
319
|
-
`equals: false` on the signal
|
|
319
|
+
`equals: false` on the bound signal is no way to reject input — a source firing with an
|
|
320
|
+
equal value is one of the causes the warning names, so it only adds re-writes.
|
|
320
321
|
22. Miscellaneous defaults: SSR-stable element ids come from `createUniqueId()` (never
|
|
321
322
|
`Math.random()` or hardcoded duplicates); pass store data to `structuredClone` /
|
|
322
323
|
`postMessage` / logs via `snapshot(store)` (proxies fail or leak reactivity) — a
|
|
@@ -563,7 +564,7 @@ directory (default `src/`).
|
|
|
563
564
|
| `createDeferred(source, { timeoutMs })` (1.x: a signal that lags by idle time) | `createDeferred(fn)` (2.0: an async memo that may lag its inputs but never leads them; `isPending(deferred)` while it catches up) <!-- upstream:create-deferred-export --> |
|
|
564
565
|
| `startTransition`, `useTransition` | automatic held updates + `isPending` |
|
|
565
566
|
| `onError` / `catchError` | `<Errored>` or effect bundle `{ effect, error }` |
|
|
566
|
-
| `from(...)` / `observable(...)` (the solid-js helpers) | inbound:
|
|
567
|
+
| `from(...)` / `observable(...)` (the solid-js helpers) | inbound: `from(source)` — the same name in 2.0, but it returns an AsyncIterable for a computation (`createMemo(() => from(source))`), not a signal <!-- upstream:from-source-adapts -->; outbound: split effect |
|
|
567
568
|
| `createDynamic(...)`, `<Dynamic component={...}>` (deprecated in 2.0) <!-- upstream:dynamic-deprecated --> | `dynamic(source)` from `@solidjs/web` — `dynamicComponent(source)` from `solid-js` when the source only answers with a component <!-- upstream:dynamic-component-export --> |
|
|
568
569
|
| `renderToStringAsync(...)` | `await renderToStream(() => <App />)` (one consumer: `pipe` / `pipeTo` / `readable`) |
|
|
569
570
|
| `clearDelegatedEvents` | delete — delegated listeners are scoped to each render root |
|
|
@@ -44,7 +44,7 @@ Practical consequences:
|
|
|
44
44
|
| App-wide state (theme, session, cart, locale) | the same provider, placed at the root of `App` — not a module-level signal/store (under SSR one module instance serves every request) |
|
|
45
45
|
| Constants (a category list, a formatter, the `createContext` call) | module scope |
|
|
46
46
|
| Tentative value during a mutation | `createOptimistic` / `createOptimisticStore` + `action` |
|
|
47
|
-
| Values pushed by an external subscription (websocket, reactive client) | async iterable returned from a memo (or function-form `createStore` for keyed reconciliation) — never `{ data, error }` signal pairs |
|
|
47
|
+
| Values pushed by an external subscription (websocket, reactive client) | async iterable returned from a memo — `from(source)` adapts a callback subscription, an Observable, or an AsyncIterable <!-- upstream:from-source-adapts --> (or function-form `createStore` for keyed reconciliation) — never `{ data, error }` signal pairs |
|
|
48
48
|
|
|
49
49
|
### Should this be an effect?
|
|
50
50
|
|
|
@@ -162,8 +162,9 @@ seed the shape through the `createStore` argument or a derivation.
|
|
|
162
162
|
**The store itself is read-only; only the draft writes.** An assignment or mutating
|
|
163
163
|
call on the store proxy outside a setter is *ignored* — no throw, the value does not
|
|
164
164
|
change, and TypeScript accepts it (`Store<T>` is `T`). Since 2.0.0-rc.17 dev warns
|
|
165
|
-
`[STORE_WRITE_OUTSIDE_SETTER]` once per store object and key (
|
|
166
|
-
|
|
165
|
+
`[STORE_WRITE_OUTSIDE_SETTER]` once per store object and key (a later delete of a key
|
|
166
|
+
already reported is not reported again; the operation is only in the event's `data`);
|
|
167
|
+
production stays silent
|
|
167
168
|
<!-- upstream:store-write-outside-setter -->. This is the
|
|
168
169
|
MobX / Vue / Solid 1 `createMutable` reflex:
|
|
169
170
|
|
|
@@ -459,9 +460,20 @@ return <StoryDetail story={story} />;
|
|
|
459
460
|
`transition-delay` so fast swaps do not flash. Inputs that feed a request follow
|
|
460
461
|
the same rule: bind `value={latest(query)}` so a controlled search box reflects
|
|
461
462
|
keystrokes while its write is held (an uncontrolled input needs nothing).
|
|
463
|
+
When one write in a handler must *not* join the hold — closing a menu before
|
|
464
|
+
`props.onSelect` starts a navigation — defer just that write with
|
|
465
|
+
`onFlush(() => setOpen(false))` (since 2.0.0-rc.19): it runs once right after the
|
|
466
|
+
pending flush as its own update, instead of flushing early
|
|
467
|
+
<!-- upstream:on-flush -->. It belongs in event handlers and effect callbacks; in a
|
|
468
|
+
component body or computation dev warns `ON_FLUSH_IN_OWNED_SCOPE`.
|
|
462
469
|
- Read every reactive input **before the first `await`** in an async computation. A read
|
|
463
470
|
after `await` does not subscribe (dev reports `[UNTRACKED_READ_AFTER_AWAIT]` on V8 —
|
|
464
471
|
Chromium, Node, Deno, Bun); production can sit pending with no retry.
|
|
472
|
+
- An async memo returns **data**, never rendered output. On the server, a memo (or async
|
|
473
|
+
iterable source) landing on JSX, a component result, or a `<Loading>`/`<Errored>`
|
|
474
|
+
boundary cannot serialize for hydration: since 2.0.0-rc.19 the memo rejects with
|
|
475
|
+
`ASYNC_MEMO_ELEMENT` and the nearest `<Errored>` contains it like any render error
|
|
476
|
+
<!-- upstream:async-memo-element -->. Render the JSX from the data the memo returns.
|
|
465
477
|
- `<Errored>` function fallbacks receive an error **accessor** and a `reset` callback:
|
|
466
478
|
`fallback={(error, reset) => ...}`. The boundary **heals** when the source succeeds
|
|
467
479
|
again (refresh, live reconnect, input change) — it is graph status, not a terminal
|
|
@@ -557,7 +569,15 @@ errors matter (the rc.8 one-argument form keeps working). <!-- upstream:render-o
|
|
|
557
569
|
Push-based sources integrate by returning an **async iterable** from a computation — reads
|
|
558
570
|
then suspend to `<Loading>` until the first value, later pushes update the settled value,
|
|
559
571
|
and thrown errors reach `<Errored>`. Integration layers should return a plain accessor, not
|
|
560
|
-
`{ data, error }` signals
|
|
572
|
+
`{ data, error }` signals.
|
|
573
|
+
|
|
574
|
+
For a callback subscription, an Observable, or an existing AsyncIterable, the adapter is
|
|
575
|
+
built in: `from(source)` returns the async iterable a computation consumes —
|
|
576
|
+
`createMemo(() => from(source))` <!-- upstream:from-source-adapts -->. Read the inputs that
|
|
577
|
+
choose the source before calling it, so a change re-runs the memo, closes the old source,
|
|
578
|
+
and opens the new one <!-- upstream:from-source-adapts -->. The hand-rolled form below remains for what `from` does not fit —
|
|
579
|
+
an event stream where every message matters (keep a queue instead of conflating to the
|
|
580
|
+
latest), or a subscribe signature that is not `(next, error, complete) => unsubscribe`:
|
|
561
581
|
|
|
562
582
|
```tsx
|
|
563
583
|
import { createMemo, onCleanup } from 'solid-js';
|
|
@@ -947,8 +967,9 @@ const [draft, setDraft] = createSignal(() => props.name);
|
|
|
947
967
|
// 3. explicit write-back when the field must follow an external value exactly
|
|
948
968
|
```
|
|
949
969
|
|
|
950
|
-
`equals: false` on the committed signal
|
|
951
|
-
|
|
970
|
+
`equals: false` on the committed signal makes it worse, not better — a source firing with
|
|
971
|
+
an equal value is one of the three causes the warning names, beside another binding in the
|
|
972
|
+
same template changing and a spread re-running — and a `createEffect` that copies the prop into the field is rule 4 again.
|
|
952
973
|
|
|
953
974
|
### Context
|
|
954
975
|
|
|
@@ -1233,7 +1254,7 @@ committed value over uncommitted user input <!-- upstream:uncommitted-input-over
|
|
|
1233
1254
|
`[ASYNC_OUTSIDE_LOADING_BOUNDARY]` when a tracked read has no boundary above it, and
|
|
1234
1255
|
`[LOADING_ON_OUTSIDE_HOLD]` when a `<Loading on>` boundary's data is also read outside it.
|
|
1235
1256
|
Each entry carries a stable `[CODE]`, what the runtime observed, an owner chain
|
|
1236
|
-
(`in <App> › <Cart> › <LineItem>`), and — since rc.
|
|
1257
|
+
(`in <App> › <Cart> › <LineItem>`), and — since rc.16, under `vite dev` — an
|
|
1237
1258
|
`at src/Cart.tsx:12:5` line naming where the scope was created (the compiler's
|
|
1238
1259
|
`sourceNames.locations`; the same `loc` sits on every artifact event)
|
|
1239
1260
|
<!-- upstream:source-names-locations -->; never silence a code before understanding it.
|
|
@@ -1291,7 +1312,7 @@ anonymous nodes print as `computed` / `effect` / `signal`; component labels
|
|
|
1291
1312
|
(`<Checkout>`) are always present under `vite dev` and survive minification only with
|
|
1292
1313
|
the compiler's `sourceNames` option (components, binding effects, primitives — the Vite
|
|
1293
1314
|
plugin turns it on under `vite dev` and `observe: true`; `componentNames` was its rc.9 name
|
|
1294
|
-
and is rejected now) <!-- upstream:source-names-option -->. Its `locations` kind (rc.
|
|
1315
|
+
and is rejected now) <!-- upstream:source-names-option -->. Its `locations` kind (rc.16)
|
|
1295
1316
|
adds `file:line:col` to every name — `createComponent(Home, props, "Home", "src/App.tsx:12:5")`,
|
|
1296
1317
|
`{ name, loc }` on primitives — which is what the `at …` line in a diagnostic and
|
|
1297
1318
|
`event.loc` in an artifact print; the plugin turns it on under `vite dev` only, and an
|
|
@@ -2179,7 +2200,7 @@ how to reuse. Prefer the form on the right.
|
|
|
2179
2200
|
| `onClick={setCount}` | `onClick={() => setCount((c) => c + 1)}` |
|
|
2180
2201
|
| `onclick={fn}` / `onmouseover={fn}` (lowercase handlers) | `onClick={fn}` — a lowercase `on*` name is a plain attribute (dev warns `[LOWERCASE_EVENT_ATTRIBUTE]`), not an event <!-- upstream:lowercase-event-attribute --> |
|
|
2181
2202
|
| `on:click={fn}` / `use:tooltip` / `attr:title` / `classList={{ on: x() }}` on a native element | `onClick`, a ref callback from a directive factory, `title`, `class={["btn", { on: x() }]}` — the 1.x forms are compile errors since rc.17 (`prop:` remains) <!-- upstream:removed-attribute-compile-error --> |
|
|
2182
|
-
| `value={props.name} onChange={(e) => props.onCommit(e.currentTarget.value)}` (bound to the committed value, no per-edit write) | a draft signal `createSignal(() => props.name)` written from `onInput`, or `defaultValue={props.name}` — the binding re-applies the committed value over uncommitted typing (`[UNCOMMITTED_INPUT_OVERWRITTEN]`); `equals: false`
|
|
2203
|
+
| `value={props.name} onChange={(e) => props.onCommit(e.currentTarget.value)}` (bound to the committed value, no per-edit write) | a draft signal `createSignal(() => props.name)` written from `onInput`, or `defaultValue={props.name}` — the binding re-applies the committed value over uncommitted typing (`[UNCOMMITTED_INPUT_OVERWRITTEN]`); `equals: false` is one of its causes, not a fix <!-- upstream:uncommitted-input-overwritten --> |
|
|
2183
2204
|
| `useDeferredValue(query())` / `startTransition(() => setQuery(q))` for an expensive derivation | `const rows = createDeferred(() => filter(all(), query()))` — an async memo that lags but never leads its inputs; `isPending(rows)` while it catches up. Unrelated to the 1.x `createDeferred(source, { timeoutMs })` <!-- upstream:create-deferred-export --> |
|
|
2184
2205
|
| `event.target.value` | `event.currentTarget.value` |
|
|
2185
2206
|
| `createContext(emptyStore)` for reactive state | `createContext<Todos>()` — dummy defaults silently no-op |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solid2-agent-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Teach AI coding agents (Cursor, Claude Code) to write correct Solid 2.0 instead of React or Solid 1.x — always-applied rules, an agent skill, and a mechanical pattern gate.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|