Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions .superpowers/sdd/branch-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Antigravity Hardening Whole-Branch Review

Base: `git merge-base origin/dev HEAD`
Head: `9757b66f9c8d76b94a21da0218d1c2b4bca31450`
Branch: `feat/antigravity-hardening`

## Strengths

- The branch ports the planned quota, geoblock, process-local cooldown, Claude
CCA wire, always-SSE, and daily/production failover behavior in focused
modules rather than adding another provider path.
- CCA unary requests now share the streaming parser, and the focused
Antigravity/Google tests cover the normal unary, host-failover, tool-pair,
geoblock, quota, and cooldown paths.
- The implementation preserves PKCE, does not add `src/lab` imports to the
protected core files, and keeps request bodies, tokens, and account data out
of diagnostics. `bun run privacy:scan` passed.
- `git diff --check` passed, and the focused Antigravity run passed: 160 tests,
0 failures across 8 files. Typechecking also passed in the task validation
runs.

## Issues

### Critical

None found.

### Important

1. **The CCA probe byte cap can be exceeded by one upstream read**
- File: `src/adapters/google-http.ts:90-107, 170-207`
- Issue: `CcaProbeBuffer.append()` grows its backing array to `required`
even when `required` is greater than `CCA_STREAM_PROBE_MAX_BYTES`. The
read loop only checks the limit before the next read, so a single large
`ReadableStream` chunk can allocate and retain more than the advertised
100 MiB cap; line 207 then returns that oversized buffer to the parser.
- Impact: The new protection against oversized CCA streams is not a hard
memory bound. A large upstream chunk can impose an avoidable process-wide
memory spike before the parser's later frame checks run.
- Fix: Make the probe stop buffering at the cap and pass the current chunk
through without copying it into the probe, or otherwise use a bounded
prefix plus a stream that preserves the unread bytes. Add a regression
test where one read crosses the cap.

2. **Standalone Antigravity image failover can duplicate a paid POST**
- File: `src/server/images.ts:230-249`
- Issue: A failed `fetch()` to the first host is followed by a second
`POST /v1internal:generateContent` to the peer. A transport failure is
ambiguous: the first host may have accepted and processed the generation
before the response was lost.
- Impact: The request can generate twice or incur duplicate provider-side
work/charges. This also contradicts the repository invariant in
`structure/04_transports-and-sidecars.md:153-159`, which says each paid
standalone Images POST receives one upstream attempt.
- Fix: Do not retry image-generation POSTs after an unknown transport
outcome unless the upstream provides a verified idempotency key. If host
candidates are retained for images, restrict fallback to a response that
is known to precede request acceptance and document that exception in the
structure note.

3. **Inline SSE quota/rate-limit errors bypass cooldown and account rotation**
- Files: `src/adapters/google-http.ts:66-76`,
`src/adapters/google.ts:619-632`, `src/server/responses/core.ts:3890-3932`
- Issue: The always-SSE path can receive an HTTP-200 stream whose first data
frame is `{ error: { code: 429, status: "RESOURCE_EXHAUSTED", ... } }`.
The probe treats this as terminal and the Google parser emits an error,
but cooldown recording is only performed for HTTP 429/403 responses and
the account carousel only enters on `upstreamResponse.status === 429`.
- Impact: An account that is quota-exhausted or rate-limited in an inline
SSE error is immediately selected again, defeating the new process-local
cooldown and failover behavior.
- Fix: Preserve the classified inline error status/reason through the
adapter response path, record the same cooldown for inline 429/geo
errors, and feed inline pre-stream 429 errors into the existing bounded
account carousel. Keep geoblock non-rotating as required by the plan.
Add an HTTP-200 SSE error regression test.

### Minor

No remaining Minor finding beyond the documentation-table triage item below.

## Documentation-table triage

The leftover Task 1 docs-table Minor is **not still real**. The English
`guides/providers.md` table and the fr/ja/ko/ru/tr/zh-cn/zh-tw mirrors have
matching header/separator structure and the updated
`google-antigravity` rows contain the expected number of cells. No malformed
pipe-delimited row or locale contradiction was found. The known Astro build
extraction issue is therefore not evidence of a markdown defect.

## Validation

- Focused Antigravity/Google validation: **160 passed, 0 failed**.
- `bun run typecheck`: passed in task validation.
- `bun run privacy:scan`: passed.
- `git diff --check`: passed.
- A full `bun run test` was also attempted, but the repository-wide run
returned nonzero because of unrelated environment/baseline failures,
including missing GUI React runtime packages, macOS `/bin/ps` permission
failures, and unrelated auth/Lab regression tests. No Antigravity-focused
failure appeared in that run.

## Assessment

**Ready to merge? No — needs changes.**

The planned feature set is substantially present and the focused tests are
strong, but the probe cap is not actually hard, image failover can duplicate a
paid operation, and inline SSE quota errors bypass the cooldown carousel.
Resolve those Important findings and rerun the focused suite plus the
repository gates before merging.

## Fix pass

- Finding 1 resolved: `CcaProbeBuffer` now refuses writes beyond the 100 MiB
cap, and the probe forwards an oversized read's unread bytes without copying
them into the probe buffer or failing over.
- Finding 2 resolved: standalone CCA image generation now performs exactly one
upstream POST. Ambiguous transport, 404, and 503 outcomes are surfaced rather
than replayed on the peer host; the one-attempt invariant is documented in
`structure/04_transports-and-sidecars.md`.
- Finding 3 resolved: inline CCA quota and geoblock SSE frames are converted to
cooldown-aware synthetic 429/403 responses. Quota enters the existing bounded
Antigravity account carousel; geoblock remains non-rotating.

Fix-pass validation: the requested Antigravity, quota, routing, wire, hardening,
and image tests passed (**175 passed, 0 failed**), and `bun run typecheck`
passed.
4 changes: 4 additions & 0 deletions .superpowers/sdd/progress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

# SDD progress — Antigravity hardening

- Task 1/2/3: implemented (commits e558a771d3f4..986e5af9aa49, review pending)
29 changes: 29 additions & 0 deletions .superpowers/sdd/task-4-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## Status
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Implemented Task 4 CCA request fidelity.

## Files changed

- `src/adapters/google-antigravity-tools.ts`
- `src/adapters/google.ts`
- `tests/google-antigravity-wire.test.ts`
- `tests/google-adapter.test.ts`
- `.superpowers/sdd/task-4-report.md`

## Test

`bun test tests/google-antigravity-wire.test.ts tests/google-adapter.test.ts tests/google-empty-content.test.ts` — 88 passed, 0 failed.

`bun run typecheck` — passed.

## Behavior

- Claude CCA sends the interleaved-thinking beta header.
- CCA requests include the system-instruction replacement preamble.
- Claude trailing model prefills are stripped while lone model turns remain.
- Orphan tool results and assistant calls without later results are removed before allocator prepass; valid parallel pairs remain intact.

## Concerns

- The full repository test suite was not rerun; validation used the requested focused adapter tests and strict typecheck.
- Task 5 transport behavior remains intentionally untouched.
70 changes: 70 additions & 0 deletions .superpowers/sdd/task-5-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Task 5 report — Transport

## Status

Implemented always-SSE Cloud Code Assist requests, daily/production host
failover, quota/image host candidate reuse, and Antigravity account cooldown
wire-up. The existing AI Studio and Vertex unary paths remain on
`generateContent`.

## Validation

- `bun test tests/google-antigravity-wire.test.ts tests/google-hardening.test.ts tests/antigravity-routing.test.ts tests/antigravity-quota.test.ts`
- 104 passed, 0 failed
- `bun run typecheck`
- passed
- `git diff --check`
- passed

## Coverage

- Unary CCA parsing buffers the SSE event contract.
- Empty CCA streams and first-host transport/404/unavailable failures try the
single maintained peer; authentication, geoblock, invalid request, and
exhausted quota do not host-fail over.
- 429 responses classify rate limits versus exhausted quota and record
account-keyed process-local cooldowns.
- Geoblock records cooldown without starting an account carousel.
- Provider documentation tables remain structurally valid after the quota and
transport notes were folded into the Antigravity rows.

## Concerns

CCA response inspection clones and reads up to 256 KiB before returning a
successful response so an empty stream can fail over deterministically. This
preserves the response body for the adapter, but can delay the first client
event until the bounded inspection completes.

## Commit

`3b48b9802` — `feat(antigravity): always-SSE unary, host failover, and account cooldowns`

## Review fixes

- P1 streaming: replaced clone-to-EOF inspection with a bounded first-meaningful-event probe. CCA responses return as soon as a candidate or terminal frame arrives, while the consumed bytes remain attached to the response body; empty streams still fail over at EOF.
- P1 oversized SSE: valid responses larger than the old 256 KiB inspection cap are no longer classified as empty or replayed.
- P2 inline `UNAVAILABLE`: a 200 SSE error frame with `UNAVAILABLE` (or code 503) now uses the single daily/production peer fallback. Terminal authentication, geoblock, invalid-request, and quota errors remain non-failover cases.

## Review-fix validation

- `bun test tests/google-antigravity-wire.test.ts tests/google-hardening.test.ts tests/antigravity-routing.test.ts tests/antigravity-quota.test.ts`
- 107 passed, 0 failed
- `bun run typecheck`
- passed
- `git diff --check`
- passed

## Re-review fixes

- EOF-residual CCA terminal frames now stay on the original host; only empty
residuals and retryable `UNAVAILABLE` residuals invoke peer failover.
- Peer fallback now re-enters the shared Google retry, quota classification,
compatibility replay, and final error-normalization path with host failover
disabled for the peer leg.

## Re-review validation

- `bun test tests/google-antigravity-wire.test.ts tests/google-hardening.test.ts tests/antigravity-routing.test.ts tests/antigravity-quota.test.ts`
- 109 passed, 0 failed
- `bun run typecheck`
- passed
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/fr/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ ocx logout <provider>
| `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Modèles de programmation Kimi K2.7/K2.6/K2.5. |
| `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Passerelle d'abonnement Nous Research (le même service en amont que celui utilisé par Hermes Agent). Connexion par autorisation d'appareil auprès de `portal.nousresearch.com` ; le jeton d'accès est le JWT d'inférence envoyé avec chaque requête. Le catalogue mixte de modèles payants et `:free` (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, ...) est découvert en direct pour le compte connecté. Les jetons d'actualisation sont à usage unique et renouvelés à chaque actualisation. |
| `kiro` | `kiro` | `https://runtime.us-east-1.kiro.dev` | La connexion initiale importe la session de l'installation locale de `kiro-cli`, déjà authentifiée (sous Unix, installez avec `curl -fsSL https://cli.kiro.dev/install` &#124; `bash`; sous Windows PowerShell, utilisez `irm 'https://cli.kiro.dev/install.ps1'` &#124; `iex`; puis exécutez `kiro-cli login`). **Ajouter un compte** déconnecte `kiro-cli`, lance une nouvelle connexion dans le navigateur qui change le compte utilisé par `kiro-cli`, puis enregistre les métadonnées propres au profil. Les comptes OpenCodex existants sont préservés ; une annulation ou un échec restaure la session `kiro-cli` précédente. |
| `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | Google OAuth avec le protocole Cloud Code Assist. La découverte en direct utilise le point de terminaison CCA authentifié `v1internal:fetchAvailableModels` et publie les modèles d'agent accessibles au compte connecté ; le catalogue maintenu reste la solution de repli. |
| `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | Google OAuth avec le protocole Cloud Code Assist. La découverte en direct utilise le point de terminaison CCA authentifié `v1internal:fetchAvailableModels` et publie les modèles d'agent accessibles au compte connecté ; le catalogue maintenu reste la solution de repli. Le quota est sondé via `retrieveUserQuota` et `retrieveUserQuotaSummary` (délai de 8 secondes). CCA utilise toujours SSE, met en mémoire tampon SSE pour les appels unitaires et réessaie le pair daily/production en cas d'échec de transport, de 404 ou d'indisponibilité sur le premier hôte ; les délais 429 sont locaux au processus et propres au compte. |
| `cursor` | `cursor` | `https://api2.cursor.sh` | Connexion PKCE expérimentale, transport HTTP/2 en direct et découverte de modèles filtrés par compte. |
| `github-copilot` | `openai-chat` | `https://api.githubcopilot.com` | Expérimental. Flux d'appareil GitHub et échange `copilot_internal` (client OAuth de VS Code). Nécessite un abonnement Copilot actif ; il ne s'agit pas d'une API tierce officielle. |

Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ ocx logout <provider>
| `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 coding models. |
| `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research subscription gateway (same backend Hermes Agent uses). Device-grant login against `portal.nousresearch.com`; the access token is the per-request inference JWT. Mixed paid + `:free` model catalog (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, ...) discovered live from the signed-in account. Refresh tokens are single-use and rotated on every refresh. |
| `kiro` | `kiro` | `https://runtime.us-east-1.kiro.dev` | Initial login imports the installed, signed-in `kiro-cli` session (on Unix, install with `curl -fsSL https://cli.kiro.dev/install` &#124; `bash`; on Windows PowerShell, use `irm 'https://cli.kiro.dev/install.ps1'` &#124; `iex`; then run `kiro-cli login`). **Add account** logs `kiro-cli` out, starts a fresh browser login that switches the account used by `kiro-cli`, and stores account-scoped profile metadata. Existing OpenCodex accounts are preserved, and cancellation or failure restores the previous `kiro-cli` session. |
| `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | Google OAuth over the Cloud Code Assist wire. Live discovery uses CCA's authenticated `v1internal:fetchAvailableModels` endpoint and publishes the agent models available to the signed-in account; the maintained catalog remains the fallback. |
| `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | Google OAuth over the Cloud Code Assist wire. Live discovery uses CCA's authenticated `v1internal:fetchAvailableModels` endpoint and publishes the agent models available to the signed-in account; the maintained catalog remains the fallback. Quota is probed live via `retrieveUserQuota` and `retrieveUserQuotaSummary` (8-second timeout). CCA always uses SSE, buffers SSE for unary callers, and retries the daily/production peer on first-host transport, 404, or unavailable failures; 429 cooldowns are process-local per account. |
| `cursor` | `cursor` | `https://api2.cursor.sh` | Experimental PKCE login, live HTTP/2 transport, and account-filtered model discovery. |
| `github-copilot` | `openai-chat` | `https://api.githubcopilot.com` | Experimental. GitHub device flow + `copilot_internal` exchange (VS Code OAuth client). Requires an active Copilot subscription; not an official third-party API. |

Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/ja/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ ocx logout <provider>
| `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 コーディングモデル。 |
| `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research サブスクリプションゲートウェイ(Hermes Agent と同じバックエンド)。`portal.nousresearch.com` へのデバイスグラントログイン; access トークンはリクエストごとの inference JWT。有料 + `:free` モデルの混在カタログ(`tencent/hy3:free`、`stepfun/step-3.7-flash:free` など)はサインイン中のアカウントからライブ探索されます。Refresh トークンは単回使用で、更新のたびにローテーションされます。 |
| `kiro` | `kiro` | `https://runtime.us-east-1.kiro.dev` | 初回ログインは、インストール済みでサインインした `kiro-cli` セッションを取り込みます(Unix では `curl -fsSL https://cli.kiro.dev/install` &#124; `bash`、Windows PowerShell では `irm 'https://cli.kiro.dev/install.ps1'` &#124; `iex` でインストールしてから `kiro-cli login` を実行)。**アカウントを追加**は `kiro-cli` をログアウトして新しいブラウザログインを開始し、`kiro-cli` 自体のアカウントを切り替えてアカウント別プロファイルメタデータを保存します。既存の OpenCodex アカウントは保持され、キャンセルまたは失敗時には以前の `kiro-cli` セッションが復元されます。 |
| `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | Google OAuth を Cloud Code Assist wire で使用。ライブ探索は認証済みの CCA `v1internal:fetchAvailableModels` エンドポイントを使用し、ログイン中のアカウントで利用可能な agent モデルのみを公開します。管理されたカタログはフォールバックとして残ります。 |
| `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | Google OAuth を Cloud Code Assist wire で使用。ライブ探索は認証済みの CCA `v1internal:fetchAvailableModels` エンドポイントを使用し、ログイン中のアカウントで利用可能な agent モデルのみを公開します。管理されたカタログはフォールバックとして残ります。Quota は `retrieveUserQuota` と `retrieveUserQuotaSummary`(8 秒タイムアウト)で取得します。CCA は常に SSE を使用し、単項呼び出しでは SSE をバッファリングします。最初のホストでの transport、404、unavailable の失敗時は daily/production peer に再試行し、429 cooldown はアカウント単位のプロセス内状態です。 |
| `cursor` | `cursor` | `https://api2.cursor.sh` | 実験的 PKCE ログイン、HTTP/2 トランスポート、アカウント別モデル探索をサポート。 |
| `github-copilot` | `openai-chat` | `https://api.githubcopilot.com` | 実験的。GitHub デバイスフロー + `copilot_internal` 交換(VS Code OAuth クライアント)。有効な Copilot サブスクリプションが必要で、公式のサードパーティ API ではありません。 |

Expand Down
Loading
Loading