test/pytest: port the rest of the differential suite, and a fourth arm that cannot fail (#432) - #1023
Conversation
|
Added a fix for a latent defect in part 1, which is merged. Found while reading the
psql_run "INSERT INTO t_heap $body;"
psql_run "INSERT INTO t_col SELECT * FROM t_heap;"with its reason stated: "both hold byte-identical logical contents regardless of any My helper ran the generator twice, once per table. Measured, 2000 rows, Every load in parts 1 and 2 is deterministic -- Both loaders now generate once and copy: the module fixture from part 1 and the per-test The generalisable bit: a test is its assertions AND its fixture. I ported the assertions |
36f6f63 to
5a2abd3
Compare
linuxhikerpm
left a comment
There was a problem hiding this comment.
The fourth unfalsifiable arm is real: tk = 'k100' matches nothing, and a bloom wrongly pushed under a mismatched collation also returns 0. Generating once into heap and copying is the right load_pair lesson; part 3's random() walk would have compared two fixtures. The bloom spread premise, the 400-row delete, and the 18462 covering-count arithmetic all look load-bearing. CI is green on 5a2abd3bbd88dd2f1828b426b8028accbcdb2fca, including pytest-cluster at cluster_tests 191.
Two leftovers in TESTS.md before I would approve:
- The section 30 intro now says this is the whole suite, then still says "The boundary, encoding, bloom and aggregate parts are separate slices."
- The heading and TOC still say "type matrix".
Do not merge until those match what the file contains. I will re-review the SHA that fixes them.
|
Both fixed at the new head, and they were the same defect twice: a name that outran what it The intro now lists the parts in the order the bash suite runs them, and the twenty-column Checked the consistency mechanically rather than by eye, since that is the thing that went Worth saying plainly: this is the same name-overran-its-content defect I spent the afternoon That is the gap #1024 is about in a narrower form -- it proposes dropping the section numbers |
db083a0 to
a222917
Compare
All seven parts of test/differential.sh now have a pytest twin. 85 tests, 232 checks, 17 seconds. Parts 1 and 2 were commandprompt#1020 and the first commits here; this adds boundary conditions, lightweight encodings, aggregates with deletes, bloom equality skipping, wide projections and the covering count. A FOURTH UNFALSIFIABLE BASH ARM, and the subtlest of the four. `textbloom collate-mismatch` probes `tk = 'k100'`, and tk is 'k' || ((g*2654435761)%50000) over 16,000 rows of a 50,000-wide domain -- 32% coverage, and measured, k100 matches 0 rows. The arm exists to catch a bloom wrongly pushed under a mismatched collation, and a wrongly-pushed bloom skips the chunks holding the match and returns 0. So the one defect it is built to detect produces exactly the answer it expects. Found by a premise arm I added asking whether the probe value exists. The port probes a value derived from the data, asserts it is present exactly once, and adds the direction the arm must fail in -- that the mismatched collation RETURNS the row rather than skipping it. FIXTURE PREMISES ARE ASSERTED WHERE THEY DECIDE WHAT IS UNDER TEST: * the bloom fixture's key spread, at least 90,000 of the domain per chunk. Ordered keys would make every bloom arm pass on zone maps alone and say nothing about blooms, and no arm would report that. * the dictionary fixture's cardinalities, 4 and 6 against an md5 per row, so the per-column verdict is visible rather than assumed. * the delete in part 4 removed exactly 400 rows. A DELETE matching nothing leaves the per-group fallback untested while every arm stays green. * the update in part 7 leaves a count neither the delete nor the update alone would give, which is the arithmetic the metadata path has to get right. Float aggregates use min/max rather than sum, because a float sum has no single right answer -- part 1 measures three from heap alone by row order. SET on the connection rather than ALTER DATABASE in part 7: that form exists because each psql invocation in the bash suite is a new session, and this is not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uf6UoeBRZYLQZa4KxNiw8a
a222917 to
d392b80
Compare
jdatcmd
left a comment
There was a problem hiding this comment.
Approving. The whole of differential.sh now has a twin, and the fourth arm is the sharpest finding either of us has produced on #432.
The collate-mismatch arm, verified arithmetically here
tk = 'k' || ((g * 2654435761) % 50000), g in 1..16000
distinct values 16000 of a 50000 domain (32.0%)
is 100 among them FALSE -- no g produces k100
So the probe value does not exist, and that is worse than the three in #1020 for the reason you give. Those compared nothing to nothing. This one compares the right answer to the wrong answer's answer: a bloom wrongly pushed under a mismatched COLLATE skips the chunks holding the match and returns 0, and the absent value returns 0. The one defect the arm exists to detect produces exactly the result it asserts.
And the heap oracle cannot save it either — heap returns 0 correctly, columnar returns 0 whether correct or wrongly skipping, so diff_query agrees at 0 in both worlds. An arm whose oracle cannot distinguish the defect from the expected answer is a strictly stronger failure than one that asserts nothing.
The fixture premises are the right things to have asserted
The bloom key-spread one especially:
If the keys were ordered, every bloom arm would pass on zone maps alone and say nothing about blooms, and no existing arm would report it.
That is the same shape as the collate arm one level up — a whole family of arms green for a reason unrelated to what they name. Asserting the spread is what makes the family mean anything, and nothing in the bash suite does it.
the delete removed exactly 400 rows is the other one I would keep: a DELETE matching nothing leaves part 4's per-group fallback untested while every arm stays green.
The load_pair fix is the reason this PR matters beyond the port
generator run twice rows differing: 2000
generated once, copied rows differing: 0
Parts 1 and 2 right by luck because every load in them is deterministic, and part 3 uses random(). Without it the oracle compares two different fixtures and reports a columnar defect that does not exist — on the suite whose entire purpose is to be believed when it says the two access methods disagree. Correcting your own merged work rather than building on it is the call I would want made.
Two judgements I agree with and would have got wrong
Float aggregates as min/max rather than sum. Part 1 measured three answers from heap alone by row order, so a sum arm there asserts a coincidence about summation order.
SET on the connection rather than ALTER DATABASE. The bash suite needs the latter because each psql is a new session; copying it here would be copying a fact about psql into a harness where it is not true. That is the kind of thing a port carries across without noticing.
Merging when CI settles.
#1023 landed. Second rebase of this PR for the same reason, and the count is the same hazard both times. expected_tests.txt: two cluster_tests lines again, 180 here and 202 on main. Both branches bumped it from a base that has since moved. Kept one line and DERIVED on the merged tree: 180 (mine) | 202 (main) | 382 (their sum) | 205 (derived) <- the right one Not either side and not their sum, which is the third time today that has been true of this file. @OffgridwithJD hit it with 177 and 191 deriving 202; I hit 169/177 deriving 180 an hour ago and 180/202 deriving 205 now. TESTS.md: two blocks, both kept, no duplicate section this time -- #1023 extended the existing test_differential section rather than adding one. 32 sections, 32 index entries, 0 dangling anchors. That last check is @OffgridwithJD's: their blind resolver kept a TOC entry pointing at an anchor their own rename had removed, because a CHANGELOG is additive, a key-value file is not, and a TOC is additive only when the headings were. One resolver over three kinds of file. Verified as separate commands rather than chained to the push, which is the other thing that shipped a red PR today: guard half 277 passed, 680 checks, enforced cluster half 205 passed, 581 checks, enforced Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EbyGSaU93XYQr8aH4NrUiw
linuxhikerpm
left a comment
There was a problem hiding this comment.
Approving d392b80ff954fbad09436a7d2bfca4fab7e27ae4.
The two leftovers from 5a2abd3b are gone: TOC, heading and intro now say the whole suite, all seven parts. CI is green, including pytest-cluster at the re-derived cluster_tests after merging main.
The collate-mismatch arm, the one-shot load_pair copy, and the fixture premises still look load-bearing. I will not merge it.
…pt#1026) docs_style.sh enforced seven rules over every user-facing page and all seven are about PROSE: sentence length, the idiom list, em and en dashes, prose double-hyphens, conflict markers, the nav entry, VERSION citations. Nothing checked structure, so a markdown table that had stopped being a table passed the gate whose whole purpose is keeping those pages readable. The measured case, on commandprompt#1022: a note and a second table spliced into the middle of configuration.md's set_options argument table left six of the nine arguments as a headerless block. docs_style.sh passed, 14 checks. Found in review by @linuxhikerpm -- I had reviewed that change twice, checking sentence length, a guard's scoping claim and a three-row mutation table, and never once asked whether the markdown still rendered. Second splice of the day. The first gave configuration.md's GUC table no blank lines, which made an awk RS='' guard read two GUC rows as one record and pass on main. Both are the same fact: a markdown table is a contiguous run of | lines, and a blank line is structural. FENCES TRACKED BY LINE, not stripped by regex. The regex form already in this file is fine for counting but loses line numbers, and a report that cannot say WHERE is one somebody has to re-derive. It also breaks on an unclosed fence, where state-tracking under-reports instead -- the safe direction, since it cannot invent a table. FIVE ARMS, and the control comes first: a rule flagging every table would catch the defect and be switched off the same day. Then the defect with its line number, a shell pipeline in a fence WITH its unfenced control, an unclosed fence, and the false-positive budget as a standing arm rather than a number measured once. THE BUDGET, measured before landing: 0 across docs/*.md and README.md, which is the gate's scope. 5 elsewhere in the tree and all five are REAL -- 3 in test/pytest/TESTS.md and 2 in design/, neither in scope. Not fixed here; the rule does not reach them and widening the scope is a separate decision. Proved by removal: splicing the commandprompt#1022 shape into configuration.md gives one headerless block at line 167 and docs_style rc=1; restoring gives rc=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uf6UoeBRZYLQZa4KxNiw8a REBASED onto 6f7691b after commandprompt#1023 merged, and the resolution fixed a defect commandprompt#1023 left in main. Both conflict hunks were keep-both -- a TOC line and a whole new section -- but placing mine correctly meant reading the order, and main's TOC was not in order: main's TOC ... 29, 31, 30 (out of order at two transitions) main's sections ... 29, 30, 31 (contiguous, correct) commandprompt#1023's TOC entry for section 30 landed after 31. Nothing caught it: this file's link arms assert every contents-list link RESOLVES, which both orders do, and nothing asserts the numbering is monotonic. Now: TOC 32 entries, 1..32, 0 out-of-order sections 32 sections, 1..32, 0 out-of-order guard_tests re-derived by collection on the new base rather than carried: 282 collected. cluster_tests 202 comes from main unchanged. Re-verified after the rebase: 282 passed / 688 checks with --pgc-expect-tests 282 armed; docs_style.sh PASSED (11 checks); the headerless rule is active in the report (`3 headerless table` on TESTS.md, all three pre-existing and outside the gate's scope) and `violations()` returns its 5 members.
…pt#1026) docs_style.sh enforced seven rules over every user-facing page and all seven are about PROSE: sentence length, the idiom list, em and en dashes, prose double-hyphens, conflict markers, the nav entry, VERSION citations. Nothing checked structure, so a markdown table that had stopped being a table passed the gate whose whole purpose is keeping those pages readable. The measured case, on commandprompt#1022: a note and a second table spliced into the middle of configuration.md's set_options argument table left six of the nine arguments as a headerless block. docs_style.sh passed, 14 checks. Found in review by @linuxhikerpm -- I had reviewed that change twice, checking sentence length, a guard's scoping claim and a three-row mutation table, and never once asked whether the markdown still rendered. Second splice of the day. The first gave configuration.md's GUC table no blank lines, which made an awk RS='' guard read two GUC rows as one record and pass on main. Both are the same fact: a markdown table is a contiguous run of | lines, and a blank line is structural. FENCES TRACKED BY LINE, not stripped by regex. The regex form already in this file is fine for counting but loses line numbers, and a report that cannot say WHERE is one somebody has to re-derive. It also breaks on an unclosed fence, where state-tracking under-reports instead -- the safe direction, since it cannot invent a table. FIVE ARMS, and the control comes first: a rule flagging every table would catch the defect and be switched off the same day. Then the defect with its line number, a shell pipeline in a fence WITH its unfenced control, an unclosed fence, and the false-positive budget as a standing arm rather than a number measured once. THE BUDGET, measured before landing: 0 across docs/*.md and README.md, which is the gate's scope. 5 elsewhere in the tree and all five are REAL -- 3 in test/pytest/TESTS.md and 2 in design/, neither in scope. Not fixed here; the rule does not reach them and widening the scope is a separate decision. Proved by removal: splicing the commandprompt#1022 shape into configuration.md gives one headerless block at line 167 and docs_style rc=1; restoring gives rc=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uf6UoeBRZYLQZa4KxNiw8a REBASED onto 6f7691b after commandprompt#1023 merged, and the resolution fixed a defect commandprompt#1023 left in main. Both conflict hunks were keep-both -- a TOC line and a whole new section -- but placing mine correctly meant reading the order, and main's TOC was not in order: main's TOC ... 29, 31, 30 (out of order at two transitions) main's sections ... 29, 30, 31 (contiguous, correct) commandprompt#1023's TOC entry for section 30 landed after 31. Nothing caught it: this file's link arms assert every contents-list link RESOLVES, which both orders do, and nothing asserts the numbering is monotonic. Now: TOC 32 entries, 1..32, 0 out-of-order sections 32 sections, 1..32, 0 out-of-order guard_tests re-derived by collection on the new base rather than carried: 282 collected. cluster_tests 202 comes from main unchanged. Re-verified after the rebase: 282 passed / 688 checks with --pgc-expect-tests 282 armed; docs_style.sh PASSED (11 checks); the headerless rule is active in the report (`3 headerless table` on TESTS.md, all three pre-existing and outside the gate's scope) and `violations()` returns its 5 members. AND THE GUARD FOR THE ORDERING, added here rather than in commandprompt#1029 because a guard belongs with its fix. Putting it in commandprompt#1029 would have reddened commandprompt#1029 until this PR merged, which is a dependency between two independent PRs. Two arms in test_docs_cover_the_corpus.py. The first requires TESTS.md's contents numbers and its section numbers each to count 1..N with no gap, and one contents entry per section. The second is the removal proof on a fixture, using the 29, 31, 30 shape that shipped rather than a single swap. MEASURED, by restoring main's order under the new arm: the new arm FAIL got '[(29, 31), (31, 30), (30, 32)]' want 'none' the link arms 1 passed So the existing link sweep is not a weaker version of this rule. It asks whether a link RESOLVES and both orders resolve, which is why a shuffled contents list was outside every arm in that file. The gap rule catches the section-number COLLISION too, which is the cause rather than a coincidence: three open PRs each claimed a number another had taken, and a number used twice leaves a gap in the section sequence. One rule reddens on a duplicate and on an omission, and the fixture names them apart -- a missing entry gives [(1, 3)] and a shuffle gives [(1, 3), (3, 2)]. guard_tests 282 -> 284, re-derived by collection. Re-verified: 284 passed / 698 checks with --pgc-expect-tests 284 armed; docs_style.sh PASSED (11 checks); TOC and sections both 1..32 with zero out-of-order transitions. The CHANGELOG's long-sentence count is unchanged at 857.
…pt#1026) docs_style.sh enforced seven rules over every user-facing page and all seven are about PROSE: sentence length, the idiom list, em and en dashes, prose double-hyphens, conflict markers, the nav entry, VERSION citations. Nothing checked structure, so a markdown table that had stopped being a table passed the gate whose whole purpose is keeping those pages readable. The measured case, on commandprompt#1022: a note and a second table spliced into the middle of configuration.md's set_options argument table left six of the nine arguments as a headerless block. docs_style.sh passed, 14 checks. Found in review by @linuxhikerpm -- I had reviewed that change twice, checking sentence length, a guard's scoping claim and a three-row mutation table, and never once asked whether the markdown still rendered. Second splice of the day. The first gave configuration.md's GUC table no blank lines, which made an awk RS='' guard read two GUC rows as one record and pass on main. Both are the same fact: a markdown table is a contiguous run of | lines, and a blank line is structural. FENCES TRACKED BY LINE, not stripped by regex. The regex form already in this file is fine for counting but loses line numbers, and a report that cannot say WHERE is one somebody has to re-derive. It also breaks on an unclosed fence, where state-tracking under-reports instead -- the safe direction, since it cannot invent a table. FIVE ARMS, and the control comes first: a rule flagging every table would catch the defect and be switched off the same day. Then the defect with its line number, a shell pipeline in a fence WITH its unfenced control, an unclosed fence, and the false-positive budget as a standing arm rather than a number measured once. THE BUDGET, measured before landing: 0 across docs/*.md and README.md, which is the gate's scope. 5 elsewhere in the tree and all five are REAL -- 3 in test/pytest/TESTS.md and 2 in design/, neither in scope. Not fixed here; the rule does not reach them and widening the scope is a separate decision. Proved by removal: splicing the commandprompt#1022 shape into configuration.md gives one headerless block at line 167 and docs_style rc=1; restoring gives rc=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uf6UoeBRZYLQZa4KxNiw8a REBASED onto 6f7691b after commandprompt#1023 merged, and the resolution fixed a defect commandprompt#1023 left in main. Both conflict hunks were keep-both -- a TOC line and a whole new section -- but placing mine correctly meant reading the order, and main's TOC was not in order: main's TOC ... 29, 31, 30 (out of order at two transitions) main's sections ... 29, 30, 31 (contiguous, correct) link arms assert every contents-list link RESOLVES, which both orders do, and nothing asserts the numbering is monotonic. Now: TOC 32 entries, 1..32, 0 out-of-order sections 32 sections, 1..32, 0 out-of-order guard_tests re-derived by collection on the new base rather than carried: 282 collected. cluster_tests 202 comes from main unchanged. Re-verified after the rebase: 282 passed / 688 checks with --pgc-expect-tests 282 armed; docs_style.sh PASSED (11 checks); the headerless rule is active in the report (`3 headerless table` on TESTS.md, all three pre-existing and outside the gate's scope) and `violations()` returns its 5 members. AND THE GUARD FOR THE ORDERING, added here rather than in commandprompt#1029 because a guard belongs with its fix. Putting it in commandprompt#1029 would have reddened commandprompt#1029 until this PR merged, which is a dependency between two independent PRs. Two arms in test_docs_cover_the_corpus.py. The first requires TESTS.md's contents numbers and its section numbers each to count 1..N with no gap, and one contents entry per section. The second is the removal proof on a fixture, using the 29, 31, 30 shape that shipped rather than a single swap. MEASURED, by restoring main's order under the new arm: the new arm FAIL got '[(29, 31), (31, 30), (30, 32)]' want 'none' the link arms 1 passed So the existing link sweep is not a weaker version of this rule. It asks whether a link RESOLVES and both orders resolve, which is why a shuffled contents list was outside every arm in that file. The gap rule catches the section-number COLLISION too, which is the cause rather than a coincidence: three open PRs each claimed a number another had taken, and a number used twice leaves a gap in the section sequence. One rule reddens on a duplicate and on an omission, and the fixture names them apart -- a missing entry gives [(1, 3)] and a shuffle gives [(1, 3), (3, 2)]. guard_tests 282 -> 284, re-derived by collection. Re-verified: 284 passed / 698 checks with --pgc-expect-tests 284 armed; docs_style.sh PASSED (11 checks); TOC and sections both 1..32 with zero out-of-order transitions. The CHANGELOG's long-sentence count is unchanged at 857. REBASED AGAIN onto 03c6c9c, and the section moved 32 -> 33 because commandprompt#1027 merged and took 32. That is the collision I measured on commandprompt#1027 before it merged, arriving exactly as predicted, and the renumbering is the one-hunk-plus-a-sort it was said to be. Main's contents list is still out of numeric order at three transitions -- (29, 31), (31, 30), (30, 32) -- because commandprompt#1023's entry for section 30 landed after 31 and commandprompt#1027 then appended 32. This resolution sorts all of it: TOC 33 entries, 1..33, 0 out-of-order sections 33 sections, 1..33, 0 out-of-order guard_tests 284, re-derived by collection rather than carried. cluster_tests 205 comes from main unchanged. Re-verified after both rebases: 284 collected, 284 passed / 698 checks with --pgc-expect-tests 284 armed, docs_style.sh PASSED (11 checks), and the CHANGELOG's long-sentence count matches main at 860.
…pt#1026) docs_style.sh enforced seven rules over every user-facing page and all seven are about PROSE: sentence length, the idiom list, em and en dashes, prose double-hyphens, conflict markers, the nav entry, VERSION citations. Nothing checked structure, so a markdown table that had stopped being a table passed the gate whose whole purpose is keeping those pages readable. The measured case, on commandprompt#1022: a note and a second table spliced into the middle of configuration.md's set_options argument table left six of the nine arguments as a headerless block. docs_style.sh passed, 14 checks. Found in review by @linuxhikerpm -- I had reviewed that change twice, checking sentence length, a guard's scoping claim and a three-row mutation table, and never once asked whether the markdown still rendered. Second splice of the day. The first gave configuration.md's GUC table no blank lines, which made an awk RS='' guard read two GUC rows as one record and pass on main. Both are the same fact: a markdown table is a contiguous run of | lines, and a blank line is structural. FENCES TRACKED BY LINE, not stripped by regex. The regex form already in this file is fine for counting but loses line numbers, and a report that cannot say WHERE is one somebody has to re-derive. It also breaks on an unclosed fence, where state-tracking under-reports instead -- the safe direction, since it cannot invent a table. FIVE ARMS, and the control comes first: a rule flagging every table would catch the defect and be switched off the same day. Then the defect with its line number, a shell pipeline in a fence WITH its unfenced control, an unclosed fence, and the false-positive budget as a standing arm rather than a number measured once. THE BUDGET, measured before landing: 0 across docs/*.md and README.md, which is the gate's scope. 5 elsewhere in the tree and all five are REAL -- 3 in test/pytest/TESTS.md and 2 in design/, neither in scope. Not fixed here; the rule does not reach them and widening the scope is a separate decision. Proved by removal: splicing the commandprompt#1022 shape into configuration.md gives one headerless block at line 167 and docs_style rc=1; restoring gives rc=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uf6UoeBRZYLQZa4KxNiw8a REBASED onto 6f7691b after commandprompt#1023 merged, and the resolution fixed a defect commandprompt#1023 left in main. Both conflict hunks were keep-both -- a TOC line and a whole new section -- but placing mine correctly meant reading the order, and main's TOC was not in order: main's TOC ... 29, 31, 30 (out of order at two transitions) main's sections ... 29, 30, 31 (contiguous, correct) link arms assert every contents-list link RESOLVES, which both orders do, and nothing asserts the numbering is monotonic. Now: TOC 32 entries, 1..32, 0 out-of-order sections 32 sections, 1..32, 0 out-of-order guard_tests re-derived by collection on the new base rather than carried: 282 collected. cluster_tests 202 comes from main unchanged. Re-verified after the rebase: 282 passed / 688 checks with --pgc-expect-tests 282 armed; docs_style.sh PASSED (11 checks); the headerless rule is active in the report (`3 headerless table` on TESTS.md, all three pre-existing and outside the gate's scope) and `violations()` returns its 5 members. AND THE GUARD FOR THE ORDERING, added here rather than in commandprompt#1029 because a guard belongs with its fix. Putting it in commandprompt#1029 would have reddened commandprompt#1029 until this PR merged, which is a dependency between two independent PRs. Two arms in test_docs_cover_the_corpus.py. The first requires TESTS.md's contents numbers and its section numbers each to count 1..N with no gap, and one contents entry per section. The second is the removal proof on a fixture, using the 29, 31, 30 shape that shipped rather than a single swap. MEASURED, by restoring main's order under the new arm: the new arm FAIL got '[(29, 31), (31, 30), (30, 32)]' want 'none' the link arms 1 passed So the existing link sweep is not a weaker version of this rule. It asks whether a link RESOLVES and both orders resolve, which is why a shuffled contents list was outside every arm in that file. The gap rule catches the section-number COLLISION too, which is the cause rather than a coincidence: three open PRs each claimed a number another had taken, and a number used twice leaves a gap in the section sequence. One rule reddens on a duplicate and on an omission, and the fixture names them apart -- a missing entry gives [(1, 3)] and a shuffle gives [(1, 3), (3, 2)]. guard_tests 282 -> 284, re-derived by collection. Re-verified: 284 passed / 698 checks with --pgc-expect-tests 284 armed; docs_style.sh PASSED (11 checks); TOC and sections both 1..32 with zero out-of-order transitions. The CHANGELOG's long-sentence count is unchanged at 857. REBASED AGAIN onto 03c6c9c, and the section moved 32 -> 33 because commandprompt#1027 merged and took 32. That is the collision I measured on commandprompt#1027 before it merged, arriving exactly as predicted, and the renumbering is the one-hunk-plus-a-sort it was said to be. Main's contents list is still out of numeric order at three transitions -- (29, 31), (31, 30), (30, 32) -- because commandprompt#1023's entry for section 30 landed after 31 and commandprompt#1027 then appended 32. This resolution sorts all of it: TOC 33 entries, 1..33, 0 out-of-order sections 33 sections, 1..33, 0 out-of-order guard_tests 284, re-derived by collection rather than carried. cluster_tests 205 comes from main unchanged. Re-verified after both rebases: 284 collected, 284 passed / 698 checks with --pgc-expect-tests 284 armed, docs_style.sh PASSED (11 checks), and the CHANGELOG's long-sentence count matches main at 860. REBASED onto 14c9dd4 after commandprompt#1029 merged, and the resolution is the one this PR's sibling work is about. `expected_tests.txt` conflicted and keep-both produced TWO guard_tests lines: guard_tests 280 <- main, after commandprompt#1029 guard_tests 284 <- this branch, from the old base Keep-both is right for the CHANGELOG hunk in the same merge and wrong for a key-value file. One line, re-derived by collection rather than by adding: 287 collected. Re-verified: 287 passed / 707 checks with --pgc-expect-tests 287 armed; docs_style.sh PASSED (11 checks); TOC and sections both 1..33 with zero out-of-order; both CHANGELOG entries survived the merge.
…pt#1026) docs_style.sh enforced seven rules over every user-facing page and all seven are about PROSE: sentence length, the idiom list, em and en dashes, prose double-hyphens, conflict markers, the nav entry, VERSION citations. Nothing checked structure, so a markdown table that had stopped being a table passed the gate whose whole purpose is keeping those pages readable. The measured case, on commandprompt#1022: a note and a second table spliced into the middle of configuration.md's set_options argument table left six of the nine arguments as a headerless block. docs_style.sh passed, 14 checks. Found in review by @linuxhikerpm -- I had reviewed that change twice, checking sentence length, a guard's scoping claim and a three-row mutation table, and never once asked whether the markdown still rendered. Second splice of the day. The first gave configuration.md's GUC table no blank lines, which made an awk RS='' guard read two GUC rows as one record and pass on main. Both are the same fact: a markdown table is a contiguous run of | lines, and a blank line is structural. FENCES TRACKED BY LINE, not stripped by regex. The regex form already in this file is fine for counting but loses line numbers, and a report that cannot say WHERE is one somebody has to re-derive. It also breaks on an unclosed fence, where state-tracking under-reports instead -- the safe direction, since it cannot invent a table. FIVE ARMS, and the control comes first: a rule flagging every table would catch the defect and be switched off the same day. Then the defect with its line number, a shell pipeline in a fence WITH its unfenced control, an unclosed fence, and the false-positive budget as a standing arm rather than a number measured once. THE BUDGET, measured before landing: 0 across docs/*.md and README.md, which is the gate's scope. 5 elsewhere in the tree and all five are REAL -- 3 in test/pytest/TESTS.md and 2 in design/, neither in scope. Not fixed here; the rule does not reach them and widening the scope is a separate decision. Proved by removal: splicing the commandprompt#1022 shape into configuration.md gives one headerless block at line 167 and docs_style rc=1; restoring gives rc=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uf6UoeBRZYLQZa4KxNiw8a REBASED onto 6f7691b after commandprompt#1023 merged, and the resolution fixed a defect commandprompt#1023 left in main. Both conflict hunks were keep-both -- a TOC line and a whole new section -- but placing mine correctly meant reading the order, and main's TOC was not in order: main's TOC ... 29, 31, 30 (out of order at two transitions) main's sections ... 29, 30, 31 (contiguous, correct) link arms assert every contents-list link RESOLVES, which both orders do, and nothing asserts the numbering is monotonic. Now: TOC 32 entries, 1..32, 0 out-of-order sections 32 sections, 1..32, 0 out-of-order guard_tests re-derived by collection on the new base rather than carried: 282 collected. cluster_tests 202 comes from main unchanged. Re-verified after the rebase: 282 passed / 688 checks with --pgc-expect-tests 282 armed; docs_style.sh PASSED (11 checks); the headerless rule is active in the report (`3 headerless table` on TESTS.md, all three pre-existing and outside the gate's scope) and `violations()` returns its 5 members. AND THE GUARD FOR THE ORDERING, added here rather than in commandprompt#1029 because a guard belongs with its fix. Putting it in commandprompt#1029 would have reddened commandprompt#1029 until this PR merged, which is a dependency between two independent PRs. Two arms in test_docs_cover_the_corpus.py. The first requires TESTS.md's contents numbers and its section numbers each to count 1..N with no gap, and one contents entry per section. The second is the removal proof on a fixture, using the 29, 31, 30 shape that shipped rather than a single swap. MEASURED, by restoring main's order under the new arm: the new arm FAIL got '[(29, 31), (31, 30), (30, 32)]' want 'none' the link arms 1 passed So the existing link sweep is not a weaker version of this rule. It asks whether a link RESOLVES and both orders resolve, which is why a shuffled contents list was outside every arm in that file. The gap rule catches the section-number COLLISION too, which is the cause rather than a coincidence: three open PRs each claimed a number another had taken, and a number used twice leaves a gap in the section sequence. One rule reddens on a duplicate and on an omission, and the fixture names them apart -- a missing entry gives [(1, 3)] and a shuffle gives [(1, 3), (3, 2)]. guard_tests 282 -> 284, re-derived by collection. Re-verified: 284 passed / 698 checks with --pgc-expect-tests 284 armed; docs_style.sh PASSED (11 checks); TOC and sections both 1..32 with zero out-of-order transitions. The CHANGELOG's long-sentence count is unchanged at 857. REBASED AGAIN onto 03c6c9c, and the section moved 32 -> 33 because commandprompt#1027 merged and took 32. That is the collision I measured on commandprompt#1027 before it merged, arriving exactly as predicted, and the renumbering is the one-hunk-plus-a-sort it was said to be. Main's contents list is still out of numeric order at three transitions -- (29, 31), (31, 30), (30, 32) -- because commandprompt#1023's entry for section 30 landed after 31 and commandprompt#1027 then appended 32. This resolution sorts all of it: TOC 33 entries, 1..33, 0 out-of-order sections 33 sections, 1..33, 0 out-of-order guard_tests 284, re-derived by collection rather than carried. cluster_tests 205 comes from main unchanged. Re-verified after both rebases: 284 collected, 284 passed / 698 checks with --pgc-expect-tests 284 armed, docs_style.sh PASSED (11 checks), and the CHANGELOG's long-sentence count matches main at 860. REBASED onto 14c9dd4 after commandprompt#1029 merged, and the resolution is the one this PR's sibling work is about. `expected_tests.txt` conflicted and keep-both produced TWO guard_tests lines: guard_tests 280 <- main, after commandprompt#1029 guard_tests 284 <- this branch, from the old base Keep-both is right for the CHANGELOG hunk in the same merge and wrong for a key-value file. One line, re-derived by collection rather than by adding: 287 collected. Re-verified: 287 passed / 707 checks with --pgc-expect-tests 287 armed; docs_style.sh PASSED (11 checks); TOC and sections both 1..33 with zero out-of-order; both CHANGELOG entries survived the merge.
The whole of
test/differential.shnow has a pytest twin. Parts 1 and 2 were #1020 andthis PR's first commits; this completes parts 3 to 7.
85 tests, 232 checks, 17 seconds. Every arm ported by name so
compare_to_bash.pycandiff the two harnesses by property.
A fourth unfalsifiable arm, and the subtlest of the four
textbloom collate-mismatchprobestk = 'k100'. The column is'k' || ((g*2654435761)%50000)over 16,000 rows of a 50,000-wide domain:The arm exists to catch a bloom wrongly pushed under a mismatched explicit
COLLATE. Awrongly-pushed bloom skips the chunks holding the match and returns 0. The absent value
also returns 0. So the one defect the arm is built to detect produces exactly the answer it
expects, and the arm passes either way.
That is worse than the three in #1020. Those compared nothing to nothing; this one compares the
right answer to the wrong answer's answer.
Found by a premise arm I added asking whether the probe value exists -- it failed, and the
failure is the finding. The port derives a present value, asserts it is there exactly once, and
adds the direction the arm must fail in: the mismatched collation must return the row rather
than skip it.
Fixture premises asserted where they decide what is under test
This is the part I would want reviewed hardest, because each of these is a way the suite could
be green and mean nothing:
domain. If the keys were ordered, every bloom arm would pass on zone maps alone and say
nothing about blooms, and no existing arm would report it.
is visible rather than assumed.
per-group fallback untested while every arm stays green.
the metadata count path has to get right and a plain scan gets right for free.
Two smaller judgements
Float aggregates use min/max, not sum. A float sum has no single right answer -- part 1
measures three from heap alone by row order -- so
sumthere would be asserting a coincidence.SETon the connection, notALTER DATABASE. The bash suite uses the latter because eachpsql invocation is a new session. This one is not, and copying the workaround would have been
copying a fact about psql into a harness it is not true of.
The
load_pairfix, which is the other reason this PR mattersPart 1 is merged and regenerated the fixture into both tables instead of generating once and
copying, which
lib.sh'sload_pairdoes deliberately -- "regardless of any volatilegenerators". Measured on part 3's own generator, 2000 rows:
Parts 1 and 2 were right by luck, because every load in them is deterministic. Part 3 uses
random(), so with the old helper the oracle would have compared two different fixtures andreported a columnar defect that does not exist -- on the suite whose whole purpose is to be
believed when it says the two access methods disagree.
I ported the assertions faithfully and rebuilt the fixture my own way, and the fixture
construction is where the previous author had buried the lesson.
Test plan
pg18awith the driver.information_schemaquery returning 81), and the collate probe value (caught the basharm above).
test_docs_cover_the_corpuspasses; all parts named in TESTS.md.docs_style.shPASSED.cluster_tests166 -> 191 inexpected_tests.txt, which ci: run the cluster-half pytest tests, and make both jobs assert their size (#1016) #1018 now enforces -- so thisis the first port slice whose tests are gated from the commit that adds them.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Uf6UoeBRZYLQZa4KxNiw8a