Skip to content

test: a test file documented outside the numbering is invisible (#1024) - #1066

Merged
jdatcmd merged 2 commits into
commandprompt:mainfrom
OffgridwithJD:docs-section-level
Sep 14, 2026
Merged

jdatcmd merged 2 commits into
commandprompt:mainfrom
OffgridwithJD:docs-section-level

Conversation

@OffgridwithJD

Copy link
Copy Markdown
Collaborator

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_order landed after #1023 and catches exactly that. Planted:

M2  a DUPLICATE section number  ->  2 failed, naming the inversion

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 gap catches a duplicate and an omission in one rule." The issue was filed against 9663f9bf, 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:

'section N' references in TESTS.md      30
  naming VACUITY_MODES.md's sections    27   unaffected
  naming THIS document's sections        3   would break

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:

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 #1057 and sat undetected until this arm was written. Planted as a mutation against main, 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.

test files on disk             33
with a NUMBERED ## section     32
with an unnumbered ### section  1   <- test_iceberg_fdw.py, the defect

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.py becomes section 37 where it already sits in the body; test_hilbert_cluster.py moves 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

CONTROL                                     37 passed
M1  a section demoted to an unnumbered ###   1 failed   <- the new arm, alone
M2  a DUPLICATE section number               2 failed   <- #1023's arm, still working
TESTS.md restored to 70a78a69

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 leg  341 passed, 870 checks, 0 fail

guard_tests 340 → 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

…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 jdatcmd left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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 jdatcmd left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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.

@jdatcmd
jdatcmd merged commit 97131e9 into commandprompt:main Sep 14, 2026
14 checks passed
jdatcmd pushed a commit that referenced this pull request Sep 16, 2026
`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
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.

TESTS.md section numbers collide on every pair of PRs that add a test file, and nothing catches it -- #996 one file over

2 participants