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
305 changes: 262 additions & 43 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 @@ -43,3 +43,4 @@ Append-only. Format: `## [YYYY-MM-DD] <ingest|revise|lint|gap|contradiction|drif
## [2026-08-06] revise | Union-merged amendments from the same 15 PRs into 24 existing pages (largest: tests-that-cannot-fail — 7 PRs: per-assertion mutation granularity, restore-mechanism-by-commit-state, suite-total-drop detection; portable-shell-scripts — 8 PRs: POSIX inline set-- reordering, ${VAR:-} vs ${VAR-} colon semantics, quote-by-what-the-text-is; test-data-and-isolation — 6 PRs: env-derived write paths, absent-variable cases, exec-bit fixtures, leak attribution; change-impact/call-site-enumeration — 8 unique additions from 7 path-variants: rename-in-place, same-type reorder, *args forwarding, two-searches-agree fallacy, codemod, coverage completion check). All non-canonical cross-page ids remapped to canonical pages; every added line traced to its source PR hunk (fabricated worker output was detected by orphan-line verification and replaced with true PR content).
## [2026-08-06] dedup | Cross-PR duplicate clusters collapsed: client-side rate limiting (8 PR versions at 3 paths → 1), call-site enumeration (7 versions at 7 paths → additions folded into the already-merged canonical page), stderr/exit-0 diagnostics (4 versions at 4 paths → 1), macOS sysroot (2→1), env-var off switch (2→1), completion predicates (2→1), robots.txt (2→1), harness-mediated results (2→1), leaked test artifacts (2→1), orchestration category naming (orchestration vs agent-orchestration → agent-orchestration). Kept distinct after trigger comparison: differential-testing vs differential-run-agreement (setup vs interpretation), unset-versus-empty-parameters vs env-var-off-switches (semantics vs design, cross-linked), import-time-side-effects vs test-level-choice edge (tactics vs level choice, cross-linked). Merged-main near-dup scan (Jaccard over title+trigger, 141 pages): 0 pairs — no duplication among previously merged content.
## [2026-08-06] ingest | Reconciled post-consolidation flush PRs #42–#43 (created against pre-#44 main). Folded unique content: platforms/filesystems/permissions-and-exec-bits (+`sh "$SCRIPT"` interpreter-invocation rows — stubs need no exec bit, avoids EDR chmod+x heuristics), platforms/shells/command-text-inspected-before-execution (+gate-AUTHOR step 8: parse all three POSIX quoting forms, expand only ~/$HOME/${HOME}; red-then-green bats evidence), testing/quality/checks-that-cannot-pass (+vacuously-green pre-implementation test row), platforms/processes/tool-diagnostics-without-a-failing-exit-code (+repeat-suppression edge, +clang reproduction source), infrastructure/ci-cd/secrets-handling (+independent credential channels row: gh token vs git SSH vs API token, git push --dry-run / author:@me probes), testing/mocking/what-to-mock (+ESM read-only-bindings DI rows, +PATH-emptied tripwire negative-proof). Dropped as duplicates of the #44 state: #42's rate-limit row (already in timeouts-and-retries + client-side-rate-limiting), #42's warning-only-diagnostics page (same trigger as tool-diagnostics-without-a-failing-exit-code), #42's leak-attribution row (already in test-data-and-isolation).
## [2026-08-12] ingest | knowledge-flush of 6 queued insights: 5 new pages, 1 dropped as an in-flight duplicate. New: testing/quality/signed-link-verification-assertions (assert a tokenized link through the verifier the receiver runs, with wrong-subject and wrong-key rejection arms in the same test and a token-stripped control on the live request — a signature is fixed-width for every key, so `?t=` presence is satisfied by a hardcoded placeholder; sources: AWS presigned-URL guide, docs.python.org hmac). backend/common/change-impact/cross-module-consumer-census (count production references to a task's new public symbols outside the defining module and outside its own tests, then classify by declared cross-module intent — knip's `ignoreExportsUsedInFile` and `includeEntryExports` encode the same internal-helper and entry-point populations a raw zero count cannot separate; measured 14 zero-consumer functions, exactly 1 a real gap). qa/process/defect-class-resweep-after-review (re-run each review finding's class search over the post-edit file including the lines the remediation just added; Yin et al. FSE'11 measured 14.8-24.4% of post-release fixes incorrect). infrastructure/containers/failing-pod-on-a-repo-synced-cluster (branch on pod phase before reading logs — `lastState.terminated` exitCode 137/OOMKilled is the runtime enforcing the limit and leaves no application log line; land the fix as a manifest PR because Argo CD does not sync live-cluster edits back to Git and self-heal reverts them). platforms/processes/cloud-cli-invocation-bounds (read the leaf subcommand's help, name region/profile/project/context on every invocation, cap list output with `--max-items` — the AWS CLI "retrieves all available items" by default). Dropped: the Python `.pyc`-cache mutation-harness insight, carried in better form by open PR #52, which additionally shows `-B` alone does not help when a stale `.pyc` already exists. Every cited URL was opened and quote-checked in this session.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
id: backend-common-change-impact-cross-module-consumer-census
domain: backend
category: change-impact
applies_to: [general]
confidence: verified
sources:
- https://knip.dev/guides/handling-issues
- https://knip.dev/reference/configuration
last_verified: 2026-08-11
related: [backend-common-change-impact-call-site-enumeration, testing-quality-tests-that-cannot-fail, infrastructure-agent-orchestration-worktree-isolated-workers]
---

# Counting the Production Consumers of a Symbol Your Task Just Added

## When this applies

Your task added a public function, endpoint, export, or hook whose consumer
belongs to a *different* task — parallel work split by file ownership, a backend
change whose UI wiring is another ticket, an agent worker producing a seam for a
sibling worker. You are deciding whether the task is done. Also when a feature is
typed, tested, reviewed, and merged, and changes nothing at runtime.

Enumerating the callers of a symbol whose contract you are *changing* →
[backend-common-change-impact-call-site-enumeration].

## Do this

1. **Take the new public symbols from the diff, not from memory**: names added by
`git diff origin/main...HEAD` in the files you own. That list is the census's
subject.

2. **Count references outside the defining module, excluding the symbol's own
tests.** Grep the bare name across the repo, drop hits in the defining file
and in test paths, and record the remaining file list per symbol. The tests
are what make an orphan look alive — a symbol its own test calls has a
non-zero reference count and no production reachability
([testing-quality-tests-that-cannot-fail]).

3. **Count references, not calls.** Search the bare name as well as `name(`:
seam injection (`estimate_fn=estimate.estimate`), callback registration,
decorator tables, and registry entries all pass the symbol as a value, and a
paren-anchored search reports those wirings as dead.

4. **Classify each zero-consumer symbol by declared intent, and treat only the
intent-bearing ones as defects.** The defect is a symbol whose docstring, plan,
task brief, or PR body states that another module consumes it. A zero count on
its own is the normal shape of a same-module helper. Unused-export tooling
encodes the same three populations: knip's `ignoreExportsUsedInFile` exists
because "In files with multiple exports, some of them might be used only
internally", and its `includeEntryExports` exists because "By default, Knip
does not report unused exports in entry files" — internal helpers and entry
points are the two populations a raw count cannot separate from real orphans.

5. **Run the census at each task's review, not at integration.** At integration
every task is already approved, so the missing wiring has no owner; at review
the owning session is still open.

6. **When the consumer task already finished, open a follow-up task naming the
file and the insertion point** — that task is the only thing standing between a
complete implementation and dead code.

## Edge cases

| Case | Then |
|------|------|
| The symbol is dispatched dynamically (`getattr`, a name in YAML/config, a route string) | Search the string form too, and record in the task that this class of site is not statically enumerable |
| The symbol is itself an entry point (CLI command, HTTP route handler, hook) | Its consumer is a registration, not a call — assert the registration file lists it (route table, plugin manifest, entry map) instead of counting references |
| A working language server exists | Use find-references for the count and state that as the method; text search stays the fallback for aliased re-exports |
| The consumer lives in another repository or a published package | The census cannot see it: record the consuming repo and the version that will adopt it, and keep the symbol out of the defect list |
| The symbol is re-exported through a package `__init__` or facade | Count references to the re-exported name as well, or every facade consumer reads as zero |
| The census returns zero for every new symbol | Suspect the search, not the code: confirm the pattern matches one symbol you know is wired before reading any zero as a finding |

## Instead of

| If you are about to | Do this instead | Why |
|---------------------|-----------------|-----|
| Report every symbol with no reference outside its defining file as dead code | Filter that list by declared cross-module intent, and report those | Internal helpers dominate the raw list; measured on one module, 14 of 14 zero-consumer functions were reported and exactly 1 was a defect, so the unfiltered list buries the finding |
| Search `name(` to find consumers | Search the bare name as well | Seam injection and callback registration pass the symbol as a value and never write the paren |
| Treat "type-check, tests, and CI all green" as proof the wiring landed | Run the consumer census before calling the task done | Nothing in a type system or a test suite requires a new public symbol to have a production caller |
| Defer the census to the integration branch | Run it in each task's review | After every task is approved, the missing 3 lines belong to nobody |

## Sources

- https://knip.dev/guides/handling-issues — a surprising unused-export report "is usually a real finding or a configuration gap, not a false positive to silence"; before deleting, check whether the export is in an entry file, re-exported from another entry point, or tagged for external use — the report is a candidate list that intent resolves
- https://knip.dev/reference/configuration — `ignoreExportsUsedInFile`: "In files with multiple exports, some of them might be used only internally. If these exports should not be reported, there is a `ignoreExportsUsedInFile` option available"; `includeEntryExports`: "By default, Knip does not report unused exports in entry files"
- Field measurement 2026-08-11 (Python module set, 6 tasks split across parallel workers by file ownership): a census of every public function counted cross-module production references; 14 came back zero. Exactly one was a real gap — a URL-building helper whose docstring named its consumer ("the caller puts this in the Slack body") and which no producer of that message ever called, leaving the notification's approval link unsigned. The other 13 were same-module helpers. All 6 tasks had passed review, 402 tests were green, and the merge had no conflicts
1 change: 1 addition & 0 deletions wiki/backend/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Match your situation to a "load when" line; load only matching pages.
| Page | Load when |
|------|-----------|
| [call-site-enumeration](common/change-impact/call-site-enumeration.md) | Changing the contract of a function/method/constructor other code calls — adding, removing, reordering or redefining a parameter — and you need the complete call-site list; scoping such a migration from a search; a migration scoped from recon came back green and then failed on call sites the search never listed; deciding whether to append a parameter or make it keyword-only (release-level re-test scope → qa/process/regression-scope) |
| [cross-module-consumer-census](common/change-impact/cross-module-consumer-census.md) | Your task added a public function, endpoint, export, or hook whose consumer belongs to a *different* task (parallel work split by file ownership, a backend change whose UI wiring is another ticket); deciding whether that task is done; a feature typed, tested, reviewed and merged changes nothing at runtime; separating same-module helpers and entry points from genuine orphans in a zero-consumer list |

### reliability

Expand Down
Loading
Loading