knowledge: 9 insights — differential-run agreement, completion predicates, robots.txt source selection, client-side rate limiting, call-site migration (+5 amendments) - #22
Open
choiyounggi wants to merge 2 commits into
Conversation
…prompt tests, executable fixtures)
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 — 9 insight(s)
Drained the whole pending queue (
~/.dev-loop/queue/, 7 rows across 5 sessionfiles), then a second pass for 2 further candidates that arrived mid-flush
(15:29 / 15:30) — folded into this same branch so the flush stays one PR.
Result: 5 new pages, 5 amendments, 1 new category. Two candidate
claims were disproved during verification and the resulting directives were
rewritten before ingest — details under Verified best-practice (B1).
testing/quality/differential-run-agreementtesting/quality/tests-that-cannot-failtesting/quality/harness-reverse-controlsbackend/common/refactoring/signature-change-call-sites(new category)testing/quality/completion-predicatesbackend/common/integrations/robots-txt-and-source-selection(claim corrected)backend/common/reliability/client-side-rate-limitingtesting/async/async-testingtesting/data/test-data-and-isolation+platforms/filesystems/permissions-and-exec-bitsVerified best-practice
T1 — a differential "agree" verdict is scoped to inputs where the asymmetric state is reachable.
Checked: McKeeman, Differential Testing for Software, Digital Technical Journal
10(1) 1998 pp. 100–107 (the method is a pseudo-oracle: agreement is only as
strong as the inputs that could have exposed a difference);
https://arxiv.org/abs/2410.21904 (RIP — "Finding test cases to kill the alive
mutants in Mutation testing needs to calculate the Reachability, Infection and
Propagation(RIP) conditions": detection requires all three, so an unreached
dimension yields no verdict); https://pitest.org/quickstart/basic_concepts/
(No coverage is "the same as Survived except there were no tests that
exercised the line of code where the mutation was created" — the tools already
keep "never reached" separate from "reached and not detected");
https://stryker-mutator.io/docs/mutation-testing-elements/mutant-states-and-metrics/
(score = "detected / valid * 100"). The session's own evidence reproduces it:
lnpl diffon a read-then-create module →EQUIVALENT4/4 on the default seed,DIVERGENTA=failed B=completedunder--no-row. → verified.T2 — mutation granularity is per assertion, and the kill is attributed per test.
Checked: https://pitest.org/quickstart/basic_concepts/ — Killed = "a test
caught the mutation successfully", Survived = "the mutation was not detected
by the covering test", No coverage = no test exercised the line. Those are
exactly the three outcomes of a per-assertion mutation, and the per-test
attribution is what makes "which test reddened" the unit of proof rather than
"did the file redden". Session evidence: renaming
workflow Checkoutreddenedtest_source_compiles_to_the_committed_irbut nottest_node_ids_and_order_are_stable, which pins only the first node id and thetrailing capability ids. → verified.
T3 — a patch-based control must target a seam the path reads at call time.
Checked: https://docs.python.org/3/library/unittest.mock.html "Where to patch"
—
patch()"works by (temporarily) changing the object that a name points towith another one … you must ensure that you patch the name used by the system
under test", and "You patch where an object is looked up, which is not
necessarily the same place as where it is defined". The candidate is a genuine
extension of that rule: the name is patched correctly and still never read,
because an upstream caller resolved the defaulted value and passed it explicitly,
leaving the callee's
if x is Nonebranch dead for that path. Session evidence:patching
backend.seeded_entities→ control green (AssertionError: True is not false); patchingbackend.READ_OPS/backend._failure_attempts, both readunconditionally, → the expected
FAIL 2/4andFAIL 3/4. → verified.T4 — enumerate call sites by callee; a positional argument carries no name.
Checked: https://docs.python.org/3/reference/expressions.html (a call binds
positional arguments by position; the parameter name is simply absent from a
positional call site's source text, so a name search structurally cannot see
those callers); https://libcst.readthedocs.io/en/latest/codemods.html and
https://github.com/facebookincubator/bowler ("Safe code refactoring for modern
Python … guaranteeing that the resulting code compiles and runs") for the
sourced replacement action — match
Callnodes in a CST rather than text.Session evidence:
grep -rn "repo_rows" impl/tests/→ 13 hits, all keyword form;full suite →
Ran 472 tests / FAILED (failures=11), all from 8 positionalverify()call sites plus arows_for()helper feeding 5 more. → verified.D1 — the bracket-expression false positive, reproduced from scratch.
Checked: https://www.gnu.org/software/grep/manual/grep.html —
-F"Interpretpatterns as fixed strings, not regular expressions";
-cprints "a count ofmatching lines";
-v"Invert the sense of matching".https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap09.html — a
bracket expression matches a single character from the enclosed set.
Reproduced live on this machine (2026-08-04, macOS/BSD grep) on a 3-line
status file with one
[completed]and two in-flight lines:→ verified (reproducible command sequence, not just the original incident).
B1 — candidate claim DISPROVED; directive rewritten. The candidate asserted
"기관 자체 사이트는 전면 크롤링 거부(
Disallow: /)" withwww.i-sh.co.kras evidence.Live fetch 2026-08-04 shows that is wrong as stated:
www.i-sh.co.kr/robots.txtgivesUser-agent: *a path list only(
/admin,/cert,/upload,/gcms/brd, per-district board paths). TheDisallow: /lines belong to 15 named groups —GPTBot,ChatGPT-User,facebookexternalhit,BaiDuSpider,MJ12bot,OAI-SearchBot,PerplexityBot,Google-Extended,ClaudeBot,Claude-SearchBot,meta-externalAgent,Applebot-Extended,CCBot,aiohttp,DuckDuckBot.The candidate read the file's last line without its group header.
www.gh.or.kr/robots.txtis notDisallow: /— it returns HTTP 410,which RFC 9309 classifies as unavailable: "the crawler MAY access any
resources on the server". That is the opposite of the candidate's reading.
housing.seoul.go.kr→User-agent: * / Allow: /;apply.gh.or.kr→User-agent: * / Allow: /*.Grounded in https://www.rfc-editor.org/rfc/rfc9309.html: "Crawlers MUST use
case-insensitive matching to find the group that matches the product token and
then obey the rules of the group";
*applies only "If no matching groupexists"; multiple matching groups "MUST be combined into one group"; the product
token "should appear as a substring in the crawler's user-agent header"
(so a client on its library's default UA — aiohttp autogenerates one per
https://docs.aiohttp.org/en/stable/client_reference.html — can land in a named
disallowed group); 4xx → "MAY access any resources", 5xx/unreachable → "MUST
assume complete disallow"; five-redirect limit; "SHOULD NOT use the cached
version for more than 24 hours". The page's directive is therefore "read the
group your product token matches, and branch on the response status", with the
republishing-portal fallback as a secondary step — not the candidate's "the
origin blocks crawling". → verified (and materially more useful than the
candidate).
B2 — mechanism verified, vendor numbers NOT verified → field-tested.
Sourced the general claims: https://www.rfc-editor.org/rfc/rfc6749.html (the
token endpoint is reached by an ordinary HTTP request from the client, so
credential acquisition consumes the same request budget as data calls) and
https://www.rfc-editor.org/rfc/rfc6585.html (429 "indicates that the user has
sent too many requests in a given amount of time",
Retry-After). I couldnot confirm the candidate's specific "한도 2건/초" or a token-issuance quota
from Korea Investment & Securities' official developer portal — public sources I
found cite a different per-second figure, so the page carries no vendor
numbers and states the mechanism only (auth refresh inside
_headers()sitsoutside a throttle wrapped around the call layer; a zero-initialized
_last_request_atmakes the first wait evaluate to zero). The timestamped logevidence (POST
:00.354→ token:00.495→ rejected:00.543, on two separatetoken-issuance days, clean on cached-token days) is real production observation.
→ field-tested, labelled as such in frontmatter and stated plainly in the
page's Sources.
No candidate was dropped, and nothing was upgraded to
verifiedwithout a citedsource or a reproduction. Every cited link was fetched (HTTP 200) or is a
bibliographic citation with no URL (McKeeman 1998).
Existing-layer check
Routed via
INDEX.md→ domain indexes → every page whose "load when" overlapped.Pages read in full before writing (dedup + conflict + link decisions):
wiki/testing/quality/harness-reverse-controls.md,wiki/testing/quality/tests-that-cannot-fail.md,wiki/testing/quality/checks-that-cannot-pass.md,wiki/backend/common/reliability/timeouts-and-retries.md, plus thetesting,backend,debugging, andplatformsdomain indexes,INDEX.md,AGENTS.mdand
templates/page.md.Merged rather than created (merge-before-create):
tests-that-cannot-fail. Its step 1 already prescribes manualmutation testing; the candidate refines the granularity of that same case, so
a new page would have split one case in two. Added: a new step 2 (one mutation
per assertion, with a three-outcome table mapping to PIT's
Killed/Survived/No-coverage), a never-fails-pattern row for assertions
inherited into a shared base class/mixin/parameterised harness, two edge-case
rows, two
Instead ofrows, the PIT source, and the field reproduction.Renumbered the following steps;
last_verified→ 2026-08-04.harness-reverse-controls. The candidate explicitly lands in thatpage's "every case green" failure mode, but the page documented only Stryker's
two sandbox-mechanics causes. Added a third cause as a table row, a new Do
item 7 (patch a seam the path consults at call time; require the control red),
an edge-case row for the refactor that creates the dead default, an
Instead ofrow, theunittest.mock"Where to patch" source, and the fieldreproduction. Page stayed at 97 body lines (limit 120).
Overlaps found but judged distinct (kept separate, cross-linked):
checks-that-cannot-passvs D1 — exact mirror cases: that page is "a gateonly ever observed failing"; D1 is a predicate only ever observed
succeeding. Its grep material is about exit-status semantics (0/1/>1) and
-qmasking; D1's is about a literal degrading into a bracket expressionthrough quoting layers, and its subject is a polling monitor rather than a
gate. Cross-linked both ways via
related.harness-reverse-controlsvs T1 — same theme ("a uniform verdict is aproperty of the harness"), different case and different remedy: the control
there is a semantics-preserving mutation that must survive; here it is an
input that forces an unmodelled dimension to decide. Made a separate page and
cross-linked; also added a T1 pointer to
tests-that-cannot-fail's edge cases.timeouts-and-retriesvs B2 — that page owns the reactive path (its onlyrate-limit content is one row: "429 | Wait the
Retry-Aftervalue…"). B2 isproactive quota pacing and which requests count. Kept separate; B2's step 7
defers to it for the reactive half and
related-links it.externally-owned-defaultsvs B1 — B1's source host/path/id scheme is anexternally-owned default; referenced from B1's edge cases rather than
duplicated.
Conflicts flagged: none. No existing directive is contradicted or
overwritten; the two amendments only extend their pages.
Links added:
differential-run-agreement↔harness-reverse-controls,tests-that-cannot-fail,minimum-case-set;completion-predicates↔checks-that-cannot-pass,tests-that-cannot-fail,portable-shell-scripts,background-services;robots-txt-and-source-selection→timeouts-and-retries,externally-owned-defaults;client-side-rate-limiting→timeouts-and-retries,jwt-server-side,intermittent-failures;signature-change-call-sites→tests-that-cannot-fail,behavior-not-implementation.Invariants checked after the change: all touched pages ≤120 body lines; every
related:id across the whole wiki resolves to an existing page id; every inline[page-id]reference resolves; every markdown link inINDEX.md,wiki/testing/index.md,wiki/backend/index.mdandwiki/platforms/index.mdresolves to a file; no banned vague qualifier remains in the touched pages;
log.mdcarries the appendedingestandreviseentries.Routing decision
testing/qualityquality/differential-run-agreement.mdtesting/qualityquality/tests-that-cannot-fail.mdtesting/qualityquality/harness-reverse-controls.mdtesting/qualityquality/completion-predicates.mdchecks-that-cannot-passcovers grep gates and "a plan's verification command"), so a polling monitor's predicate belongs here rather than indebugging(nothing is being diagnosed) orplatforms/shells(the bracket-expression behaviour is not OS-specific)backend/integrationscommon/integrations/robots-txt-and-source-selection.mdexternally-owned-defaults(both are "a resource the repo does not own")backend/reliabilitycommon/reliability/client-side-rate-limiting.mdtimeouts-and-retries(proactive pacing vs reactive retry)backend/refactoring(NEW category)common/refactoring/signature-change-call-sites.mdNew category:
backend/common/refactoring. The candidate arrived taggeddomain: testingbecause a test suite is what caught the miss, but the practicegoverns changing application code, not writing tests — routing protocol step 1
sends it to the domain that owns the artifact being changed. No existing category
covers it:
testing/qualityis about what tests assert;testing/quality/behavior-not-implementationcovers "a behavior-preservingrefactor broke tests" (test coupling), which is the opposite direction — here the
tests were right and the migration was short;
debuggingis for diagnosing afailure, and nothing is being diagnosed. Placed under
backend/commonbecauseINDEX.mdassigns language-agnostic application-code concerns there, matchingthe existing
common/api-design,common/orm,common/errorspattern. Categoryname follows the lowercase-kebab-noun rule; the page id is
backend-common-refactoring-signature-change-call-sites, matching its path.INDEX.mdwas updated (the backend and testing "route here when" lines) — no newdomain, so the domain table itself is unchanged.
wiki/backend/index.mdgainedthe
refactoringsection plus two rows;wiki/testing/index.mdgained two rowsand an extended "Route here for" line.
Review note. Opened for review only; nothing is auto-merged. The one item
worth a maintainer's eye is B2's
field-testedconfidence — the mechanism andthe timestamped production evidence are solid, but the vendor's published quota
could not be confirmed, so the page deliberately carries no numbers. Reject that
page alone if the bar for a
reliabilityentry is a cited provider limit.Addendum — second pass (A1, A2)
Two candidates were written to the queue at 15:29 and 15:30, after the first
drain. They are folded into this same branch so the flush remains one PR.
Verified best-practice — second pass
A1 — feeding a line-oriented stream consumer from a test double. The claim was
that batching several answers into one
writesilently loses all but the first.Reproduced live, Node v25.8.1,
readline.createInterfaceover aPassThroughwith three sequential
questioncalls:Mechanism as the candidate described it: a readable hands the consumer one
concatenated chunk, and readline walks every newline in that chunk synchronously,
emitting
'line'for input noquestioncallback is waiting on — those lines aregone. Documented API surface: https://nodejs.org/api/readline.html. The
"one shared interface per interaction" half is the same root cause seen from the
other side (a second interface competes for the same buffered data).
→ verified by reproduction.
A2 — an executable test fixture: mode at creation, and where to put it.
Measured live, Node v25.8.1 / macOS / umask 022:
That second line is a caveat the candidate did not state and the page now carries:
rewriting an existing fixture keeps the original mode, so a fixture that changes
mode between tests must be deleted and recreated. API:
https://nodejs.org/api/fs.html (
writeFileSyncmode,mkdtemp).The EDR rationale is not vendor-documented — "a +x file created under a system
temp dir is a dropper heuristic" is operational practice, and the page labels it
as such rather than citing a detection vendor. What is verifiable and stated: the
fixture needs the bit, not the location, and a repo-local gitignored build-output
path additionally leaves
git statusclean when a run crashes (field evidence:25 fixtures moved, suite green 59/59, build dir empty afterwards).
→ verified for the mechanics, field-tested for the EDR rationale.
Existing-layer check — second pass
Read before writing:
wiki/testing/async/async-testing.md,wiki/testing/data/test-data-and-isolation.md,wiki/platforms/filesystems/permissions-and-exec-bits.md.Both candidates merged, no new pages:
testing/async/async-testing. Its "Async shape" table is exactly therouting structure this case needs, and its root rule ("the test must not finish
before the work does") is the same principle. Added one table row, two edge-case
rows (hang after the first record; a consumer rebuilt per prompt), one
Instead ofrow, the readline source and the reproduction. A separate pagewould have duplicated the table.
per-test directory, teardown) extends
test-data-and-isolation's existing"Filesystem / temp files" row — one new Do row plus two edge cases. The
mode mechanics half (set at creation, umask, creation-only semantics, EDR
location) extends
permissions-and-exec-bits, whose Do table already ownsexec-bit rules — two new Do rows. Cross-linked via
relatedin bothdirections rather than repeating the content.
Conflicts: none. Neither amendment contradicts an existing directive; both extend
tables their pages already own.
Index lines updated for all three pages (
wiki/testing/index.md×2,wiki/platforms/index.md×1) so the new use cases are routable. Re-ran theinvariant checks over the full wiki after these edits: every
related:id andinline
[page-id]resolves, every index link resolves, all touched pages remainunder 120 body lines.
Routing decision — second pass
testing/asyncasync/async-testing.mdtesting/dataandplatforms/filesystemsdata/test-data-and-isolation.md+filesystems/permissions-and-exec-bits.mdNo new categories in this pass.
Queue state after this flush: 0 pending rows. 9 candidates ingested; 3 later
re-emissions of B1/D1/B2 (the same session files re-appended their blocks at
15:37/15:40) were verified byte-identical to already-processed rows and retired
as duplicates without re-ingesting.