Repository navigation
EPBDS-16211: CLAUDE.md says how the engine keeps a field's props stable, and how to find a render's cost - #215
Merged
Merged
Conversation
…r renders every field again
A document built its whole meta anew for every new state (`meta` in rules.tsx, keyed on the state
object). Two writes made that common: a named Select with no onChange of its own writes its pick into
the state (toOpenLConfig gives it `setState,<name>`), and the form layer writes canSave there on the
first edit. Each built the meta anew, so every Select, and every field taking an object or a function,
rendered again, and every table's cells were built anew.
The meta is now kept while the new state holds what the build read from the previous one
(metaStateReads.ts). The build reads the state in three ways only: the `{...}` templates in names,
resolved against the instance ({state.x} reads state.x, {data.x} the data); the currency; and whether
a Select's state is empty yet, to seed it (initSelectStatesFromData). So it is kept while the state
holds the same meta and data slices, the same currency, the same value under each key a template
reads, and the same emptiness under each key a Select seeds. A template reading anything else of the
instance, or the whole state, keeps the old rule. FIELD.FUNC is read only by the build, into each
meta's own copy, so fewer builds bind nothing differently.
rules.meta-cache.test.js pinned "every new state is a new meta"; it now pins that a state the meta
did not read keeps its handlers, and one it read builds anew with new handlers. meta-rebuild-budget
pins it on the selectCascading example: a product pick (read by nothing) builds nothing and renders
one Select (was 1 build, both Selects); a category pick, read by {state.categoryX,0}, builds the meta
and the product list follows. Two budgets record their mount counts halving (one build at mount, not
two) and the first edit rendering no Select. Measured in jsdom on React 18 with a form of 101 Selects:
builds/Select renders at mount 2/202 -> 1/101, first edit 1/101 -> 0/0, a pick 1/101 -> 0/1.
…eta rebuilds reached Two instances of one class are equal only when they are the same one. Nothing tested that branch directly: the document's meta, built anew for every new state, reached it, and lodash-lite.ts's per-file coverage threshold rested on it. With the meta kept across a state it does not read, the branch went unreached and the threshold failed (95.66 % statements against 96 %).
…le, and how to find a render's cost A Render stability section, after the engine's mapping: every field's host is memoised, so a function, array or object the mapper or the transforms build anew for a field's prop renders it, and every field like it, again. It lists what keeps them (keptVerify, boundedValidator, keptHandler, keptMappedOptions, BuiltCell, the meta kept with metaStateReads.ts, formData's lastMerges and ValidatingForm), the *-budget contracts that count the renders, and the rule to count calls before naming a cost's cause.
AlexSamBY
added a commit
that referenced
this pull request
Oct 13, 2026
## What Each push to master gets a CI run of its own. A push to master now has a concurrency group named by its commit (`github.sha`). A pull request's group is still its ref, and its newer push still cancels the run before it. ## Why #205 was not enough #205 stopped a push to master from cancelling the run in progress: `cancel-in-progress` is on for pull requests only. But a group still holds at most one running run and one pending run. GitHub cancels the pending one when another is queued, whatever `cancel-in-progress` says. From [GitHub's documentation](https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency): "any existing `pending` job or workflow in the same concurrency group will be canceled". It happened on 2026-10-12, when #214, #215 and #216 merged within two minutes: | commit | its run was created | what happened to it | |---|---|---| | 1b16e4d (#214) | 16:12:35 | ran until 16:18:20, success | | 5cb6bf6 (#215) | 16:13:29 | pending behind it; cancelled at 16:14:02 with no job started | | 1710577 (#216) | 16:14:01 | success | 5cb6bf6 is the case #205 set out to prevent: a master commit with no finished run. ## The change - **`.github/workflows/ci.yml`:** the group is `ci-${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}`. Master's runs no longer share a group, so none waits and none is cancelled; merges in quick succession run in parallel. The comment says why one group for the branch was not enough. - **Why not `queue: max`:** it keeps up to 100 pending runs per group, but GitHub's documentation says it cannot be combined with `cancel-in-progress: true`, which pull requests use. - **The changelog:** its entry said "CI cancels a run only when a newer push to the same pull request supersedes it". It now says that each master commit gets a run of its own. The same fix for release/v0.34's `ci-0.34.yml` is #218. ## Verified - The workflow parses (js-yaml). - For a push, the group comes out as `ci-CI-<sha>`; for a pull request, as `ci-CI-refs/pull/<n>/merge`. `&&` and `||` return one of their operands, the common way to pick a value in a workflow expression. This PR's own run evaluates the expression, so a syntax error would have kept it from starting. - This PR's own run uses the pull-request group, which is unchanged. The push groups show on the next merges in quick succession: each commit should get a finished run. ## Gates All 22 gates and the manifest contract exit 0 on HEAD, on Node 24.14.0. - The suite has 2875 tests. All pass on React 18 and 19. - On React 16.14 and 17, 2871 pass and #207's 4 transition tests are skipped, as before. - In the browser, the demo's 62 tests pass in Chromium on React 18 and 19, and so do the packed tarball's on React 16.14 to 19. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
CLAUDE.mdgains a Render stability section, after the engine's mapping. It says:keptVerify,boundedValidator,keptHandler,keptMappedOptions,BuiltCell, the meta kept withmetaStateReads.ts, andformData.ts'slastMergesandValidatingForm. A new wrapper, mapping or copy made for a field's prop must be kept the same way.src/library/__tests__/*-budget.test.jscontracts count the renders a mount, an edit and a blur cost.jest.mockbefore naming a cause. A timing with and without a feature names none, as EPBDS-16211: a period table checked by notWithinRange no longer slows down with its rows #209 found.No code changes.
Base
This is built on #214, since it names
metaStateReads.ts, which #214 adds. It therefore targets #214's branch, and its diff is this section alone. Once #214 is merged, GitHub retargets it to master, and I will bring it up to date with master before it is merged.Gates
Documentation only. Nothing reads
CLAUDE.md: inscripts,srcande2e, two comments name it.git diff --checkis clean. The seven*-budget.test.jsfiles the section names exist on this branch. The gates of the code under it are those of #214.🤖 Generated with Claude Code