Skip to content

Migrate field-create onto the field-add lifecycle driver#61

Merged
HynLcc merged 1 commit into
mainfrom
migrate-field-create-lifecycle
Jun 19, 2026
Merged

Migrate field-create onto the field-add lifecycle driver#61
HynLcc merged 1 commit into
mainfrom
migrate-field-create-lifecycle

Conversation

@HynLcc

@HynLcc HynLcc commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

What

Third and widest member of field-add-lifecycle.ts — 4 cases: 5 simple fields, 5 formula fields, mixed-19, and single-select with 1k options.

field-create seeds an empty (base-fields-only) table, adds N fields in one measured trace step with per-field engine routing, optionally polls until the formula columns finish their computed backfill (a DB aggregate over all rows), verifies the created fields and single-select options, then restores the seed by deleting the added (non-base) fields.

Unlike the prior two members its prepare is a single measured phase (prepareFieldCreate in execute; a synthetic zero-duration seedBuild/seedRestore in seed mode), so prepareFixture owns that measurement and parks its name+duration on the (mutable, in-place) fixture; buildResult rebuilds the prepare measurement from the live object after seedReady/backfill mutate it. The driver is unchanged — a third runner, with the most divergent shape yet, slots in with zero driver edits. Cleanup re-resolves created fields by "not a base field", the same invariant assertSeedReady already enforces.

diff-artifacts.mjs masks

All proven volatile by an unmodified-main baseline A vs B:

  • field-create generated field ids: createdFields[].id, ready.computedFields[].id, ready.dependencyFields[].id, the flat details.fieldIds list, and the compiled details.verifiedFields[].expression (embeds A/B/C ids), plus details.ready.dbTableName.
  • details.prepare.seedHash / seedTableName — the same content-addressed seed-cache key the cache.seedHash rule masks for other runners (stable run-to-run, moves only on refactor; the seed config that also feeds it is frozen because cases/** is untouched).

Field names and computedFields[].expectedKind keep the semantic identity visible.

Validation (local, all 4 cases, v1+v2)

  • Baseline A vs B clean after the noise masks.
  • pnpm check green.
  • G1 baseline vs candidate clean for all 8 artifacts.
  • Negative tests: phase / per-field routing.routeMatched / computed-backfill checks.mismatches / ready.totalRows / createdFields[].name / single-select verifiedOptions[].name drift all caught; only the seedHash + field-id keys ignored (over-mask check: createdFields[].name still caught).
  • Per-field routing asserts v2 actualXTeableV2=true, feature createField; formula backfill verified 10000/10000, 0 nulls / 0 mismatches.
  • Trace ref counts unchanged (6/6/20/2).
  • Shared driver untouched → no sibling regression needed.

Tracker: 22/35 runner kinds, 29/55 cases. This closes the field-add family campaign (conditional-lookup #59, field-duplicate #60, field-create here).

🤖 Generated with Claude Code

Third and widest member of field-add-lifecycle (4 cases: 5 simple, 5 formula,
mixed-19, single-select-1k-options). field-create seeds an empty base-fields-only
table, adds N fields in one measured trace step with per-field engine routing,
optionally polls until the formula columns finish their computed backfill (a DB
aggregate over all rows), verifies the created fields and single-select options,
then restores the seed by deleting the added (non-base) fields.

Unlike the prior two members its prepare is a single measured phase
("prepareFieldCreate" in execute, a synthetic zero-duration "seedBuild"/
"seedRestore" in seed mode), so prepareFixture owns that measurement and parks
its name + duration on the (mutable, in-place) fixture; buildResult rebuilds the
prepare measurement from the live object after seedReady/backfill mutate it. The
driver itself is unchanged — a third runner, with the most divergent shape yet,
slots in with zero driver edits. Cleanup re-resolves the created fields by "not a
base field", the same invariant assertSeedReady already enforces.

diff-artifacts.mjs: mask field-create's generated field ids (createdFields[].id,
ready.computedFields[].id, ready.dependencyFields[].id, the flat details.fieldIds
list, and the compiled details.verifiedFields[].expression which embeds A/B/C
ids) plus details.ready.dbTableName — all proven volatile by an unmodified-main
baseline A vs B. Also mask details.prepare.seedHash / seedTableName, the same
content-addressed seed-cache key the cache.seedHash rule masks for other runners
(stable run-to-run, moves only on refactor; the seed config that also feeds it is
frozen because cases/** is untouched). Field names and computedFields[].expectedKind
keep the semantic identity visible.

Validation (local, all 4 cases, v1+v2): baseline A vs B clean after the noise
masks; pnpm check green; G1 baseline vs candidate clean for all 8 artifacts;
negative tests confirm phase / per-field routing / computed-backfill
checks.mismatches / ready.totalRows / createdFields[].name / single-select
verifiedOptions drift is caught while only seedHash and field-id keys are ignored;
per-field routing asserts v2 actualXTeableV2=true, feature createField; formula
backfill verified 10000/10000 with 0 nulls/0 mismatches; trace ref counts
unchanged (6/6/20/2). Shared driver untouched, so no sibling regression needed.

Tracker: 22/35 runner kinds, 29/55 cases.

Co-Authored-By: Claude <noreply@anthropic.com>
@HynLcc HynLcc merged commit f794f74 into main Jun 19, 2026
6 checks passed
@HynLcc HynLcc deleted the migrate-field-create-lifecycle branch June 19, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant