Skip to content

Development - #14

Merged
pavelhov merged 27 commits into
mainfrom
development
Aug 15, 2026
Merged

Development#14
pavelhov merged 27 commits into
mainfrom
development

Conversation

@pavelhov

Copy link
Copy Markdown
Owner

No description provided.

pavelhov added 27 commits August 13, 2026 02:40
Genuine usage.jsonl read/stat/schema failures now respond 503 with a
{ error: read_failed, range, surface } body instead of a 200 zeroed
summary. Missing log files still return 200 with a zeroed summary via
readUsageSnapshotForManagement. Tests updated and extended to assert the
503 contract and that success responses carry estimatedCostUsd,
pricedRequests, unpricedRequests, and unmeteredRequests.
The Usage page now validates GET /api/usage success bodies before any cache
write: error envelopes and malformed summaries (missing or non-finite
required summary fields, including estimatedCostUsd/pricedRequests/
unpricedRequests/unmeteredRequests) throw a typed UsageReportValidationError
and are never persisted. A defined zero cost renders $0.00 while a
genuinely missing legacy field renders "Unavailable". Cold failures keep
the failed-cold Notice with retry, and failed refreshes retain last-known-
good data with the stale/error banner. Shared validator lives in
gui/src/usage-report-validation.ts for reuse by the upcoming domain store.
…alignment

- .select-trigger > span now ellipsizes inside the pill instead of spilling
  past it (global rule matching the dashboard sidecar pattern).
- Roster/library/fallback/matrix model IDs wrap with overflow-wrap:anywhere
  instead of clipping mid-ID; name spans carry title tooltips.
- Run Policy grid: align-items start (kills the 30px label staircase),
  guidance spans 4 columns + save cell pinned to column 5 (kills the void
  next to Save changes), helper text uses --text-label, 150px tracks widened
  to 170px, save cell magic min-height removed.
- Library filter chips wrap instead of clipping at the right edge.
- Notice tone=err now announces with role=alert; ok/warn stay status.
- Rail IDs on Models/ClaudeCode/Storage/Combos get title tooltips.
- Drop redundant style={{width:'100%'}} on policy selects (CSS owns it).
…nology

- subagents-classic/busy-race tests assert the Configured Roster rename
  (heading + add/remove aria-labels); the aria-labels were never regressed.
