Skip to content

fix: phase 9/10 usage ledger, review instrumentation, cost tests, dependency conflicts (#393, #428, #430, #445) - #509

Merged
Ayinkx merged 4 commits into
AyinkxLab:mainfrom
jiggy-techy:fix/phase-9-10-393-428-430-445
Oct 17, 2026
Merged

Ayinkx merged 4 commits into
AyinkxLab:mainfrom
jiggy-techy:fix/phase-9-10-393-428-430-445

Conversation

@jiggy-techy

Copy link
Copy Markdown
Contributor

Summary

Implements the four assigned Phase 9/10 issues on a branch cut from upstream main:

The branch also repairs CI breakage already present on main (see "Baseline fixes" below) so ruff, black and the full pytest suite are green.

Changes

Usage ledger correlation fields (#428)

  • Added nullable request_id (64 chars, indexed), latency_ms (non-negative integer) and status (lowercased, indexed) to UsageRecord and to_dict().
  • Added migration f9e8d7c6b5a4 (down_revision = c4d5e6f7a8b9) with matching upgrade/downgrade.
  • record_usage() validates/truncates the new fields; existing rows and callers remain valid because everything is optional.
  • Migration tests assert the new columns, indexes and downgrade behaviour.

AI review instrumentation (#430)

  • Review completions now capture provider token counts and latency through the provider contract (provider.chat), while test doubles that only expose complete() keep working via a documented estimate fallback.
  • _save_result() appends exactly one source="review" ledger row per run (success and failure), carrying workspace_id/project_id, provider/model, tokens_estimated, request_id, latency_ms and status.
  • Tests run two project reviews and assert two scoped rows; a provider failure test asserts one status="error" row.

Cost service tests (#445)

  • Price lookup now supports optional custom tables and * wildcards with deterministic precedence: exact → (provider, "*") → ("*", model) → ("*", "*").
  • estimate_cost_usd() clamps each token count to MAX_TOKEN_COUNT while still rejecting negative counts.
  • New tests pin the arithmetic and cover precedence, every wildcard fallback, unknown models, and both input/output clamping.

Plugin dependency conflicts (#393)

  • The resolver now walks the whole graph first, collecting PEP 440 constraints with their dependency paths instead of failing on the first version mismatch.
  • PluginDependencyConflictError is raised when no version can satisfy all constraints, naming every conflicting requirement and path. Direct and transitive conflicts (plugin and Python-package dependencies) are covered, plus a registry-level test proving the plugin stays disabled.

Baseline fixes (pre-existing on main)

  • Guarded the optional alert-state fixture so collection does not import a missing module.
  • Fixed the tests/test_alerts.py syntax error and made its missing-module skip module-level safe.
  • Fixed lint violations in app/services/email.py.
  • Added the small per-period app/services/budget_alerts.py evaluator that the already-merged notification tests import.

Verification

python -m pytest -q            # full suite: exit 0
python -m ruff check .         # All checks passed
python -m black --check .      # 276 files would be left unchanged

Targeted runs also cover the changed areas:

pytest tests/test_usage_ledger.py tests/test_pricing.py tests/test_plugin_deps.py tests/test_migrations.py   # 122 passed
pytest tests/test_reviews_service.py tests/test_reviews_api.py                                              # 91 passed

Issue links

Closes #393
Closes #428
Closes #430
Closes #445

main was failing to collect tests: the shared alert-state fixture imported a missing app.services.alerts module unconditionally, tests/test_alerts.py had a syntax error and no module-level skip allowance, app/services/email.py violated the lint rules, and tests/test_notifications.py imported an unmerged budget_alerts service. Guard the optional fixture, repair the test syntax, fix the email docstring/imports, and add the small per-period budget alert evaluator the merged notification tests expect.
…yinkxLab#430)

Add nullable request_id, latency_ms and status columns to the usage ledger (with a reversible migration) and populate them from review instrumentation. AI reviews now record exactly one ledger row per run with project/workspace scope, token counts, provider/model, estimated-token confidence and outcome. Provider usage/latency is captured through the provider contract while test doubles that only implement complete() still work.
Cover exact-vs-wildcard precedence, provider/model/global wildcard fallbacks, unknown models, token-count clamping and the exact cost arithmetic with offline unit tests. The price table helpers accept an optional table so these branches are testable without mutating the shipped defaults.
…Lab#393)

Walk the whole plugin graph before failing, collect PEP 440 constraints per dependency and report a conflict with both dependency paths when no single version can satisfy them. Direct and transitive conflicts (plugin and Python package dependencies) now refuse enable with a clear message, while version mismatches remain PluginDependencyVersionError.
@drips-wave

drips-wave Bot commented Oct 17, 2026

Copy link
Copy Markdown

@jiggy-techy Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Ayinkx
Ayinkx merged commit 07a0e27 into AyinkxLab:main Oct 17, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants