knowledge: 4 verified insights — surviving-mutant triage, source-text wiring assertions, query state vs fetch state, python text-io encoding - #52
Open
dch0202-rsquare wants to merge 2 commits into
Conversation
…ing assertions, query state vs fetch state, python text-io encoding)
…, regex-reach claim, equivalence gate, missing state cells)
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.
Knowledge flush — 4 insights
Queue drained: 4 pending candidates across 3 session files
(
9dab7c31…×2,a26ea793…×1,df9561a2…×1). All 4 ingested; 0 dropped.Verified best-practice
1. Classify a surviving mutant before writing a test for it (
testing)Claim. When a mutant survives, decide whether it is a missing test, an
equivalent mutant, or an uncovered line before changing anything. When it is
equivalent, the branch it mutates is redundant — delete it and correct the
comment that justified it, rather than adding a test.
Sources checked (all opened this session).
— "There is no definitive way for Stryker to find and ignore them"; the
documented remedy is "by finding these by hand, which is time consuming and
try to rewrite the code so it won't occur, or accept that you won't make
100%". This is the primary support, and both halves are load-bearing: the
docs name rewriting the code and accepting a classified survivor as the two
outcomes — neither of them is "add a test for it".
behave differently than the unmutated class. These mutants are referred to as
equivalent mutations"; "The resulting mutant behaves in exactly the same
way as the original"; and the two distinct verdicts "Survived: The mutation
was not detected by the covering test" vs "No coverage: The same as Survived
except there were no tests that exercised the line of code where the mutation
was created" — which is the three-way split the page's step-1 table encodes.
— the mutant state set and
detected / validscoring.faults and requiring failure is the measurement.
How verified. The mutation-testing docs substantiate the classification and
both remedies directly. The comment-correction step is the session's field
observation, recorded as a dated field-measurement line in the page's Sources
rather than attributed to a doc. After the adversarial pass, the page no longer
lets one hand-run input establish equivalence: the same Stryker sentence that
supports the remedy ("no definitive way … to find and ignore them") is what
makes a domain argument the required evidence for deleting a branch.
Confidence: verified (classification + both remedies doc-backed; the
comment-correction step carries its field measurement inline).
2. Anchor source-text wiring assertions per site instead of counting (
testing)Claim. A guard that asserts by regex that a call is present, using
toHaveLength(n)or>= nover match count, stays green when one of the N callsites is deleted. Bind each occurrence to its own context — a bounded order
anchor
A[\s\S]{0,N}Bwhose anchor occurs exactly once in the file, or afunction-body slice — and prove each by deleting only its own site.
Sources checked (all opened this session).
— the Block Statement mutator "removes the content of every block statement".
Corrected after the adversarial pass: this empties a whole block rather than
removing one call, so the per-site deletion is a hand-seeded mutation and
the page now says so instead of claiming tool support it does not have.
mutation was not detected by the covering test": the per-site deletion that
leaves the suite green is exactly this verdict.
— documents
{min,max}as bounded repetition and?as the non-greedy formthat "will try to match as few times as possible". Corrected after the
adversarial pass: an earlier draft presented MDN's
{min,max}table as aprose quotation, and claimed the lazy form limits the anchor's reach. Neither
holds — see the Node measurement below.
toHaveLengthcompares a.lengthvalue; ona match array it is a total and carries no per-site information.
— cited for the change-detector category (the refactor cost a source-text
guard accepts), without a quotation: the sentence an earlier draft
attributed to this article is a reader comment, and the body was not
retrievable in full. See the cross-check table, row 1.
How verified. The "a lower bound survives deleting one of N" property is
arithmetic and is stated as such. The regex mechanism was measured, not
assumed: in Node,
/ANCHOR\([\s\S]{0,20}CALL\(/and its lazy variant returnidentical verdicts on four inputs (in range, call-before-anchor only, beyond the
bound, and call on both sides of the anchor), so the bound plus a once-occurring
anchor is what constrains the match. The concrete red/green pair (count
assertion green vs anchored assertion red on the same mutant, comment-only
control green) is the session's field measurement, dated in the page's Sources.
Confidence: verified.
3.
data === undefinedis not "loading" in TanStack Query (frontend)Claim. A component contract of
data | undefinedcollapses two orthogonalaxes. A disabled (
enabled: false) or offline-paused query isstatus: 'pending'with
isLoading === falseandisError === falseanddata === undefined, so"undefined means loading" renders a spinner no fetch will resolve.
Sources checked (all opened this session).
"The
statusgives information about thedata: Do we have any or not? ThefetchStatusgives information about thequeryFn: Is it running or not?";"Background refetches and stale-while-revalidate logic make all combinations
for
statusandfetchStatuspossible"; the value definitions includingpaused: "The query wanted to fetch, but it is paused".isLoading"Istruewhenever the first fetch for a query is in-flight. Isthe same as
isFetching && isPending";data"Defaults toundefined".— a disabled query with no cached data is "status === 'pending' and
fetchStatus === 'idle'"; "Lazy queries will be in
status: 'pending'rightfrom the start because
pendingmeans that there is no data yet … you likelycannot use this flag to show a loading spinner"; the
skipToken/refetchincompatibility quoted in the page's edge table.
"Queries can be in
state: 'pending', butfetchStatus: 'paused'if they aremounting for the first time, and you have no network connection"; "it might
not be enough to check for
pendingstate to show a loading spinner".How verified. Docs above, plus a local source check of the shipped build:
@tanstack/query-core@5.100.14,build/modern/queryObserver.jsline 308const isPending = status === "pending", line 310const isLoading = isPending && isFetching, line 332isPaused: newState.fetchStatus === "paused". The derivation in the shippedcode matches the reference, so
pending+ non-fetchingyieldsisLoading === falsewithdata === undefined.Confidence: verified.
4. Prove a Python
encoding=fix withEncodingWarning, not byte round-trip (backend/python)Claim. On a UTF-8 locale, removing
encoding="utf-8"fromopen()producesbyte-identical output, so a round-trip regression test is green on the defect.
Run the real entry point under
-X warn_default_encoding -W always::EncodingWarningand assert zero warning lines naming the file under test. Scope correction from
the adversarial pass: this replaces the round-trip only for an omitted
argument —
EncodingWarningnever fires on an explicitly wrong value, so thepage keeps a value assertion (run under a non-UTF-8 locale) for the encodings
you set on purpose.
Sources checked (all opened this session).
EncodingWarning"is emitted when theencodingargument toopen()is omitted and the default locale-specificencoding is used"; "The
-X warn_default_encodingoption and thePYTHONWARNDEFAULTENCODINGenvironment variable are added. They are used toenable
EncodingWarning"; "Developers using macOS or Linux may forget thatthe default encoding is not always UTF-8".
3.15; "many Python developers using Unix forget that the default encoding is
platform dependent … Inconsistent default encoding causes many bugs"; "this
change mostly affects Windows users". This is the mechanism for "invisible on
your machine".
open(): "The defaultencoding is platform dependent (whatever
locale.getencoding()returns)";"For reading and writing raw bytes use binary mode and leave encoding
unspecified".
How verified. Reproduced locally this session (CPython 3.14.6, macOS,
locale.getpreferredencoding(False) == 'UTF-8'): a script containing oneopen(p, "w")and oneopen(p, "w", encoding="utf-8")produced byte-identicaloutput — the round-trip assertion cannot distinguish them. Running
python3 -X warn_default_encoding -W always::EncodingWarning script.py out.txtemitted exactly one line, naming the unencoded call by file and line number; the
same run without the flag emitted nothing (which is why the page requires proving
the harness reddens on a deliberately unencoded
open()).Confidence: verified.
Adversarial cross-check (run before this PR was opened)
Cross-Check: independent
claudeCLI (headless,--permission-mode plan) reviewed the wiki diff for fabricated citations, overreach, internal contradiction, bare prohibitions, and vague qualifiers — it returned 18 findings (4 critical, 9 warning, 5 info); every critical was re-verified by me against the primary source or by measurement, and all 18 were fixed before this PR was created.The four criticals were real, and two of them were citation defects:
source-text-wiring-assertionsquoted "you cannot safely refactor code if you know you need to adapt the tests afterwards…" as the Google Testing Blog article's own sentencetesting-quality-guard-shape-vs-consequence— I inherited it from there rather than opening the source. That bullet is corrected in this PR with the correction stated inline{0,20}and{0,20}?return identical verdicts on all four inputs, and a call appearing both before and after the anchor still matchesNand an anchor that occurs exactly once. Added an occurrence-count step, a "no unique anchor" row, and the measurement as a source. A separate MDN pseudo-quote (a table rendered as prose) was also removedsurviving-mutant-equivalence-triageauthorised deleting production code on the basis of one hand-run input, while its own cited source says "There is no definitive way for Stryker to find and ignore them"No coverageverdict; step 2 requires a stated argument over the branch's whole input domain and routes to the missing-test row when that argument cannot be written; step 5 splits a moved pass count into behavior-test vs implementation-test causesWarnings fixed: selective half-quote of the Stryker remedy; the universal claim that any change in pass count means misclassification; the missing
success+pausedcell (with astatus: 'error'row that had collapsed the fetch axis intoany, contradicting the page's own premise) in a table that step 5 makes a coverage contract;applies_to: generalon a page whose every field name is TanStack-specific (now[react, tanstack-query], with an edge row for single-axis caches); the "keep the flag on the test invocation only" step contradicting the next step's "enable it repo-wide"; and the claim that a round-trip test "can only fail on a machine you are not testing on" — plus the gap it hid, thatEncodingWarningfires only on an omitted argument and says nothing about an explicitly wrong one (new step 6 keeps a value assertion for those).Info fixed: banned qualifiers "usually", "commonly", "generally" removed from directive sentences; a "sixth combination" ordinal that did not match its own table.
Re-checked after the fixes: 183 pages / 0 duplicate ids, 0 unresolved
[page-id]refs in the new pages, 0 broken index links, all four sections present in each page, bodies 83–94 lines (limit 120).Existing-layer check
Routed each candidate via
INDEX.md→ domainindex.md, then read every pagewhose "load when" line overlapped.
Pages read: testing-quality-tests-that-cannot-fail, testing-quality-harness-reverse-controls, testing-quality-behavior-not-implementation, testing-quality-guard-shape-vs-consequence, frontend-data-fetching-async-ui-states, frontend-state-client-vs-server-state, frontend-data-fetching-race-conditions, platforms-environment-timezone-and-locale, backend-python-language-mutable-state-traps, backend-python-language-bytecode-cache-staleness
Overlaps found and what was done.
testing-quality-tests-that-cannot-failrelated:both waystesting-quality-harness-reverse-controlsrelated:both ways, and the new page routes uniform-verdict cases to ittesting-quality-behavior-not-implementationtesting-quality-guard-shape-vs-consequencerelated:both waysfrontend-data-fetching-async-ui-statesisLoadingvsisFetchingin one line. It has no coverage of the status × fetchStatus product, and its four-state model has no cell for disabled/pausedrelated:both waysfrontend-state-client-vs-server-state,frontend-data-fetching-race-conditionsisPending/fetchStatus/isLoading/isFetching: zero hits. No overlapplatforms-environment-timezone-and-localeTZfor tests. Says nothing about text-encoding defaults orEncodingWarning(repo-wide grep forEncodingWarning/warn_default_encoding/getpreferredencoding/cp949: 0 hits before this PR)backend/python/language;related:both ways, new page routes upward for the general casebackend-python-language-mutable-state-trapsbackend-python-language-bytecode-cache-staleness.pyfiles, which insight 4's harness doesrelated:both ways; new page carries an edge row routing to itConflicts flagged: none. The one directive that needed adjusting
(
tests-that-cannot-fail's whole-suite row) was incomplete rather thancontradictory, so it was refined in place and routed onward, per
wiki-ingeststep 4.Health checks run on the checkout after the edits: 183 pages, 0 duplicate
ids; 0 unresolved
[page-id]references introduced (the 3 the scan reports arepre-existing false positives — a regex character class in two testing pages and
the literal
[openai-compatible]in an LLM page); 0 broken relative links fromany index; all 4 new pages 75–80 body lines (limit 120).
Open-PR check
Listed with
gh pr list --repo choiyounggi/dev-loop --state open --search "head:knowledge/".Four open heads:
knowledge/dch0202-20260806-183029knowledge/dch0202-20260806-172420knowledge/dch0202-rsquare-20260806-142309(head ref deleted on remote; diffed viarefs/pull/49/head)knowledge/dch0202-20260806-130040related:id and one edge-row rewording); noted as a possible textual conflict for the owner to resolve at merge, not a content duplicatePer-candidate verdict: 1 = new, 2 = new, 3 = new, 4 = new.
No candidate was folded or dropped — no open PR carries any of these four
insights.
Note for the owner: #50, #49 and this PR all add pages under
wiki/testing/qualityand all append a row towiki/testing/index.md, sowhichever merges second will need the index rows rebased. The page files
themselves do not collide.
Routing decision
testing / quality→testing-quality-surviving-mutant-equivalence-triage(new page)qualityalready owns assertion strength and mutation verificationtesting / quality→testing-quality-source-text-wiring-assertions(new page)frontend / data-fetching→frontend-data-fetching-query-state-vs-fetch-state(new page) + 1 edge row and arelated:link onfrontend-data-fetching-async-ui-statesdata-fetchingalready owns in-UI fetching statesbackend / python / language→backend-python-language-default-encoding-in-text-io(new page)python/languageis described inINDEX.mdas the home for "language traps"Why insight 4 went to
backendand nottestingorplatforms. Thedirective changes Python source (
encoding=at every text-mode call site) andits test is a property of that language's tooling, so the routing protocol's
"own the artifact you will change" rule puts it in
backend/python. It routesupward to
platforms-environment-timezone-and-localefor the generalhidden-environment-input case and to
testing-quality-tests-that-cannot-failfor proving the harness reddens.
Plumbing updated:
wiki/testing/index.md(+2 rows),wiki/frontend/index.md(+1 row),wiki/backend/python/index.md(+1 row),log.md(+1 ingest entry).INDEX.mdunchanged — no new domain, and everytarget domain's "route here when" line already covers these cases.
Decision Log (AI 생성)
의도 — 무엇을 / 왜
~/.dev-loop/queue에 쌓인 pending 후보 4건을 검증 통과시켜 wiki 에 편입하는 것이 목적. 각 후보를 1차 출처(공식 문서)로 확인하고, 2건은 로컬에서 재현(CPython 3.14.6 EncodingWarning,@tanstack/query-core@5.100.14queryObserver.js)해confidence: verified근거를 만들었다.tests-that-cannot-fail)가 이미 ~100 body line 이라 절차를 덧붙이면 ≤120 규칙을 깬다. 대신 그 페이지의 "surviving mutant = missing test" edge 행을 분류 우선으로 정정하고 새 페이지로 라우팅하도록 고쳤다.guard-shape-vs-consequence)까지 같은 PR 에서 정정했다 — 알면서 거짓 귀속을 남길 수 없다고 판단.배제한 대안 — 무엇을 안 했나 / 왜
testing/이 아니라backend/python/language/로. 지시가 바꾸는 산출물이 Python 소스이고 판별자가 그 언어 도구의 성질이라, 라우팅 프로토콜의 "바꿀 artifact 를 소유한 도메인" 규칙을 따랐다.EncodingWarning은 인자 누락만 잡는다 — 명시했지만 틀린 값(encoding="latin-1")은 값 단정이 아니면 아무도 못 잡으므로 둘을 병행하게 했다.최영기 <dch0202@rsquare.co.kr>로 커밋했다. 이 레포는 public 이고, 마침 열려 있는 PR knowledge: 9 insights — closed value table widening, guardrail read-vs-write correction, dispatch binding taxonomy #51 이 "public 레포에는 forge no-reply 주소를 쓰라"는 페이지를 추가하는 중이라 상충 소지가 있다 — 바꿀지는 작성자 판단.리뷰어가 볼 곳 — 신뢰성 판단 포인트
wiki/testing/quality/surviving-mutant-equivalence-triage.md:49(step 2) — 이 단계가 운영 코드 분기 삭제를 승인하는 게이트다. 도메인 논증 요구가 충분한 강도인지 봐 달라.wiki/testing/quality/source-text-wiring-assertions.md:39(step 2~3) — anchor 유일성 + bound N. 적대검증 전 버전은 lazy quantifier 가 reach 를 제한한다고 틀리게 적었다가 실측으로 뒤집힌 자리다.wiki/testing/quality/guard-shape-vs-consequence.md(Sources 마지막 bullet) — 이번 PR 범위 밖이지만 위조 인용을 정정한 out-of-band 수정. 되돌릴지 판단 필요.wiki/frontend/data-fetching/query-state-vs-fetch-state.md(step 2 표) — step 5 가 이 표를 테스트 커버리지 계약으로 못박으므로 빠진 셀이 곧 커버리지 구멍이다. 8행이 status × fetchStatus 를 다 덮는지 확인해 달라.wiki/testing/index.md— knowledge: one test per success-return site when a handler applies one policy at several returns #50, knowledge: 3 verified testing-quality insights (value-preserving refactor tests, unasserted return fields, stale artifact baselines) #49 도 같은 파일에 행을 추가한다. 두 번째로 머지되는 쪽이 이 행을 rebase 해야 한다(페이지 파일 자체는 충돌 없음).