Skip to content

[DRAFT EVIDENCE] competing API-cost outbox implementation - #988

Closed
groupthinking wants to merge 16 commits into
mainfrom
agent/harden-api-cost-outbox-17376027973963893260
Closed

[DRAFT EVIDENCE] competing API-cost outbox implementation#988
groupthinking wants to merge 16 commits into
mainfrom
agent/harden-api-cost-outbox-17376027973963893260

Conversation

@groupthinking

Copy link
Copy Markdown
Owner

Canonical issue

Closes #

Outcome

Describe the user or operational result this PR produces.

Scope

  • Included:
  • Explicitly excluded:

Risk

  • Risk level: low / medium / high
  • Failure mode:
  • Rollback:

Verification

List exact automated and manual checks, tied to the current head SHA.

  • Focused tests
  • Required CI
  • Review threads resolved

Production evidence

Provide the Vercel preview, production deployment, runtime evidence, or state why production evidence is not applicable.

Agent handoff

  • One canonical issue is linked
  • No competing PR implements the same issue
  • Acceptance criteria are satisfied
  • Required checks pass on the current head
  • Human decision is requested only for product, security, irreversible infrastructure, or production approval

Agent provenance

Human-authored pull requests may delete this section. Agent-authored pull requests must replace agent-lock-example with agent-lock-manifest and fill the values. Scope and test paths remain authoritative in the linked issue.

The declared agent publishes a result comment on the linked issue or PR with the exact run ID and current 40-character head SHA. Replace agent-lock-event-example with agent-lock-event only when publishing real evidence.

google-labs-jules Bot and others added 16 commits July 22, 2026 05:27
…-outbox-17376027973963893260

# Conflicts:
#	.github/workflows/coverage.yml
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…o the first/most-expensive pricing key (`gemini-3-pro`), overcounting cost by ~16x

This commit fixes the issue reported at src/youtube_extension/services/ai/hybrid_processor_service.py:334

## Bug

`calculate_cost` in `src/youtube_extension/backend/services/api_cost_monitor.py` had this fallback for unknown models:

```python
service_costs = self.COST_MODELS[service]
if model not in service_costs:
    # Use average cost for unknown models
    model = list(service_costs.keys())[0]
```

The comment says "average cost", but the code picks the **first** key. For Google that is `gemini-3-pro` (`input 0.000875 / output 0.0035`) — the **most expensive** Google model.

### Concrete trigger

`_track_gemini_usage` (hybrid_processor_service.py:330) records usage with `model=result.model_name`. `GeminiResult.model_name` defaults to `DEFAULT_GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-3.5-flash")` (gemini_service.py:60,283).

