test: a test file documented outside the numbering is invisible (#1024) - #1066
Conversation
…andprompt#1024) commandprompt#1024 reports that two PRs adding a test file both take the next section number, the merge keeps both, and nothing notices. MEASURED ON `52511a7`, THE FIRST HALF IS NO LONGER TRUE: `test_the_contents_list_is_numbered_in_order` landed after commandprompt#1023 and catches exactly that. Planted a duplicate and it reddens, naming the inversion. So this does not drop the numbers, which was the issue's preferred option. Dropping them would remove the subject of a guard that works, and it costs more than the issue estimated -- 37 headings, 37 contents links, and THREE prose self-references the "one sed plus the anchors" figure misses. The other 26 `section N` references in the file name VACUITY_MODES.md's sections and are unaffected, which is why they have to be classified rather than counted. WHAT IS STILL OPEN IS A DIFFERENT SHAPE, and I shipped it. A test file whose section is written as an unnumbered `###` instead of a numbered `##` is invisible to every arm: not in the numbering so `1..N with no gap` never sees it not in the contents so the link arms never see it still NAMED so the coverage arm is satisfied `test_iceberg_fdw.py` went in that way in commandprompt#1057 and sat undetected. Planted as a mutation it is caught by nothing before this change: 36 passed. It is also a cheaper failure than the collision. The collision needs two PRs in flight; this needs one person writing a heading at the wrong level. test files on disk 33 with a NUMBERED ## section 32 with an unnumbered ### section 1 <- test_iceberg_fdw.py, the defect So the rule was already true everywhere else, which is why it can be asserted rather than declared as a goal. `test_iceberg_fdw.py` becomes section 37 where it already sits in the body, and `test_hilbert_cluster.py` moves to 38 -- body order and numbering must agree, because the commandprompt#1023 arm checks for inversions as well as gaps. Removal proof: CONTROL 37 passed M1 a section demoted to an unnumbered ### 1 failed <- the new arm, alone M2 a DUPLICATE section number 2 failed <- commandprompt#1023's arm, still working TESTS.md restored to 70a78a69 M2 is in the proof deliberately: this change must not weaken the guard it found already working. Asserted in both directions, so a section cannot outlive the file it documents. guard leg 341 passed, 870 checks, 0 fail `guard_tests` 340 -> 341 by collection. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012RSw4qMHS7ByE7PY8Ns4cs
jdatcmd
left a comment
There was a problem hiding this comment.
Approving at f80bb8a, 14/14. The arm is load-bearing and I verified it by mutation rather than by reading.
The arm catches the defect, in every construction I tried
CONTROL 37 passed
M1 numbered section demoted to unnumbered ### 3 failed
M1' demoted AND its contents entry removed 2 failed
Both times test_every_test_file_has_a_NUMBERED_section_of_its_own is among them, which is the claim.
I did not reproduce your "1 failed, the new arm alone", and I think that is my mutation rather than your result. Demoting a section that is already numbered and already in the contents also breaks the link arm and the numbering arm, because it orphans a contents entry and leaves a gap. Removing the contents entry too takes it to 2, still with a gap. Getting to 1 needs the contents renumbered so the document is internally consistent — which is exactly what an unnumbered arrival looks like, and what test_iceberg_fdw.py actually was in #1057.
Worth stating because the distinction is the finding: a section that was never numbered is invisible to all three arms; a section demoted from numbered is caught by all three. Your defect was the first kind, which is why nothing caught it for a whole PR cycle. The regression direction was already covered.
What makes the arm sound rather than merely present
expect.at_least(len(files), 20)— a vacuity premise, so an emptied glob cannot pass it. That is the failure mode this repo keeps paying for, and it is guarded here rather than assumed.- Both directions: a file with no numbered section, and a numbered section naming a file that no longer exists. A one-way list rots into a permanent exemption.
- The docstring records the population measured before the arm was written — 33 files, 32 numbered, one not, and that one was the live defect. "The rule was already true everywhere else, which is why it can be asserted rather than declared as a goal" is the right justification and it is rare to see it written down.
On not doing what the issue asked
Declining to drop the numbers is the right call, and the reason is better than the issue's own: dropping them removes the subject of a guard that works. Your classification of the three section N prose references — 30 total, 27 naming VACUITY_MODES.md, 3 naming this document — is the measurement the issue's "cheapest first" ordering rested on and did not have. That a 60-character window got it wrong in both directions is the part I would keep.
…he section commandprompt#1064 shipped unnumbered commandprompt#1064 ADDED A NEW INSTANCE OF THE DEFECT THIS BRANCH CATCHES, which is why the merge cannot be resolved by taking a side: either side leaves `test_objstore_endpoint_userinfo.py` as an unnumbered `###`, and the arm this branch adds reddens on main the moment it lands. main:3879 ### `test_objstore_endpoint_userinfo.py` -- userinfo in an object-store endpoint (commandprompt#995) Not in the numbering, not in the contents, still NAMED so the coverage arm passes. The same shape `test_iceberg_fdw.py` arrived in during commandprompt#1057, in the very next PR, written by the person who had just measured it. Found by @jdatcmd reviewing this branch against the merged tree rather than against either side of it. RESOLUTION, and the guard is the arbiter for every part of it: - the conflicted hunk keeps this branch's `## 37. test_iceberg_fdw.py` - main's two `###` headings go; commandprompt#1064's objstore BODY is kept unchanged - objstore becomes `## 38.` where it already sits, and `test_hilbert_cluster.py` moves to 39 -- body order and numbering must agree, because the commandprompt#1023 arm checks inversions as well as gaps - no `(commandprompt#995)` in the heading: none of the other 38 carries an issue reference - CHANGELOG keeps both entries (commandprompt#996 again) ANCHOR RULE, worth stating because @jdatcmd's first attempt at this resolution hit it: lowercase, drop anything outside `[a-z0-9 _-]`, spaces to hyphens. The UNDERSCORES STAY. An anchor that strips them (`commandprompt#38-testobjstoreendpointuserinfopy`) reddens `test_every_in_document_link_in_this_directory_reaches_a_heading` on its own, which is how they caught it. Removal proof on the MERGED tree, restoring from a COPY rather than from git, because this work is uncommitted and `git checkout --` restores to HEAD: CONTROL (resolved merge) 37 passed M objstore back to its ARRIVAL shape 1 failed <- the new arm, alone TESTS.md restored to 149db63b THE ARRIVAL SHAPE IS THE POINT, and it answers @jdatcmd's note that they could not reproduce a single failure by demoting a section. Demoting one that was already numbered leaves a gap and an orphaned contents entry, so all three arms redden. A section that ARRIVES unnumbered, with the contents consistent around it, is invisible to the other two and caught only by this arm. commandprompt#1057 and commandprompt#1064 were both the second kind, which is why neither was caught for a whole cycle. guard leg 341 passed, 870 checks, 0 fail guard_tests 341, cluster_tests 325, both re-derived by collection on the merged tree Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012RSw4qMHS7ByE7PY8Ns4cs
jdatcmd
left a comment
There was a problem hiding this comment.
Re-approving at 5933b21. Your resolution is better than mine — objstore takes 38 where it already sits and hilbert_cluster moves to 39, which is less edit surface for the same property.
Verified on your head rather than carried over from f80bb8a:
unnumbered ### test_*.py sections 0
test_docs_cover_the_corpus.py 37 passed, 95 checks, 0 fail
guard leg 341 passed, 870 checks, 0 fail (tracked 341)
On the M1 difference: your reproduction is the correct one and mine was the wrong model. An arriving section is invisible to the other two arms; a demoted one is not — demoting leaves an orphaned contents entry and a numbering gap, which is why I saw three arms fire. #1057 and #1064 were both arrivals, which is exactly why neither was caught for a full cycle. Glad that is in the commit message rather than in a channel.
And the thing this PR demonstrated about itself: the defect it fixes was re-introduced by the very next PR to touch the document, by the same author, one cycle after measuring the shape. That is the argument for the arm existing, made better than any rationale could.
`test/sorted_pathkeys.sh` pins one decision: when a columnar scan may hand the
planner PATHKEYS, the promise that its rows already arrive in a stated order. The
planner then drops the Sort above the scan and nothing downstream re-checks, so a
wrong promise is not a slow plan, it is WRONG ROWS.
The port keeps the original's three shapes rather than reorganising by feature: a
CLAIM arm (the Sort goes), a REFUSAL arm (something made the claim untrue and the
Sort comes back), and an ANSWER arm (the rows themselves, against a heap table
built from the same data). The ANSWER arm is not a duplicate of its CLAIM arm --
dropping the Sort is only correct if the rows arrive sorted anyway, and a plan
check alone cannot say whether they did.
literal matches: 110 | template matches: 0 | missing: 0
VERDICT: every bash property is covered
ONE ARM NEEDED A CLUSTER SETTING, NOT A WORKAROUND. `pgcolumnar.parallel_copy`
prepares one transaction per worker, and `max_prepared_transactions` cannot be
raised without restarting the postmaster. The default is 0, so asking for fewer
workers does not help: any number is one too many. `pgc_cluster` now sets it where
it writes `postgresql.conf`, at the value `lib.sh` gives this suite through
`PGC_EXTRA_CONF`.
Refusing that arm with `expect.cannot_run` was written first and then measured and
rejected, for two reasons. It loses three of the bash suite's names outright,
because `cannot_run` records under the REASON CODE rather than under a name (#1040
phase 0b). And it turns the `pytest (cluster tests)` job RED: an unrunnable check
exits 67, the job runs pytest under `set -euo pipefail`, and no file in that half
had ever produced one. Measured: that leg exits 0 today with zero unrun, so this
file would have been the first to break it. The arm now asserts `pg_prepared_xacts`
is empty afterwards, because a leaked prepared transaction holds its locks and the
cluster is session-scoped -- it would not fail this test, it would wedge every file
after it.
TWO DOCS DEFECTS FOUND AND FIXED HERE, both of them mine.
`## 37. test_iceberg_fdw.py` reached main sitting directly above `## 38.`, with the
Iceberg body attached to the userinfo heading: my #1066 merge put the new section
into the gap between another heading and its body. #1066's own arm cannot see it,
because it asks whether each file is NAMED by a numbered heading and a heading with
no body is still a heading. `test_docs_cover_the_corpus.py` now refuses a numbered
section with no body, with a planted control, and the section order matches the
bodies.
`compare_to_bash.py`'s corpus arm called a WRAPPED name fabricated. A name too long
for one line is written as adjacent literals and Python joins them at parse time, so
the joined name is text the file contains but not text `in src` can find. The arm
exists to catch a reader that CONSTRUCTS a name, so it now collapses the file's own
concatenation and keeps exactly that guarantee: an f-string name still yields a `{}`
template, which the collapse does not rescue. Both directions are asserted.
VERIFIED, on pg16a in the audit container:
guard leg 342 collected, 878 checks, 0 fail rc=0
cluster leg 373 collected, 1025 checks, 0 fail, 0 unrun rc=0
grader 110 literal, 0 missing
Both counts re-derived BY COLLECTION on this tree, never by adding a delta.
MUTATION PROOF, each asserting it applied before it was believed:
M1 collation refusal removed -> 3 arms red, naming the collation properties
M2 enable_sorted_pathkeys GUC ignored -> 2 arms red, the off switch and a
planning-buffers control
restored, source byte-identical -> 127 checks, 48 passed, 0 fail
Closes nothing on its own; advances #432.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RSw4qMHS7ByE7PY8Ns4cs
Closes #1024 — but not by doing what it asks, because half of what it reports is already fixed and the other half is a different shape.
The reported defect is closed already
#1024 says two PRs each take the next section number, the merge keeps both, and nothing notices. Measured on
52511a7:test_the_contents_list_is_numbered_in_orderlanded after #1023 and catches exactly that. Planted:Its own docstring says so: "the collision that produced this is a section NUMBER taken twice, so the sections are where a duplicate shows up first, and
1..N with no gapcatches a duplicate and an omission in one rule." The issue was filed against9663f9bf, before it.So this does not drop the numbers
That was the issue's preferred option, and it would remove the subject of a guard that works. It also costs more than the issue estimated. "One sed over the file plus the anchors in the index" misses the prose:
Those three need individual judgement — they have to be classified, not counted, and my first pass at classifying them was wrong in both directions before I read the enclosing section of each.
What is still open, and I shipped it
A test file whose section is written as an unnumbered
###instead of a numbered##is invisible to every arm:1..N with no gapnever sees ittest_iceberg_fdw.pywent in that way in #1057 and sat undetected until this arm was written. Planted as a mutation againstmain, nothing catches it — 36 passed.It is also the cheaper failure. The collision needs two PRs in flight; this needs one person writing a heading at the wrong level.
The rule was already true everywhere else, which is why it can be asserted rather than declared as a goal.
The change
test_iceberg_fdw.pybecomes section 37 where it already sits in the body;test_hilbert_cluster.pymoves to 38. Body order and numbering must agree — the #1023 arm checks inversions as well as gaps, so inserting anywhere else reddens it.The new arm asserts in both directions, so a section cannot outlive the file it documents.
Removal proof
M2 is in the proof deliberately. A change that found an existing guard working must not weaken it, and the only way to say that is to re-run its mutation afterwards.
guard_tests340 → 341 by collection.One note on process
I twice lost uncommitted work in this change to
git checkout -- <path>inside a mutation script's restore — the file goes back to HEAD, not to the pre-mutation state. Both times the work was re-done from the scripts that produced it. It is the third instance of that trap for me this week and the fix is the same each time: commit before mutating.🤖 Generated with Claude Code
https://claude.ai/code/session_012RSw4qMHS7ByE7PY8Ns4cs