Skip to content

quota: gatherer reads only the opencode quota subcommand + Supabase sink (#6127) - #6136

Merged
dezren39 merged 6 commits into
mainfrom
quota/gatherer-subcommand-source
Nov 5, 2026
Merged

dezren39 merged 6 commits into
mainfrom
quota/gatherer-subcommand-source

Conversation

@dezren39

@dezren39 dezren39 commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Single-source quota rewire — program #6125, closes the gatherer half of #6127 once the fork subcommand (developing-today-forks/opencode#1718) is deployed to the tick.

What changes

  • The tick's only quota read is now the opencode quota subcommand: opencode quota --json (configured listing) + opencode quota --json meta command-code (explicit ask for route-disabled live pools; a named ask always fetches). Results map through the unchanged quota-gather-map contract.
  • Retired from the gatherer: in-process OpenChamber module import, gatherer-side Turso read, native ClinePass adapter fill, file-export family, Claude expiry side-read (subcommand results carry credentialExpiresAt/credentialSource).
  • Kept: OpenDesign session keeper (credential maintenance, runs before the read; its store accessors still resolve from the OpenChamber lib — plumbing, not a reading path), perf(quota-plane): parallel provider fetching + per-provider timeout budget for the 15-min tick #1268 retention, feat(quota-plane): split gatherer rows per pool — OpenCode Go per-workspace + Antigravity pool grouping for the /quota overlay #1331 pool splits, Command Code plan-window mapping, fail-soft heartbeat (a broken subcommand leaves the previous quota-current.json standing).
  • quota-current.json source becomes opencode-quota (GATHERER_SOURCE) — the file names its real producer.
  • Supabase sink added: one agent.quota_records row per pool entry per tick, source opencode-quota, pm-pool payload shape. The previous pool writer (source pm-pool) died 2026-10-29 — verified in muse-dev2: 12 rows ever, none since. Fail-soft after the file write.
  • README gatherer section rewritten to match.

Verification so far: bunx tsc --noEmit clean; quota test files (quota-gather-map, quota-current, credential-lifecycle) 106 pass / 0 fail. Live tick against the fork-built subcommand binary + the production drop-in flip land with opencode#1718's proof on #6125 — this PR merges in the same motion as that deployment so the timer never runs the new gatherer against a binary without the subcommand.


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

Single-source rewire (Drew 2026-11-05, program #6125): the tick's
only quota read is now two invocations of DESCRIPTION
  OpenCode command line interface

USAGE
  opencode <subcommand> [flags] [<directory>]

ARGUMENTS
  directory string    Directory to start OpenCode in (optional)

FLAGS
  --standalone            Run with a private server instead of the background service
  --server string         Connect to a server URL instead of the background service
  --auto                  Auto-approve permissions that are not explicitly denied
  --continue, -c          Continue the last session
  --session, -s string    Session ID to continue, or to create if it does not exist
  --prompt string         Prompt to use

GLOBAL FLAGS
  --help, -h                                                          Show help information
  --version, -v                                                       Show version information
  --wizard                                                            Start wizard mode for a command
  --completions <bash|zsh|fish|sh>                                    Print shell completion script (choices: bash, zsh, fish, sh)
  --log-level <all|trace|debug|info|warn|warning|error|fatal|none>    Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none)
  --print-logs                                                        Print logs to stderr (server logs require --standalone)

SUBCOMMANDS
  upgrade, update    Upgrade OpenCode to the latest or a specific version
  uninstall          Uninstall OpenCode, keeping session data, configuration, and state
  acp                Start an Agent Client Protocol server
  api                Make a request to the running server
  debug              Debugging and troubleshooting tools
  auth               manage integrations and credentials
  mcp                Manage MCP (Model Context Protocol) servers
  plugin             Manage plugins
  models             List all available models
  stats              Show shareable usage statistics
  mini               Start the minimal interactive interface
  run                Run OpenCode with a message
  session            Manage sessions
  msg                Send, read and search inter-session messages
  service            Manage the background server
  reload             Reload configuration
  pair               Print one-time links to connect a browser or app
  serve              Start the v2 API and web server
(configured listing + explicit ask for the route-disabled live
pools meta/command-code), mapped through the unchanged
quota-gather-map contract. Retired from the gatherer: the in-process
OpenChamber module import, the gatherer-side Turso read, the native
ClinePass adapter fill, the file-export family, and the Claude
expiry side-read (the subcommand results carry the metadata now).

Kept: the OpenDesign session keeper (credential maintenance, runs
before the read), #1268 last-known retention, #1331 pool splits,
Command Code plan-window mapping, fail-soft heartbeat contract.
quota-current.json source becomes "opencode-quota".

Added: Supabase sink — one agent.quota_records row per pool entry
per tick (source "opencode-quota"), replacing the "pm-pool" writer
that died 2026-10-29. Fail-soft after the file write.

QUOTA_SUBCOMMAND env overrides the whole command (interim fork
builds); the systemd drop-in points at the fork-built binary until
the nix switch ships the new system opencode.
@dezren39
dezren39 requested a review from a team as a code owner November 5, 2026 07:44
@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 21 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 832a8779-2f87-47ad-a308-5cc66164d9c7
Commits

Reviewing files that changed from the base of the PR and between ae9069f and 2ce613d.

Files selected for processing: 3

  • pm-stack/aggregator/README.md
  • pm-stack/aggregator/scripts/gather-quota.ts
  • pm-stack/aggregator/src/quota-gather-map.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-05T09:37:41.632586Z 2ce613d New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 97f8871b8b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

windows: e.windows.map((w) => ({ name: w.name, percent: w.pctOfLimit, resetsAt: w.resetsAt })),
provider: e.providerName,
};
const id = `${e.serviceId}:${tickAt}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve credential identity in Supabase row IDs

When a provider has multiple credentials, entryFromResult assigns each credential the same serviceId, so this ID collides within a tick. The existing two-workspace Go case in test/quota-gather-map.test.ts explicitly produces two opencode-go entries. With ON CONFLICT (id) DO NOTHING, the sink silently discards all but the first credential's reading, and the payload omits credential identity as well. Include the credential ID in the row identity and payload, or explicitly aggregate entries into a single pool reading before inserting.

Useful? React with 👍 / 👎.

plan: e.planLabel ?? null,
state: e.state,
source: GATHERER_SOURCE,
windows: e.windows.map((w) => ({ name: w.name, percent: w.pctOfLimit, resetsAt: w.resetsAt })),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve label-only measurements in the Supabase payload

For DeepSeek, the measured balance is carried solely in valueLabel (for example, ¥44.63), with pctOfLimit null, as demonstrated in test/quota-gather-map.test.ts. The mapper explicitly accepts these CNY balances as measured windows, but this projection drops valueLabel without storing the raw usage elsewhere in the payload. Consequently, every DeepSeek row written to Supabase loses its actual balance and contains only a null percentage. Preserve the label or serialize the numeric balance with its unit so this sink retains the reading.

Useful? React with 👍 / 👎.

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.

1 participant