Skip to content

feat(acp): enable Claude CLI via ACP bridge by default (experimental switch) + status#1681

Merged
gsxdsm merged 5 commits into
mainfrom
feature/acp-route-a-enable
Jun 15, 2026
Merged

feat(acp): enable Claude CLI via ACP bridge by default (experimental switch) + status#1681
gsxdsm merged 5 commits into
mainfrom
feature/acp-route-a-enable

Conversation

@gsxdsm

@gsxdsm gsxdsm commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #1680 (Route A core, merged). Flips the Route A ACP transport from a manual FUSION_CLAUDE_ACP env var to an experimental feature switch, default ON, and surfaces its state to operators.

Changes

  • Experimental switch (default ON). experimentalFeatures.claudeCliAcp is on unless explicitly set false. The engine translates it into the FUSION_CLAUDE_ACP dispatch the pi-claude-cli provider reads, at registerExtensionProviders time (new testable helper claude-acp-enable.ts, 6 tests).
    • Fail-closed: with no bridge path published (acp-runtime plugin absent / bridge not installed), the provider falls back to claude -p. So "default on" only engages where the bridge is actually available.
    • Explicit FUSION_CLAUDE_ACP env always wins (operator / test override).
  • U12 — status surface. GET /providers/claude-cli/status now returns an acp block (enabled / bridgeAvailable / active) so operators can see whether Claude CLI is routing through the ACP bridge vs -p.

Net effect

With the acp-runtime plugin installed, Claude CLI routes through the claude-code-cli-acp bridge by default; set experimentalFeatures.claudeCliAcp=false to force -p. The Claude-via-pi OAuth path is unchanged.

The safety gate this rests on (forwarded MCP tools + native tools refuse to execute when cancelled; no TOCTOU) was verified live in #1680.

Remaining

U13 (workflow model-node regression) is largely covered by the dispatch + enable unit tests (the workflow path goes through the same createFnAgent → streamSimple routing). Runtime fallback-on-auth-failure (detached-daemon robustness) and OS sandboxing remain follow-ups.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added the experimental “Claude CLI ACP” flag to control ACP bridge routing (default-enabled unless explicitly disabled or overridden).
    • Extended Claude CLI status responses and the provider card UI to report ACP availability, activity, and ACP auth-failure state.
    • Implemented cross-process ACP auth-failure signaling and an automatic dashboard fallback to route via -p with re-test support.
  • Documentation
    • Expanded guidance for claudeCliAcp, including effectiveness conditions and how to force -p.
  • Tests
    • Added/updated tests for enable/disable semantics, environment override behavior, and auth-failure signal recording/clearing.

gsxdsm and others added 2 commits June 15, 2026 12:14
…lt ON

Replace the manual FUSION_CLAUDE_ACP env enable with an experimental feature
switch. `experimentalFeatures.claudeCliAcp` is ON by default (off only when
explicitly set false); the engine translates it into the FUSION_CLAUDE_ACP
dispatch the pi-claude-cli provider reads, at registerExtensionProviders time.

- Still fail-closed: with no bridge path published (acp-runtime plugin absent),
  the provider falls back to `claude -p`.
- Explicit FUSION_CLAUDE_ACP env always wins (operator / test override).
- New testable helper claude-acp-enable.ts (6/6 tests); flag documented in the
  core experimentalFeatures doc.

So with the acp-runtime plugin installed, Claude CLI now routes through the ACP
bridge by default; set experimentalFeatures.claudeCliAcp=false to force `-p`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GET /providers/claude-cli/status now returns an `acp` block:
{ enabled (experimental flag), bridgeAvailable (KTD10 published path), active
(enabled && acpEnabled && bridgeAvailable) } so operators can see whether Claude
CLI is routing through the ACP bridge vs `claude -p` — important for the
default-on rollout. Additive; typechecks clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 15, 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 59f069bc-4651-44bc-be02-30bbd848e92e

📥 Commits

Reviewing files that changed from the base of the PR and between 5696d44 and dc85104.

📒 Files selected for processing (3)
  • packages/dashboard/app/components/ClaudeCliProviderCard.tsx
  • packages/pi-claude-cli/src/__tests__/acp-driver.test.ts
  • packages/pi-claude-cli/src/acp-driver.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/pi-claude-cli/src/tests/acp-driver.test.ts
  • packages/pi-claude-cli/src/acp-driver.ts
  • packages/dashboard/app/components/ClaudeCliProviderCard.tsx

📝 Walkthrough

Walkthrough

Adds a default-on claudeCliAcp experimental feature flag that routes Claude CLI traffic through an ACP bridge. A new claude-acp-enable.ts module evaluates the flag and sets FUSION_CLAUDE_ACP in the process environment. The engine's registerExtensionProviders wires this before constructing DefaultPackageManager. The ACP driver detects authentication failures from the bridge (when the response is "not logged in" with no tool calls) and signals this to the dashboard via a JSON file in the OS temp directory. The dashboard's Claude CLI status endpoint reads this signal file and returns ACP state in a new acp response object. The frontend displays an alert when auth fails, offering users two options: fall back to claude -p (which disables the flag) or retry after fixing authentication.

Changes

Claude CLI ACP experimental flag and auth-failure handling

Layer / File(s) Summary
claudeCliAcp flag evaluation and env application
packages/core/src/types.ts, packages/engine/src/claude-acp-enable.ts, packages/engine/src/__tests__/claude-acp-enable.test.ts
New claude-acp-enable.ts exports claudeAcpExperimentalEnabled (default-on unless claudeCliAcp === false) and applyClaudeAcpEnable (sets FUSION_CLAUDE_ACP=1 unless overridden by FUSION_CLAUDE_ACP_FORCE). JSDoc on GlobalSettings.experimentalFeatures documents the flag. Tests verify default-on semantics, explicit enable/disable, env overrides, and side effects.
Engine wiring in registerExtensionProviders
packages/engine/src/pi.ts
Imports applyClaudeAcpEnable, creates the PI settings view, applies the flag to mutate the environment, and passes the view as settingsManager into DefaultPackageManager.
ACP driver auth-failure signaling
packages/pi-claude-cli/src/acp-driver.ts, packages/pi-claude-cli/src/__tests__/acp-driver.test.ts
Detects "not logged in" responses from the bridge (zero tool calls + specific text pattern), writes auth-failure signal to a JSON file in the OS temp directory (ACP_BRIDGE_AUTH_SIGNAL_PATH), and clears it when real output is present. Tests mock filesystem operations and verify signaling. Best-effort errors are suppressed.
API type definition for ACP status
packages/dashboard/app/api/legacy.ts
ClaudeCliStatus gains an optional acp field with enabled, bridgeAvailable, active, authFailed, and optional authReason.
Dashboard /providers/claude-cli/status ACP state
packages/dashboard/src/routes/register-auth-routes.ts
Endpoint reads experimentalFeatures.claudeCliAcp and FUSION_CLAUDE_ACP_BRIDGE env to compute ACP enabled/bridge-available state, reads the auth-failure signal file, and returns the populated acp response object.
UI fallback handler and auth-failure alert
packages/dashboard/app/components/ClaudeCliProviderCard.tsx
Component imports settings APIs, adds handleFallbackToDashP to disable claudeCliAcp in global settings (fallback to claude -p), and conditionally renders an alert banner with "Use claude -p" and "I fixed auth — re-test" actions when status.acp.authFailed is true.

Sequence Diagram

sequenceDiagram
  participant User
  participant Dashboard
  participant Engine
  participant ACPBridge
  participant SignalFile as Temp File<br/>fusion-acp-bridge-auth.json

  User->>Dashboard: Access Claude CLI status
  Dashboard->>Engine: GET /providers/claude-cli/status
  Engine->>SignalFile: Read auth-failure signal
  SignalFile-->>Engine: authFailed, authReason
  Engine-->>Dashboard: ACP state (enabled, bridgeAvailable, active, authFailed)
  Dashboard-->>User: Show alert if authFailed=true
  User->>Dashboard: Click "Use claude -p"
  Dashboard->>Dashboard: Disable experimentalFeatures.claudeCliAcp
  Dashboard->>SignalFile: Clear signal file
  Dashboard-->>User: Show fallback active message
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Runfusion/Fusion#1680: Introduces the core dispatch logic that routes Claude CLI through the ACP bridge when FUSION_CLAUDE_ACP is set; this PR adds the experimental flag, environment wiring, and dashboard UI for controlling that dispatch path.

Poem

🐇 A flag springs alive, the bridge opens wide,
Auth fails? Write it down—we'll detect with pride!
The dashboard reads signals from temp-file tales,
"Use dash-p," the bunny advises when ACP fails.
Default-on routing with grace when it falls—
This experimental hop answers the calls! 🌉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(acp): enable Claude CLI via ACP bridge by default (experimental switch) + status' directly and comprehensively describes the main changes: enabling ACP bridge by default with an experimental switch and adding status reporting.
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 feature/acp-route-a-enable

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.

@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR flips the Route A ACP transport (Claude CLI via claude-code-cli-acp bridge) to default ON via an experimental feature switch (experimentalFeatures.claudeCliAcp), and surfaces the ACP routing state to operators through an extended GET /providers/claude-cli/status response plus a new dashboard auth-failure banner (R17).

  • claude-acp-enable.ts: new helper that translates experimentalFeatures.claudeCliAcpFUSION_CLAUDE_ACP env var on each createFnAgent call, using FUSION_CLAUDE_ACP_FORCE as an operator-level override; recomputes every call so flag changes take effect on the next turn without a restart.
  • acp-driver.ts R17 signal: writes a tmpdir JSON sentinel when the bridged claude returns a short "Not logged in" message; clears it on a real response; GET /providers/claude-cli/status reads the file and the UI presents a fall-back-to--p / re-test banner.
  • Status endpoint: acp.active now correctly mirrors FUSION_CLAUDE_ACP (the actual dispatch determinant) rather than the settings flag alone.

Confidence Score: 4/5

Safe to merge with one known UI state bug: the R17 auth-failure banner doesn't dismiss after clicking "Use claude -p".

The enable/disable logic and status endpoint are sound. The one defect is in the R17 fallback flow: handleFallbackToDashP writes claudeCliAcp: false to settings but never clears the on-disk auth-signal file, so the "Claude CLI bridge can't authenticate" banner persists in the UI after the user has already acted on it. The signal can only be cleared by a successful ACP turn, which will never happen because ACP was just disabled.

packages/dashboard/src/routes/register-auth-routes.ts and packages/dashboard/app/components/ClaudeCliProviderCard.tsx — the interplay between the fallback handler and the signal file needs the banner render condition or the status response to gate authFailed on whether ACP is actually enabled.

Important Files Changed

Filename Overview
packages/engine/src/claude-acp-enable.ts New helper: translates experimentalFeatures.claudeCliAcp → FUSION_CLAUDE_ACP env var; correctly uses FUSION_CLAUDE_ACP_FORCE for operator overrides and recomputes on every call (no latch)
packages/dashboard/src/routes/register-auth-routes.ts Adds ACP status block to /providers/claude-cli/status; authFailed is returned even when acpEnabled=false, causing the UI banner to persist after the "Use claude -p" fallback
packages/dashboard/app/components/ClaudeCliProviderCard.tsx Adds R17 auth-failure banner with fallback-to-dash-p and retest buttons; handleFallbackToDashP doesn't clear the on-disk signal file so the banner remains visible after the user acts
packages/pi-claude-cli/src/acp-driver.ts Adds R17 cross-process auth-failure signal: writes/unlinks a tmpdir JSON file on turn finish with an 80-char length guard to avoid false positives
packages/engine/src/tests/claude-acp-enable.test.ts Unit tests for enable/disable semantics and force-override behavior
packages/pi-claude-cli/src/tests/acp-driver.test.ts Extends ACP driver tests with R17 auth-signal cases
packages/core/src/types.ts Documents claudeCliAcp in experimentalFeatures JSDoc
packages/dashboard/app/api/legacy.ts Extends ClaudeCliStatus type with optional acp block
packages/engine/src/pi.ts Calls applyClaudeAcpEnable at registerExtensionProviders time using a reused settingsView
plugins/fusion-plugin-acp-runtime/src/index.ts Minor FNXC comment addition only; no logic changes

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[createFnAgent / registerExtensionProviders] --> B[applyClaudeAcpEnable]
    B --> C{FUSION_CLAUDE_ACP_FORCE?}
    C -- =1 --> D[FUSION_CLAUDE_ACP=1]
    C -- =0 --> E[FUSION_CLAUDE_ACP=0]
    C -- not set --> F{claudeCliAcp !== false?}
    F -- true --> D
    F -- false --> E
    D --> G[pi-claude-cli dispatch]
    G --> H{FUSION_CLAUDE_ACP_BRIDGE resolvable?}
    H -- yes --> I[streamViaAcp]
    H -- no --> J[streamViaCli claude -p]
    I --> K{Turn content?}
    K -- short Not-logged-in --> L[write signal file]
    K -- real response/tools --> M[delete signal file]
    N[GET /providers/claude-cli/status] --> O[read FUSION_CLAUDE_ACP + signal file]
    O --> P[acp: enabled/bridgeAvailable/active/authFailed]
    P --> Q{authFailed?}
    Q -- yes --> R[UI: auth-failure banner]
    R --> S[handleFallbackToDashP: claudeCliAcp=false]
    S --> T[refresh]
    T -.->|signal file NOT cleared| O
Loading

Reviews (4): Last reviewed commit: "fix(review): address PR #1681 round-2 co..." | Re-trigger Greptile

Comment thread packages/engine/src/claude-acp-enable.ts
Comment thread packages/dashboard/src/routes/register-auth-routes.ts Outdated
Comment thread packages/engine/src/claude-acp-enable.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
packages/engine/src/claude-acp-enable.ts (1)

1-13: ⚡ Quick win

Align new ACP comments with the FNXC comment format requirement.

The new comments/JSDoc added here are missing the FNXC:Area-of-product prefix and timestamp convention required by the repo guidelines.

As per coding guidelines, “Add FNXC_LOG comments describing the date of the change (format yyyy-MM-dd-hh:mm) ... Write FNXC:Area-of-product in front of all comments.”

Also applies to: 23-27

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/engine/src/claude-acp-enable.ts` around lines 1 - 13, Add the
required FNXC comment format to all comments in this module. For the JSDoc
comment block at the beginning of the file (lines 1-13) and any other comments
mentioned in "Also applies to: 23-27", prepend each comment with the
FNXC:Area-of-product prefix and include a timestamp in the format
yyyy-MM-dd-hh:mm according to the repository guidelines. Ensure all comments
follow the established FNXC convention to comply with coding standards.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/dashboard/src/routes/register-auth-routes.ts`:
- Around line 600-612: The calculation for acp.active in the status response
does not account for the explicit FUSION_CLAUDE_ACP environment variable
override, which can cause the endpoint to report active: true when the actual
runtime routing is disabled. Add a check for the FUSION_CLAUDE_ACP environment
variable (similar to the existing check for FUSION_CLAUDE_ACP_BRIDGE) and
include it in the active field calculation so that acp.active accurately
reflects whether ACP will actually be active at runtime, respecting operator
overrides.

In `@packages/engine/src/__tests__/claude-acp-enable.test.ts`:
- Around line 18-38: Add a new test case in the applyClaudeAcpEnable describe
block that verifies the function correctly reverses a previously set
FUSION_CLAUDE_ACP environment variable. Create a test that initializes a
NodeJS.ProcessEnv object with FUSION_CLAUDE_ACP set to "1", then calls
applyClaudeAcpEnable with { experimentalFeatures: { claudeCliAcp: false } }, and
asserts both that the function returns false and that FUSION_CLAUDE_ACP is
properly cleared or set to "0" in the env object. This regression test ensures
the sticky routing bug is prevented where a prior auto-set value could remain
when the flag is later disabled.