`COST_MODELS["google"]` only contains: `gemini-3-pro`, `gemini-3-flash`, `gemini-1.5-pro`, `gemini-1.5-flash`. Since `gemini-3.5-flash` (and the test's `gemini-2.0-flash`) are absent, the fallback selects `gemini-3-pro`.

Intended flash tier `gemini-3-flash` is `input 0.000052 / output 0.00021`, so `0.000875 / 0.000052 ≈ 16.8x` and `0.0035 / 0.00021 ≈ 16.7x`. **Every tracked Gemini call is overcounted by ~16x.** This directly undermines the budget-alert/outbox feature: alerts trip far too early and dashboards inflate.

## Fix

Rewrote the fallback into a tier-aware resolver `_fallback_model_cost`:

1.  Tokenizes the model name on non-alphanumeric separators (crucial: naive substring matching would match `mini` inside `gemini`).
2.  Matches a shared pricing tier keyword (`flash`, `pro`, `mini`, `haiku`, etc.), cheapest-tier-first, so `gemini-3.5-flash` → `gemini-3-flash` and `gemini-2.0-flash` → `gemini-3-flash`.
3.  If no tier matches, uses the **true average** across known models (matching the original comment's intent) instead of the most-expensive key.

Also moved the `youtube` quota branch above the lookup (its result is independent of the model key) and guarded against `None`.

### Verification

*   `gemini-3.5-flash`, `gemini-2.0-flash`, `gemini-2.5-flash-lite` → flash pricing (`0.000052 / 0.00021`).
*   `gemini-3-pro-preview` → pro pricing.
*   Fully unknown names → averaged pricing.
*   Exact-match models (e.g. the `test_anthropic_migration.py` `claude-*` keys) hit `service_costs.get(model)` directly and are unchanged.

`re` and `Any` were already imported in the file, so no new imports were needed.


Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: groupthinking <garveyht@gmail.com>
Copilot AI review requested due to automatic review settings July 25, 2026 00:42
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v0-uvai Canceled Canceled Open in v0 Jul 25, 2026 12:42am

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • [‘architecture-gap’, ‘bug’, ‘ci-cd’, ‘ci/cd’, ‘copilot-rabbit’, ‘documentation’, ‘duplicate’, ‘enhancement’, ‘frontend’, ‘github_actions’, ‘good first issue’, ‘help wanted’, ‘high-priority’, ‘invalid’, ‘javascript’, ‘ml-model’, ‘needs-triage’, ‘pipeline-critical’, ‘placeholder-code’, ‘priority:high’, ‘python’, ‘python:uv’, ‘question’, ‘styling’, ‘tests’, ‘v0’]

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 920f15a7-0e5b-4a64-bd73-28fcd1a491c1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/harden-api-cost-outbox-17376027973963893260
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch agent/harden-api-cost-outbox-17376027973963893260

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

🔍 PR Validation

⚠️ PR title should follow conventional commits format
⚠️ Large PR detected (1520 lines changed)

@github-actions github-actions Bot added documentation Improvements or additions to documentation python labels Jul 25, 2026
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 3eeb0ea.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Scanned Files

None

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

Agent Completion Truth Gate: BLOCKED

Reasons: invalid_payload

Machine-readable verdict
{
  "details": {
    "invalid_fields": [
      "issue.number",
      "policy.agent_login",
      "policy.run_id"
    ]
  },
  "reasons": [
    "invalid_payload"
  ],
  "verdict": "blocked"
}

Workflow evidence

@groupthinking
groupthinking marked this pull request as draft July 25, 2026 00:43
@groupthinking groupthinking changed the title Agent/harden api cost outbox 17376027973963893260 [DRAFT EVIDENCE] competing API-cost outbox implementation Jul 25, 2026
@groupthinking groupthinking added ci/cd duplicate This issue or pull request already exists needs-triage labels Jul 25, 2026 — with ChatGPT Codex Connector

Copy link
Copy Markdown
Owner Author

Duplicate disposition receipt

#988 has no focused child issue or valid execution manifest and directly competes with the existing canonical API-cost outbox unit. #869's exact head has the full CI/security/PostgreSQL suite passing and zero unresolved review threads.

Closing #988 without merge as duplicate evidence. The branch and all commits remain preserved; no implementation progress is credited.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens API-cost accounting and webhook delivery with transactional usage tracking, durable retries, and Gemini usage metadata.

Changes:

  • Adds atomic outbox claims, retry scheduling, recovery, and idempotency headers.
  • Tracks Gemini usage metadata and expands pricing entries.
  • Adds lifecycle, concurrency, migration, and cost-accounting tests.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/youtube_extension/backend/services/api_cost_monitor.py Implements transactional accounting and durable outbox processing.
src/youtube_extension/services/ai/gemini_service.py Preserves provider usage metadata.
src/youtube_extension/services/ai/hybrid_processor_service.py Records Gemini usage and isolates telemetry failures.
tests/unit/test_api_cost_outbox_worker.py Tests outbox durability, concurrency, retries, and lifecycle.
tests/unit/test_api_cost_monitor.py Tests pricing and atomic alert staging.
tests/unit/test_api_cost_database_substrate.py Updates transaction-boundary expectations.
tests/unit/test_hybrid_processor_service.py Tests Gemini usage recording.
tests/unit/test_gemini_service.py Tests metadata preservation.
tests/unit/test_gh_aw_workflow_governance.py Updates the coverage-floor assertion.
pyproject.toml Adjusts the measured coverage baseline.
docs/reports/PR869_OUTBOX_PROOFS.md Records historical verification evidence and remaining gates.

},
"google": {
# Current generation (routable from GeminiService)
"gemini-3.5-flash": {"input": 0.0001, "output": 0.0004},
Comment on lines +321 to +322
input_tokens = int(getattr(usage, "prompt_token_count", 0) or 0)
output_tokens = int(getattr(usage, "candidates_token_count", 0) or 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd documentation Improvements or additions to documentation duplicate This issue or pull request already exists needs-triage python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants