Skip to content

fix(quota-plane): Meta percentage read — restore portal-API fetcher (subscription-quota) as the gatherer's source #6079

Closed

Description

@dezren39

Problem

The Meta (Muse Code High Usage) pool's percentage read rests on POST https://api.meta.ai/muse-code/key (subs_usage), which Meta's server currently does not populate — and has a proven history of not populating in non-exhausted states too (51 consecutive null probes 2026-10-28→11-02 while the console showed 9%→100%). Determination with full evidence: #3347 comment 6650593668. The key endpoint is a valid subscription-active/tier signal but cannot be the system of record for percentages.

The faithful source is the dev.meta.ai portal API (the #1301 exporter's source, retired by #5040 in favour of the key endpoint — that trade should be reversed for percentages).

Fix: laptop-side portal fetcher for the gatherer

On the existing ~15-min gatherer tick, from the LAPTOP (same egress/device as the session, per the 2026-10-26 console investigation's Phase 1 design):

  1. Cookie capture: read the llama_dev_sess cookie (plus datr for the same host) for dev.meta.ai from the live Helium profile via CDP (Storage.getCookies against the laptop Helium debug port). The session is in the desktop Helium's default profile, which currently runs without a debug port — the capture step needs Helium launched/attached with --remote-debugging-port (or an equivalent profile-copy launch) at capture time. Cookie value goes directly into the gatherer's secret handling — never into a file, log, or this repo. Expected lifetime ~1 year (captured cookie expiry 2027-10-27); treat 401/Not authenticated as failure class session-expired → row goes stale-with-reason per the fix(quota-gatherer): ok-but-null retains last-known (no-data); Command Code explicit ask + plan windows (#5704) #5719 retention behaviour, never zeros.
    • Note (2026-11-04): the Oct-era profile copy at ~/atlas/helium-chatgpt-profile-copy no longer authenticates (401 on /api/auth/me) — do not reuse it; capture from the live profile.
  2. Reads (cookie-auth GETs, base https://dev.meta.ai, team 1073226932208501 = "My Team"):
    • GET /api/portal/teams/{team_id}/subscription-quota → {subscription_quota: {tier: "Muse Code High Usage", as_of, window_weighted_used, window_weighted_limit: "100000000000", window_duration_secs: 18000, window_resets_at, weekly_weighted_used, weekly_weighted_limit: "300000000000", weekly_resets_at}} — used/limit are stringified integers in weighted units; % = used/limit; the 18000s window is the rolling window, plus the weekly window. Proven live payload 2026-10-27 (window 1.02%, weekly 8.83%; resets matched the key endpoint's boundaries exactly).
    • GET /api/portal/teams/{team_id}/billing-banner → {kind, remaining_minor_units, currency} — free credits remaining (minor units = cents; $148.57 at last read).
    • Map into the existing meta row shape (meta:high-usage): rolling + weekly windows with usedPercent + resetsAt, free credits as the balance figure. The portal's own note applies: "new usage can take up to an hour to appear" — carry as_of as measuredAt.
  3. Keep the key-endpoint fetcher as a cross-check, not the source: its is_subs_active / subs_tier_name / require_payment remain the cheapest active/tier signal, and an inference-path 429 (quota exhausted, with reset) corroborates a 100% weekly. If portal and key-endpoint disagree about exhaustion, prefer the portal's percentages and record the disagreement in the row's reason.
  4. Testing: fixture tests from the captured 2026-10-27 payload shape (stringified weighted units, % derivation, reset mapping) + the session-expired and portal-error classes; oracle = the recorded payload + a live console read at verification time.

Acceptance

Related: #3347 (root-cause determination), #1301 (original exporter, closed), #5040 (source switch being partially reversed), #5719 (retention behaviour), #5101 (board stale-fallback display).

Acceptance criteria

  • The gatherer's Meta percentage read comes from the dev.meta.ai portal API (subscription-quota) fetched laptop-side on the existing gatherer tick; both the rolling (18000s) and weekly window percentages are computed from used/limit.
  • The cookie is captured from the live Helium profile at capture time and passes only through the gatherer's secret handling — it appears in no file, log, or repo content.
  • A 401 / Not authenticated response is failure class session-expired: the row goes stale-with-reason per fix(quota-gatherer): ok-but-null retains last-known (no-data); Command Code explicit ask + plan windows (#5704) #5719 retention, never zeros.
  • The key endpoint remains only as a subscription-active/tier signal; it is no longer the system of record for percentages.

Activity

  1. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    priority/highImportant and time-sensitive
    effort/mMedium: expected under 1 day of work
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Nov 5, 2026
  3. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Intake review

  4. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Auth-renewal requirement (Drew's standing rule, 2026-11-05 01:10 CST — provider browser-auth auto-renewal): the restored portal fetcher must NOT depend on a manually captured llama_dev_sess cookie with a silent expiry. The restore design must include cookie auto-renewal as a built-in: on cadence and on auth failure (401), re-capture/refresh the portal session cookie automatically from the standing signed-in laptop Helium profile via CDP (the capture step this issue already names, run by the fetcher itself rather than by a human lane), verify with a live subscription-quota read after renewal, and raise an alert BEFORE hard expiry when renewal fails (the fetcher's state must name the cookie's remaining horizon, not just fail at zero). A one-shot manual capture is the bootstrap, not the mechanism. Inventory + tracking: see the provider browser-auth auto-renewal tracking issue filed 2026-11-05 and ~/memory/topics/provider-auth-renewal-2026-11-05.md.

  5. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Correction / supersession (2026-11-05, Drew's quota single-source order, tracked on #6125): this restore should NOT land as a gatherer-side fetcher. Drew's rule: "dashboard and all other sources should rely on opencode quota subcommand only, 1 single source for quota info" — and any reading the subcommand can't yet produce gets implemented IN THE PROVIDER, never scraped gatherer-side.

    So the portal-API fetcher designed here moves INTO the meta provider's quota implementation in the opencode fork, behind the new opencode quota subcommand. The gatherer's only quota input becomes the subcommand's output. The portal-API design itself (dev.meta.ai portal API, cookie auth, weighted units — proven 2026-10-27) stands and is the implementation spec for the provider-side port; the auto-renewal requirement recorded here (cookie must auto-renew per Drew's 2026-11-05 standing rule) carries into the provider credential machinery. This issue stays open as the design record; implementation + acceptance live on #6125.

  6. added
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 5, 2026
  7. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Meta quota measurement — diagnosis + blocker (2026-11-05, 'fix meta' directive):

    Root cause: both read paths (this issue's provider portal read; the laptop file-export) ride the single Helium dev.meta.ai session, and that session is logged out. Verified twice today: a fresh-tab CDP probe of /api/portal/teams/1073226932208501/subscription-quota returns HTTP 401 {"error":"Not authenticated"} (same as the exporter's last document, 2026-11-04). The provider read currently returns ok:false 'Quota fetch timed out after 30000ms'; the gatherer's Meta row is retained-from-failed-tick (measuredAt 2026-11-04T18:30:20Z, null windows). Last good read remains 2026-11-03 21:00Z.

    Compounding defect, fixed in passing: the pre-existing dev.meta.ai tab had a hung renderer — trivial CDP evaluates timed out on it — which is why both consumers timed out instead of failing fast on the 401. That tab is closed.

    Also found: meta-quota-export.service/.timer were renamed to .backup on 2026-11-01; the exporter has been unscheduled since. The renewal build (OpenDesign-keeper pattern, per the requirement recorded on this issue) must restore scheduling, not just the session.

    Blocker — one Drew-only step: re-login was driven through auth.meta.com (email door, account identifier accepted) to the emailed-code challenge: a login code was sent to Drew's email at ~09:31 CST and the laptop Helium tab is parked on the 'Check your email' page. Once the code is entered there, the session lands and the remaining steps (fresh-read verification on both paths, keeper build, exporter timer restore, gatherer confirmation, registry entry) proceed.

  8. added a commit that references this issue on Nov 5, 2026
  9. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor

    Fix-meta complete — measurement restored 2026-11-05.

    • Path taken: Drew signed in himself on the laptop (~10:28 CST) after the emailed-code step stalled two agent routes; this lane re-checked the session first and SKIPPED the code flow entirely — no code was resent or entered by an agent.
    • Session verified (two independent reads): the portal endpoint /api/portal/teams/1073226932208501/subscription-quota returns HTTP 200 in the Helium page context, and the exporter independently read the same state. Faithful exhausted read — weekly 300,549,363,810 / 300,000,000,000 (100.18%), resets 2026-11-09T00:00Z; 5h window unused; free credits $148.57.
    • Exporter schedule restored: meta-quota-export.service/.timer moved back from their .backup names (renamed 2026-11-01), timer active + enabled, first run Result=success — latest.json fresh with status ok (2026-11-05T16:30Z), ticking every 15 min.
    • Second latent defect found + fixed: the fork's meta quota parser required window_resets_at, which the live portal omits while the 5h window is unstarted — so opencode quota --json meta published ok-but-percentless results and the gatherer retained last-known (no-data: provider reported ok but no window carried a percentage). Fixed, regression-tested (live payload shape), and merged: developing-today-forks/opencode PR laptop-untracked-review: bare git commit sweeps pre-staged work into its commits — the junk-ignore commit also lands the newly tracked files and any unrelated staged edit #1751, merge 24784651b. Percentages land in quota-current.json on the first gather tick after a fork build from main ≥ that merge deploys (the fork-deploy lane's in-flight track); until then the gatherer keeps retaining the last-known row, which is the designed response to a percentless read.
    • Auto-renewal keeper built + live: PR feat(quota): Meta session keeper — exporter-probe watch, unit re-arm, first-tick alert (#6079) #6315 (merge b830347c2a) adds pm-stack/aggregator/src/meta-renewal.ts — the opendesign-renewal pattern adapted to a browser-only session: watch the exporter probe every tick, re-arm the exporter units (including restoring .backup renames), take a fresh probe, and alert in meta-renewal.json from the first bad tick. Verified in production on a live tick: status=valid. Registered in ~/memory/topics/provider-auth-renewal-2026-11-05.md.
    • Measurement only throughout: no provider enablement, no route/config changes.
  10. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  11. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — task 10442 (triage, #6079) TRIAGED CONFIRMED by lane code-u at main c26e058 (2026-11-05, includes PR #6262 merge).

    Evidence at current main:

    • pm-stack/aggregator/scripts/gather-quota.ts (finalizeRun, ~line 353) still documents the failure this issue files: Meta runs come back ok-but-null (every pctOfLimit null — the active-but-no-subs_usage shape since 2026-11-03) and are downgraded to error runs so perf(quota-plane): parallel provider fetching + per-provider timeout budget for the 15-min tick #1268 retention can engage. The key endpoint remains the percentage source; it does not populate.
    • Repo-wide grep over pm-stack at c26e058: no dev.meta.ai portal client, no subscription-quota fetch, no llama_dev_sess cookie capture anywhere in the tree. The fix has not been started.

    Routing: follow-up implementation enqueued as task 10642 (small_fix, repo-health-code-pilot, dedupe repo-health:v1:fix:developing-today/code:issue:6079) carrying the issue's fix section verbatim in scope: laptop-side portal fetcher beside src/meta-renewal.ts wired into gather-quota.ts, team 1073226932208501 subscription-quota + billing-banner, session-expired failure class per #5719 retention, key endpoint demoted to cross-check, fixture tests from the 2026-10-27 payload shape.

    Blockers/ordering recorded: the only runtime prerequisite is the live Helium session on the laptop being reachable over CDP at capture time (the Oct-era profile copy no longer authenticates — do not reuse it, per the issue body). No code blocker. Also noted: this issue carried a stale status:done label while open and unimplemented; removed during this triage's label sync.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

effort/mMedium: expected under 1 day of workkind/bugSomething isn't working (prefixed form of the classic bug label)meta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/highImportant and time-sensitivetask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions