Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 42 additions & 176 deletions .dev-loop/INGEST_REPORT.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions log.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ Append-only. Format: `## [YYYY-MM-DD] <ingest|revise|lint|gap|contradiction|drif
## [2026-08-03] dedup | Dropped 3 candidate pages as duplicates/superseded during the #6–#13 consolidation: testing/docs-as-spec/document-conformance-checks (#9 — same case as testing/quality/spec-artifact-checks from #8: coverage-vs-validity split, per-check negative controls, GFM pipe parsing; #8 kept as canonical, docs-as-spec category not created); backend/common/llm/gateway-model-alias-defaults (#6 — subsumed by the generalized integrations/externally-owned-defaults; the model-alias case is one instance); backend/common/integrations/llm-response-completeness (#12 — folded into llm/completion-response-validation, kept in llm/ for category coherence with context-window-budget).
## [2026-08-04] ingest | knowledge-flush of 3 queued insights. New: testing/quality/schema-additions-under-a-golden-gate (a new node kind absent from the golden example is untouched by every mutant derived from it — commit a minimal conforming fixture, one negative per keyword the new branch adds, restore each and require red; judge the suite by whether anything loads the schema at all), backend/common/change-impact/call-site-enumeration (NEW category change-impact: enumerate by callee name, treat a parameter-name search as a partial index — positional-or-keyword is Python's default parameter kind and ast.Call keeps args/keywords in separate fields; re-run the enumeration after the edit). Merged: testing/data/test-data-and-isolation +1 Do row / +1 edge case / +1 Instead-of (a factory whose shape depends on a value the test also passes to the code under test takes it as a parameter, never as a module-level default). All cited URLs live-verified this session; one local reproduction (Python 3.14.6: keyword search 1 hit vs AST callee enumeration 4).
## [2026-08-04] ingest | knowledge-flush: 3 queued session insights merged into existing pages (no new pages — merge-before-create). platforms/environment/path-resolution +keg-only case: a package manager reports a tool installed but `command -v`/`which` find nothing because keg-only/unlinked formulae (llvm, openssl, curl) are deliberately off PATH — run from `$(brew --prefix)/opt/<f>/bin` (verified: `which mlir-opt` not found vs `/opt/homebrew/opt/llvm/bin/mlir-opt` → LLVM 22.1.8; source docs.brew.sh/FAQ). platforms/processes/non-interactive-cli-invocation +bracketed-paste edge: injecting a long/multiline prompt into a REPL (tmux `send-keys -l`) stalls at `❯ [Pasted text #1]` because the input is one bracketed-paste block (ESC[200~…201~) whose embedded newline is not submit — send Enter as a separate keystroke a beat later (source en.wikipedia.org/wiki/Bracketed-paste + claude-code#43169). testing/strategy/test-level-choice +import-side-effect edge/instead-of: a "pure" function's test is not dependency-free if its module runs I/O at import; `@pytest.mark.skipif` evaluates after the module import so it can't gate it — use `importorskip`/`skip(allow_module_level=True)` or move the function to a side-effect-free module (source docs.pytest.org skipping). Harvested "infrastructure" hint for the keg-only insight re-routed to platforms/environment (dedicated PATH page). Confidence: keg-only & pytest verified vs official docs; bracketed-paste mechanism doc-verified, the claude-CLI submit specifics field-tested.
## [2026-08-05] ingest | knowledge-flush of 7 queued insights. New: platforms/shells/warnings-on-stderr-with-exit-zero (gate a warning-emitting tool on captured stderr, not the exit code; `2>&1 >/dev/null` order; Claude Code hook exit-2 feedback), platforms/toolchains/macos-sdk-sysroot (Homebrew clang needs `-isysroot "$(xcrun --show-sdk-path)"`; `-Wmissing-sysroot` proceeds without headers so the failure lands one step downstream), backend/common/reliability/client-side-rate-limiting (route token/auth requests through the throttle; stamp immediately before send; check `last_request_at=0` initial state). Merged: testing/quality/tests-that-cannot-fail (+uncommitted-mutation restore: copy+hash, `git checkout --` restores from the index and eats the unstaged fix — local git repro), testing/data/test-data-and-isolation (+artifact-leak attribution by prefix counts, static-check enforcement proved red first), platforms/shells/portable-shell-scripts (+`${VAR:-}` empty-vs-unset off-switch trap, bash 3.2/zsh 5.9 repro + GNU manual quote), backend/common/change-impact/call-site-enumeration (+test-helper fan-out edge row). Dropped 1 duplicate: a re-harvest of the call-site-enumeration insight already ingested 2026-08-04. Verification: 4 local reproductions (redirection order, param expansion, git checkout index source, xcrun) + 9 URLs fetched live; one draft source swapped for pages that actually state the claim (Okta rl2-token-oauth → rate-limits overview). Note: heavy overlap with open PRs #32/#34 from earlier flushes of parallel sessions — reviewer should pick one and close the others.
6 changes: 4 additions & 2 deletions wiki/backend/common/change-impact/call-site-enumeration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ sources:
- https://docs.python.org/3/glossary.html
- https://docs.python.org/3/library/ast.html
- https://peps.python.org/pep-0570/
last_verified: 2026-08-04
related: [qa-process-regression-scope, backend-python-language-mutable-state-traps]
last_verified: 2026-08-05
related: [qa-process-regression-scope, backend-python-language-mutable-state-traps, testing-data-test-data-and-isolation]
---

# Enumerating Call Sites Before Changing a Callee's Contract
Expand Down Expand Up @@ -64,6 +64,7 @@ the search never listed.
| Call sites live in another repository or a published package | The change is a versioned deprecation, not an in-place edit: keep the old contract accepting its old shape for a release, and enumerate what you own now |
| The language has no keyword arguments at all (JavaScript, Go) | Every site is positional, so a parameter-name search returns nothing at all — enumerate by callee name from the start |
| The repo has no working language server for the language | Enumerate by callee name and say so; an AST pass over `Call` nodes is the fallback that survives aliasing |
| A test helper wraps the callee or rebuilds its data shape (a fixture builder feeding it) | Read every helper definition the enumeration surfaces and enumerate the helper's own call sites too — the helper appears once in the callee enumeration while supplying the old contract to every one of its callers ([testing-data-test-data-and-isolation]) |

## Instead of

Expand All @@ -81,3 +82,4 @@ the search never listed.
- https://peps.python.org/pep-0570/ — the `/` marker for positional-only parameters, alongside the existing `*` marker for keyword-only, as the way a signature fixes how an argument may be passed
- Local reproduction 2026-08-04 (Python 3.14.6, macOS): over four call sites of `verify(...)` where one passes `repo_rows=` by keyword, a regex search for `repo_rows\s*=` matches 1 while an AST pass over `Call` nodes named `verify` finds 4 — 3 sites invisible to the keyword search
- Field incident 2026-08-04 (`linkly-t1-repo-policy`, Python): recon by keyword search reported "13 call sites, 7 need editing"; 8 further seeds passed the same value as `verify()`'s fourth positional argument, and the suite the session had reported green then ran `472 tests / FAILED (failures=11)`
- Field incident 2026-08-05 (`linkly`, Python): a `rows_for()` test helper kept reproducing a removed rule for five call sites while appearing as a single hit in the callee enumeration — helper definitions are fan-out points, not one site
60 changes: 60 additions & 0 deletions wiki/backend/common/reliability/client-side-rate-limiting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
id: backend-common-reliability-client-side-rate-limiting
domain: backend
category: reliability
applies_to: [general]
confidence: field-tested
sources:
- https://developer.okta.com/docs/reference/rate-limits/
- https://auth0.com/docs/troubleshoot/customer-support/operational-policies/rate-limit-policy/authentication-api-endpoint-rate-limits
last_verified: 2026-08-05
related: [backend-common-reliability-timeouts-and-retries]
---

# Client-Side Throttles That Miss Auth Requests

## When this applies

You added a requests-per-second throttle to an API client wrapper, yet the
provider still returns rate-limit errors — especially on the **first call of a
process**, or only on some days. Also when designing the throttle layer of any
client whose requests carry a token the client itself refreshes.

## Do this

1. **Route every HTTP request through the throttle, including token/auth
acquisition.** Identity providers rate-limit their auth endpoints like any
other endpoint (Auth0 limits its Authentication API endpoints; Okta's
org-wide rate-limit buckets cover the OAuth2 endpoints), and a token POST
plus the first real API call land in the same second — deterministically
exceeding a low per-second cap.
2. **Audit the interceptor path.** Token refresh usually happens inside a
header-builder or request interceptor, which sits *below* a wrapper-level
throttle and silently bypasses it. The throttle must wrap the layer that
actually performs HTTP, not the layer that composes calls.
3. **Stamp the throttle timestamp immediately before the request goes out**,
not at wrapper entry — work done between the stamp and the send (like a
nested token fetch) otherwise consumes the gap the stamp claimed.
4. **Check the initial state.** A `last_request_at = 0` default makes the
first gap check pass trivially; the first two physical requests of the
process then go out unthrottled.

## Edge cases

| Case | Then |
|------|------|
| The failure reproduces only on some days and looks like provider flakiness | Correlate failure timestamps with token issuance in logs: a cached token skips the extra request, so the bug only fires when the cache is cold/expired — that schedule-shaped intermittency is the signature |
| The provider counts limits per endpoint, not globally | The token POST may have its own (often stricter) limit; throttling it with the data calls is still safe, but its own 429 handling needs backoff too |

## Instead of

| If you are about to | Do this instead | Why |
|---------------------|-----------------|-----|
| Dismiss first-call rate-limit errors as intermittent provider issues | Diff a failing day's log against a working day's around the first call | The extra token request is visible as one added line; the "intermittency" is the token cache's TTL |
| Throttle at the public-method layer of the client | Throttle at the transport layer every request traverses | Auth refresh, retries, and pagination helpers all issue requests the public layer never sees |

## Sources

- https://developer.okta.com/docs/reference/rate-limits/ — Okta's org-wide rate-limit buckets cover the OAuth2 endpoints; only the public metadata endpoints (`/oauth2/v1/keys`, the `.well-known` documents) are exempt
- https://auth0.com/docs/troubleshoot/customer-support/operational-policies/rate-limit-policy/authentication-api-endpoint-rate-limits — Auth0 limits the number of requests made to Authentication API endpoints, which include the token endpoint
- Field incident 2026-08-05 (`stock-trader` `kis_client.py`, 2 req/s provider cap): `_headers()` called `_get_token()` *after* `_throttle()`, so on token-issue days the log shows token POST at 00.354 → token issued 00.495 → balance call rejected 00.543; on cached-token days the identical code passed, which had the failure filed as intermittent
2 changes: 1 addition & 1 deletion wiki/backend/common/reliability/timeouts-and-retries.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ sources:
- https://sre.google/sre-book/addressing-cascading-failures/
- https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
last_verified: 2026-07-10
related: [backend-common-api-design-idempotency, backend-common-llm-completion-response-validation]
related: [backend-common-api-design-idempotency, backend-common-llm-completion-response-validation, backend-common-reliability-client-side-rate-limiting]
---

# Calling Another Service over the Network: Timeouts, Retries, Backoff
Expand Down
1 change: 1 addition & 0 deletions wiki/backend/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Match your situation to a "load when" line; load only matching pages.
| Page | Load when |
|------|-----------|
| [timeouts-and-retries](common/reliability/timeouts-and-retries.md) | Your service calls another service/external API/DB over the network — setting timeouts and deadlines, deciding what to retry per failure type, backoff/jitter, capping concurrency against a slow dependency; debugging pool exhaustion or retry storms |
| [client-side-rate-limiting](common/reliability/client-side-rate-limiting.md) | A client-side request throttle exists yet the provider still returns rate-limit errors — especially on a process's first call, or only on some days; designing the throttle layer of a client that refreshes its own auth token |

### caching

Expand Down
2 changes: 1 addition & 1 deletion wiki/platforms/environment/path-resolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ sources:
- https://www.sudo.ws/docs/man/sudoers.man/
- https://docs.brew.sh/FAQ
last_verified: 2026-08-04
related: [platforms-toolchains-version-management, platforms-processes-background-services]
related: [platforms-toolchains-version-management, platforms-processes-background-services, platforms-toolchains-macos-sdk-sysroot]
---

# The Wrong Binary (or None) Resolving From PATH
Expand Down
4 changes: 3 additions & 1 deletion wiki/platforms/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Match your situation to a "load when" line; load only matching pages.

| Page | Load when |
|------|-----------|
| [portable-shell-scripts](shells/portable-shell-scripts.md) | Writing a shell script that must run on more than one machine/OS/shell or in CI; a script that works locally fails elsewhere; choosing a shebang (bash vs sh); a bash script misbehaves in zsh or vice versa (unquoted vars, `=word`, array indexing); deciding how `set -euo pipefail` protects (and doesn't); building argument lists safely |
| [portable-shell-scripts](shells/portable-shell-scripts.md) | Writing a shell script that must run on more than one machine/OS/shell or in CI; a script that works locally fails elsewhere; choosing a shebang (bash vs sh); a bash script misbehaves in zsh or vice versa (unquoted vars, `=word`, array indexing); deciding how `set -euo pipefail` protects (and doesn't); building argument lists safely; an empty env override (`VAR=`) fails to disable a feature |
| [warnings-on-stderr-with-exit-zero](shells/warnings-on-stderr-with-exit-zero.md) | Wiring a compiler/linter/build tool into a CI step, pre-commit check, or agent hook and the tool emits warnings on stderr while exiting 0; a gate keyed on the exit code lets warnings through silently; capturing stderr for feedback without mixing in the tool's stdout |
| [command-text-inspected-before-execution](shells/command-text-inspected-before-execution.md) | A hook, policy gate, allow-list, or audit rule blocked a command that is correct as written; composing a command that must satisfy such a gate first try; deciding whether to write a path literally or as `"$VAR"` in an inspected argument; a gate reports an argument missing or a file nonexistent though both are right; a gate must read a file your command creates; prose containing a dangerous-looking command (release notes, docs, fixtures) trips a text scanner |

## tools
Expand Down Expand Up @@ -51,6 +52,7 @@ Match your situation to a "load when" line; load only matching pages.
| Page | Load when |
|------|-----------|
| [version-management](toolchains/version-management.md) | "Works on my machine" from tool-version drift; a project needs a pinned language/tool version (.nvmrc, .python-version, .tool-versions); making CI use the same versions as local; onboarding a machine reproducibly; a script/cron/CI step can't find a version-managed binary (shims absent in non-interactive shells); deciding where lockfiles fit in reproducibility |
| [macos-sdk-sysroot](toolchains/macos-sdk-sysroot.md) | Homebrew keg-only clang on macOS cannot find system headers (`stdio.h`) while Apple's `/usr/bin/clang` works; mass test failures through a toolchain right after a CommandLineTools/Xcode change; deciding how a build script should locate the macOS SDK |

## Planned (unseeded categories)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sources:
- https://code.claude.com/docs/en/hooks
- https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
last_verified: 2026-07-30
related: [platforms-shells-portable-shell-scripts, platforms-environment-path-resolution]
related: [platforms-shells-portable-shell-scripts, platforms-environment-path-resolution, platforms-shells-warnings-on-stderr-with-exit-zero]
---

# Commands Read as Text by a Gate Before the Shell Runs Them
Expand Down
8 changes: 6 additions & 2 deletions wiki/platforms/shells/portable-shell-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ applies_to: [bash, zsh, posix-sh]
confidence: verified
sources:
- https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
- https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
- https://zsh.sourceforge.io/Doc/Release/Expansion.html
- https://zsh.sourceforge.io/Doc/Release/Parameters.html
- https://google.github.io/styleguide/shellguide.html
- https://www.shellcheck.net/
last_verified: 2026-07-10
related: [platforms-tools-bsd-vs-gnu-cli, platforms-toolchains-version-management, platforms-shells-command-text-inspected-before-execution]
last_verified: 2026-08-05
related: [platforms-tools-bsd-vs-gnu-cli, platforms-toolchains-version-management, platforms-shells-command-text-inspected-before-execution, platforms-shells-warnings-on-stderr-with-exit-zero]
---

# Shell Scripts That Must Run on More Than One Machine or Shell
Expand Down Expand Up @@ -62,6 +63,7 @@ non-interactive environment).
| Critical command is in a pipeline but the interpreter is POSIX sh (no `pipefail`) | Run the critical command outside the pipeline (temp file between stages) and test `$?` directly |
| Script runs via cron/CI/hooks and commands are "not found" | Non-interactive shells load no rc files — no user PATH, no version-manager shims. Call binaries by absolute path (see platforms-toolchains-version-management) |
| `set -u` breaks on optional variables | Expand with an explicit default: `"${OPT:-}"` |
| Passing `VAR=` (empty) to disable a feature has no effect | `${VAR:-default}` substitutes for unset **and** empty — omitting the colon (`${VAR-default}`) tests only for unset. Make the script read `${VAR-default}` when empty must mean "off"; when you cannot edit the script, pass a value its own validation rejects (e.g. `WATCH_TMUX=/nonexistent` so a `command -v` probe fails) |

## Instead of

Expand All @@ -70,10 +72,12 @@ non-interactive environment).
| Build a command string and `eval` it | Build an array and expand it: `cmd "${args[@]}"` | `eval` re-parses quotes and globs; arrays pass arguments through exactly |
| Put a command plus its flags in one variable and run `$cmd` | Variable holds the binary path only; flags are separate words | zsh runs the whole value as one command name; bash re-splits and re-globs it |
| Trust a trailing `echo "done"` as proof a step ran | Verify the produced state with an independent command | Inside `&&` chains and subshells, `set -e` misses failures and the echo still prints |
| Disable a script feature by exporting an empty value against a `${VAR:-default}` read | Pass a deliberately invalid value that fails the script's own probe, or change the read to `${VAR-default}` | The colon form treats empty as unset, silently re-enabling the default you meant to turn off |

## Sources

- https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html — POSIX shell quoting and field splitting (sections 2.2, 2.6.5)
- https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html — "Omitting the colon results in a test only for a parameter that is unset"; behavior reproduced identically in bash 3.2 and zsh 5.9 (2026-08-05)
- https://zsh.sourceforge.io/Doc/Release/Expansion.html — zsh: no word splitting of unquoted parameters (14.3); `=word` expansion (14.7.3)
- https://zsh.sourceforge.io/Doc/Release/Parameters.html — zsh arrays numbered from 1 (KSH_ARRAYS excepted)
- https://google.github.io/styleguide/shellguide.html — quote variables, prefer bash for scripts, arrays over eval
Expand Down
Loading
Loading