Skip to content

add provider-first onboarding - #9039

Merged
tulsi-builder merged 8 commits into
mainfrom
tulsi/onboarding
May 6, 2026
Merged

add provider-first onboarding#9039
tulsi-builder merged 8 commits into
mainfrom
tulsi/onboarding

Conversation

@tulsi-builder

@tulsi-builder tulsi-builder commented May 5, 2026

Copy link
Copy Markdown
Collaborator

Category: new-feature
User Impact: New users get a guided first-run setup that imports existing tools when available, connects a usable provider, and lands them on Home ready to chat.
Problem: First-run setup could leave users in Goose without a usable model/provider, and provider auth/import state was scattered across UI-only flows. That made setup confusing for non-technical users and brittle for native OAuth providers like ChatGPT.
Solution: This adds a provider-first onboarding gate backed by typed ACP methods, real import scanning/apply behavior, shared provider credential plumbing, and a concise ready screen that explains the selected default plus imported skills/extensions.

File changes

crates/goose-sdk/src/custom_requests.rs
Adds typed ACP contracts for saving defaults, onboarding import scan/apply, and provider-native authentication.

crates/goose/acp-meta.json
Regenerates ACP metadata so the new onboarding/default/auth custom requests are exposed to SDK generation.

crates/goose/acp-schema.json
Regenerates the ACP JSON schema for the new typed request and response shapes.

crates/goose/src/acp/server.rs
Registers the onboarding server module.

crates/goose/src/acp/server/config.rs
Implements _goose/defaults/save with provider/model validation before writing Goose defaults.

crates/goose/src/acp/server/custom_dispatch.rs
Dispatches the new defaults, onboarding import, and provider auth custom methods.

crates/goose/src/acp/server/onboarding.rs
Adds backend scan/apply logic for existing Goose config and Claude Desktop MCP tools, including duplicate-safe extension and skill import behavior.

crates/goose/src/acp/server/providers.rs
Adds provider-owned native authentication through ACP and refreshes provider inventory after auth completes.

crates/goose/src/providers/chatgpt_codex.rs
Marks ChatGPT/Codex configured when the OAuth token cache exists so inventory reflects successful browser auth.

crates/goose/tests/acp_custom_provider_methods_test.rs
Adds coverage that native auth rejects providers without an OAuth flow.

ui/goose2/src/app/AppShell.tsx
Gates the app behind onboarding after startup data is loaded and prevents Home session creation while setup is active.

ui/goose2/src/app/hooks/useAppStartup.ts
Returns startup readiness and error state so onboarding waits for initial ACP, provider, persona, session, and distro loading.

ui/goose2/src/features/agents/ui/AvatarDropZone.tsx
Removes setup-surface shadows for the flatter onboarding/settings visual direction.

ui/goose2/src/features/chat/ui/ChatContextPanel.tsx
Removes a toolbar shadow to match the updated surface treatment.

ui/goose2/src/features/onboarding/api/onboarding.ts
Adds a feature API wrapper around typed onboarding/default ACP SDK calls.

ui/goose2/src/features/onboarding/hooks/useOnboardingFlow.ts
Coordinates the three onboarding steps and final completion state without putting workflow logic in the view shell.

ui/goose2/src/features/onboarding/hooks/useOnboardingGate.test.tsx
Covers fresh-state gating, completed usable setup, unusable completed setup, ACP agent setup, and completion persistence.

ui/goose2/src/features/onboarding/hooks/useOnboardingGate.ts
Computes whether onboarding should show based on local completion plus actual usable provider/model or ACP agent inventory.

ui/goose2/src/features/onboarding/hooks/useOnboardingImportStep.ts
Owns import scan/apply state, selected candidates, setup counts, and imported provider defaults.

ui/goose2/src/features/onboarding/hooks/useOnboardingProviderStep.ts
Owns provider/default selection state, promoted provider filtering, credential setup wiring, and model/agent selection.

ui/goose2/src/features/onboarding/hooks/useOnboardingReadyStep.ts
Loads current skill count for the ready summary only when the ready step is shown.

ui/goose2/src/features/onboarding/lib/importCounts.ts
Extracts import count formatting and summing helpers for reuse across onboarding UI.

ui/goose2/src/features/onboarding/lib/providerDefaults.ts
Extracts provider ordering and first-usable-model selection helpers.

ui/goose2/src/features/onboarding/types.ts
Defines onboarding completion, readiness, setup, step, and import-related feature types.

ui/goose2/src/features/onboarding/ui/ImportStep.tsx
Renders the import step with neutral unselected cards and selected-only emphasis.

ui/goose2/src/features/onboarding/ui/OnboardingFlow.tsx
Keeps the full-screen onboarding shell small and delegates workflow and step rendering to hooks/components.

ui/goose2/src/features/onboarding/ui/ProviderStep.tsx
Renders connected defaults, provider setup rows, and the “show more” provider expansion path.

ui/goose2/src/features/onboarding/ui/ReadyStep.tsx
Renders the final ready summary with the selected default, extension count, and skill count.

ui/goose2/src/features/providers/api/credentials.test.ts
Adds coverage for the new ACP provider-auth API wrapper.

ui/goose2/src/features/providers/api/credentials.ts
Adds authenticateProviderConfig through the generated SDK.

ui/goose2/src/features/providers/api/modelSetup.ts
Routes native provider auth through ACP instead of the old Tauri invoke path.

ui/goose2/src/features/providers/hooks/useCredentials.test.tsx
Covers applying an ACP native-auth result without doing an extra status refresh.

ui/goose2/src/features/providers/hooks/useCredentials.ts
Accepts provider auth results directly, updates status, and starts inventory sync from the backend-provided refresh plan.

ui/goose2/src/features/settings/ui/AppearanceSettings.tsx
Removes selected-control shadows from appearance settings.

ui/goose2/src/features/settings/ui/GeneralSettings.tsx
Adds a settings action to reset onboarding completion for retesting or rerunning setup.

ui/goose2/src/features/settings/ui/ModelProviderRow.tsx
Passes native auth results into shared credential handling and keeps setup output keys unique across retries.

ui/goose2/src/features/settings/ui/SettingsModal.tsx
Removes active-sidebar shadows to match the flatter settings style.

ui/goose2/src/shared/i18n/constants.ts
Registers the onboarding i18n namespace.

ui/goose2/src/shared/i18n/i18n.ts
Loads onboarding translations into the app i18n resources.

ui/goose2/src/shared/i18n/locales/en/onboarding.json
Adds English onboarding copy for import, provider setup, counts, and ready summary.

ui/goose2/src/shared/i18n/locales/en/settings.json
Adds English settings copy for resetting onboarding.

ui/goose2/src/shared/i18n/locales/es/onboarding.json
Adds Spanish onboarding translations.

ui/goose2/src/shared/i18n/locales/es/settings.json
Adds Spanish settings copy for resetting onboarding.

ui/goose2/src/shared/ui/button.tsx
Removes default/outline/destructive button shadows.

ui/goose2/tests/e2e/fixtures/tauri-mock.ts
Seeds mocked onboarding completion/default model state and handles the new onboarding/default ACP methods.

ui/goose2/tests/e2e/smoke.spec.ts
Runs smoke tests through the Tauri mock fixture so onboarding does not block the Home assertions.

ui/sdk/src/generated/client.gen.ts
Regenerates typed SDK client methods for defaults save, onboarding scan/apply, and provider auth.

ui/sdk/src/generated/index.ts
Regenerates SDK exports and method metadata for the new ACP methods.

ui/sdk/src/generated/types.gen.ts
Regenerates TypeScript DTOs for onboarding imports, defaults save, and provider auth.

ui/sdk/src/generated/zod.gen.ts
Regenerates Zod schemas for the new ACP request and response types.

Reproduction Steps

  1. Clear goose:onboarding:v1 in local storage or use Settings → General → Reset onboarding.
  2. Launch goose2 and confirm the full-screen onboarding flow appears after startup completes.
  3. On the import step, verify detected Goose/Claude Desktop candidates can be selected or skipped and unselected cards stay neutral.
  4. Continue to provider setup and connect or choose a configured model provider or ACP agent.
  5. Finish onboarding and verify Home opens with the composer usable and the selected default available.
  6. For ChatGPT/Codex, run browser auth and confirm returning to Goose marks the provider connected instead of staying on “waiting for sign-in.”

Screenshots/Demos

Screen.Recording.2026-05-05.at.5.42.43.PM.mov

@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: e60906e192

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

Comment thread ui/goose2/src/features/onboarding/hooks/useOnboardingGate.ts Outdated
Comment thread crates/goose/src/acp/server/onboarding.rs Outdated
Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>

@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: 22d5db4e66

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

Comment thread crates/goose/src/acp/server/onboarding.rs Outdated
Comment thread ui/goose2/src/features/onboarding/hooks/useOnboardingProviderStep.ts Outdated
Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>
@tulsi-builder
tulsi-builder enabled auto-merge May 6, 2026 14:04
@tulsi-builder
tulsi-builder added this pull request to the merge queue May 6, 2026

@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: 3178f8d5b4

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

}
return a.displayName.localeCompare(b.displayName);
});
}, [distro]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Subscribe provider list to catalog updates

modelProviders is memoized with [distro] only, but it is derived from getModelProviders() (an external store snapshot). Startup intentionally loads the provider catalog in the background, so onboarding can render before catalog entries arrive; when that happens, this memo stays empty and the provider step can render no setup rows, leaving users unable to pick/configure a provider and unable to proceed.

Useful? React with 👍 / 👎.

Comment on lines +62 to +66
filterModelProvidersForDistro(getModelProviders(), distro).map(
(provider) => provider.id,
),
),
[distro],

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 Recompute model provider IDs when catalog changes

This memo also reads getModelProviders() from external store state but only depends on distro, so it can retain an empty/stale ID set if the catalog loads after initial render. The later readiness filter requires modelProviderIds.has(entry.providerId), which can incorrectly exclude configured non-custom providers and misclassify readiness, causing unnecessary onboarding gating for otherwise usable setups.

Useful? React with 👍 / 👎.

Merged via the queue into main with commit 6fc44bf May 6, 2026
26 of 27 checks passed
@tulsi-builder
tulsi-builder deleted the tulsi/onboarding branch May 6, 2026 14:15
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 6, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
boolean depended on BOTH `readiness.isUsable` (does the user have a
configured provider with models?) AND `readiness.hasCompletedOnboarding`
(is localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider (which the model picker
triggers) re-evaluated the gate and snapped them back into
OnboardingFlow's default ImportStep, even though they already had a
working openrouter (or any other) provider.

Drop the !hasCompletedOnboarding check from shouldShowOnboarding. The
gate is now purely capability-based:

  shouldShowOnboarding: startupReady && !readiness.isUsable

Behavior matrix:

  | user                                   | isUsable | result        |
  |----------------------------------------|----------|---------------|
  | new user (no provider)                 | false    | onboarding    |
  | pre-existing user (provider works)     | true     | normal app    |
  | returning user (completed onboarding)  | true     | normal app    |
  | user who deleted all providers         | false    | onboarding    |

The completion record is still written when a user finishes
OnboardingFlow's ReadyStep (via AppShell.tsx:741) — it just no longer
gates whether onboarding shows. The hasCompletedOnboarding field stays
on OnboardingReadiness for future analytics/UX hints.

Updated test "shows onboarding after startup when there is no completed
state" to reflect the new grandfathering behavior, and added a separate
test for the new-user path (no usable provider, no completion → flow
appears).
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 6, 2026
… pre-existing users

Two related issues with PR aaif-goose#9039's onboarding gate:

1. modelProviderIds was permanently empty.
   The memo called getModelProviders() (which reads via .getState())
   but only listed [distro] as a dependency. When the catalog populated
   from the backend (1 entry → 27 entries), the memo never recomputed,
   so the configuredEntry fallback in readiness never matched any
   provider. Same pattern in useOnboardingProviderStep.ts (modelProviders
   and usableAgentEntries memos).

   Fix: subscribe to catalogEntries via useProviderCatalogStore, switch
   call sites to the *FromEntries pure variants, and add catalogEntries
   to the affected memo deps.

2. Pre-existing users (installed before aaif-goose#9039) were trapped on
   ImportStep because hasCompletedOnboarding stayed false forever. The
   previous fix dropped the completion check from the gate, but that
   silently broke the "Reset onboarding" button — users who clicked it
   couldn't get back into the flow because their setup was still
   isUsable.

   Fix: restore the original (!hasCompletedOnboarding || !isUsable)
   gate, plus an auto-grandfathering effect that synthesizes a
   completion record once for users with a usable provider but no
   record. A separate ONBOARDING_GRANDFATHERED_KEY persists a "we've
   seen this user" marker so the effect doesn't re-fire after an
   explicit reset (resetOnboardingCompletion now sets that flag too).

   Behaviour matrix:

     | user                         | result                       |
     |------------------------------|------------------------------|
     | new (no provider)            | onboarding shows             |
     | pre-existing (usable, no     | auto-grandfathered, normal   |
     |   completion record)         |   app                        |
     | returning (completion + ok)  | normal app                   |
     | reset → reload (usable)      | onboarding shows again       |
     | provider deleted             | onboarding shows             |

Tests: existing 7 cases keep passing; renamed grandfathering test to
assert the new auto-completion behaviour and added a new test for the
post-reset path.
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 6, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
boolean depended on BOTH `readiness.isUsable` (does the user have a
configured provider with models?) AND `readiness.hasCompletedOnboarding`
(is localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider (which the model picker
triggers) re-evaluated the gate and snapped them back into
OnboardingFlow's default ImportStep, even though they already had a
working openrouter (or any other) provider.

Drop the !hasCompletedOnboarding check from shouldShowOnboarding. The
gate is now purely capability-based:

  shouldShowOnboarding: startupReady && !readiness.isUsable

Behavior matrix:

  | user                                   | isUsable | result        |
  |----------------------------------------|----------|---------------|
  | new user (no provider)                 | false    | onboarding    |
  | pre-existing user (provider works)     | true     | normal app    |
  | returning user (completed onboarding)  | true     | normal app    |
  | user who deleted all providers         | false    | onboarding    |

The completion record is still written when a user finishes
OnboardingFlow's ReadyStep (via AppShell.tsx:741) — it just no longer
gates whether onboarding shows. The hasCompletedOnboarding field stays
on OnboardingReadiness for future analytics/UX hints.

Updated test "shows onboarding after startup when there is no completed
state" to reflect the new grandfathering behavior, and added a separate
test for the new-user path (no usable provider, no completion → flow
appears).
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 6, 2026
… pre-existing users

Two related issues with PR aaif-goose#9039's onboarding gate:

1. modelProviderIds was permanently empty.
   The memo called getModelProviders() (which reads via .getState())
   but only listed [distro] as a dependency. When the catalog populated
   from the backend (1 entry → 27 entries), the memo never recomputed,
   so the configuredEntry fallback in readiness never matched any
   provider. Same pattern in useOnboardingProviderStep.ts (modelProviders
   and usableAgentEntries memos).

   Fix: subscribe to catalogEntries via useProviderCatalogStore, switch
   call sites to the *FromEntries pure variants, and add catalogEntries
   to the affected memo deps.

2. Pre-existing users (installed before aaif-goose#9039) were trapped on
   ImportStep because hasCompletedOnboarding stayed false forever. The
   previous fix dropped the completion check from the gate, but that
   silently broke the "Reset onboarding" button — users who clicked it
   couldn't get back into the flow because their setup was still
   isUsable.

   Fix: restore the original (!hasCompletedOnboarding || !isUsable)
   gate, plus an auto-grandfathering effect that synthesizes a
   completion record once for users with a usable provider but no
   record. A separate ONBOARDING_GRANDFATHERED_KEY persists a "we've
   seen this user" marker so the effect doesn't re-fire after an
   explicit reset (resetOnboardingCompletion now sets that flag too).

   Behaviour matrix:

     | user                         | result                       |
     |------------------------------|------------------------------|
     | new (no provider)            | onboarding shows             |
     | pre-existing (usable, no     | auto-grandfathered, normal   |
     |   completion record)         |   app                        |
     | returning (completion + ok)  | normal app                   |
     | reset → reload (usable)      | onboarding shows again       |
     | provider deleted             | onboarding shows             |

Tests: existing 7 cases keep passing; renamed grandfathering test to
assert the new auto-completion behaviour and added a new test for the
post-reset path.
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 6, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
boolean depended on BOTH `readiness.isUsable` (does the user have a
configured provider with models?) AND `readiness.hasCompletedOnboarding`
(is localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider (which the model picker
triggers) re-evaluated the gate and snapped them back into
OnboardingFlow's default ImportStep, even though they already had a
working openrouter (or any other) provider.

Drop the !hasCompletedOnboarding check from shouldShowOnboarding. The
gate is now purely capability-based:

  shouldShowOnboarding: startupReady && !readiness.isUsable

Behavior matrix:

  | user                                   | isUsable | result        |
  |----------------------------------------|----------|---------------|
  | new user (no provider)                 | false    | onboarding    |
  | pre-existing user (provider works)     | true     | normal app    |
  | returning user (completed onboarding)  | true     | normal app    |
  | user who deleted all providers         | false    | onboarding    |

The completion record is still written when a user finishes
OnboardingFlow's ReadyStep (via AppShell.tsx:741) — it just no longer
gates whether onboarding shows. The hasCompletedOnboarding field stays
on OnboardingReadiness for future analytics/UX hints.

Updated test "shows onboarding after startup when there is no completed
state" to reflect the new grandfathering behavior, and added a separate
test for the new-user path (no usable provider, no completion → flow
appears).
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 6, 2026
… pre-existing users

Two related issues with PR aaif-goose#9039's onboarding gate:

1. modelProviderIds was permanently empty.
   The memo called getModelProviders() (which reads via .getState())
   but only listed [distro] as a dependency. When the catalog populated
   from the backend (1 entry → 27 entries), the memo never recomputed,
   so the configuredEntry fallback in readiness never matched any
   provider. Same pattern in useOnboardingProviderStep.ts (modelProviders
   and usableAgentEntries memos).

   Fix: subscribe to catalogEntries via useProviderCatalogStore, switch
   call sites to the *FromEntries pure variants, and add catalogEntries
   to the affected memo deps.

2. Pre-existing users (installed before aaif-goose#9039) were trapped on
   ImportStep because hasCompletedOnboarding stayed false forever. The
   previous fix dropped the completion check from the gate, but that
   silently broke the "Reset onboarding" button — users who clicked it
   couldn't get back into the flow because their setup was still
   isUsable.

   Fix: restore the original (!hasCompletedOnboarding || !isUsable)
   gate, plus an auto-grandfathering effect that synthesizes a
   completion record once for users with a usable provider but no
   record. A separate ONBOARDING_GRANDFATHERED_KEY persists a "we've
   seen this user" marker so the effect doesn't re-fire after an
   explicit reset (resetOnboardingCompletion now sets that flag too).

   Behaviour matrix:

     | user                         | result                       |
     |------------------------------|------------------------------|
     | new (no provider)            | onboarding shows             |
     | pre-existing (usable, no     | auto-grandfathered, normal   |
     |   completion record)         |   app                        |
     | returning (completion + ok)  | normal app                   |
     | reset → reload (usable)      | onboarding shows again       |
     | provider deleted             | onboarding shows             |

Tests: existing 7 cases keep passing; renamed grandfathering test to
assert the new auto-completion behaviour and added a new test for the
post-reset path.
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 6, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
boolean depended on BOTH `readiness.isUsable` (does the user have a
configured provider with models?) AND `readiness.hasCompletedOnboarding`
(is localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider (which the model picker
triggers) re-evaluated the gate and snapped them back into
OnboardingFlow's default ImportStep, even though they already had a
working openrouter (or any other) provider.

Drop the !hasCompletedOnboarding check from shouldShowOnboarding. The
gate is now purely capability-based:

  shouldShowOnboarding: startupReady && !readiness.isUsable

Behavior matrix:

  | user                                   | isUsable | result        |
  |----------------------------------------|----------|---------------|
  | new user (no provider)                 | false    | onboarding    |
  | pre-existing user (provider works)     | true     | normal app    |
  | returning user (completed onboarding)  | true     | normal app    |
  | user who deleted all providers         | false    | onboarding    |

The completion record is still written when a user finishes
OnboardingFlow's ReadyStep (via AppShell.tsx:741) — it just no longer
gates whether onboarding shows. The hasCompletedOnboarding field stays
on OnboardingReadiness for future analytics/UX hints.

Updated test "shows onboarding after startup when there is no completed
state" to reflect the new grandfathering behavior, and added a separate
test for the new-user path (no usable provider, no completion → flow
appears).
lifeizhou-ap added a commit that referenced this pull request May 7, 2026
…-refactor

* origin/main:
  refactor: switch to official new rust-sdk for ACP (#9062)
  refactor(goose2): remove attachment preamble (#9052)
  Align CODEOWNERS with pull request review rules in GOVERNANCE.md (#9056)
  bring MAINTAINERS.md up to date (#9053)
  feat(acp): expose built-in skills through sources list acp calls (#9045)
  add provider-first onboarding (#9039)
  feat: ACP streamable http spec compliance (#9034)
  Skip automatic fix which crashes (#9036)
  fix(openai): accept null tool_call arguments in streaming chunks (#9035)

Signed-off-by: Lifei Zhou <lifei@squareup.com>

# Conflicts:
#	ui/goose2/src/features/chat/hooks/useChat.ts
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 7, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 7, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 8, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 8, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 11, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 11, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 12, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 12, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
enilsen16 added a commit to enilsen16/goose that referenced this pull request May 12, 2026
PR aaif-goose#9039 added a useOnboardingGate hook whose shouldShowOnboarding
depended on both \`readiness.isUsable\` (does the user have a configured
provider with models?) AND \`readiness.hasCompletedOnboarding\`
(localStorage[goose:onboarding:v1] set?). The completion record only
gets written when a user finishes the new ReadyStep — so users who
installed goose2 before the gate existed have hasCompletedOnboarding
permanently false even though their setup works fine.

Result: every change to selectedProvider re-evaluated the gate and
snapped them back into OnboardingFlow's default ImportStep, even
though they already had a working provider.

Collapse the gate to a single reset-flag:

  shouldShowOnboarding = startupReady && (resetRequested || !isUsable)

resetOnboarding() sets the flag; completeOnboarding() clears it. The
completion payload (providerId/modelId) — never read outside the hook
— is no longer persisted, and completeOnboarding's signature drops to
() => void. resetOnboardingCompletion opportunistically removes the
legacy ONBOARDING_STORAGE_KEY for users on the upgrade path.

Behavior matrix:

  | user                                   | result        |
  |----------------------------------------|---------------|
  | new user (no provider)                 | onboarding    |
  | pre-existing user (provider works)     | normal app    |
  | returning user (completed onboarding)  | normal app    |
  | user who deleted all providers         | onboarding    |
  | user who clicked "Reset onboarding"    | onboarding    |

Drops hasCompletedOnboarding from OnboardingReadiness and the
"not_completed" reason it implied. Tests updated for the new state
model.

Signed-off-by: Erik Nilsen <enilsen16@live.com>
shafqatevo pushed a commit to shafqatevo/goose that referenced this pull request Aug 7, 2026
Signed-off-by: tulsi <tulsi@block.xyz>
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.

2 participants