test: the docs gate checks that a table is still a table (#1026) - #1028
Conversation
b3bc46a to
81ce139
Compare
linuxhikerpm
left a comment
There was a problem hiding this comment.
Approving 81ce139b7d01688da59136481293c51e84b97c87.
This is the gate #1022 was missing. The control comes first, the splice is flagged at the orphaned block's line, the fence arm has its unfenced control, and an unclosed fence under-reports. CI is green, including pytest-guards at guard_tests 282 and docs_style.sh on the suites jobs.
The pytest file drives headerless_tables rather than reimplementing it, which is the right shape for a checker: a second python of the same rule would agree with itself. docs_style.sh already calls report(), and the 5-tuple change is consumed there.
Section 32 collides with #1027. guard_tests collides with #1022 and #1029. Re-derive on rebase. I will not merge it.
81ce139 to
28f3bb2
Compare
|
Rebased onto #1023's TOC entry for section 30 landed after 31. Nothing caught it, and the reason is specific: this file's link arms assert every contents-list link RESOLVES, which both orders do, and nothing asserts the numbering is monotonic. Placing my own entry meant choosing an order, so the fix is in this PR rather than deferred: I am adding the monotonicity arm to #1029, which already edits
Re-verified after the rebase: 282 passed / 688 checks with |
28f3bb2 to
d6be198
Compare
|
Added the ordering guard here rather than in #1029, correcting what I said above. A guard belongs with its fix -- putting it in #1029 would have reddened #1029 until this PR merged, which is a dependency between two independent PRs. Two arms in
Measured, by restoring main's order under the new arm: 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 exactly why a shuffled contents list was outside every arm in that file. The gap rule catches the section-number collision too, and that is the cause rather than a coincidence. Three open PRs each claimed a number another had taken (#1022 wanted 31, #1027 and this one both wanted 32). A number used twice leaves a gap in the section sequence, so one rule reddens on a duplicate and on an omission. The fixture names them apart: a missing entry gives This does not make #1024 unnecessary -- dropping the numbers removes the collision class entirely, where this only makes it visible. It does mean the next collision fails loudly instead of merging. |
d6be198 to
22ff304
Compare
|
Rebased onto Main's contents list is still out of order at three transitions, which this resolution sorts: Two rebases were needed: #1027 merged (TESTS.md + CHANGELOG conflict), then #1034 merged (CHANGELOG only). Both keep-both, and I checked both entries survived rather than assuming it. #1029 will need its |
22ff304 to
8c1573a
Compare
…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.
8c1573a to
21de2b1
Compare
I put the note and its measurement table between `stripe_row_limit` and `compression` in the set_options argument table. A blank line ends a markdown table, so the six arguments after it -- compression, compression_level, encode_effort, sort_by, ttl_column, ttl_interval -- rendered as a headerless block or as literal pipes. docs_style.sh passed this page with 14 checks, and passes the fixed page with 14 checks, because all seven of its rules are about prose. That is what #1028 adds a structure rule for; @OffgridwithJD found this reviewing #1022. The note now follows the table it was splitting, still inside the section that documents the setting, and the `stripe_row_limit` row points at it the way the GUC table's row already did. Verified: #1028's headerless_tables() flags docs/configuration.md at line 175 on the previous commit and flags nothing on this one; main was clean, so this branch introduced it. Both #1017 guards still pass in both harnesses. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EbyGSaU93XYQr8aH4NrUiw
jdatcmd
left a comment
There was a problem hiding this comment.
Approving. I verified both rules against the real defects rather than the fixtures, because a guard that lands green has only its fixture to stand on until someone does that.
The table rule fires on the measured case, and the measured case is mine. The splice this PR describes is live on #1022 right now, not in history: my #1017 note and its measurement table sit between stripe_row_limit and compression in the set_options argument table, leaving six of the nine arguments headerless.
branch docs/1017-... @1747cc7 headerless_tables(docs/configuration.md) -> [175]
origin/main clean
branch after the fix @5928438 clean
docs_style.sh passes the broken page with 14 checks and the fixed page with 14 checks. That is the argument for this PR, stated as a number.
I pushed the page fix to #1022 (5928438): the note now follows the table it was splitting, still inside the section that documents the setting. So this can merge in either order without arriving red.
The contents-list rule fires on the real damage too. Running _gaps over main's last twelve commits that touched TESTS.md:
9553e4dc toc gaps=[(29, 31), (31, 30), (30, 32)]
ab37f81d toc gaps=[(29, 31), (31, 30), (30, 32)]
d392b80f toc gaps=[(29, 31), (31, 30)]
82548eb3 none <- and silent on the eight before it
...
Three consecutive commits of main, exactly the 29, 31, 30 shape you describe, and no false positive on the rest. It would also have caught what I resolved by hand in #1022's merge this morning: a section numbered 31 twice, and an index entry left pointing at #30-...-type-matrix after your rename removed that heading.
Numbers checked, not read. guard_tests 287 runs green on your head (707 checks, 0 unrun).
One thing to fix, and I will take it. The comment under the value contradicts it:
guard_tests 287
# 282 -> 284: two arms about TESTS.md's own numbering ...
A reader arriving at 287 is told about 284. This file's whole case for existing is that the diff explains itself to a reviewer, so an incoherent note costs more here than elsewhere. I am rewriting that same region when I rebase #1022 on top of this, and I will fold the correction in there rather than send you round again.
Not blocking, for the record: headerless_tables keys on a leading |, so a GFM table written without leading pipes is invisible to it. That under-reports rather than false-positives, and no page in the tree uses that form. Worth a line in the docstring if you touch the file again.
#1028 landed while this was open. Three conflicts, resolved by file kind: - test/pytest/test_harness_deps.py: a python LIST is additive, both entries kept. - test/pytest/TESTS.md: both sides numbered a section 33, so this branch's test_docs_stripe_floor.py becomes 34 and follows #1028's section. #1028's own new rule now enforces that ordering, and it reports toc=34 sec=34 with no gap, no inversion and no dangling anchor. - test/pytest/expected_tests.txt: re-derived, not resolved. Three branches had each added three arms to 277 and each derived 280, every one correct against a tree holding only its own three. Keeping either side ships a value no tree collects, and so does adding the deltas up. Collection on the merged tree says 290 and 205. Also dropped the note #1028 left under its value, which described a move to 284 beside a value of 287; I said in review I would take that rather than send the author round again. Verified: guard half green at 290 (715 checks, 0 unrun), docs_style.sh 14 checks PASSED. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EbyGSaU93XYQr8aH4NrUiw
#1022 landed while this was open. Two conflicts: - test/pytest/TESTS.md: main's test_docs_stripe_floor.py took 34, so this branch's two sections become 35 and 36. #1028's numbering rule reports toc=36 sec=36, no gap, no inversion, no dangling anchor. - test/pytest/expected_tests.txt: re-derived, not resolved. Both sides had a guard number measured against a tree holding only its own arms. Collection on the merged tree says 298 and 217. Verified: guard half green at 298 (737 checks, 0 unrun). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EbyGSaU93XYQr8aH4NrUiw
Closes #1026.
docs_style.shenforced seven rules over every user-facing page: sentence length, the idiomlist, em and en dashes, prose double-hyphens, conflict markers, the nav entry, and every
VERSIONcitation. All seven are about prose. Nothing checked structure, so a markdowntable that had stopped being a table passed the gate whose whole purpose is keeping those
pages readable.
The measured case
On #1022, a note and a second table spliced into the middle of
configuration.md'sset_optionsargument table:Six of the nine
set_optionsarguments rendered as a headerless table, anddocs_style.shpassed with 14 checks. Found by @linuxhikerpm in review. I had reviewed that change twice
-- sentence length, the guard's scoping claim, the chunk-group question, a three-row mutation
table -- and never once asked whether the markdown still rendered. That is a worse miss than
anything I did check, because it is visible to a reader of the published page and the others
are not.
It was the second splice that day. The first gave the GUC table no blank lines, which made
an
awk RS=''guard readstripe_row_limit's row andchunk_group_row_limit's row as onerecord and pass on
main. Both are the same fact: a markdown table is a contiguous run of|lines, and a blank line is structural.
The false-positive budget, measured before landing
This is what a static guard in this tree owes, and it is the part worth checking hardest:
I read all five. Every one is a genuine run of
| name | description |rows with no headerafter prose -- not a false positive among them. Neither file is in the gate's scope, so the
rule does not reach them and I have not fixed them here: widening the scope is a separate
decision, and
TESTS.mdis a test document rather than a user-facing page.Fences by line, not by regex
The file already strips fences with
re.sub(r'```.*?```', '', t, flags=re.S)for thedouble-hyphen rule. I did not reuse it:
scanned as prose. State-tracking swallows what follows instead -- which under-reports rather
than inventing a table, and that is the safe direction for a new guard.
Both are asserted rather than argued: there is an arm for a shell pipeline inside a fence, and
an arm for an unclosed fence.
Five arms, control first
test_a_well_formed_table_is_not_flaggedtest_rows_orphaned_by_a_splice_are_flagged_with_their_linetest_a_pipe_inside_a_fenced_code_block_is_not_a_tabletest_an_unclosed_fence_does_not_swallow_the_rest_of_the_filetest_the_documents_the_gate_checks_are_cleanTest plan
configuration.mdgives oneheaderless block at line 167 and
docs_style.shrc=1; restoring it gives rc=0.guard_tests277 -> 282.NO_CLUSTER, inTESTS.mdas section 31, and the classifier arm passes.docs_style.shPASSED, 11 checks.🤖 Generated with Claude Code
https://claude.ai/code/session_01Uf6UoeBRZYLQZa4KxNiw8a