Skip to content

[Findings] Recover the two C1 false negatives — cross-function batch + inline-parallel unbatched #117

@AndresL230

Description

@AndresL230

Summary

PR #111 (C1 PR-4) closed #83 by driving both lingering FPs to zero. Two labeled false negatives remain on the benchmark corpus and were intentionally accepted as out-of-scope:

  1. batch FN at flask-mixed-providers/src/providers/anthropic_helper.py:11 — two calls to _client.messages.create(...) in two different module-level functions (summarize and summarize_with_style). The same SDK method is called repeatedly across functions in one module, which is genuinely batchable, but PR-3's (provider, enclosingFunction) bucketing now suppresses it.
  2. unbatched_parallel FN at langchain-openai/src/libs/langchain-openai/src/tools/dalle.ts:242Promise.all over Array.from({length: this.n}).map(() => this.client.images.generate(...)) fans out n parallel image-generation requests with identical params. DALL-E accepts n directly in a single request, so this is provably wasteful — but the BOUNDED_REPLICATION guard from PR fix(detection): A3 + A5 — barrel re-exports + factory/DI/aliased clients (closes #75, #77) #110 (added to suppress legitimate Array.from({length:N}) patterns) currently silences this detection.

Why bundled

Both are recall-recovery problems where a previously-shipped guard (PR-3 bucketing, PR #110 BOUNDED_REPLICATION) is suppressing a real positive. Both need new structural signals beyond what the AST currently exposes. Design-first plan.

What to do — design sketch

For the batch FN (Python cross-function)

  • Add a secondary bucketing pass in src/scanner/python-waste-detector.ts detectSequentialBatching: after the (providerKey, enclosingFunction) pass, run a (providerKey, methodChain) pass at module scope.
  • Suggestion: "X calls to {methodChain} across multiple functions in this module — consolidate into a single batched call."
  • Must NOT re-introduce the FPs that motivated PR-3 (calls across different SDKs / different methodChains).

For the unbatched_parallel FN

  • The current BOUNDED_REPLICATION guard suppresses ALL Array.from({length:N}) patterns. The DALL-E case is exactly this shape but IS wasteful.
  • Need a finer signal: the count expression is a runtime parameter (this.n, an arg) rather than a constant literal (Array.from({length: 4})).
  • Or: when inlineParallelCapable flag exists (per [Detection] Narrow images.generate batchCapable to a separate inlineParallelCapable flag #116), the suppression should target ONLY that case, not all bounded replication.

Acceptance criteria

  • Batch FN recovered: npm run benchmark shows batch row at TP 1 / FP 0 / FN 0 (currently 0/0/1).
  • Unbatched_parallel FN recovered: npm run benchmark shows unbatched_parallel row at TP 1 / FP 0 / FN 0 (currently 0/0/1).
  • No regression to PR-3 or PR-4 fixtures: all 7 existing C1 tests still pass.
  • No new FPs introduced (per-type precision stays at 100% for both rows).

Depends on

Risk hotspot

This wave has historically re-introduced FPs (PR-3 → PR-4 was exactly that loop). Save for last when corpus expansion (#113) and CI gate (#119) are firmer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/findingsdocs/accuracy/findings.md — calibrated waste detector findingsenhancementNew feature or requestwave/4-recall-recoveryRecover the two C1 FNs (anthropic_helper.py batch + dalle.ts unbatched_parallel)

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions