feat(config-nudge): distinguish install/auth state in cli_login nudge cards#1633
Merged
Conversation
wpfleger96
pushed a commit
that referenced
this pull request
Jul 8, 2026
… cards Splits the collapsed Requirement::CliLogin into four distinct failure states using the existing AcpAvailabilityStatus classifier from Doctor (classify_runtime in discovery.rs). The nudge card now shows actionable per-state copy and a deep-link CTA to Settings → Doctor instead of routing every harness issue through Edit Agent. Backend (Rust): - readiness.rs: rework cli_login_requirements to call classify_runtime before deciding whether to probe. States: Available → run probe; AdapterMissing/CliMissing/NotInstalled → skip probe, emit CliLogin with the precise state. availability field added to Requirement::CliLogin. - discovery.rs: make find_command and classify_runtime pub(crate) for reuse in readiness.rs. - types.rs: add Deserialize to AcpAvailabilityStatus derive. - runtime.rs: include availability in the cli_login serde JSON payload. - Tests: 4 new unit tests covering each arm + updated codex_not_ready test to use make_cli_runtime stub (function now requires a runtime arg). Frontend (TS): - configNudge.ts: add required availability field to cli_login union arm. Type guard rejects old-format payloads without the field. - config-nudge-attachment.tsx: per-state copy via cliLoginMessage(); (A) pure cli_login card routes whole card to Doctor; (B) mixed card routes card to Edit Agent + each cli_login row gets inline Open Doctor CTA with stopPropagation. Always-visible CTA label replaces opacity-0 fade-in hint. cursor-pointer + hover:shadow-sm affordances. - AppShellContext.tsx/AppShell.tsx: onOpenSettings added to context so config-nudge-attachment can deep-link to Doctor via useAppShell(). - configNudge.test.mjs: update cli_login fixtures to include availability, add test pinning rejection of old-format payloads. - check-file-sizes.mjs: bump readiness.rs override to 1370. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
The cli_login sentinel the FE parses was missing the `availability` field because `RequirementPayload::CliLogin` in setup_mode.rs did not have the field — serde silently dropped it during deserialization of the desktop-emitted JSON, so nudge_body() re-serialized a struct that never had it. Add an `AcpAvailabilityStatus` mirror enum (snake_case, Serialize + Deserialize) and add `availability` to `RequirementPayload::CliLogin`. The field now round-trips desktop → buzz-acp → sentinel → FE intact. Add 4 boundary tests that exercise the full desktop→from_raw_env_value →nudge_body→sentinel extraction path for each availability state. Update `instruction()` prose fallback to name the specific install gap (adapter missing / CLI missing / not installed) for non-card clients instead of always emitting the login instruction. FE MINOR: replace the inline availability union in configNudge.ts with the shared `AcpAvailabilityStatus` import from api/types.ts. The runtime validator still enumerates wire literals explicitly (correct); the type annotation now uses the shared type (no more drift point). Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Replace review-thread reference with a description of the invariant being guarded. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Captures the four availability states the Doctor-CTA nudge card can render in: available (logged-out), not_installed, adapter_missing, and cli_missing. Also covers the mixed-requirements case showing the inline per-row Doctor CTA alongside the card-level Edit Agent trigger. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…login cards
On pure allCliLogin cards the card-level trigger already routes to Doctor
("Open Doctor →" in AttachmentActions). The per-row "Open Doctor →" button
in the cli_login RequirementRow was additionally rendering for each row,
producing two identical Doctor CTAs visible at once.
Thread showRowDoctorCta={!allCliLogin} into RequirementRow and guard the
inline button behind it. Mixed cards (card CTA = "Edit Agent →") are
unchanged — each cli_login row still renders its own inline Doctor CTA.
Pure cli_login cards now show exactly one "Open Doctor →" (the card action).
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
pushed a commit
that referenced
this pull request
Jul 8, 2026
71548f9 to
05b3d72
Compare
#1640 persona-env-vars-refresh rebase added live-persona env merge path changes that grew readiness.rs by 4 lines beyond the existing override. Availability-classification growth, not generic debt. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Q1: change codex setup_copy from 'codex login --with-api-key' to plain 'codex login'. The --with-api-key flag is wrong for the majority of users (ChatGPT OAuth) and over-prescribes the login method. Updated all 8 sites: the production line in readiness.rs, the doc-comment, test comment, three Rust fixtures, and two TS fixtures in configNudge.test.mjs. Q2: fix Windows CI portability for cli_login_requirements tests. The four new tests used POSIX 'true'/'false' as stand-in binaries which are not guaranteed on the Windows/Git-for-Windows PATH. Replace with std::env::current_exe() via a new present_binary_str() helper that returns the absolute path of the running test binary (always present, resolves via path.exists() regardless of platform). Success probe uses --list (exits 0 on all platforms); failure probe uses an unrecognized flag (libtest exits non-zero for unknown flags on all platforms). Bump readiness.rs file-size override 1374 to 1403. Q3: fix config-nudge card visual issues in mixed-card layout. (a) Row CTA was styled text-destructive (red), making the navigation button look like a danger action. Changed to text-muted-foreground to match the card-level CTA color. (b) AttachmentActions now has items-end self-end so the 'Edit Agent' pill bottom-anchors in its panel rather than vertically centering alongside requirement rows, which was causing false visual pairing with the per-row 'Open Doctor' button. Nit: extract openDoctor() helper in ConfigNudgeCard and add a console.warn guard so onOpenSettings null is not a silent dead click on surfaces without AppShell context. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
pushed a commit
that referenced
this pull request
Jul 8, 2026
The mixed-card layout placed 'Open Doctor →' inside AttachmentContent (after the cli_login row text) and 'Edit Agent →' in a separate AttachmentActions column. Two different flex columns have two different right edges, so the CTAs could never line up vertically and the visual pairing between each CTA and its requirement was unclear. Fix: every requirement row on a mixed card now owns its CTA, right- aligned to a shared edge via the same 'justify-between' / 'flex-1 span + shrink-0 button' pattern already used by cli_login rows. - cli_login rows → 'Open Doctor →' (unchanged, routes to Doctor) - env_key rows → new per-row 'Edit Agent →' button - normalized_field rows → new per-row 'Edit Agent →' button All per-row CTAs: relative z-20 (above AttachmentTrigger overlay), stopPropagation (no double-fire), text-muted-foreground (no regression to red). Extract openEditAgent() helper called by both the card-level fallback trigger and the new per-row handler. AttachmentActions on mixed cards is removed (per-row CTAs replace it). All-cli_login cards keep the card-level 'Open Doctor →' in AttachmentActions — single destination, no alignment issue, unchanged. Replace showRowDoctorCta prop with allCliLogin to uniformly gate all per-row CTA types from one boolean. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…odel
The test-03 doc-comment and inline assertions still described the old
card-level CTA shape ('card-level CTA says Edit Agent'). Update to
describe the per-row model: each requirement row owns its right-aligned
CTA sharing one edge. Assertions unchanged — they still verify both
'Open Doctor' and 'Edit Agent' are visible, which remains correct
for the new layout.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
pushed a commit
that referenced
this pull request
Jul 8, 2026
Doctor only installs the harness/ACP adapter — it has no auth functionality. Pointing an installed-but-unauthenticated user at Doctor is a misleading dead-end; the setup_copy already carries the exact login command. Gate: availability === "available" cli_login requirements never get a Doctor CTA or Doctor routing in any position. - Add isAuthOnly() helper: true when all requirements are cli_login with availability === "available" - authOnly cards: drop AttachmentTrigger, AttachmentActions, and the cursor-pointer/hover-shadow affordance — purely informational - Per-row Doctor button in RequirementRow: gate on !allCliLogin && req.availability !== "available" - Update ConfigNudgeCard doc-comment with (A-auth) case - e2e test-01: rename to informational state, flip assertion to toHaveCount(0) for "Open Doctor →" Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
The isAllCliLogin helper comment and the handleOpen (A) branch comment both said the card routes to Doctor unconditionally for all-cli_login cards. That was true before the auth-only suppression but is now stale: auth-only cards (all cli_login rows availability === 'available') never mount AttachmentTrigger so handleOpen never fires for them. Narrow both comments to reflect that Doctor routing only applies to non-authOnly install-state all-cli_login cards. No behavior change. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Collaborator
Author
01 — Auth-only cli_login card (informational, no CTA)Installed-but-needs-auth 02 — cli_login not-installed state
03 — Mixed requirements (adapter_missing + env_key)Mixed card: 04 — cli_login cli-missing state
|
wpfleger96
pushed a commit
that referenced
this pull request
Jul 8, 2026
wpfleger96
added a commit
that referenced
this pull request
Jul 8, 2026
…#1633 #1633 added AcpAvailabilityStatus to the types import in readiness.rs alongside our GlobalAgentConfig import, bringing the merged line count to 1405 (gate) vs the prior 1403 cap. Ratchet to 1408. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
added a commit
that referenced
this pull request
Jul 8, 2026
…#1633 #1633 added AcpAvailabilityStatus to the types import in readiness.rs alongside our GlobalAgentConfig import, bringing the merged line count to 1405 (gate) vs the prior 1403 cap. Ratchet to 1408. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
added a commit
that referenced
this pull request
Jul 8, 2026
…#1633 #1633 added AcpAvailabilityStatus to the types import in readiness.rs alongside our GlobalAgentConfig import, bringing the merged line count to 1405 (gate) vs the prior 1403 cap. Ratchet to 1408. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
added a commit
that referenced
this pull request
Jul 8, 2026
…#1633 #1633 added AcpAvailabilityStatus to the types import in readiness.rs alongside our GlobalAgentConfig import, bringing the merged line count to 1405 (gate) vs the prior 1403 cap. Ratchet to 1408. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
added a commit
that referenced
this pull request
Jul 8, 2026
…#1633 #1633 added AcpAvailabilityStatus to the types import in readiness.rs alongside our GlobalAgentConfig import, bringing the merged line count to 1405 (gate) vs the prior 1403 cap. Ratchet to 1408. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




The config nudge card that appears when a managed agent needs CLI login treated every non-ready state the same way — a single generic "needs login" message with no path to fixing it. A user whose adapter or CLI binary isn't installed got the same copy as a user who just needs to run
tool login, and neither had a direct affordance to open Doctor where the actual fix lives.This distinguishes the four availability states and gives each a path to resolution.
Backend
cli_login_requirementsreuses the existingclassify_runtimelogic to stamp a granularAcpAvailabilityStatus(available/adapter_missing/cli_missing/not_installed) onto eachRequirement::CliLogin. The login probe only runs when the runtime isAvailable— for the other states, probing a missing/broken binary is meaningless, so it's skipped and the state is reported directly.The setup payload crosses a process boundary: desktop serializes it into
BUZZ_ACP_SETUP_PAYLOAD, andbuzz-acpdeserializes it, renders the nudge, and re-serializes it into thebuzz:config-nudgesentinel the frontend parses.buzz-acpcarries a localAcpAvailabilityStatusmirror enum on itsRequirementPayload::CliLoginso the field survives that round-trip intact. Boundary tests assert the field survives desktop →buzz-acpSetupPayload→ sentinel for all four states.Codex
setup_copyuses plaincodex login— the--with-api-keyflag was over-prescriptive for the common ChatGPT OAuth path.Frontend
cli_login: card click routes to Doctor; card-level "Open Doctor →" label inAttachmentActionsconfirms the action at rest. No per-row CTAs.cli_loginrows get "Open Doctor →",env_key/normalized_fieldrows get "Edit Agent →". TheAttachmentActionscolumn is omitted on mixed cards.relative z-20(above theAttachmentTriggeroverlay) andstopPropagation(no double-fire), andtext-muted-foregroundcolor (no false "danger" signal).Card routing uses
useAppShell()rather than threading a new prop throughProfilePanelContext— every render site already hasAppShellin scope. Aconsole.warnguard surfaces null context on surfaces without AppShell.Tests
New
cli_login_requirementsintegration tests are host-portable: POSIX-specifictrue/falsestand-ins are replaced withstd::env::current_exe()(always present, resolves via absolute-path check) so the tests pass on thewindows-latestCI shard.Stack
Merges before #1448 (global agent config defaults), which is parked awaiting manual E2E.