In `@packages/engine/src/claude-acp-enable.ts`:
- Around line 32-35: The function applyClaudeAcpEnable latches ACP to enabled
once it is auto-enabled, preventing later disablement through settings changes.
The issue is on line 32 where any existing FUSION_CLAUDE_ACP environment
variable is treated as authoritative, but line 34 writes to this variable when
claudeAcpExperimentalEnabled returns true, causing subsequent calls to always
return true regardless of current settings. Remove or refactor the early return
check on line 32 that treats the environment variable as authoritative, and
ensure the function always evaluates the current settings through
claudeAcpExperimentalEnabled(globalSettings) to allow settings changes to
dynamically enable or disable ACP in a long-lived process.

---

Nitpick comments:
In `@packages/engine/src/claude-acp-enable.ts`:
- Around line 1-13: Add the required FNXC comment format to all comments in this
module. For the JSDoc comment block at the beginning of the file (lines 1-13)
and any other comments mentioned in "Also applies to: 23-27", prepend each
comment with the FNXC:Area-of-product prefix and include a timestamp in the
format yyyy-MM-dd-hh:mm according to the repository guidelines. Ensure all
comments follow the established FNXC convention to comply with coding standards.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4d6fe21a-be68-431f-a00e-3f15079e160f

📥 Commits

Reviewing files that changed from the base of the PR and between e409f2d and 2e0bcd7.

📒 Files selected for processing (5)
  • packages/core/src/types.ts
  • packages/dashboard/src/routes/register-auth-routes.ts
  • packages/engine/src/__tests__/claude-acp-enable.test.ts
  • packages/engine/src/claude-acp-enable.ts
  • packages/engine/src/pi.ts

Comment on lines +600 to +612
const acpBridgeAvailable =
typeof process.env.FUSION_CLAUDE_ACP_BRIDGE === "string" &&
process.env.FUSION_CLAUDE_ACP_BRIDGE.length > 0;

res.json({
binary,
enabled,
extension,
acp: {
enabled: acpEnabled,
bridgeAvailable: acpBridgeAvailable,
active: enabled && acpEnabled && acpBridgeAvailable,
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

acp.active should include explicit FUSION_CLAUDE_ACP override resolution.

Line 611 can report active: true when an operator/test sets FUSION_CLAUDE_ACP=0. That makes the status endpoint disagree with actual runtime routing.

Proposed fix
       const acpBridgeAvailable =
         typeof process.env.FUSION_CLAUDE_ACP_BRIDGE === "string" &&
         process.env.FUSION_CLAUDE_ACP_BRIDGE.length > 0;
+      const acpEnvOverride = process.env.FUSION_CLAUDE_ACP;
+      const acpResolvedEnabled =
+        typeof acpEnvOverride === "string" ? acpEnvOverride === "1" : acpEnabled;

       res.json({
         binary,
         enabled,
         extension,
         acp: {
           enabled: acpEnabled,
           bridgeAvailable: acpBridgeAvailable,
-          active: enabled && acpEnabled && acpBridgeAvailable,
+          active: enabled && acpResolvedEnabled && acpBridgeAvailable,
         },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/dashboard/src/routes/register-auth-routes.ts` around lines 600 -
612, The calculation for acp.active in the status response does not account for
the explicit FUSION_CLAUDE_ACP environment variable override, which can cause
the endpoint to report active: true when the actual runtime routing is disabled.
Add a check for the FUSION_CLAUDE_ACP environment variable (similar to the
existing check for FUSION_CLAUDE_ACP_BRIDGE) and include it in the active field
calculation so that acp.active accurately reflects whether ACP will actually be
active at runtime, respecting operator overrides.

Comment thread packages/engine/src/__tests__/claude-acp-enable.test.ts
Comment thread packages/engine/src/claude-acp-enable.ts Outdated
gsxdsm and others added 2 commits June 15, 2026 12:32
…auth (R17)

When the bridged `claude` can't authenticate (detached daemon / no keychain),
the turn returns "Not logged in" instead of a real answer. Rather than silently
relay that, detect it and let the user choose.

- Driver: detect a "Not logged in"-only turn and write a cross-process signal
  (fusion-acp-bridge-auth.json); a real response clears it (acp-driver test).
- Dashboard status: GET /providers/claude-cli/status reports
  acp.authFailed + authReason from the signal.
- UI: the Claude CLI provider card shows an auth-failure banner with
  "Use claude -p" (sets experimentalFeatures.claudeCliAcp=false) and
  "I fixed auth — re-test", plus a fix hint (run `claude` to log in).
- Enable resolution now recomputes each call with an operator force-override
  (FUSION_CLAUDE_ACP_FORCE), so the "Use -p" fallback takes effect on the next
  turn — no restart. claude-acp-enable tests updated.

pi-claude-cli + engine tests green; dashboard typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…mments)

- Greptile P2: `acp.active` now reflects the ACTUAL dispatch determinant
  (FUSION_CLAUDE_ACP, which includes the operator force-override), not the
  experimental flag alone — so the status isn't misleading when forced on/off.
- CodeRabbit/Greptile P2: add FNXC:ClaudeAcp comments to the new code blocks
  per the AGENTS.md greppable-comment convention.

Already fixed in the prior commit (daa37d0): the P1 "sticky env" / latch
(applyClaudeAcpEnable now recomputes each call + FUSION_CLAUDE_ACP_FORCE
override) and the enable->disable-on-same-env regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/dashboard/app/components/ClaudeCliProviderCard.tsx`:
- Line 263: Fix the inconsistent Tailwind CSS animation class name in the
Loader2 component. On line 263, change the className from "spin" to
"animate-spin" to match the correct Tailwind animation class used elsewhere in
the file (such as line 169). The current "spin" class name does not exist in the
Tailwind CSS framework and will prevent the spinner from animating.

In `@packages/pi-claude-cli/src/__tests__/acp-driver.test.ts`:
- Around line 124-135: The test "records the R17 auth-failure signal when the
bridge turn is only 'Not logged in'" only verifies the positive case where
authFailed is set to true, but does not assert the invariant across other
branches. Expand this test to include additional test cases or assertions within
the existing test that verify: (1) that normal agent messages with actual
content do not set authFailed:true, and (2) that tool-call turns do not set
authFailed:true even when the text contains login-related keywords. This ensures
the authFailed signal fix works correctly across all relevant code branches and
prevents false positives in different message types handled by the streamViaAcp
function.

In `@packages/pi-claude-cli/src/acp-driver.ts`:
- Line 90: The regex pattern NOT_LOGGED_IN_RE matches too broadly, detecting the
auth-failure keywords anywhere in a response rather than requiring them to be
the primary content of the turn. Update the NOT_LOGGED_IN_RE regex to use
anchors (^ and $) to match only when the not-logged-in or login message
constitutes the core response, not merely a substring within additional
legitimate content. This ensures the auth-failure detection at the usage site in
lines 209-214 only triggers for true authentication failures where the response
is specifically about missing login, preventing false positives that incorrectly
surface the auth-failure UI state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a2b75e07-eb8e-48fd-8cfd-410d244cbf1f

📥 Commits

Reviewing files that changed from the base of the PR and between 2e0bcd7 and daa37d0.

📒 Files selected for processing (7)
  • packages/dashboard/app/api/legacy.ts
  • packages/dashboard/app/components/ClaudeCliProviderCard.tsx
  • packages/dashboard/src/routes/register-auth-routes.ts
  • packages/engine/src/__tests__/claude-acp-enable.test.ts
  • packages/engine/src/claude-acp-enable.ts
  • packages/pi-claude-cli/src/__tests__/acp-driver.test.ts
  • packages/pi-claude-cli/src/acp-driver.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/engine/src/tests/claude-acp-enable.test.ts

Comment thread packages/dashboard/app/components/ClaudeCliProviderCard.tsx Outdated
Comment on lines +124 to +135
it("records the R17 auth-failure signal when the bridge turn is only 'Not logged in'", async () => {
fsSpies.writeFileSync.mockClear();
scriptedUpdates = [
{ sessionUpdate: "agent_message_chunk", content: { type: "text", text: "Not logged in · Please run /login" } },
];
const stream = streamViaAcp(MODEL, CTX, OPTS) as unknown as { _events: Array<Record<string, unknown>> };
await flush();
// signal file written with authFailed:true
const wrote = fsSpies.writeFileSync.mock.calls.find((c) => String(c[1]).includes("authFailed"));
expect(wrote).toBeTruthy();
expect(String(wrote![1])).toContain("\"authFailed\":true");
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Expand this regression to assert the full auth-signal invariant across known surfaces.

This test only checks the reported symptom (authFailed:true write). Please also cover at least: (1) non-auth real output clears/doesn’t set auth-failed, and (2) tool-call turns don’t set auth-failed even if text mentions login, so the fix is protected across all relevant branches.

Suggested additions
+  it("clears auth-failure signal when a subsequent real response arrives", async () => {
+    fsSpies.writeFileSync.mockClear();
+    fsSpies.unlinkSync.mockClear();
+    scriptedUpdates = [{ sessionUpdate: "agent_message_chunk", content: { type: "text", text: "Not logged in · Please run /login" } }];
+    const s1 = streamViaAcp(MODEL, CTX, OPTS) as unknown as { _events: Array<Record<string, unknown>> };
+    await flush();
+    expect(eventsOf(s1).some((e) => e.type === "done")).toBe(true);
+
+    scriptedUpdates = [{ sessionUpdate: "agent_message_chunk", content: { type: "text", text: "Hello from Claude" } }];
+    const s2 = streamViaAcp(MODEL, CTX, OPTS) as unknown as { _events: Array<Record<string, unknown>> };
+    await flush();
+    expect(eventsOf(s2).some((e) => e.type === "done")).toBe(true);
+    expect(fsSpies.unlinkSync).toHaveBeenCalled();
+  });

As per coding guidelines, for bug fixes the regression must assert the general invariant across all known surfaces, not just the single reproduction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/pi-claude-cli/src/__tests__/acp-driver.test.ts` around lines 124 -
135, The test "records the R17 auth-failure signal when the bridge turn is only
'Not logged in'" only verifies the positive case where authFailed is set to
true, but does not assert the invariant across other branches. Expand this test
to include additional test cases or assertions within the existing test that
verify: (1) that normal agent messages with actual content do not set
authFailed:true, and (2) that tool-call turns do not set authFailed:true even
when the text contains login-related keywords. This ensures the authFailed
signal fix works correctly across all relevant code branches and prevents false
positives in different message types handled by the streamViaAcp function.

Source: Coding guidelines

Comment thread packages/pi-claude-cli/src/acp-driver.ts
- CodeRabbit: spinner class `spin` -> `animate-spin` (matches the card's other
  Loader2 usages).
- CodeRabbit (major): tighten auth-failure detection so it only fires when the
  WHOLE turn is the short "Not logged in" message (<=80 chars), not when a long
  legitimate answer merely mentions the phrase — avoids false positives.
- CodeRabbit (major): expand the auth-signal test to assert the full invariant —
  set on a not-logged-in turn, clear (unlink) on a real response, and NOT flag a
  long answer that mentions the phrase.

pi-claude-cli acp-driver 5/5; typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gsxdsm gsxdsm merged commit f816598 into main Jun 15, 2026
6 checks passed
@gsxdsm gsxdsm deleted the feature/acp-route-a-enable branch June 15, 2026 19:51
Comment on lines +634 to +639
acp: {
enabled: acpEnabled,
bridgeAvailable: acpBridgeAvailable,
active: enabled && acpBridgeAvailable && acpEnvOn,
authFailed: acpAuthFailed,
authReason: acpAuthReason,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Auth-failed banner persists after "Use claude -p" fallback

handleFallbackToDashP sets claudeCliAcp: false in settings and calls refresh(), but neither deletes the signal file nor asks the server to clear it. The next GET /providers/claude-cli/status call still finds the file, so authFailed: true is returned even though ACP has just been disabled. The UI banner only checks status?.acp?.authFailed (not acp.enabled), so "Claude CLI bridge can't authenticate" keeps showing indefinitely — the signal can only be cleared by a successful ACP turn, but ACP is now off.

The simplest server-side fix is to gate authFailed on acpEnabled:

authFailed: acpEnabled && acpAuthFailed,
authReason: acpEnabled ? acpAuthReason : undefined,

Alternatively, handleFallbackToDashP could call a dedicated clear endpoint, or the JSX could add && status?.acp?.enabled to the render condition.

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