Repository navigation
Conversation
…ta freshness The GA sidebar printed every row as plain text although the projection already computes a tone per quota row and status, and it always said "quota not checked yet" because both GA state sources hard-coded status.checkedAt to null. Vault pools also always read "no quota reading yet" because the vault source dropped each row's reading time. - state answers report the newest cached quota reading as checkedAt, for local and vault custody; vault rows forward cachedQuotaUpdatedAt - the GA renderer reads optional theme tokens from the host context and colors figures, bars, status, secondary text and notices by tone - each pool with a reading draws a remaining-quota bar sized from the measured sidebar width (dropped when it does not fit, so narrow sidebars keep today's text) - the header is a clickable ANTIGRAVITY badge that collapses the panel to one line per account; the choice persists in host plugin storage Without a theme or storage the sidebar renders the same text uncolored and collapse lasts for the session. The GA module graph is unchanged.
There was a problem hiding this comment.
5 issues found across 6 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/opencode/docs/OPENCODE-2.md">
<violation number="1" location="packages/opencode/docs/OPENCODE-2.md:51">
P2: This sentence presents theme coloring and collapse persistence as unconditional, but hosts without theme or storage support retain default colors and a session-only collapse choice. Document both fallbacks so users are not promised capabilities their host does not provide.</violation>
</file>
<file name="packages/opencode/src/plugin/ga-location-services.ts">
<violation number="1" location="packages/opencode/src/plugin/ga-location-services.ts:1763">
P2: The vault projection drops `cachedQuotaUpdatedAt` whenever `cachedQuota` is absent, even though vault state permits and hydrates those fields independently. Forward the timestamp independently so `status.checkedAt` remains accurate for timestamp-only readings.</violation>
<violation number="2" location="packages/opencode/src/plugin/ga-location-services.ts:1776">
P2: Over-limit state responses always report `checkedAt: null` because both sources discard all rows before calculating freshness. Compute the newest timestamp from the ready roster before the over-limit projection so clients do not lose quota freshness in this response mode.</violation>
</file>
<file name="packages/opencode/src/ga/tui/host-ga.tsx">
<violation number="1" location="packages/opencode/src/ga/tui/host-ga.tsx:1517">
P2: `quotaBarCells` reserves six cells even when a window label is longer, such as `Gm weekly`; `padEnd` cannot shorten it. Base the calculation on `Math.max(LABEL_CELLS, row.label.length)` so bars do not overflow rows with quota windows.</violation>
<violation number="2" location="packages/opencode/src/ga/tui/host-ga.tsx:1537">
P2: The sidebar reads a theme shape that OpenCode 2 does not provide, so all new color lookups are `undefined` in the real host and the advertised coloring never appears. Map tones to the host's flat `success`/`warning`/`error`/`textMuted`/`text` fields and use `accent`/`background` for the badge.</violation>
</file>
Reply to a comment to ask cubic a question or push back. It learns from your replies.
View guided diff | Re-trigger cubic
| ## UI and evidence limits | ||
|
|
||
| OpenCode 2's sidebar and menu use location-scoped snapshots through native host RPC, not OpenCode 1's sidebar/port-file configuration. Credentials, project IDs, and fingerprints do not belong in renderer snapshots or support reports. See [commands](COMMANDS.md) and [credential safety](CONFIGURATION.md#security-and-redaction). | ||
| OpenCode 2's sidebar and menu use location-scoped snapshots through native host RPC, not OpenCode 1's sidebar/port-file configuration. The sidebar colors quota with the host theme's feedback colors (remaining above 30 % success, 11–30 % warning, 10 % or less error) and collapses from its `ANTIGRAVITY` header; the collapse choice lives in the host's plugin storage, separate from OpenCode 1's `tui-preferences.jsonc`. Credentials, project IDs, and fingerprints do not belong in renderer snapshots or support reports. See [commands](COMMANDS.md) and [credential safety](CONFIGURATION.md#security-and-redaction). |
There was a problem hiding this comment.
P2: This sentence presents theme coloring and collapse persistence as unconditional, but hosts without theme or storage support retain default colors and a session-only collapse choice. Document both fallbacks so users are not promised capabilities their host does not provide.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/docs/OPENCODE-2.md, line 51:
<comment>This sentence presents theme coloring and collapse persistence as unconditional, but hosts without theme or storage support retain default colors and a session-only collapse choice. Document both fallbacks so users are not promised capabilities their host does not provide.</comment>
<file context>
@@ -48,6 +48,6 @@ The host retry API identifies the session but not the exact HTTP attempt. The pl
## UI and evidence limits
-OpenCode 2's sidebar and menu use location-scoped snapshots through native host RPC, not OpenCode 1's sidebar/port-file configuration. Credentials, project IDs, and fingerprints do not belong in renderer snapshots or support reports. See [commands](COMMANDS.md) and [credential safety](CONFIGURATION.md#security-and-redaction).
+OpenCode 2's sidebar and menu use location-scoped snapshots through native host RPC, not OpenCode 1's sidebar/port-file configuration. The sidebar colors quota with the host theme's feedback colors (remaining above 30 % success, 11–30 % warning, 10 % or less error) and collapses from its `ANTIGRAVITY` header; the collapse choice lives in the host's plugin storage, separate from OpenCode 1's `tui-preferences.jsonc`. Credentials, project IDs, and fingerprints do not belong in renderer snapshots or support reports. See [commands](COMMANDS.md) and [credential safety](CONFIGURATION.md#security-and-redaction).
The [released-host contract](opencode2-ga-2.0.22-contract.md) records pinned contracts and proof obligations. Source tests, a packed TUI smoke run, and a native-host run are distinct evidence. A native host using simulated OAuth responses does not prove Google's live OAuth acceptance or account entitlement. Live model verification means sending requests to the actual Antigravity service, not a mock server. This guide does not claim that native gates or live-service verification have run: [Argon MEDIUM/HIGH remain unverified live](MODEL-VARIANTS.md#gemini).
</file context>
| OpenCode 2's sidebar and menu use location-scoped snapshots through native host RPC, not OpenCode 1's sidebar/port-file configuration. The sidebar colors quota with the host theme's feedback colors (remaining above 30 % success, 11–30 % warning, 10 % or less error) and collapses from its `ANTIGRAVITY` header; the collapse choice lives in the host's plugin storage, separate from OpenCode 1's `tui-preferences.jsonc`. Credentials, project IDs, and fingerprints do not belong in renderer snapshots or support reports. See [commands](COMMANDS.md) and [credential safety](CONFIGURATION.md#security-and-redaction). | |
| OpenCode 2's sidebar and menu use location-scoped snapshots through native host RPC, not OpenCode 1's sidebar/port-file configuration. When available, the host theme colors quota (remaining above 30 % success, 11–30 % warning, 10 % or less error); without those theme tokens, the sidebar remains uncolored. The sidebar collapses from its `ANTIGRAVITY` header, and the collapse choice is saved in host plugin storage when available; otherwise it lasts only for the session, separate from OpenCode 1's `tui-preferences.jsonc`. Credentials, project IDs, and fingerprints do not belong in renderer snapshots or support reports. See [commands](COMMANDS.md) and [credential safety](CONFIGURATION.md#security-and-redaction). |
| route, | ||
| status: { | ||
| checkedAt: null, | ||
| checkedAt: newestQuotaReadingAt(projected.map(({ row }) => row)), |
There was a problem hiding this comment.
P2: Over-limit state responses always report checkedAt: null because both sources discard all rows before calculating freshness. Compute the newest timestamp from the ready roster before the over-limit projection so clients do not lose quota freshness in this response mode.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/plugin/ga-location-services.ts, line 1776:
<comment>Over-limit state responses always report `checkedAt: null` because both sources discard all rows before calculating freshness. Compute the newest timestamp from the ready roster before the over-limit projection so clients do not lose quota freshness in this response mode.</comment>
<file context>
@@ -1727,30 +1746,34 @@ function createGaVaultStateSource(input: {
route,
status: {
- checkedAt: null,
+ checkedAt: newestQuotaReadingAt(projected.map(({ row }) => row)),
quotaBackoffUntil: null,
routingAuthoritative: true,
</file context>
| ...(row.cachedQuota !== undefined && | ||
| row.cachedQuotaUpdatedAt !== undefined | ||
| ? { cachedQuotaUpdatedAt: row.cachedQuotaUpdatedAt } | ||
| : {}), |
There was a problem hiding this comment.
P2: The vault projection drops cachedQuotaUpdatedAt whenever cachedQuota is absent, even though vault state permits and hydrates those fields independently. Forward the timestamp independently so status.checkedAt remains accurate for timestamp-only readings.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/plugin/ga-location-services.ts, line 1763:
<comment>The vault projection drops `cachedQuotaUpdatedAt` whenever `cachedQuota` is absent, even though vault state permits and hydrates those fields independently. Forward the timestamp independently so `status.checkedAt` remains accurate for timestamp-only readings.</comment>
<file context>
@@ -1727,30 +1746,34 @@ function createGaVaultStateSource(input: {
+ ...(row.cachedQuota !== undefined
+ ? { cachedQuota: row.cachedQuota }
+ : {}),
+ ...(row.cachedQuota !== undefined &&
+ row.cachedQuotaUpdatedAt !== undefined
+ ? { cachedQuotaUpdatedAt: row.cachedQuotaUpdatedAt }
</file context>
| ...(row.cachedQuota !== undefined && | |
| row.cachedQuotaUpdatedAt !== undefined | |
| ? { cachedQuotaUpdatedAt: row.cachedQuotaUpdatedAt } | |
| : {}), | |
| ...(row.cachedQuotaUpdatedAt !== undefined | |
| ? { cachedQuotaUpdatedAt: row.cachedQuotaUpdatedAt } | |
| : {}), |
| const reset = row.reset === '' ? 0 : row.reset.length + 1 | ||
| const cells = Math.min( | ||
| BAR_CELLS, | ||
| width - LABEL_CELLS - 1 - row.figure.length - reset, |
There was a problem hiding this comment.
P2: quotaBarCells reserves six cells even when a window label is longer, such as Gm weekly; padEnd cannot shorten it. Base the calculation on Math.max(LABEL_CELLS, row.label.length) so bars do not overflow rows with quota windows.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/ga/tui/host-ga.tsx, line 1517:
<comment>`quotaBarCells` reserves six cells even when a window label is longer, such as `Gm weekly`; `padEnd` cannot shorten it. Base the calculation on `Math.max(LABEL_CELLS, row.label.length)` so bars do not overflow rows with quota windows.</comment>
<file context>
@@ -1469,9 +1501,100 @@ interface SidebarView {
+ const reset = row.reset === '' ? 0 : row.reset.length + 1
+ const cells = Math.min(
+ BAR_CELLS,
+ width - LABEL_CELLS - 1 - row.figure.length - reset,
+ )
+ return cells >= MIN_BAR_CELLS ? cells : 0
</file context>
| ): GaColor | undefined { | ||
| switch (tone) { | ||
| case 'ok': | ||
| return theme?.text?.feedback?.success?.base |
There was a problem hiding this comment.
P2: The sidebar reads a theme shape that OpenCode 2 does not provide, so all new color lookups are undefined in the real host and the advertised coloring never appears. Map tones to the host's flat success/warning/error/textMuted/text fields and use accent/background for the badge.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/ga/tui/host-ga.tsx, line 1537:
<comment>The sidebar reads a theme shape that OpenCode 2 does not provide, so all new color lookups are `undefined` in the real host and the advertised coloring never appears. Map tones to the host's flat `success`/`warning`/`error`/`textMuted`/`text` fields and use `accent`/`background` for the badge.</comment>
<file context>
@@ -1469,9 +1501,100 @@ interface SidebarView {
+): GaColor | undefined {
+ switch (tone) {
+ case 'ok':
+ return theme?.text?.feedback?.success?.base
+ case 'warn':
+ return theme?.text?.feedback?.warning?.base
</file context>
Why
On OpenCode 2 the Antigravity sidebar is hard to read and partly wrong:
projectSidebar()already computes a tone per quota row and per status;status.checkedAt: null;cachedQuotaUpdatedAt.OpenCode 1 users get colored bars and a collapsible header; GA users get neither.
What changes
State freshness (
plugin/ga-location-services.ts)stateanswers report the newest cached quota reading asstatus.checkedAt(local and vault), ornullwhen no row holds a reading. AcheckedAtthe location reports itself still wins.cachedQuotaUpdatedAt, so vault pools show their figure and age like local pools.checkedAtwas already a nullable number.GA sidebar (
ga/tui/host-ga.tsx)text.base,text.muted,text.feedback.{success,warning,error}.base,text.action.primary.base,background.base) and colors figures, bars and status by the existing projection tones; secondary text is muted, degraded-state notices use the warning color.▼/▶ ANTIGRAVITYbadge; collapsed, each account takes one line (label, lowest remaining figure, status dot). The choice persists throughcontext.storage.storewhen the host provides it.The GA module graph is unchanged (still pinned by
tui.test.tsx);@opentui/coreis used as a type-only import.Out of scope
quotaBackoffUntilin GA staysnull.remainingTone: ≤30 warn, ≤10 err).host-ga.tsxandga/server(see fix: OpenCode 2.0.29 GA RPC compatibility and Windows support #40).Tests
ga-location-services.test.ts: newest-reading helper; localcheckedAtfrom rows; reportedcheckedAtkept; vault rows forward reading times and report the newest; no identity in the answer.tui.test.tsx: colors by tone with a fake theme (span colors), bar sizing and fill, collapsed figure, header click collapses and saves to storage, starts collapsed from storage; the existing width-32 reset-span frame is unchanged; one frame expectation updated for the new bar.build,typecheck,lint,format:check.bun test --isolate ./src ./scripts/build-tui.test.tsinpackages/opencode: the 36 failures are the same onmainwithout this change in this environment (Pi native path, setup CLI, GA test-case lifetime), none in touched areas. Existingmutations.tomlanchors in touched files still match exactly once.Specified with OpenSpec (proposal, two capability specs
ga-sidebarandga-state-status, design, tasks); the artifacts are kept out of the repository.Summary by cubic
Makes the OpenCode 2 Antigravity sidebar readable and accurate: quota rows, bars, and status are now colored with the host theme, and
stateanswers report the newest cached quota reading so the sidebar stops claiming "quota not checked yet."State freshness
stateanswers report the newest cached quota reading asstatus.checkedAtfor local and vault accounts, ornullwhen no reading exists; a reportedcheckedAtstill wins.cachedQuotaUpdatedAt, so they show their figures and ages instead of "no quota reading yet."Sidebar UI
▼/▶ ANTIGRAVITYbadge that collapses the panel to one line per account (label, lowest remaining figure, status dot); the choice persists in host plugin storage when available.Written for commit ab7a9b1. Summary will update on new commits.