knowledge: 7 insights — robots.txt group attribution, done-predicate controls, pyc staleness, client throttling, call-site enumeration - #24
Open
choiyounggi wants to merge 1 commit into
Conversation
5 new pages, 3 revised, 1 new category (backend/common/refactoring).
New:
- backend/common/integrations/crawl-permission-by-user-agent (RFC 9309 group
attribution; 4xx = MAY access; client-library default UAs as denied tokens)
- testing/quality/polling-completion-predicates (negative-control a done
predicate; count matches; grep -F for bracketed status tokens)
- backend/python/language/bytecode-cache-staleness (timestamp+size pyc
validation at 1s resolution; clear cache / bump mtime / PEP 552)
- backend/common/reliability/client-side-rate-limiting (throttle the transport,
count the token fetch, stamp the clock at dispatch)
- backend/common/refactoring/call-site-enumeration (enumerate by call target,
not by parameter name; migrate test helpers first)
Revised: testing/data/test-data-and-isolation (env-derived write paths),
platforms/shells/portable-shell-scripts (${VAR:-} vs ${VAR-}),
testing/quality/harness-reverse-controls (2 routing edge cases).
Candidate #1's evidence was refuted on live re-fetch and the page was rewritten
around the mechanism that holds; logged as a correction entry in log.md.
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 — 7 insight(s)
Drained
~/.dev-loop/queue(7 pending rows across 5 session files). Result:5 new pages, 3 revised pages, 1 new category, 2 log entries — including one
correction, where live re-verification refuted the candidate's stated evidence
and the page was rewritten around the mechanism that actually holds.
backend/common/integrations/crawl-permission-by-user-agent— rewritten, candidate's evidence refutedtesting/quality/polling-completion-predicates~/Library/LaunchAgentstesting/data/test-data-and-isolationbackend/python/language/bytecode-cache-stalenessbackend/common/reliability/client-side-rate-limitingbackend/common/refactoring/call-site-enumeration(new category)VAR=to disable a feature read as${VAR:-default}platforms/shells/portable-shell-scriptsVerified best-practice
1. robots.txt and scrape-source selection — candidate evidence refuted, page rewritten
Candidate claimed: agency sites blanket-deny crawling (
www.i-sh.co.krrobots.txt"last line
Disallow: /";www.gh.or.krlikewiseDisallow: /), so route to thepermissive upstream portal instead.
Checked (live fetch, 2026-08-04) — two of the four claims are wrong:
www.i-sh.co.kr= blanketDisallow: /User-agent: *group disallows only specific path prefixes (/admin,/upload,/gcms/brd, …) and has no blanket rule. The thirteenDisallow: /lines each open a named group: GPTBot, ChatGPT-User, facebookexternalhit, BaiDuSpider, MJ12bot, OAI-SearchBot, PerplexityBot, Google-Extended, ClaudeBot, Claude-SearchBot, meta-externalAgent, Applebot-Extended, CCBot, aiohttp, DuckDuckBotwww.gh.or.kr= blanketDisallow: /housing.seoul.go.kr=Allow: /text/plain:User-agent: */Allow: /apply.gh.or.kr=Allow: /*text/plain:User-agent: */Allow: /*Sources checked: RFC 9309 §2.2.1
(case-insensitive product-token match; multiple matching groups MUST be combined;
*only as fallback when no group matches), §2.3.1.1–2.3.1.4 (2xx follow; ≤5 redirects;
4xx MAY access; 5xx "MUST assume complete disallow"), §2.5 (24-hour cache ceiling) —
plus the four live
robots.txtfetches above.What the page says instead: the candidate's conclusion (check other publishers)
survives as directive 4, but the mechanism it gave was a misreading. The page is
built on the rule that actually governs: attribute every
Disallowto itsUser-agentgroup before concluding anything, and decide from the HTTP statuscode, not the rendered body. The
aiohttpfinding is the sharp, checkable payoff —a Python scraper sending its client library's default UA lands in a blanket-denied
group that the very same scraper with an explicit UA never matches. →
verified.2. Polling completion predicates
Claim: a text-match "everything finished" predicate must be validated against the
not-yet-finished state; bracketed status tokens need
grep -F.Verified by reproduction (2026-08-04). Status board with 1 of 4 done:
Every status word contains a character from
{c,o,m,p,l,e,t,d}, so as a BRE thebracket expression matches all four lines and the "nothing unfinished" test is
vacuously true on the first poll.
Sources checked: POSIX grep
("-F Match using fixed strings. Treat each pattern specified as a string instead of a
regular expression"; BRE by default), POSIX RE §9.3.5 bracket
expressions,
POSIX shell quote removal.
→
verified.3.
$HOMEredirection for filesystem test isolationClaim: override
process.env.HOMEin the test rather than widening the productionsignature with a test-only directory parameter;
os.homedir()re-reads$HOMEper call.Verified by reproduction (Node v25.8.1, 2026-08-04) — mutating
process.env.HOMEbetween two calls in the same process changed the second return value, and restoring
it restored the original. That rules out caching, which is the load-bearing part of the
claim:
Source checked: Node os.homedir() — "On POSIX, it
uses the
$HOMEenvironment variable if defined. Otherwise it uses the effective UID…";Windows reads
USERPROFILE. No caching is documented. →verified.4. CPython bytecode-cache staleness
Claim: an equal-byte-size revert inside the same second reuses stale
.pyc, so amutation harness reports results detached from disk.
Verified by reproduction (Python 3.14.6, macOS, 2026-08-04). With mtime pinned via
touch -tand every revision exactly 18 bytes:Decoded
.pycheader:flags=0(timestamp invalidation),mtime=1785812400,size=18— exactly matching
os.stat('mod.py'). The forward direction reproduces too (a same-sizemutation having no effect), which is why both uniform harness verdicts are reachable.
Sources checked: CPython import
reference — "By default, Python does
this by storing the source's last-modified timestamp and size in the cache file"; "the
import system then validates the cache file by checking the stored metadata … against
the source's metadata"; hash-based
.pyc"store a hash of the source file's contentsrather than its metadata". PEP 552,
py_compile (
PycInvalidationMode).→
verified.5. Client-side rate limiting and the hidden token request
Claim: the auth/token fetch bypasses a method-level throttle, so two requests leave
in the window the throttle believes holds one; reproduces only on token-issuance days.
Sources checked: Okta OAuth token rate
limits, eBay OAuth rate
limits, GitHub REST
rate limits,
AWS Builders' Library on timeouts/retries.
Where the research narrowed the claim: providers do meter token endpoints (all
three publish limits attached to them), but they do not universally share one bucket
with the data API — Okta, eBay and GitHub each meter the token endpoint separately. So
the candidate's implied "the token POST eats your API quota" is not a general truth. The
page therefore rests on the part that is provider-independent — the throttle's own
accounting is wrong because a request left without being counted, and the clock was
stamped before it — and the shared-bucket question is handled as an edge-case row rather
than a premise.
Evidence is the contributor's own production timeline (brokerage client, documented
2 req/s): token POST
00.354→ issuance00.495→ balance rejected00.543, on the twotoken-issuance days (2026-07-23, 2026-08-04) only. No external source establishes this
for that specific provider. →
field-tested, not upgraded.6. Call-site enumeration
Claim: enumerate callers by call target, not by parameter name; positional callers
carry no keyword text; test helpers reproduce the old shape behind a single hit.
Sources checked: Refactoring catalog — Change Function
Declaration (URL
verified 200; the public page shows the example but not the full mechanics text, so it
is cited for the named refactoring and its migration-style approach, not quoted for
a claim it does not visibly make), POSIX
grep for the
"matching is textual, not call-graph-aware" point.
Evidence is the contributor's own reproduction:
grep -rn "repo_rows" impl/tests/→ 13 hits, all keyword-form, migration scoped as "7 of 13"; full suite then reported
Ran 472 tests / FAILED (failures=11), all intest_backend.pywhere the seed wasverify()'s 4th positional argument; a follow-upgrep -n "verify(" …surfaced 8positional sites plus a
rows_for()helper feeding the old shape to 5 more.No external source states the keyword-grep failure mode. →
field-tested, not upgraded.7.
${VAR:-default}vs${VAR-default}Claim: the colon form substitutes the default for empty as well as unset, so passing
VAR=to disable a feature is silently ignored.Verified by reproduction (zsh, macOS, 2026-08-04):
Source checked: POSIX Shell §2.6.2 Parameter
Expansion —
"use of the <colon> in the format shall result in a test for a parameter that is unset
or null; omission of the <colon> shall result in a test for a parameter that is only
unset." →
verified.Existing-layer check
Routed via
INDEX.md, then read thebackend,testing,platformsanddebuggingdomain indexes and every page whose "load when" overlapped.
Pages read in full before deciding merge-vs-create:
testing/quality/tests-that-cannot-fail,testing/quality/harness-reverse-controls,testing/quality/checks-that-cannot-pass(index line),testing/data/test-data-and-isolation,platforms/shells/portable-shell-scripts,backend/common/reliability/timeouts-and-retries,backend/common/integrations/externally-owned-defaults, plus thebackend/pythonandbackend/nodesubtree indexes.Merged rather than created (2):
testing/data/test-data-and-isolation. The page already carried"Filesystem / temp files" and "Global config / environment variables / singletons"
rows. The uncovered case is narrower and worth a row of its own: production code that
derives a write path from the environment, where the fix is redirecting the variable
rather than adding a parameter. Added one row to the isolate-by-resource-type table,
one
Instead ofrow (test-only directory parameter → redirect the env var), the Nodeos.homedir()source, andlast_verified→ 2026-08-04. No new page.platforms/shells/portable-shell-scripts. The page's edge-case table alreadyhad "
set -ubreaks on optional variables →"${OPT:-}"", which uses:-withoutdistinguishing it from
-. Added one edge-case row and twoInstead ofrows coveringthe empty-value feature-flag case, quoted POSIX §2.6.2 into the existing source line,
last_verified→ 2026-08-04. No new page.Overlaps found but deliberately kept separate:
testing/quality/harness-reverse-controls— same discipline (negativecontrol), different trigger: that page is about citing a harness's score, this one
about a poll loop's done signal gating an action. Cross-linked both ways
(edge-case row added there,
related:on both) instead of stretching either "loadwhen".
testing/quality/tests-that-cannot-fail— that page is scoped to testsand their assertions; a tmux/status-file monitor is not a test. Linked, not merged.
harness-reverse-controls— that page's "every case caught / every casesurvives" rows describe the symptom; the pyc mechanism is the Python-specific
cause. Followed the wiki's own common-owns-principle / stack-owns-mechanics split:
page lives in
backend/python/language, with a routing edge-case row added toharness-reverse-controls.backend/common/reliability/timeouts-and-retries— that page coverstimeouts, retry policy, and concurrency caps against a slow dependency; it does not
cover throttling to a published request-rate quota or which layer the throttle wraps.
Adjacent, cross-linked via
related:, not merged.backend/common/integrations/externally-owned-defaults— both concernresources the repo does not own; that page is about a name silently ceasing to
resolve, this one about permission to fetch at all. Cross-linked; an edge-case row in
the new page routes to it for the inherited-source-constant case.
Conflicts flagged: none. No existing directive contradicts anything ingested. The
only contradiction found was between candidate #1 and reality, resolved by rewriting the
candidate (logged as a
correctionentry inlog.md, alongside theingestentry).Related-links added (both directions):
harness-reverse-controls↔polling-completion-predicates;harness-reverse-controls↔bytecode-cache-staleness;portable-shell-scripts→polling-completion-predicates;client-side-rate-limiting→timeouts-and-retries,jwt-server-side,intermittent-failures;crawl-permission-by-user-agent→externally-owned-defaults,timeouts-and-retries;call-site-enumeration→tests-that-cannot-fail,test-data-and-isolation;test-data-and-isolation→behavior-not-implementation.Routing decision
backend/common/integrations/crawl-permission-by-user-agent.md(new page)integrationsalready owns "consuming external-API responses / externally-owned defaults"; deciding whether an external publisher permits your fetch is the same concern one step earliertesting/quality/polling-completion-predicates.md(new page)testing/qualityalready holds the can-this-check-fail family (tests-that-cannot-fail,checks-that-cannot-pass,harness-reverse-controls); a done-predicate that cannot say "not yet" is the same defect classtesting/data/test-data-and-isolation.md(merge)backend/python/language/bytecode-cache-staleness.md(new page)backend/pythonroutes "language traps"; the mechanism is CPython's import cache, so the stack subtree owns the mechanics whiletesting/qualitykeeps the harness principlebackend/common/reliability/client-side-rate-limiting.md(new page)reliabilityalready owns outbound-call behaviour (timeouts, retries, backoff); staying under a provider's quota is the same axisbackend/common/refactoring/call-site-enumeration.md(NEW categoryrefactoring)platforms/shells/portable-shell-scripts.md(merge):-without distinguishing it from-New category:
backend/common/refactoring— why nothing existing fitRe-checked every seeded category before creating it. The case is "changing a function's
declaration and migrating its callers":
debugging/*owns diagnosing a failure; here nothing is broken yet — the work is aplanned change, and the failure is what happens if enumeration is incomplete.
testing/*owns authoring tests. Broken tests were the symptom; the directive isa search strategy for production call sites, and the test helpers matter as sources of
the old shape, not as tests.
backend/common/{api-design, orm, errors, concurrency, …}are each scoped to a runtimeconcern, none of which is code-change methodology.
refactoringcategory exists in any of the ten domains (checked all ten indexes).Placed under
backend/common/because that subtree is explicitly the language-agnosticapplication-code home and the wiki has no cross-cutting "code craft" domain.
Known routing limitation for the owner to weigh: the directive applies equally to a
frontend signature migration, and a frontend task would not route into
backend. Twoalternatives if you prefer: (a) promote
refactoringto a top-level domain inINDEX.md,or (b) add a cross-pointer line from
wiki/frontend/index.md. I did neither — both changethe domain map, which
AGENTS.mdputs under owner approval. Happy to follow up withwhichever you pick.
Verification run
backend-common-*subtree convention.related:id and every inline[page-id]reference in thetouched pages resolves to an existing page; every relative link in the four touched
index files resolves to an existing file.
index.mdwith a "load when"line enumerating its distinct use cases;
INDEX.mdbackend row updated for the newconcerns;
log.mdhas theingestentry plus thecorrectionentry.touched page; every prohibition sits in an
Instead ofrow paired with its replacement.was written from memory.