# Changelog
All notable changes to **kerf** are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.16.0] - 2026-07-01
- Fixed keyed-list selection breaking after a row was removed: a signal read only inside `each()`'s `cacheKey` (such as a `selectedId` toggling a row's class) no longer drops out of the reactive dependency set, so later changes re-render correctly.
- Fixed appending items to a list after clearing it rendering nothing.
- `each()` on an `arraySignal`: appending rows to a list that was just emptied (e.g. **Clear** then **Append**) now renders the new rows immediately, instead of showing nothing until a second append. After the list was emptied its binding was empty but no longer in its first-render state, so the granular insert path emitted a segment the reconciler rendered as empty; repopulating an emptied list now takes the snapshot (build-from-scratch) path, the same as a first render.
- `each()` on an `arraySignal`: a signal read only inside the `cacheKey` comparator (the "external state drives the row" pattern — e.g. a `selectedId` flipping a row's class) now stays tracked across a granular structural update. Previously, after a granular insert/remove/update/move, that signal dropped out of the `mount()` effect's dependency set (the granular path never re-evaluates `cacheKey` for untouched rows), so a later change to it silently failed to re-render — e.g. row selection stopped working after a row was deleted. The granular path now re-reads every row's `cacheKey`, which both keeps those signals tracked and detects content drift the patches can't express (a selection flip batched together with a structural change), falling back to the snapshot path when it does.
## [0.15.5] - 2026-06-30
- Corrected the advertised bundle size in `llms.txt` to ~11 KB minified + gzipped (including the `@preact/signals-core` runtime dependency; ~12 KB with `arraySignal`), matching the README.
## [0.15.4] - 2026-06-30
- `llms.txt` is now published at a public docs-site URL and bundled in the npm package, making kerf's AI-assistant documentation index discoverable to llms.txt directories and tooling.
- The `kerfjs` package now bundles `llms.txt` (the AI-discovery index) at the package root, and the docs site serves it at `https://brianwestphal.github.io/kerf/llms.txt`. Its links are now absolute GitHub URLs so the file is portable across GitHub, the site, and the installed package.
## [0.15.3] - 2026-06-30
- `npm create kerf-component` with no directory argument now prompts for the target directory (defaulting to `my-kerf-component`, with a `.` hint for the current directory) instead of printing usage text and exiting with an error.
## [0.15.2] - 2026-06-30
- Added the `create-kerf-component` initializer — scaffold a ready-to-publish kerf component package with `npm create kerf-component@latest
`, no need to reverse-engineer the packaging rules.
## [0.15.1] - 2026-06-30
- README refresh + eslint rule-count fixes + CHANGELOG hygiene (`cfbaef3`)
## [0.15.0] - 2026-06-30
- List updates now morph same-identity rows in place instead of recreating their DOM nodes, avoiding full-table relayout on large lists and preserving DOM identity, focus, and IME composition across re-renders.
- New guide on incremental migration: kerf can own a single DOM subtree and coexist with React (or any framework), letting you migrate one island at a time.
- New guide on building and publishing reusable kerf components as npm packages.
- Example app documentation pages now open with an animated SVG preview of the real app in action, plus a gallery on the complete-examples index.
## [0.14.0] - 2026-05-27
- Fix `toElement()` first-paint divergence in WebKit by adopting its result into the live document
- Fix `mount()` first render in WebKit by adopting an inert `rootEl` into the live document
## [0.13.0] - 2026-05-23
- Add `KERF_DEV_WARN_DELEGATE_IN_EFFECT` dev warning to catch `delegate()` calls inside reactive effects
- New `require-delegate-disposer` ESLint rule flags `delegate()` calls whose disposer is discarded
- Document `delegate()` disposer gotchas and canonical cleanup patterns
## [0.12.1] - 2026-05-22
- Add GitHub Sponsors link to README, homepage, and npm `funding` field
## [0.12.0] - 2026-05-22
- `toElement` now returns `Element | DocumentFragment` to support multi-root inputs
## [0.11.1] - 2026-05-21
- `attr()` redesign: typed `AttrSpec` exposes `.attrs` with dual overloads for cleaner attribute handling
## [0.11.0] - 2026-05-21
- `attr()` redesigned with `AttrSpec` shape, `.attrs` accessor, and dual overloads
- Hardened defensive programming across the runtime for safer edge-case handling
- Refreshed published performance numbers from a fresh cross-framework benchmark run
## [0.10.0] - 2026-05-20
- Expose `kerfjs/ai/*` subpaths via package `exports` so the bundled skill/cursorrules files are resolvable
- Add a defensive fallback in `kerfjs/ai-assistant-configs` ESLint rule so it fires against installed kerfjs versions whose `exports` block subpath resolution
## [0.9.1] - 2026-05-20
- Bundle the kerf-app Claude Code skill and Cursor rules inside the npm package at `ai/skill.md`, `ai/cursorrules`, and `ai/manifest.json`
- Add `kerfjs/ai-assistant-configs` rule to `eslint-plugin-kerfjs` (warn in recommended) to flag drift in installed AI assistant configs
- `eslint --fix` now replaces only the canonical section above the `KERF-APP-CANONICAL-END` marker, preserving consumer customizations below it
## [0.9.0] - 2026-05-20
- Bundle the kerf-app Claude Code skill and Cursor rules inside the npm package at `ai/skill.md`, `ai/cursorrules`, and `ai/manifest.json`
- Add `kerfjs/ai-assistant-configs` rule (warn in recommended) to `eslint-plugin-kerfjs` v0.9.0 to surface AI-config drift on every lint pass
- Canonical-file contract (`kerf-skill-version` + `KERF-APP-CANONICAL-END` marker) lets `eslint --fix` refresh the canonical section while preserving consumer customizations below the marker
## [0.8.2] - 2026-05-19
- Package `homepage` fields now point to the published docs site, with prominent links in both READMEs
## [0.8.1] - 2026-05-19
- New `eslint-plugin-kerfjs` with four AST rules enforcing kerf Hard Rules
## [0.8.0] - 2026-05-18
- Add opt-in dev warning `KERF_DEV_WARN_NARROW_SET=1` that fires when `set()` is called with a partial-state object (replace semantics would silently drop missing keys); names the missing keys and points at the `set({ ...get(), ...next })` merge fix
- Widen `KerfBaseAttrs.contentEditable` to accept `'plaintext-only'` and add the lowercase `contenteditable` alias
- Expand the `/kerf/migrating/` hub to 13 frameworks — adds Vue 3, Svelte 5, Solid, Preact, htmx, Angular, jQuery, Redux, and Astro pages alongside a refreshed 8-framework comparison matrix
- New runnable example apps: `cart-htmx` (htmx swap → kerf island mount pattern) and `counter-store` (sync + async + persisted store)
- Fix TodoMVC example: store actions now spread `get()` into `set()` so filter/edit interactions no longer wipe state
- Drop AI-evidence pages, the AI marketing page, the blog, and the built-by-an-AI example; remaining docs re-toned to verifiable claims only
- New `scripts/check-docs-examples.mjs` doc/example consistency gate (wired into `npm run check`): verifies every example linked from a migration page is built + tested, and typechecks self-contained doc code blocks against `dist/`
## [0.7.0] - 2026-05-18
- Granular list updates now preserve DOM identity, focus, scroll, IME state, ``/`