docs(claude): a pytest count is a property of a run, never of a suite (phaze-ljfi5) - #540
Merged
Merged
Conversation
β¦ (phaze-ljfi5) This repo treats the pytest summary line as the standard of green, correctly. Nothing said that the COUNT in it is not a stable quantity. It describes the population that RAN, not the suite, so two green lines are not comparable and neither carries what you would need to compare them. QUALIFIES the pytest-summary-line rule, does not weaken it. Every other paragraph in that section is about a status that LIES; this is the adjacent case where nothing lies and a reader is still misled, and the note says so explicitly so it cannot be read as licence to trust a gate less. === TWO MECHANISMS, SPLIT BY WHETHER THE LINE ADMITS TO IT === The bead named three sources of variation -- marker filter, --deselect set, selected-vs-escalated recipe. Measured on this tree 2026-08-25, the first two are one mechanism: `grep -rn -- "--deselect" justfile pyproject.toml .github/ scripts/` returns nothing, and `uv run pytest --collect-only -q -m browser tests/browser` collects exactly 180 -- so the `180 deselected` in every full-suite line in this file is the `-m 'not browser'` marker filter, all of it. All three are still named; the note states the measured relationship rather than implying a --deselect set that does not exist, and says a future one lands in the same visible counter. That regrouping is what makes the point sharper than the bead had it: the marker filter is DECLARED by the line, and the recipe is NOT. Where the gate selects, it hands pytest explicit node ids, so unselected tests are never collected and leave no `deselected`, no trace at all. The variation that dwarfs the other by a factor of 19 is the invisible one. === DELIBERATELY DOES NOT ENUMERATE THE GATE'S VERDICTS === An earlier draft said "RUN and ESCALATE are two populations". phaze-fqfds landed a third (a docs-only diff runs the prose floor), which would have dated that sentence within the day. The note now makes the quantifier-free claim -- one command, several populations, and the VARIATION is the hazard rather than any particular count of branches -- and points a reader wanting the enumeration at scripts/select_impacted_tests.py, which is the thing that decides. Enumerating them here is a separate docs bead's territory, and a fixed enumeration is the trap phaze-g9cus had just finished removing from this same file three times over. === COMPOSES WITH phaze-g9cus RATHER THAN AROUND IT === g9cus landed while this bead was in flight and took two things off the table: it forbade re-enumerating the ledger's field list anywhere but the ledger section, and it established the report-vs-rc-only ratio with its mechanism and a warning not to read it forward. An earlier draft did both. Neither is restated now. The ledger paragraph instead states only what SURVIVES a report being present: no field records which branch of the recipe ran, the key is (tree hash, validate-cmd hash), and every phaze boundary hashes the same command -- so a replayed count is a number with no population attached. === FIGURES === Selected: 417 passed, 1 skipped in 35.57s (dev/fastsuite, 2026-08-25, already the check-fast row of the recipes table). The bead and the dispatch both cited 8027 for the escalated side; the ledger's report entries read 8038 of 8041. Both are real and both are in this file -- g9cus's 8027 was a green full suite on a pre-opt-in tree, the 8038 is the report beside it. Rather than pick one, the note uses the pair: two green full-suite runs eleven apart, because the suite GREW between them. That is a third axis of variation and it lands squarely in this bead's scope -- it is why "the suite passes" does not survive being carried from one run to the next even with the recipe held fixed. The headline comparison is given as ~8,000 and ~20 min, since neither exact figure is the argument; the factor of 19 is. Cross-references phaze-qsyc0's "a gate's M is a property of a RUN, never of a COMMAND" as the same idea one level down, rather than restating it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GazEx6kCcyQuRvifWb3aBF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a short note to the end of
CLAUDE.md's "A gate is green only if its own pytest summary line says so" section: the summary line is the standard of green, but the count in it is not a portable quantity. It describes the population that ran, not the suite.This qualifies the pytest-summary-line rule; it does not weaken it. Every other paragraph in that section is about a status that lies. This is the adjacent case where nothing lies and a reader is still misled, and the note opens by saying so, so it cannot be read as licence to trust a gate less.
Two mechanisms, split by whether the line admits to it
uv run pytest --collect-only -q -m browser tests/browsercollects exactly 180, andgrep -rn -- "--deselect" justfile pyproject.toml .github/ scripts/returns nothing. So the180 deselectedin every full-suite line in this file is the-m 'not browser'marker filter, all of it β the bead's first two "sources of variation" are one mechanism, and the note says so rather than implying a--deselectset that does not exist.deselectedand no trace at all. 417 passed / 35.57s selected against ~8,000 / ~20 min for the whole suite β a factor of 19, both green, both printing a summary line. The variation that dwarfs the other is the invisible one.Deliberately does not enumerate the gate's verdicts
An earlier draft said "RUN and ESCALATE are two populations". phaze-fqfds landed a third (a docs-only diff runs the prose floor), which would have dated that sentence within the day. The note makes the quantifier-free claim instead β one command, several populations, and the variation is the hazard rather than any particular count of branches β and points a reader who wants the enumeration at
scripts/select_impacted_tests.py, which is the thing that decides. Enumerating them inCLAUDE.mdis a separate docs bead's territory, and a fixed enumeration is the trap phaze-g9cus had just finished removing from this same file three times over.Composes with phaze-g9cus rather than around it
g9cus landed mid-flight and took two things off the table: it forbade re-enumerating the ledger's field list anywhere but the ledger section, and it established the report-vs-rc-only ratio with its mechanism and a warning not to read it forward. An earlier draft did both. Neither is restated. The ledger paragraph now states only what survives a
reportbeing present: no field records which branch of the recipe ran, the key is(tree hash, validate-cmd hash), and every phaze boundary hashes the same command β so a replayed count is a number with no population attached.Figures
The bead cited 8027 for the escalated side; the ledger's
reportentries read 8038 of 8041. Both are real and both are already in this file β g9cus's 8027 was a green full suite on a pre-opt-in tree, the 8038 is thereportbeside it. Rather than pick one, the note uses the pair: two green full-suite runs eleven apart, because the suite grew between them. That is a third axis of variation and it is why "the suite passes" does not survive being carried from one run to the next even with the recipe held fixed.Validation
bh work check phaze-ljfi5, seatcounts(phaze_counts_cdd93696_test, Redis DB 21):bh work submitreplayed that verdict (validation verdict reused (sha 0a43a8d, tree 8adf24d, recorded 2026-08-25T13:55:36-07:00)) and ran no tests of its own β thecheckrun above is the measurement.The gate demonstrated the note's own claim. It produced a third green count β 193, not 417, not ~8,000 β and the JUnit hook recorded
{"tests": 193, "passed": 193, ...}onto the ledger entry thatsubmitthen replayed. The durable record for this bead's submit says "193 passed", under the same key shape as an 8038-passed full-suite verdict, with nothing in it naming which of the two you are looking at.Notes for the reviewer
GATE_EXITtable's "green" row is unsatisfiable on this path. Left alone deliberately β a separate docs bead owns the fast gate's un-enumerated outcomes.CLAUDE.md, +56 lines, no code touched.π€ Generated with Claude Code
https://claude.ai/code/session_01GazEx6kCcyQuRvifWb3aBF