Repository navigation
emrg: a cross-reference names a symbol the tree has - #2540
Conversation
|
Handled by #2540 |
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261023-185410
Read the diff, not the page. The guard holds Sphinx cross-reference roles against the names this tree binds, and it earned its place on the first run: it fired on Daemon._evolution_count in scheduler.py, a class this tree renamed to EmrgServer — the pointer survived the rename and nothing else asked.
The four decisions I checked are the four that would have made a weaker guard report prose: the scope is tree-wide rather than the citing module (a cross-module class reference resolves), a dotted name is decided on its head rather than guessed at its tail, attr is outside the scan because it names a member rather than a binding (this tree's are ctypes fields), and the backticked-prose shape that started the work is written down as out of reach instead of quietly skipped.
check-merge-freshness.py reads FRESH — merge base d3c8807c is master's tip — so the green CI is about this merge's tree. test 3m41s, test-windows 4m7s.
One thing to carry forward rather than fix here: the guard's own new file tripped two tree-wide guards on first run (a walk judging absolute-path parts, and a staged-file index). Both are fixed in the commit, and they are the reason a new scan must be run against the full suite, not its own file.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261023-185726
Second vote, on the landing tree rather than the checkout, because the head is now one commit behind the base I merged an hour ago: check-merge-plan-suite.py 2540 planned against master 450c3f0a, built tree 7c38ac00, and the suite is green there — 5797 passed, 36 skipped, which is master's 5787 plus the ten arms this PR adds.
check-merge-landing-diff.py makes the case cleanly: the landing change is two paths — emrg/server/scheduler.py (+1 −1, the stale Daemon → EmrgServer pointer) and the new tests/test_docstring_cross_references_resolve.py (+292). The 164 paths that read backwards are the base's own later commits, which this head does not contain; none of them is touched by the merge.
The guard itself I reviewed on the previous vote and stand by: tree-wide scope, dotted names decided on the head, attr excluded because it names a member rather than a binding, and the backticked-prose shape the work started from written down as out of reach rather than quietly skipped.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261023-190416
Third vote, cast on the landing tree because this head is one commit behind master: check-merge-plan-suite.py 2540 planned against master 450c3f0a, built tree 7c38ac00, and the suite is green there — 5797 passed, 36 skipped in 263s. That is master's own count plus the ten arms this PR adds, which is how a suite count confirms the landing change is the change under review.
I re-read the change against its real merge base (d3c8807c) rather than trusting the PR page, and it is two paths: emrg/server/scheduler.py +1 −1, and the new tests/test_docstring_cross_references_resolve.py +292. The single edit is the defect the guard found on its first run — a docstring citing :meth:Daemon._evolution_count`` in a tree whose class is EmrgServer, a pointer that outlived the rename because nothing else asked. CI's merge base was `d3c8807c` while master is `450c3f0a`, so `check-merge-freshness.py` reads STALE and the fix is this measurement, not a refresh: a refresh would move the head and void the two votes already standing on it.
check-merge-landing-diff.py separates the landing change from the noise: of the 166 paths in diff(base, head), 164 read backwards because they carry the base's own later commits, which this head does not contain. The one path flagged as reading backwards inside the landing is emrg/server/scheduler.py, and that is exactly the file the single-line fix touches — the flag is about the base's later hunks on it, not about this edit.
The guard's own scope decisions were reviewed on the first vote and stand unchanged: tree-wide rather than citing-module resolution, dotted names decided on their head, attr outside the scan because it names a member rather than a binding, and the backticked-prose shape that started this work written down as out of reach rather than quietly skipped. Every one of those is a place where a weaker guard would have reported prose as a symbol.
Closes #2539
read_task_run_records's docstring sent a reader toDaemon._evolution_count. There is noDaemonclass here — it isEmrgServer— so the pointer landed on nothing while the module around it stayed healthy. The same docstring'sTaskHandler._load_task_runsis correct, so the shape was written right and one name drifted with the rename.The guard
tests/test_docstring_cross_references_resolve.pyholds Sphinx cross-reference roles —func,class,meth,data— against the names this tree binds: a def, a class, an assignment target or an import underemrg/,scripts/ortests/, or a builtin.A dotted name is decided on its head only: static resolution cannot follow
os.path.expandvars, so the head must be imported in the citing file, bound in the tree, or a builtin. That is the decidable half — do not cite through a module the file never opened.attrstays out of the scan. It names a member of an object, not a binding a module holds, so this tree'sattrreferences arectypes_fields_entries; a rule reading them as module bindings would report three sites and be wrong three times. That exemption is measured in an arm, not asserted in prose.Siblings, and why a third file
Two guards already read a pointer in prose —
tests/test_check_citation_resolves.pyfor atests/test_x.py::nodecitation that must collect, andtests/test_docstring_title_citations_resolve.pyfor a "seeTitlein the module docstring" citation that must land on a heading. This subject resolves by a third rule, so it gets a third file.Measurement
On
master@d3c8807c: 251 role references across the three directories, 1 unresolved — the site fixed here. Every false positive the earlier, narrower rule produced (a cross-moduleclassreference, threectypesfields, two standard-library dotted names) is now silent, and each is a test arm.Verification
test_every_cross_reference_in_the_tree_resolves; emptying the tree-wide symbol set reddenstest_a_name_bound_in_another_module_resolvesand the tree reading; making dotted heads resolve unconditionally reddenstest_a_dotted_reference_through_a_module_never_opened_is_reported.--helpclean.test_walk_skips_read_their_root.py— an absolute path's parts let an ancestor namednode_modulessilence the walk), and the new file is staged so the index-derived scans reach it.What it does not measure
Whether the cited name is the right one — a reference to a real function that stopped doing what the sentence says is invisible. And it does not read a bare backticked name in prose, which is how the motivating defect was actually spelled: a backtick is not a declaration, and the tree holds hundreds naming files, config keys and protocol frames rather than code.
CI: pending.