Skip to content

Merge driver for the sorted per-feature registries (dragon-sorted) - #190

Merged
thejackshelton merged 31 commits into
masterfrom
sorted-merge
Oct 5, 2026
Merged

thejackshelton merged 31 commits into
masterfrom
sorted-merge

Conversation

@thejackshelton

Copy link
Copy Markdown
Contributor

Two PRs that each add one line at the same sorted place in a per-feature registry (for example #176's env and #179's ctx-proof in packages/parity/src/fixtures.ts) conflict in git's line merge, and the landing driver ejects the second PR, costing a whole round. This adds a git merge driver, dragon-sorted (scripts/sorted-merge.ts), modeled on dragon-floor.

What it does

  • Runs git merge-file --diff3 -p of %O %A %B. A conflict hunk is resolved only when both sides keep every base line of the hunk, in order, and add only whole registry lines: a registry import (import { X } from './<dir>/<file>.ts';) outside the sorted block, or an entry of the sorted block ( id: X, / 'id': X,, or ...X_ANIMATION, in animation-kinds).
  • Added lines are merged per gap by the key the registry's test sorts by: the id for entries (quoted and unquoted alike, so contexts < 'ctx-proof' < env); the file name with .ts for fixture-groups and regen-steps imports (as registry-claims.test.ts sorts them); the feature id for the codes, faults and animation-kinds imports (their existing order, which no test pins). A line both sides added appears once.
  • Left as a conflict (exit 1, diff3 markers): a deletion, a modification, a key added with two contents, an added line that is not a registry line, a side whose own additions are unsorted, or a result whose import or entry list would not be strictly sorted. A file not in SORTED_REGISTRIES, a side without a final newline or with marker-like lines falls back to git's plain text merge, like floor-merge.
  • Marked merge=dragon-sorted in .gitattributes: packages/dragon/src/css/animation-kinds.ts, packages/dragon/src/diagnostics/codes.ts, packages/dragon/src/faults.ts, packages/parity/src/fixtures.ts, scripts/regen.ts (exactly the central lists registry-claims.test.ts in both packages holds sorted, one line per feature).
  • Registered by pnpm setup:git and in MERGE_DRIVERS (scripts/floor-merge.ts), which the landing driver's prepareWorktree already writes into the shared git config, so landing merges use it with no change to land.ts.

Tests

  • New packages/parity/test/sorted-merge.test.ts: the env/ctx-proof case for imports and GROUPS lines (both orders give the same file); the same insertion on both sides; several interleaved additions from each side; a modification on one side and a deletion on one side left as conflicts (other hunks still resolved); one id added with two contents; a non-registry added line; refused inputs; the driver inside a real git merge (and the same merge conflicting without it); the CLI writes %A whole with no temp file left; .gitattributes marks exactly SORTED_REGISTRIES; each real registry parses (block found, every block line an entry, imports and entries sorted by its key, one import per entry, self-merge is identity).
  • regen.test.ts merge-policy test: also skips the new merge=dragon-sorted lines (it already skipped dragon-floor; they are checked in sorted-merge.test.ts). No check removed.

End to end

Scratch worktree at origin/master (33efede) with the attributes committed and the driver configured, then git merge of origin/env-safe, origin/ctx-proof-rem, origin/ctx-proof-auto: all three merged with no conflict in any file; the last one printed sorted-merge: merged packages/parity/src/fixtures.ts (2 sorted hunk(s) interleaved) and gave contexts, 'ctx-proof', env in both the imports and GROUPS. With merge.dragon-sorted.driver=false the same last merge conflicts in fixtures.ts. Both registry-claims.test.ts files pass on the merged tree (18 tests).

Passed

  • pnpm typecheck: pass
  • vitest run packages/parity/test/sorted-merge.test.ts packages/parity/test/floor-merge.test.ts packages/parity/test/registry-claims.test.ts packages/dragon/test/registry-claims.test.ts: 52 passed
  • vitest run packages/parity/test/regen.test.ts -t "merge policy": 4 passed
  • Full pnpm test left to the landing driver (lane contract). No generated outputs change; no regen needed.

After this lands, run pnpm setup:git once per clone to register the driver (the landing driver does it itself).

🤖 Generated with Claude Code

thejackshelton and others added 30 commits October 5, 2026 09:53
…ated insets; native refused

The compiler accepts env(safe-area-inset-top|right|bottom|left), with an optional fallback, wherever a length
is accepted (alone, in shorthands, through var(), and inside calc(), min(), max() and clamp()). Web output keeps
env() as written. The value is keyed <env()>, so only env()'s own profile rows prove it; the web-only env
fixtures prove web rows under Emulation.setSafeAreaInsetsOverride, and native targets have no row, so they
refuse it until a native runtime reads the root view's insets. The native lowering to the engine's EnvLength is
proven at host level: the engine with the fixture's insets injected matches Chrome's capture.

Every other environment variable (safe-area-max-inset-*, keyboard-inset-*, unknown names with or without a
fallback, wrong case) and env() outside a length is refused with DRAGON_UNSUPPORTED_VALUE.

Planted faults: envResolvedToZero (chrome-dual), envSideSwapped (engine host test).
# Conflicts:
#	packages/parity/src/cli/capture.ts
… flex and positioned contexts

ctx-proof-rem (both directions): padding and min-height in rem on relative flex-row items, padding in rem on absolute
boxes, width, max-width, left and top in rem on flex-column items, min-width in rem on flex-row items. Passes
linux-dragon-layout and chrome-dual against live Chrome.
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: 4b975fe
Run: https://github.com/compiled-run/dragoncss/actions/runs/37329181178
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: 8b47a5c
Run: https://github.com/compiled-run/dragoncss/actions/runs/37335981744
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: f24f174
Run: https://github.com/compiled-run/dragoncss/actions/runs/37342969009
…ve flex-row items (review of #180)

A flex-start row: b3's content is 30px, so min-height: 2.5rem sets its 40px height; b4 (no min-height) is 42px from
padding-bottom: 1.5rem; b5 is 54px with padding-bottom: 1rem under a taller child. The stretched row r1 could not
detect an ignored min-height or a wrong rem padding-bottom.
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: cdd642a
Run: https://github.com/compiled-run/dragoncss/actions/runs/37346681984
… a literal name), and env() in @Keyframes

Review #176: a var() name made Dragon emit the inset where Chrome drops the declaration (or, through a custom property,
computes unset); a var() in a safe-area name's fallback is refused with what Chrome does (it renders the inset). env()
in a keyframe is refused until a frame fixture proves it. env-var.test.ts renders all five shapes in Chrome under insets.
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: cc53581
Run: https://github.com/compiled-run/dragoncss/actions/runs/37349291047
…registered fixtures, not a per-feature prefix list

Every new fixture group (CTX-PROOF #179/#180, WEBKIT-BOX #181) failed hit-capture-identity until it added its prefix to
IDENTITY_NEW, one shared line. The check now derives ownership from the fixture registry: an extra capture or emitted file
passes only when its name, less the ~ixN, #N and -rtl case suffixes, is a registered fixture id. Orphans still fail.
Commands: pnpm regen; pnpm run parity:devices; pnpm regen
CTX-PROOF 2/2: parity fixture proving rem lengths in the music player's flex and positioned contexts
@thejackshelton
thejackshelton merged commit 2e26b04 into master Oct 5, 2026
5 checks passed
@thejackshelton
thejackshelton deleted the sorted-merge branch October 5, 2026 21:43
thejackshelton added a commit that referenced this pull request Oct 5, 2026
…st) into form-a-v2. rt-animator.ts keeps both sides: findStyle and patchChild walk control boxes (FORM-a) and read and patch replaced leaves (master's img/iframe fix); rt-animator.test.ts imports both helpers
thejackshelton added a commit that referenced this pull request Oct 6, 2026
…st) into inl1a-lowering. hit-capture-identity.test.ts takes master's registered-fixture check and keeps INL1a's: no file beyond the base belongs to a base fixture (now judged by fixtureOf, which knows the ~ixN and #N suffixes). glyph-clearance-pins.json keeps both sides' entries. rt-animator.ts patchChild (master's replaced-leaf patch) takes INL1a's inline children and passes them through unchanged, as INL1a's patchBox did
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