Skip to content

fix(deploy): let --reconnect refresh a revoked harness LLM credential#235

Merged
khaliqgant merged 1 commit into
mainfrom
fix/cloud-reconnect-harness-credential
Jun 14, 2026
Merged

fix(deploy): let --reconnect refresh a revoked harness LLM credential#235
khaliqgant merged 1 commit into
mainfrom
fix/cloud-reconnect-harness-credential

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Jun 14, 2026

Copy link
Copy Markdown
Member

Problem

The pr-reviewer cloud persona (and any oauth-harness persona) was failing every fire across every repo with The review harness exited with code 1. Root cause traced via Daytona: the baked codex/ChatGPT OAuth token was revoked server-side (401 token_invalidated / refresh_token_invalidated). Each codex session ended in ~3.6s with last_agent_message: null — the harness never authenticated.

This happens whenever you re-run codex login locally on the same ChatGPT account: OpenAI rotates the refresh token and revokes the copy cloud baked into each fire.

The gap that made it unrecoverable from the CLI:

  • Cloud reports a credential row as status: connected even when its stored token is revoked (it never re-validates the token).
  • ensureHarnessOauth / ensureSubscriptionOauth short-circuit on that connected status, so a plain redeploy can never refresh a dead harness credential.
  • --reconnect <provider> only flowed to the integrations connect path (connect.ts), never the LLM harness credential.

The only recovery was manually disconnecting the credential in the dashboard.

Fix

Thread reconnectProviders into ModeLaunchInput and both harness-oauth paths. When --reconnect <provider> matches the persona's model provider (openai/anthropic) or harness name (codex/claude), force a fresh connectProvider flow that overwrites the stored token even when cloud reports it connected. connectProvider blocks until cloud stores the fresh credential, so the new token is live when deploy proceeds. Under --no-prompt it fails with actionable guidance (the connect flow needs a TTY).

Recovery is now one flag instead of a dashboard round-trip:

agentworkforce deploy ./review/persona.ts --on-exists update --reconnect codex …

Changes

  • types.tsreconnectProviders on ModeLaunchInput
  • deploy.ts — thread it into the launch input + ensureCloudSubscriptionReady
  • modes/cloud/index.tsensureHarnessOauth + ensureSubscriptionOauth honor reconnect; new harnessReconnectRequested() (matches provider key or harness name)
  • cli/src/deploy-command.ts — clarify --reconnect help to cover the harness LLM credential
  • modes/cloud.test.ts — 2 new tests

Testing

  • @agentworkforce/deploy: 202/202 pass (incl. the 2 new reconnect tests); typecheck clean
  • @agentworkforce/cli: deploy-command 12/12; typecheck clean

🤖 Generated with Claude Code

Review in cubic

Cloud marks a harness credential row `connected` even after its OAuth
token is revoked server-side (it never re-validates the token), so
`ensureHarnessOauth`/`ensureSubscriptionOauth` short-circuited and a
plain redeploy could never refresh a dead credential. `--reconnect`
only reached the integrations connect path, never the LLM harness
credential — leaving a manual dashboard disconnect as the only recovery.

This is the codex/ChatGPT failure mode: re-running `codex login` locally
rotates and revokes the refresh token cloud baked into every fire, so the
pr-reviewer (and any oauth-harness persona) fails every run with "review
harness exited with code 1" (401 token_invalidated) until reconnected.

Thread `reconnectProviders` into `ModeLaunchInput` and both harness-oauth
paths. When the user passes `--reconnect <provider>` matching the persona's
model provider (openai/anthropic) or harness name (codex/claude), force a
fresh `connectProvider` flow that overwrites the stored token even when
cloud reports it connected. Under --no-prompt it fails with actionable
guidance (the connect flow needs a TTY).

Recovery is now one flag instead of a dashboard round-trip:
  agentworkforce deploy ./review/persona.ts --on-exists update --reconnect codex

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b603c18e-d0ff-472a-809e-87cb075dd5bd

📥 Commits

Reviewing files that changed from the base of the PR and between 77e95c1 and 866105a.

📒 Files selected for processing (5)
  • packages/cli/src/deploy-command.ts
  • packages/deploy/src/deploy.ts
  • packages/deploy/src/modes/cloud.test.ts
  • packages/deploy/src/modes/cloud/index.ts
  • packages/deploy/src/types.ts

📝 Walkthrough

Walkthrough

Adds a reconnectProviders option that forces a fresh OAuth/connect flow for harness or subscription credentials even when the cloud reports them as already connected. The option propagates from the ModeLaunchInput type through deploy() into cloudLauncher.launch, ensureHarnessOauth, and ensureSubscriptionOauth, gated by a new harnessReconnectRequested() helper. CLI help text and tests are included.

Changes

Force-reconnect provider flow

Layer / File(s) Summary
Type contract and CLI help text
packages/deploy/src/types.ts, packages/cli/src/deploy-command.ts
ModeLaunchInput gains reconnectProviders?: string[]; the --reconnect CLI flag help text is expanded to a multi-line description covering integration and harness LLM credentials.
Cloud OAuth reconnect logic
packages/deploy/src/modes/cloud/index.ts
ensureHarnessOauth and ensureSubscriptionOauth now short-circuit the "already connected" path only when reconnect is not requested. A new harnessReconnectRequested() helper matches provider strings case-insensitively against both persona model provider and harness name. ensureHarnessReady and ensureCloudSubscriptionReady signatures accept reconnectProviders; cloudLauncher.launch forwards it into ensureHarnessReady.
Deploy forwarding and tests
packages/deploy/src/deploy.ts, packages/deploy/src/modes/cloud.test.ts
deploy() passes reconnectProviders into both ensureCloudSubscriptionReady and launcher.launch. Two new tests cover the forced-reconnect path when already connected and the --no-prompt rejection path.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • AgentWorkforce/workforce#228: Adds characterization tests for ensureCloudSubscriptionReady's "already connected" vs. connectProvider behavior — directly overlapping with the same function whose signature and OAuth skip logic this PR modifies.

Poem

🐇 Hop-hop, I knock on the OAuth door,
"Already connected?" — I'll knock some more!
With --reconnect in paw, I force a fresh flow,
Revoked tokens begone, watch credentials glow.
No dashboard detours, just one flag to run —
This rabbit refreshes credentials for fun! 🔑

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the primary change: enabling --reconnect to refresh revoked harness LLM credentials, which is the core fix addressing the root cause of persona failures.
Description check ✅ Passed The description is well-structured and directly related to the changeset, clearly explaining the problem (revoked OAuth tokens), root cause, the fix, and how it applies to the code changes made.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cloud-reconnect-harness-credential

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request updates the deployment process to support forcing a fresh OAuth connect flow for harness LLM credentials using the --reconnect <provider> flag, even when the cloud already reports them as connected. This is particularly useful for refreshing revoked tokens without manual dashboard intervention. The changes include CLI help text updates, passing the reconnectProviders option through the deployment pipeline, implementing the reconnect logic in the cloud launcher, and adding corresponding unit tests. There are no review comments, and I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@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: 866105aa5d

ℹ️ 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".

...(opts.noPrompt ? { noPrompt: true } : {}),
...(opts.harnessSource ? { harnessSource: opts.harnessSource } : {}),
...(opts.byokKey ? { byokKey: opts.byokKey } : {}),
...(opts.reconnectProviders ? { reconnectProviders: opts.reconnectProviders } : {}),

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 Avoid replaying the harness reconnect after subscription setup

When useSubscription:true uses an OAuth provider that does not produce credentialSelections (notably openai/codex with no connected anthropic fallback, where resolveOauthCredentialSelections returns {}), deploy() first calls ensureCloudSubscriptionReady() with reconnectProviders and opens the fresh provider connect flow, but then launches without credentialSelections and still forwards the same reconnect request here. cloudLauncher.launch() treats missing selections as a signal to run ensureHarnessReady(), so it sees the still-connected row plus reconnectProviders and opens the same browser reconnect flow a second time in one deploy.

Useful? React with 👍 / 👎.

@khaliqgant khaliqgant merged commit a90bfe8 into main Jun 14, 2026
3 checks passed
@khaliqgant khaliqgant deleted the fix/cloud-reconnect-harness-credential branch June 14, 2026 12:18
@agent-relay-code

Copy link
Copy Markdown
Contributor

Findings

  • P2 packages/deploy/src/deploy.ts: reconnectProviders is forwarded to cloudLauncher.launch() even after ensureCloudSubscriptionReady() has already consumed it for a useSubscription:true OAuth persona. For OpenAI/Codex OAuth without an Anthropic fallback, ensureCloudSubscriptionReady() returns no credentialSelections, so the launcher runs ensureHarnessReady() and opens the same reconnect flow a second time. This is a semantic behavior fix, so I did not auto-edit it. Suggested human patch: once subscription setup has consumed a matching reconnect, either pass a sentinel/selection that prevents harness setup replay or omit that consumed provider from the launch-time reconnectProviders.

Addressed comments

  • coderabbitai[bot]: reported no actionable comments; also flagged docstring coverage as a warning. No change made because this is not a demonstrated CI failure and adding docstrings would be nonessential churn for this PR.
  • gemini-code-assist[bot]: left a no-feedback review summary. No change required.
  • chatgpt-codex-connector[bot]: raised duplicate reconnect replay at packages/deploy/src/deploy.ts:330. Valid in the current checkout; not auto-fixed because it changes runtime behavior and needs a human-authored semantic patch.
  • chatgpt-codex-connector[bot] review summary: informational wrapper for the inline suggestion above. No separate change required.

Verification

  • corepack pnpm install --frozen-lockfile: passed.
  • corepack pnpm -r run build: passed.
  • corepack pnpm -r lint: passed.
  • corepack pnpm -r typecheck && corepack pnpm run typecheck:examples: passed.
  • corepack pnpm -r test: passed.

Notes: the sandbox has Node v25.6.0; CI uses Node 22.14.0. The bare pnpm shim was missing, so root scripts that shell out to pnpm could not run verbatim; I used the same recursive pnpm subcommands via Corepack. GitHub reports the PR is already merged/closed, with CodeRabbit status successful, so I am not printing READY.

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