Skip to content

feat(spend-control): evaluation, enforcement, and usage-trigger runtime - #4548

Merged
subomi merged 7 commits into
mainfrom
cursor/spend-control-runtime-92fd
Jul 27, 2026
Merged

feat(spend-control): evaluation, enforcement, and usage-trigger runtime#4548
subomi merged 7 commits into
mainfrom
cursor/spend-control-runtime-92fd

Conversation

@subomi

@subomi subomi commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary by cubic

Ships Budgets v1: a spend-rules API, dashboard, and a runtime that evaluates spend and enforces blocks within seconds. Enforcement is behind the Budgets flag and applies to Claude only.

  • New Features

    • Spend rules API: create/list/get/update/archive, preview matched actors and current-window usage, list warning/breach events, overview metrics, and list actor attributes; OpenAPI, CLI, and generated @gram/client hooks included.
    • Dashboard: new Costs → Budgets tab with rules list, detail, editor with live preview, events feed, and overview cards; targets use the backend actor-attribute catalog.
    • Runtime: Temporal workflows schedule org sweeps and run debounced per-org evaluations; evaluator computes per-actor window spend from ClickHouse, records warning/breach events, and publishes Redis gate snapshots; telemetry logger observes Claude Code OTEL and Codex/Cursor usage on both server and worker paths and signals re-evaluation with per-org throttling; Claude hooks consult the spend gate before policy scans and block prompts and tool calls (native and MCP, even mid-turn) with a user-facing reason and block URL.
  • Bug Fixes

    • Usage signals run off the write path in a bounded, cancellation-detached context and flush on shutdown.
    • Evaluator fails loudly without ClickHouse, retries transient event writes, and logs-and-skips per-rule logic errors.
    • Gate rejects nil cache, bounds the compiled-CEL cache, lifts blocks when windows reset, clears snapshots when the flag is off or no rules exist, and uses a longer snapshot TTL (4x the evaluation interval).
    • Debounced workflow continues-as-new when an error occurs and a signal arrived mid-run, so pending signals aren’t stranded.
    • Dedupes blocked prompt telemetry per session+prompt for clients that lack idempotency keys.
    • Key actor evaluation and gate snapshots by user ID (not email) to avoid aliasing across addresses.

Written for commit 8952dfb. Summary will update on new commits.

Review in cubic

@subomi
subomi requested a review from a team as a code owner July 24, 2026 20:10
@changeset-bot

changeset-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8952dfb

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 19 files

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread server/internal/background/activities/spend_rules/evaluate.go Outdated
Comment thread server/internal/background/spend_rule_evaluation.go
Comment thread server/internal/telemetry/logger.go
Comment thread server/cmd/gram/worker.go
Comment thread server/internal/background/activities.go
Comment thread server/internal/spendrules/gate.go Outdated
Comment thread server/internal/hooks/session_capture.go
Comment thread server/internal/background/spend_rule_evaluation.go
Comment thread server/cmd/gram/start.go
Comment thread server/internal/background/activities/spend_rules/evaluate.go Outdated
@subomi
subomi force-pushed the cursor/spend-control-runtime-92fd branch 2 times, most recently from 26b1225 to 02e06f8 Compare July 24, 2026 22:08
@subomi
subomi force-pushed the cursor/spend-control-feature-92fd branch from c1e019d to 178dacd Compare July 24, 2026 22:19
@subomi
subomi requested a review from a team as a code owner July 24, 2026 22:19
Base automatically changed from cursor/spend-control-feature-92fd to main July 25, 2026 13:04
@subomi
subomi force-pushed the cursor/spend-control-runtime-92fd branch from 02e06f8 to 0da7498 Compare July 25, 2026 15:13
Stacked on the spend-control management API PR. Adds the runtime that
evaluates and enforces budget rules:

- Background evaluator: temporal workflow/activity computing per-actor
  window spend and opening/closing warning + breach circuits.
- Hooks spend gate: blocks over-budget actors on the ingest path.
- Telemetry usage trigger: throttled per-org re-evaluation on fresh
  spend-relevant telemetry, wired via a telemetry LogObserver.
- Wires the concrete evaluation signaler into the spend rules API
  service and registers the worker-side activity + observers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@subomi
subomi force-pushed the cursor/spend-control-runtime-92fd branch from 0da7498 to 0edd554 Compare July 25, 2026 15:50
- UsageTrigger: fire signals off the telemetry write path in a bounded,
  cancellation-detached context, so a slow Redis/Temporal dependency
  can't stall LogBulk, a canceled poll activity still wakes enforcement,
  and graceful shutdown stays within its drain deadline.
- EvaluateOrg: fail loudly instead of panicking when the worker has no
  ClickHouse connection; surface transient event-write failures so the
  activity retries (events dedupe on their unique index); log-and-skip
  per-rule logic errors rather than aborting the org.
- Gate: reject a nil cache at construction (fail-open contract), and
  bound the compiled-CEL cache so repeated rule edits can't grow memory.
- Raise the gate snapshot TTL to 4x the evaluation interval so a slow
  scheduled sweep does not let snapshots expire and enforcement fail open.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@subomi
subomi force-pushed the cursor/spend-control-runtime-92fd branch from 0edd554 to bcb5853 Compare July 25, 2026 17:01

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 15 files (changes from recent commits).

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread server/internal/spendrules/gate.go
Comment thread server/internal/spendrules/impl.go Outdated
Comment thread server/internal/spendrules/impl.go Outdated
Comment thread server/internal/spendrules/impl.go Outdated
Comment thread server/internal/background/spend_rule_evaluation.go Outdated
Comment thread server/internal/spendrules/gate.go
Comment thread server/internal/spendrules/gate.go Outdated
Comment thread server/internal/spendrules/trigger.go Outdated
Comment thread server/internal/spendrules/gate.go

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 9 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread server/internal/spendrules/impl.go Outdated
Co-authored-by: Cursor <cursoragent@cursor.com>
@blacksmith-sh

This comment has been minimized.

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 8 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread server/internal/spendrules/impl.go
subomi and others added 2 commits July 27, 2026 16:38
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@subomi subomi added the review:bypass Merge without human review approval. Required status checks still apply. label Jul 27, 2026
@subomi
subomi enabled auto-merge July 27, 2026 21:41

@gram-bot gram-bot Bot 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.

Auto-approved: review:bypass label applied by @subomi. Required status checks still gate this merge.

@subomi
subomi added this pull request to the merge queue Jul 27, 2026
Merged via the queue into main with commit 4c488a4 Jul 27, 2026
42 checks passed
@subomi
subomi deleted the cursor/spend-control-runtime-92fd branch July 27, 2026 21:49
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

review:bypass Merge without human review approval. Required status checks still apply.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant