Skip to content

chore: record the fork's conventions where agents will read them - #53

Merged
anoop-narang merged 3 commits into
mainfrom
chore/fork-conventions
Sep 24, 2026
Merged

anoop-narang merged 3 commits into
mainfrom
chore/fork-conventions

Conversation

@anoop-narang

Copy link
Copy Markdown
Collaborator

Nothing in this repo says it is a fork. AGENTS.md and README.md are upstream's and describe the project itself, so an agent arriving here sees an ordinary liquid-cache checkout and learns the rest by breaking something.

Two files, neither of which upstream has — which is the point. A convention written into an upstream-owned file conflicts on every sync; a file upstream will never create cannot.

CLAUDE.md — read automatically, states only what differs here:

  • main is upstream 0033b15 plus our patches
  • work off main, and git fetch first — a stale local main gives no signal
  • upstream PRs branch from upstream under upstream/<topic>, never from main
  • cargo +1.96.0; the default fails resolution on the vortex deps
  • the shuttle feature needs a shuttle_ filter, or ~49 unrelated tests fail by design
  • dev-tools needs a generated assets/tailwind.css, and habitually passing --exclude dev-tools hides real failures
  • after a structural edit, compare the test inventory, not the pass count — a #[cfg(feature = "shuttle")] test can be deleted without moving the default total
  • the disk reclaim race is known and open; do not re-report it

.github/workflows/upstream-branch-guard.yml — enforces the branch rule instead of trusting it. main is upstream plus our patches, so a correct upstream/** branch cannot have main in its ancestry. One merge-base --is-ancestor tests that directly, rather than a proxy like which files are present. Runs on push, so the author finds out before a PR exists.

The failure output explains rather than rejects — what was detected, why it matters (the reviewer gets a diff far larger than the change, mixed with work never meant for them), and the commands to redo the branch and to self-check before pushing.

Both paths were executed against real branches, not assumed:

chore/fork-conventions               -> exit 1, full explanation
upstream/keep-column-free-conjuncts  -> exit 0, "does not contain our main"
fork/main                            -> exit 1
upstream 0033b15                     -> exit 0

Nothing in this repo said it was a fork. `AGENTS.md` and `README.md` are
upstream's and describe the project, so an agent arriving here saw an
ordinary liquid-cache checkout and had to learn the rest by breaking
something: branching off a stale local `main`, cutting an upstream PR
from our `main` and carrying the whole patch stack into it, or
re-reporting the reclaim race as new.

`CLAUDE.md` is a file upstream does not have, which is the point. A
convention recorded in an upstream-owned file conflicts on every sync,
and this fork has already paid enough for history problems. Adding a
file upstream will never create cannot conflict.

It states what differs here and nothing else: that `main` is upstream
plus our patches, that upstream PRs branch from upstream under
`upstream/<topic>`, that the toolchain is `cargo +1.96.0`, that the
shuttle feature has to be run with a `shuttle_` filter or ~49 unrelated
tests fail by design, that `dev-tools` needs a generated asset, and that
the disk reclaim race is known and open.

The guard workflow enforces the branch rule rather than trusting it.
`main` is upstream plus our patches, so a correct `upstream/**` branch
cannot have `main` in its ancestry; one `merge-base --is-ancestor` tests
exactly that, and tests the real property rather than a proxy like which
files are present. It runs on push, so the author learns before a PR
exists.

Its failure output explains rather than rejects: what was detected, why
it matters — the reviewer sees a diff far larger than the change, mixed
with work never meant for them — and the commands to redo the branch
from upstream and to check before pushing. Both paths were run against
real branches: this one fails, and `upstream/keep-column-free-conjuncts`
passes.
@anoop-narang
anoop-narang requested a review from a team as a code owner September 24, 2026 13:26
@anoop-narang
anoop-narang requested review from eddietejeda and removed request for a team September 24, 2026 13:26
Comment thread .github/workflows/upstream-branch-guard.yml Outdated
Comment thread .github/workflows/upstream-branch-guard.yml Outdated
Comment thread CLAUDE.md Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — Blocking Issues: (1) .github/workflows/upstream-branch-guard.yml:28: The ancestry test checks only the current tip of main. A branch cut from main before a later merge passes the guard, even though the branch carries fork patches. (2) .github/workflows/upstream-branch-guard.yml:71: The "must print nothing" self-check excludes every commit in our main. The check never shows fork patches, and it always prints the author's own commits.

Action Required: Test whether git merge-base HEAD origin/main is an ancestor of upstream's main. Fetch upstream in the job to run the test. Replace the self-check command with the same merge-base test, or with git log FETCH_HEAD..HEAD plus correct wording.

CI checks were still queued or in progress when this review started. This review makes no claim about CI results.

…s tip

Review found the guard passes the case it exists for.

It asked `git merge-base --is-ancestor main HEAD`, which tests whether a
branch contains `main`'s *current* tip. `main` moves with every merge, so
a branch cut from `main` last week has today's tip nowhere in its history
and the check reported "OK". Verified: a branch at `9298d97`, our own
main a few hours ago, passed while carrying 19 fork commits. Every case I
tested cut from the tip as it stood, which is the one arrangement where
the wrong test gives the right answer.

Test the merge base instead. A branch cut from upstream shares only
upstream history with `main`, so that point is a commit upstream has; a
branch cut from `main` shares a fork commit, and upstream never contains
one. Run against six refs — upstream's tip, a branch off upstream, our
main's tip, our main as of two merges ago, a commit mid fork history, and
this branch — it is right on all six.

The self-check printed in the failure was wrong in the same spirit.
`git log origin/main..HEAD ^FETCH_HEAD` excludes everything reachable
from `main`, which is every fork patch, so it lists the author's own
commits on a clean branch and a contaminated one alike. It can never be
empty, and the instruction said it must be. Now
`git log FETCH_HEAD..HEAD`, described as what it is: a list that should
contain only your own commits.

The failure also now names the branch point, the upstream tip, how many
fork commits are carried and the first five of them, rather than
asserting that some are.

`CLAUDE.md` said `git fetch fork`, which is one local remote naming and
not what a fresh clone has. It says `origin` and notes the alternative,
and carries the corrected self-check.
Comment thread CLAUDE.md
claude[bot]
claude Bot previously approved these changes Sep 24, 2026
`FETCH_HEAD` holds whatever the last fetch wrote. The bullet above tells
the author to fetch their own remote, and after that `FETCH_HEAD` is our
`main` — so `git log FETCH_HEAD..HEAD` would exclude every fork patch and
show a contaminated branch as clean. The workflow's copy already repeated
the fetch; this one now does too.
@anoop-narang
anoop-narang merged commit 3ee236d into main Sep 24, 2026
13 checks passed
@codecov

codecov Bot commented Sep 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

📊 Benchmark Comparison

Current: 7d2686aa (Liquid) vs Baseline: 7d2686aa (DataFusionDefault)

Query Cold Time Δ Warm Time Δ CPU Time Δ
Q1 2.0ms (2.0ms) +0.0% 0.000ms (0.000ms) +0.0% 0.000ms (0.000ms) +0.0%
Q2 7.0ms (6.0ms) +16.7% 4.0ms (5.0ms) -20.0% 7.0ms (7.0ms) +0.0%
Q3 19.0ms (12.0ms) +58.3% 5.5ms (12.0ms) -54.2% 4.0ms (22.5ms) -82.2%
Q4 13.0ms (12.0ms) +8.3% 3.5ms (11.0ms) -68.2% 3.0ms (23.5ms) -87.2%
Q5 53.0ms (54.0ms) -1.9% 45.5ms (51.0ms) -10.8% 4.5ms (24.0ms) -81.2%
Q6 211.0ms (109.0ms) +93.6% 70.5ms (105.5ms) -33.2% 23.0ms (81.0ms) -71.6%
Q7 1.0ms (1.0ms) +0.0% 0.000ms (0.000ms) +0.0% 0.000ms (0.000ms) +0.0%
Q8 7.0ms (5.0ms) +40.0% 5.0ms (5.5ms) -9.1% 9.0ms (6.0ms) +50.0%
Q9 91.0ms (91.0ms) +0.0% 74.5ms (84.0ms) -11.3% 6.0ms (44.0ms) -86.4%
Q10 96.0ms (85.0ms) +12.9% 71.0ms (87.0ms) -18.4% 6.5ms (61.5ms) -89.4%
Q11 38.0ms (26.0ms) +46.2% 20.0ms (25.0ms) -20.0% 37.0ms (35.0ms) +5.7%
Q12 40.0ms (32.0ms) +25.0% 19.5ms (30.5ms) -36.1% 35.5ms (44.5ms) -20.2%
Q13 208.0ms (113.0ms) +84.1% 84.0ms (108.5ms) -22.6% 48.0ms (84.5ms) -43.2%
Q14 483.0ms (142.0ms) +240.1% 126.0ms (139.0ms) -9.4% 66.5ms (107.0ms) -37.9%
Q15 411.0ms (102.0ms) +302.9% 111.0ms (99.5ms) +11.6% 67.5ms (94.0ms) -28.2%
Q16 116.0ms (108.0ms) +7.4% 120.5ms (106.0ms) +13.7% 5.5ms (25.5ms) -78.4%
Q17 647.0ms (212.0ms) +205.2% 244.0ms (206.0ms) +18.4% 77.5ms (104.0ms) -25.5%
Q18 694.0ms (208.0ms) +233.7% 259.5ms (209.0ms) +24.2% 97.5ms (103.5ms) -5.8%
Q19 1.04s (428.0ms) +142.8% 516.5ms (386.5ms) +33.6% 104.5ms (146.0ms) -28.4%
Q20 17.0ms (13.0ms) +30.8% 4.5ms (11.5ms) -60.9% 8.5ms (24.5ms) -65.3%
Q21 700.0ms (169.0ms) +314.2% 470.0ms (172.5ms) +172.5% 303.5ms (265.0ms) +14.5%
Q22 896.0ms (165.0ms) +443.0% 611.5ms (162.0ms) +277.5% 173.0ms (338.0ms) -48.8%
Q23 1.81s (456.0ms) +296.1% 1.70s (467.5ms) +262.6% 574.5ms (732.5ms) -21.6%
Q24 23.95s (883.0ms) +2612.2% 979.0ms (904.5ms) +8.2% 616.0ms (2.50s) -75.3%
Q25 310.0ms (67.0ms) +362.7% 17.0ms (57.5ms) -70.4% 48.0ms (118.0ms) -59.3%
Q26 129.0ms (46.0ms) +180.4% 18.5ms (47.5ms) -61.1% 52.0ms (86.0ms) -39.5%
Q27 287.0ms (56.0ms) +412.5% 25.5ms (57.5ms) -55.7% 74.0ms (118.0ms) -37.3%
Q28 787.0ms (221.0ms) +256.1% 944.5ms (211.5ms) +346.6% 222.0ms (270.5ms) -17.9%
Q29 1.39s (989.0ms) +40.5% 963.0ms (988.0ms) -2.5% 394.5ms (338.0ms) +16.7%
Q30 29.0ms (44.0ms) -34.1% 22.0ms (27.0ms) -18.5% 7.0ms (21.5ms) -67.4%
Q31 660.0ms (110.0ms) +500.0% 78.5ms (100.0ms) -21.5% 76.5ms (141.0ms) -45.7%
Q32 967.0ms (99.0ms) +876.8% 150.0ms (96.5ms) +55.4% 114.0ms (147.5ms) -22.7%
Q33 315.0ms (349.0ms) -9.7% 286.0ms (327.0ms) -12.5% 9.0ms (68.5ms) -86.9%
Q34 757.0ms (401.0ms) +88.8% 463.5ms (382.0ms) +21.3% 138.5ms (267.5ms) -48.2%
Q35 804.0ms (392.0ms) +105.1% 458.0ms (385.0ms) +19.0% 141.0ms (268.0ms) -47.4%
Q36 105.0ms (116.0ms) -9.5% 93.5ms (96.0ms) -2.6% 5.0ms (24.0ms) -79.2%
Q37 303.0ms (95.0ms) +218.9% 76.5ms (92.5ms) -17.3% 29.0ms (68.5ms) -57.7%
Q38 73.0ms (42.0ms) +73.8% 27.5ms (42.5ms) -35.3% 17.0ms (23.0ms) -26.1%
Q39 279.0ms (44.0ms) +534.1% 35.0ms (47.0ms) -25.5% 20.0ms (72.0ms) -72.2%
Q40 691.0ms (178.0ms) +288.2% 232.5ms (170.0ms) +36.8% 63.5ms (121.5ms) -47.7%
Q41 24.0ms (28.0ms) -14.3% 10.0ms (18.0ms) -44.4% 7.0ms (16.0ms) -56.2%
Q42 21.0ms (17.0ms) +23.5% 10.5ms (17.5ms) -40.0% 8.0ms (15.0ms) -46.7%
Q43 17.0ms (18.0ms) -5.6% 11.0ms (15.5ms) -29.0% 7.0ms (11.5ms) -39.1%

⚠️ LiquidCache is slower on 11 queries (warm)

  • Q28: warm +346.6% (944.5ms vs 211.5ms)
  • Q22: warm +277.5% (611.5ms vs 162.0ms)
  • Q23: warm +262.6% (1.70s vs 467.5ms)
  • Q21: warm +172.5% (470.0ms vs 172.5ms)
  • Q32: warm +55.4% (150.0ms vs 96.5ms)
  • Q40: warm +36.8% (232.5ms vs 170.0ms)
  • Q19: warm +33.6% (516.5ms vs 386.5ms)
  • Q18: warm +24.2% (259.5ms vs 209.0ms)
  • Q34: warm +21.3% (463.5ms vs 382.0ms)
  • Q35: warm +19.0% (458.0ms vs 385.0ms)
  • Q17: warm +18.4% (244.0ms vs 206.0ms)

Compared Liquid vs DataFusionDefault on the same runner
Regressions: warm-time increases of at least 15%. Cold Time: first iteration; Warm Time: median of remaining iterations.

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