- Copy updates: no-preferred-model hint, shortened fallback hint, rewritten
  V2 compatibility notices (drop lidge-jun#92 and off-topic clauses), consolidated
  save/timing instructions (sub.policy.saved is now one line; timing lives
  in the details note), de-jargoned Usage subtitle, V1/V2 capitalization,
  'protocol' as the single word for the collaboration selector, and
  'configured roster' terminology (en/de/ja/ko landed with the usage
  validation commit; ru/zh follow here).
- models-empty-provider test expects 'Reliable V1'.
Run under tsc --noUnusedLocals --noUnusedParameters: 356 diagnostics in
src/server/management were stale imports left by earlier route
consolidations. Removed unused bindings (compiler-API driven, verified per
file), dropped unused destructured ctx fields, and normalized the blank
lines left behind. No behavior change: bun run typecheck clean, management
route tests (395) and privacy:scan pass.
Cross-client grep: no GUI or other runtime client calls /api/disabled-models
or /api/key-providers anymore; only tests, docs, and structure notes
reference them. Add deprecation notes pointing at the replacements (PUT
/api/model-visibility, GET /api/providers). Routes stay live for script
compatibility.
Sync English guide copy with the GUI labels: Reliable V1, Concurrent V2,
V1/base/V2 mode descriptions, and prose references. CLI command syntax
(ccx v2 mode v1, /api/v2) stays lowercase. Translated docs had no label
strings to contradict.
Introduces gui/src/usage-report-store.ts, a keyed zustand domain store for
GET /api/usage reports (${apiBase}:${range}:${surface}) with
client-resource-shaped snapshots, singleflight per key, AbortController
cancellation, and sessionStorage persistence of validated reports plus a
timestamp only (never errors or in-flight state). Rehydrated seeds are
marked seedNeedsRevalidate so the first subscriber quiet-revalidates.

Usage.tsx and the Dashboard now select the same 30d/all entry, collapsing
the previous three independent usage fetches into one. The dashboard usage
client-resource poll and USAGE_CACHE_PREFIX session-cache are removed;
fetchDashboardUsage is deleted. The page-loading contract pin now accepts
Usage's classifyDataSurface wiring through the shared data-surface state
machine. Adds store unit tests, a rehydration test file, and updates
usage-validation and dashboard-contract tests.
Introduces gui/src/provider-quota-store.ts, a zustand domain store keyed by
apiBase for GET /api/provider-quotas. ProviderWorkspaceShell now routes its
quota fetch through the store (quotaRefreshEpoch/quotaForceRefresh map to a
refresh({ force }) action that adds the ?refresh=1 TTL bypass), keeping its
strict capacity-aggregation display filter on top of the store's permissive
ingest so reference-window-only reports stay representable for the upcoming
Dashboard Plan & quota section.

Privacy invariant: only quota reports (provider/label/source/quota/updatedAt/
aggregation) plus a timestamp are persisted — never account emails or ids;
stray identity fields on the wire are projected away. Stale (>30 min)
rehydrated seeds are rejected. Store tests cover force-refresh, singleflight,
last-good retention, stale-seed rejection, and the privacy invariant.

Also fixes global hygiene in the store test files: the default bun test
runner shares one global scope across files, so each test file now restores
every installed global (sessionStorage/window/document/fetch) after its run.
Extends UsageSummary30d with estimatedCostUsd/pricedRequests/unpricedRequests/
unmeteredRequests and shows a 30-day estimated cost stat (API list-price
equivalent, never billed spend) with a request-coverage line in the dashboard
overview head ($0.00 for a defined zero, em-dash when absent).

Adds a Plan & quota section fed by the provider-quota store (same apiBase-keyed
entry as the Providers workspace shell): per-provider plan, 5h/week/month
windows via ProviderCapacityQuota, and observed reference spend vs published
caps (referenceWindows) — all labeled provider-reported/estimates. Styling
reuses existing dashboard tokens/classes; no new stylesheet. All new strings
land in all 6 locales (lint:i18n green).

Tests cover the cost stat (estimate, zero, absent), the Plan & quota render
from a provider-quotas fixture, and the privacy invariant that the section
never persists account identities to sessionStorage.
…ve button

- sub.pageSubtitle now reads 'Choose which models sub-agents may use, which
  model guides them, and the fallback order.' (all 6 locales) — 'advertised'
  was jargon per the designer audit (C1).
- Policy save cell right-aligns the button so it sits at the card edge
  (17px from the grid edge vs 423px void before; measured at 1380px).
- Visual verification (playwright + mock API): labels all at 17px (no 30px
  staircase), select labels ellipsize with zero spill at 1380/1024/390/360,
  roster/library IDs fully visible (no mid-ID clip), filter chips wrap with
  no overflow at 360px.
- management-api.md: GET /api/usage now documents the 503 read_failed
  envelope; missing log file stays 200/zero.
- cli/agents.md: ccx usage reports the read failure instead of a zeroed
  report; missing log still prints empty.
- web-dashboard.md: Dashboard summary includes the 30-day estimated cost;
  the cost/Plan & quota notes clarify provider-reported estimates are never
  billed spend.
…freshness

Addresses the post-review findings:

- usage-report-store: a failed quiet revalidation of a rehydrated seed restores
  seedNeedsRevalidate (next subscriber retries) and seeds read as hasSucceeded
  (last-known-good, not never-succeeded). refresh() gains replace:false so the
  Dashboard can quiet-revalidate on a 60s interval (singleflight, pause-when-
  hidden) without reintroducing a client-resource poll.
- usage-report-validation: days/models/providers array elements are now validated
  (finite numeric fields, string ids) instead of cast wholesale; a malformed
  element rejects the whole report so nothing unvalidated is cached.
- provider-quota-store: quota/aggregation rows are deep-projected onto the known
  keys at ingest, so stray identity fields can never reach sessionStorage;
  ensure({force:true}) now always fetches.
- ProviderWorkspaceShell: mount uses ensure() (healthy-entry short-circuit, never
  aborts shared in-flight fetches) with a StrictMode guard; explicit quota
  revision bumps still use refresh({force}).
- logs-usage-routes: the 503 read_failed catch is narrowed to the file-read
  machinery (revision stat + snapshot read); derivation/cache-layer errors
  propagate as ordinary server errors.
- Dashboard: 30-day cost stat uses a locale-aware zero formatter, hides the
  coverage line when all request classes are 0; Usage cold-failure Notice keeps
  localized text and moves raw error detail to the retry button title.

Tests: element-level validation unit tests, malformed-element store rejection,
HTTP 503 cold-failure page test, hostile identity fields inside quota/aggregation,
seed-semantics assertions, and strengthened $0.00 (no tilde) assertions.
…oken swap

- OpenCode config-destination <code> now carries title={full path}; it
  ellipsizes inside .integration-facts (verified truncated=true with title
  set via mock-API harness). Grok model names already had titles (no-op).
- styles-integrations.css: min-height 34px -> var(--control-md); off-scale
  gaps 18/10/7px and 14px paddings -> nearest space tokens (16/8/6/12px);
  the 6px/28px/4px chip values were already exact tokens.
Swap hardcoded paddings/gaps/margins to the nearest design token where the
delta is <=2px and imperceptible (18->space-4, 14->space-3, 10->space-2,
9->space-2, 7->space-1-5, 3->space-1, 31->space-8, 6->space-1-5,
34->control-md, 11px->text-caption). Font-size 10.5px, line-height 1.45,
font-weight 550, and the select/trigger pill box-shadow 0 2px 8px are
deliberate tuning -> marked /* deliberate */ instead of swapped. Verified
visually at 1380/390 via the mock-API harness; full GUI suite 791/0 green.
…logy

Sweep the 8 guide/reference files: lowercase v1/v2 in prose that refers to
the collaboration protocol becomes V1/V2 (code literals, config values,
CLI syntax, /api/v2 paths, plaintext/encrypted options, multi_agent_v2
flag stay untouched). Align wording with the GUI labels: 'collaboration
protocol' for the three-state selector (was 'surface mode'), V2 thread
limit, and keep Configured Roster / Agent Library / quick picks / catalog
nouns consistent. 503 and Est. cost/Plan & quota prose reviewed in
context. Docs build: 46 pages.
…, chip tokens

- styles.css: grok-model-names 10.5px comment corrected (value sits between
  --text-micro and --text-caption, not below micro).
- styles-integrations.css: client-apps-flow-chip padding 4px 9px + gap 6px +
  min-height 28px now use tokens (space-1/space-2/space-1-5/control-sm).
- sub-agent-surface.md: v1/v2 mode bullets -> V1/V2 (prose labels).
- cli/agents.md: active V1/V2 thread limit row.
- configuration/agents.md: V1/V2 developer guidance row.
- Deferred (ledger): out-of-scope pages codex-app-models.md / how-it-works.mdx
  terminology, and remaining off-grid values outside the story's enumerated
  sweep list.
…der overview

Parity with the Mac app: /api/provider-quotas availability rows are now
projected into the shared store (in-memory only — the persisted slice stays
reports + timestamp) and rendered where a provider has no report:

- Store: quotaAvailabilityFromResponse (provider/status/reason/checkedAt
  only; unknown reason codes dropped) + unavailableQuotaProviders selector
  (status !== available AND no report, sorted). Refresh populates; failed
  fetch retains last-known-good. authAttention flow untouched.
- Dashboard: full-width 'Quota unavailable' strip below the Plan & quota
  grid listing '{provider} — {reason copy}' with a shared Retry
  (refresh(force) -> ?refresh=1); hidden when nothing is unavailable.
- Provider Overview: quota slot shows a compact warn notice with reason copy
  + Retry when the selected provider has no report and is unavailable;
  quota card unchanged when a report exists. Threaded shell -> Providers ->
  ProviderDetails -> Overview.
- Copy matches the Mac app summary: reauth_required -> Sign in required,
  local_cli_refresh_required -> Login needs refresh, else Temporarily
  unavailable. 7 new keys in all 6 locales (lint:i18n green).
- Tests: store projection/selector/privacy/failure-retention, dashboard
  strip render + Retry-disappears + hidden cases, overview notice + Retry.
  Full GUI suite 804 pass / 0 fail; visual check via mock harness at
  1380/390 (strip full-width, grid unchanged).
…ason-copy tests

- useProviderQuota uses module-level EMPTY availability/reports so derived
  memos don't recompute while the entry is absent (restores zero lint
  warnings; was 2 react-hooks/exhaustive-deps).
- quotaAvailabilityFromResponse allowlists status to available/stale/
  unavailable; hostile status strings are dropped at ingest.
- Tests: selector covers stale-without-report inclusion; projection covers
  hostile status; dashboard strip covers the reauth_required reason copy
  (Sign in required) next to upstream_unavailable.
- Full GUI suite 804 pass / 0 fail; typecheck + lint clean.
@pavelhov
pavelhov merged commit 92c5e2e into main Aug 15, 2026
1 check failed
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