Skip to content

fix: distinguish billing refusals across workflow calls - #394

Closed
hamitarsln wants to merge 4 commits into
tin-computer:mainfrom
hamitarsln:codex/workflow-billing-refusals
Closed

hamitarsln wants to merge 4 commits into
tin-computer:mainfrom
hamitarsln:codex/workflow-billing-refusals

Conversation

@hamitarsln

@hamitarsln hamitarsln commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Organic audit, Ads monitoring and the AI answers ledger called every billing refusal a spending limit. Payment recovery could also blame credits when drafting stopped for another billing reason.

Keep limits separate from other billing refusals, and save the fixed error code. Required campaign reads keep their cause. The final Ads message now says "request", since the failure may be a Google Ads read, not a model call.

Verification

The three required-read checks failed before the message fix. The follow-up suite passed 121 tests with a disposable database, no skips. Both PRs #394 and #400 also passed 185 tests together. That includes actual ledger replay with simulated billing failures: one provider attempt, no model call, and no campaign changes.

Ruff, formatting and diff checks passed.

Limits

Local provider fixtures only. No live Ads account, customer mail or paid provider call was used. These tests do not verify production deployment or live provider access.

The new Python CI passed. Browser CI failed in the unchanged extension test concurrent project connects serialize onto one browser credential (condition was not met). All extension files match main and the same test passed 12 local repeats. CI retry is blocked by the GitHub integration's missing Actions write permission. This PR is not fully green yet.

@hamitarsln
hamitarsln requested a review from a team as a code owner October 11, 2026 22:36
Copilot AI balanced review requested due to automatic review settings October 11, 2026 22:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Non-model Ads billing refusals still lose their classified cause in the projected failure message.

1 open finding
What changed in this PR

Centralizes billing-refusal classification so workflows preserve accurate, sanitized failure causes.

Changes:

  • Adds a shared billing refusal classifier.
  • Updates audit, Ads monitor, AI answers, and email-drafting behavior.
  • Adds regression coverage for classification and replay safety.
File Description
src/​tin_lite/​billing_contracts.py Adds the shared classifier.
src/​tin_lite/​organic_audit_activities.py Preserves classified audit refusals.
src/​tin_lite/​organic_audit.py Explains non-limit billing gaps.
src/​tin_lite/​paid_ads_monitor_activities.py Projects model billing causes.
src/​tin_lite/​ai_answers_activities.py Classifies ledger failures.
src/​tin_lite/​payment_recovery_activities.py Reports fixed billing codes.
tests/​test_workflow_billing_refusals.py Covers classification, replay, and sanitization.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


result = (
{"status": "unavailable", "reason": "spending_limit"}
{"status": "unavailable", **billing_refusal(exc)}
@demegire

Copy link
Copy Markdown
Contributor

Superseded by #403: organic audit, Ads monitor, AI answers ledger and payment recovery use the shared billing_refusal wording. It also fixes this PR's payment-recovery case, which dropped the credits/limits guidance.

@demegire demegire closed this Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants