Repository navigation
Conversation
skrawcz
left a comment
There was a problem hiding this comment.
AI-assisted preliminary review — findings must be fixed or technically refuted before human review.
The glossary and developer-guide cleanup are useful, and historical decision records could help contributors. The combined PR currently needs significant restructuring. It introduces 2,600+ lines of custom executable verification tooling plus 25 duplicated CI recipes, eight reconstructed ADRs marked Accepted, and unrelated documentation fixes in one 47-file change.
Concrete blockers reproduced during the AI-assisted review:
- No PR workflow runs for these changed paths.
node --test scripts/verify.test.mtsfails on macOS path canonicalization (19 passed, 1 failed:/tmpvs/private/tmp, likewise/var/folders).- The Apache sdist ships
scripts/verify*withoutverification/, so the released command has no settings/recipes and is incomplete. - The reconstructed ADRs are marked
Acceptedeven where rationale/alternatives were not recovered and no current public acceptance is cited.
Please split docs/glossary, proposed ADRs, and verification tooling. ADRs should remain proposed until publicly accepted with stable source links. If maintainers choose to own the harness, wire its tests into CI, make them cross-platform, and ship a complete runnable system or exclude it from the sdist. If keeping this combined approach, each point needs a technical/governance refutation.
The first of three stacked pull requests split out of apache#1806 at the review's request; the decision records and scripts/verify follow on top of it. CONTEXT.md records eight terms where ordinary usage or generic tool knowledge misleads, such as "adapter", which names three different things, and the default result builder, which differs between Driver and driver.Builder. Each term names the code it describes. CONTRIBUTING.md gains a "Finding your way around" section that points at it. The documentation fixes: - CONTRIBUTING.md linked the developer setup guide by a path that does not resolve, said "getting setup", and described CircleCI, which the project no longer uses. - README.md's link to the developer setup guide did not resolve. - writeups/developer_setup.md installed with `pip install '.[dev,test]'`, which installs neither the dev nor the test dependency group, and its test section described CircleCI, .ci/ scripts and requirements-test.txt, none of which exist. It now installs with `uv sync --group test` and says where CI's exact commands live. - The SQL lineage records 2609-02 and 2609-03 now cite each other by their own numbers.
The second of three stacked pull requests split out of apache#1806 at the review's request, on the glossary and documentation fixes. writeups/adr/2611-02 to 2611-09 record why Hamilton's foundations are as they are: functions define nodes; function modifiers resolve in a fixed lifecycle; deprecations follow a warn/fail version contract; integrations load through an autoloaded registry; data I/O goes through registered loaders and savers; lifecycle adapters replace graph adapters; packages ship as apache-hamilton* with sf-hamilton* redirects; released artifacts do not phone home. Each record was written after the fact, from the code, its commits, the pull requests that carried them (on stitchfix/hamilton for those from before 2023), their issues, and the Incubator mailing-list threads. Its status is `Reconstructed from codebase`, which writeups/adr/README.md adds to its list: the record documents a decision the code already embodies, names where that decision was made, and claims no acceptance of the record itself. What those discussions recorded about rationale, alternatives and consequences is quoted and linked; where they recorded nothing, the record says so. Every source is linked by a stable URL: pull requests and issues by full URL, commits by full SHA, and file:line citations as permalinks at a commit on main. CONTEXT.md links the function-modifier record, and CONTRIBUTING.md points at the records.
…e per area The top of three stacked pull requests (apache#1806), on the glossary and the decision records. Each recipe under verification/recipes names the paths it covers and runs the same commands as its step in .github/workflows/hamilton-main.yml: the suite recipe has one scenario per CI step, the area recipes run a step or a scoped part of the main test step, and ci-canary rehearses the workflow's daily schedule and Slack report under act. `scripts/verify affected` names the recipes a change touches, `scripts/verify drive` runs them and keeps their output on this machine, and `check` and `doctor` validate the recipes and their prerequisites. It needs Node 22.18 or newer and no dependencies; CI does not run it. CONTRIBUTING.md and the developer setup guide mention it as optional. The verify-tool recipe runs the tool's own Node tests (scripts/verify.test.mts); verification/scripts/check_recipes_match_ci.py, which fails when a suite scenario stops running its workflow step's commands, when its Python version check stops matching the Pythons its step's if: condition runs on, or when an area recipe stops matching the suite scenario it copies; that script's tests; doctor; and an sdist scenario. Answering the review: - The Node tests reach every fixture project through a symbolic link and expect the canonical path, so the macOS failure (/tmp is /private/tmp) is checked on Linux too. - [tool.flit.sdist] excludes scripts/verify, scripts/verify.mts and scripts/verify.test.mts by name, since the source release leaves out verification/ and .github/, which they read. The sdist scenario fails if any of the three ships, or if a tracked file that shares the prefix, such as verify_apache_artifacts.py, goes missing. Also: a front-matter key the harness does not read is refused, so a misspelled ask-first cannot drive without asking; doctor reads the test job's Python matrix from the workflow (verification/scripts/doctor.sh) and fails a .venv on a Python CI does not test; and the recipes point at the workflow and tests/conftest.py rather than copying their versions.
c91d9c5 to
d58764a
Compare
|
This was split into three stacked pull requests, one commit each:
|
The problem: a contributor, person or AI agent, can't tell from the repository which of CI's commands check a given change: each plugin's extras and installs are spread across
.github/workflows/hamilton-main.yml, so contributors guess, run the wrong subset, or push and wait for CI.What changes:
scripts/verify, one command with a recipe per area underverification/, most running their CI step's commands or a slice of the main test step:affectednames the recipes a change touches, anddrive <recipe>runs one. It is optional, needs only Node 22.18 or newer, and adds no CI job. Nothing underhamilton/,tests/or.github/changes;pyproject.tomlgains three source-release excludes, so CI runs here. Since the review, the macOS test failure and the sdist packaging are fixed.Where this sits: split at the review's request into three stacked pull requests, one commit each:
They merge bottom-up, each rebased onto
mainafter the one below lands; until then GitHub shows the lower commits here too.Shown working:
check,doctor, the lint andverify-toolpass at d58764a; every recipe was driven and passed, except two left to CI; the checks for both fixes fail when a fix is undone; CI passed (Unit Tests, Contrib Test Workflow). Details under How I tested this.Decisions (no decision record is reopened; reasons are folded below):
main's workflow, not the lockfile change in Commit uv.lock and install CI's test dependencies from it #1807.recipes-match-cichecks the recipes against the workflow.ci-canaryships, not marked ask-first.Awaiting the author, raised in the review: whether to add a CI job for the harness.
Debt left: two recipes didn't run here, polars ran on a stand-in, the recipes copy CI's commands, two parsers read the recipes, the redirect packages and
contrib/have no area recipe, and two workflow issues sit outside this change; all six are at the end.Before and after (an illustrative example). Task: check a change to the polars plugin before pushing it.
hamilton-main.ymlfor the steps that touch polars, copy each one'suv syncextras anduv pip installlines into a shell, and hope you found them all, or you push and wait for CI.scripts/verify affectednamesh_polars,plugin-extensionsandsuite;scripts/verify drive h_polarsruns the same commands as CI's polars steps, says which scenario failed, and keeps its output.Decisions, with their reasons
main's workflow as it is, with itsuv pip installsteps and no lockfile, rather than the lockfile change in Commit uv.lock and install CI's test dependencies from it #1807. Whichever of the two lands second updates the recipes.recipes-match-ci), including the Pythons each step'sif:runs it on, rather than relying on someone remembering to copy each change.tests/conftest.pydeclare versions (a step'sif:, the test job's matrix,collect_ignore) rather than restating them.verify doctorreads the matrix through the drift check's own parser.ci-canaryrehearsal ships with the rest. It needs Docker and act, but it posts only to a local stub and reads one public run without credentials, so it is not marked ask-first.scripts/verify*glob would also dropverify_apache_artifacts.pyand the other release files that share the prefix.What changes, in full
scripts/verifyis a launcher that checks the Node version and startsscripts/verify.mts, a dependency-free TypeScript file Node runs directly. It is adapted from manifest-dev 14.20.1's default harness, which ships no tests. Its header lists what was changed for Hamilton: the license comment before each recipe's front matter,upstream/mainbeforeoriginas the default base, front-matter errors that name their file, a refusal of front-matter keys it does not read, and the exit-code help.verification/holds:harness.md: the settings and what every recipe assumes.suite, with one scenario per workflow step.ci-canary, which rehearses the workflow's daily schedule, fork guard and Slack report under act.verify-tool, which checks the harness itself: its settings and recipes,doctor, its Node tests, the drift check and its tests, and the source release.scripts/ci_canary_rehearsal.py: the act rehearsal. It stubs every job but the Slack notifier, compares the jobs that ran with the expected set exactly, and treats a missing Docker daemon, network orjqas unreachable rather than failed.scripts/check_recipes_match_ci.pyand its 51 tests.scripts/doctor.sh, whichverify doctorruns.verifycreatesverification/evidence/with its own.gitignoreon first use, so drive output stays on the machine that ran it.scripts/verify.test.mts: 22node --testtests ofcheck,affectedanddriveon temporary fixture projects, each reached through a symbolic link.pyproject.toml:[tool.flit.sdist]excludesscripts/verify,scripts/verify.mtsandscripts/verify.test.mts.CONTRIBUTING.mdgains thescripts/verifybullet under "Finding your way around", andwriteups/developer_setup.mdone paragraph mentioning it as optional.Harness issues also fixed while answering the review
h_polarsdidn't cover the polars 2 readersmainadded, soverify affectednamed nothing for a change to them, and its list of loader kinds left out ndjson.verifyignored front-matter keys it doesn't read, so a recipe that misspelledask-firstdrove without asking.runner.oscase-sensitively, accepted a Python version check as the check for a step's system packages, and crashed on a step whose run holds only apt lines, and its test of the committed tree accepted a count of zero scenarios.verify doctorpassed a.venvon a Python CI doesn't test. It now fails it.mainremoved the exit-5 hook), called every check adopted from the workflow without exceptingverify-tool's own, and said nothing about the redirect packages' test orhamilton-contrib.yml, which now runs on pull requests.How I tested this
All runs used Python 3.14 on Linux. The recipe drives ran at c91d9c5, this branch's head before the split; between it and d58764a only Markdown under
writeups/adr/differs, which no recipe reads apart from the lint, so the drives at c91d9c5 still apply;check,doctor, the lint andverify-toolwere also run again at d58764a.openlineage(no PostgreSQL server here) andvaex(CI runs it on 3.11 and 3.12 only) stop as unreachable here; CI ran both on d58764a. This machine's CPU lacks AVX2, so polars ran on its compat runtime: a shim outside the repository installedpolars-runtime-compatof the same polars version after eachuv syncanduv pip install. CI runs the standard build.check,doctor, the repository lint andverify-tool, at d58764aRecipes driven and their results, at c91d9c5
Each is
scripts/verify drive <recipe> [scenario]; the drive keeps its full output on this machine underverification/evidence/. Polars ran onpolars-runtime-compatof the same version, because this CPU lacks AVX2; dependencies were resolved fresh, as CI resolves them. At c91d9c5,.venvran Python 3.14, anddoctorreported "one CI tests (3.11 3.12 3.13 3.14 3.15)".suite static-checkssuite mainsuite integrationssuite mcpsuite pandassuite polarssuite polars-1xsuite narwhalssuite dasksuite raysuite pysparksuite openlineage,openlineagesuite vaex,h_vaexcachingclidata-qualitydriverexecutionexperimentalfunction-modifiersgraphh_daskh_narwhalsh_pandash_polarspolars11 passed;extensions128 passed;polars-1x80 passed, 9 skipped, 39 xfailedh_rayh_sparkiolifecyclemcppanderaplugin-extensionsregistryverify-toolcheck;doctor; 22 Node tests;recipes-match-ci; its 51 tests;sdistci-canaryThe two fixes, at d58764a
The macOS test failure. Every fixture is reached through a symbolic link, as
/var→/private/varis on macOS:The source release.
uv build --sdistapplies the same[tool.flit.sdist]rules as the release'sflit build --no-use-vcs:The drift check fails when the recipes fall out of step
Each of the drift check's 51 tests plants one mismatch in a copy of the recipes or the workflow and asserts every line the check prints. Two planted changes in a scratch copy:
CI on this pull request
The
pyproject.tomlchange puts this pull request insidehamilton-main.yml'spull_requestfilter, so the full matrix runs on it, andhamilton-contrib.ymlruns too.contrib/testson Python 3.11 to 3.15. Notify Slack is skipped, as it is on every pull request.writeups/adr/, both passed too: Unit Tests, Contrib Test Workflow.Debt left
openlineage(no PostgreSQL server here) andvaex(CI runs it on Python 3.11 and 3.12 only; the drives used 3.14). Both stop as unreachable here; CI ran both on d58764a, and they passed.recipes-match-cinames every copy that drifts, but someone still makes the edit.scripts/verify.mtsand the drift check each parse the front matter and scenarios their own way.contrib/have no area recipe. Onlysuitecovers them, and no recipe adoptshamilton-contrib.yml; the harness notes say which test checks each.sh, and every job carries a hand-copied fork guard. Both are in.github/, which this pull request doesn't change. The canary rehearsal fails if a job is added without the guard, which limits the second.