Skip to content

Repatriate single-consumer provider-bridge SDK exports to their owning plugins - #1729

Merged
ymichael merged 4 commits into
mainfrom
provider-bridge-surface-repatriation
Aug 17, 2026
Merged

Repatriate single-consumer provider-bridge SDK exports to their owning plugins#1729
ymichael merged 4 commits into
mainfrom
provider-bridge-surface-repatriation

Conversation

@ymichael

@ymichael ymichael commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Executes the follow-up recorded in docs/api_to_audit.md under the @get-bb/plugin-sdk/provider-bridge audit (item 2, surface size): repatriate single-consumer bridge-kit exports to their owning plugins and shrink the published surface. Pure move/deletion refactor — no behavior change, no wire shapes, no version bumps.

What moved (each verified single-consumer)

  • extractEnvOverrides (bridge-kit adapter-utils.ts) → plugins/provider-claude-code/src/bridge/env-overrides.ts, with its round-trip test.
  • getMessageContentTypes (bridge-kit provider-visibility-helpers.ts) → module-local in plugins/provider-claude-code/src/visibility.ts.
  • pending-interaction-normalization.ts (whole module + test) → plugins/provider-codex/src/; its only consumer was codex's interactive-requests.ts. The surface gained pendingInteractionRequestedPermissionProfileSchema (the domain composite the normalizer parses against; its component siblings were already exported).
  • cloneReasoningEfforts → out of @bb/domain into plugins/provider-claude-code/src/model-catalog.ts — both consumers are claude-code, and a helper function in @bb/domain violated its types/schemas-only rule.

What deliberately stayed

The audit item's originally named candidates turned out to have core consumers, so they stay; the sweep covered every export on the surface:

  • claudeCodeMockCliTrafficConfigSchema + default: type/default consumed by @bb/agent-runtime and the server.
  • claudeTaskToolNameSchema / claudeTaskToolOutputSchema: share a contract file with exports @bb/thread-view renders.
  • acpNativeReasoningSchema, acpPermissionCliSchema, acpReasoningCliSchema: parsed by host-daemon-contract and @bb/config.
  • Workflow snapshot types: rendered by the app.

docs/api_to_audit.md item 2 is updated to record this ground truth so the stabilization audit starts from facts.

Numbers and verification

  • Published surface: 197 → 194 named exports; regenerated bundled-types/bb-plugin-sdk-provider-bridge.d.ts 6,615 → 6,498 lines. Net −112 lines.
  • Typecheck green via turbo for provider-bridge-protocol, plugin-sdk, domain, all four provider plugins, and downstream agent-runtime/thread-view/server/config/host-daemon-contract.
  • Tests pass: domain (25 files), provider-bridge-protocol (9), provider-claude-code (18), provider-codex (13), provider-acp (7).

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Also in this PR: two small follow-up fixes from the #1640 issue sweep

Each is its own commit and closes its issue on merge:

Verification for the full stack: @bb/server suite 183 files / 1721 tests green, plus typecheck via turbo.

🤖 Generated with Claude Code

AGENT GENERATED: by Claude Fable 5

Executes audit item 2 (Surface size) of the
@get-bb/plugin-sdk/provider-bridge entry in docs/api_to_audit.md:

- extractEnvOverrides and getMessageContentTypes move from the bridge kit
  into bb-plugin-provider-claude-code (their only consumer), with the
  env-override round-trip test.
- The pending-interaction-normalization module (and test) moves from the
  bridge kit into bb-plugin-provider-codex; the SDK surface gains
  pendingInteractionRequestedPermissionProfileSchema (the domain composite
  the normalizer validates against) in its place.
- cloneReasoningEfforts moves from @bb/domain into claude-code's model
  catalog (its only consumer; domain stays types/schemas).

The other named candidates stay: the Claude mock-CLI traffic config, the
claudeTaskTool* schemas, the ACP reasoning/permission CLI schemas, and the
workflow snapshot types all have core consumers (agent-runtime, server,
thread-view, host-daemon-contract, config, app), and buildEditDiff,
completeStartedToolItem, and decodeToolCallResponsePayload are used inside
the kit itself. Surface: 197 -> 194 names; bundled provider-bridge d.ts
6615 -> 6498 lines. No wire shapes change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bb-slop-cop

bb-slop-cop Bot commented Aug 17, 2026

Copy link
Copy Markdown

🚨 SLOP COP 🚨 · review

I am SlopCop. I am reviewing this pull request for security, code quality, performance, architecture, and end-to-end behavior.

resolveProviderWorkflowsEnabled applied the claudeCodeWorkflowsDisabled
app setting to every provider that passes the supportsWorkflows
capability policy, so the first third-party provider declaring
supportsWorkflows: true would silently inherit a Claude-named user
preference. The setting now only affects providerId "claude-code";
other providers' answer comes from the declared capability alone.

Behavior-preserving today: grepping provider declarations confirms
provider-claude-code is the only provider declaring
supportsWorkflows: true (provider-codex, provider-acp, provider-pi,
the echo example, and the ACP tier all declare false).

Fixes #1722

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pendingInteractionFileSystemPermissionsSchema,
pendingInteractionMacOsPermissionsSchema,
pendingInteractionNetworkPermissionsSchema,
pendingInteractionRequestedPermissionProfileSchema,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚨 slopcop/review — Avoid a replacement single-consumer SDK export

This new public schema has one source consumer: the moved Codex normalizer. It replaces one single-consumer helper with another public name.

The local transform already creates the complete typed output. Please return its parsed result or compose a local schema from existing public component schemas.

Then remove this export and rebuild the declarations.

@bb-slop-cop bb-slop-cop 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.

🚨 SLOP COP 🚨 · review

Plain-English summary: This change moves four shared helpers into the two provider plugins that use them. It reduces the published bridge SDK without runtime changes.

I found no security, performance, or correctness issue.

Findings:

  • Low: pendingInteractionRequestedPermissionProfileSchema is a new public SDK export with only one Codex consumer. This partly replaces the public surface that this pull request removes. Keep the final validation local to Codex and remove this export.
  • Non-blocking refactor: model-list.ts still copies reasoning efforts with the same map operation. Reuse the new local cloneReasoningEfforts helper there.

Validation:

  • All 740 focused tests passed across the domain, SDK, bridge protocol, Codex, and Claude packages.
  • All 11 focused Turbo test and typecheck tasks passed.
  • Both provider conformance suites passed.
  • All GitHub checks passed.
  • Browser QA did not apply because this change has no user interface, route, or visible workflow.

I found no blocking issue. The SDK export concern is small, but it conflicts with the stated surface reduction goal.

ymichael and others added 2 commits August 17, 2026 15:08
…ssful build

Two defects in dev-loop build status handling:

- Every dev build problem was labeled "frontend bundle build failed:",
  including HOST build failures. setDevBuildProblem now takes the build
  kind ("frontend" | "host") and labels the problem accordingly; the two
  targets keep independent problem slots so a frontend success cannot
  hide a host failure or vice versa.
- The problem was sticky: a later successful host rebuild through the
  enable/load path (loadHostArtifactCandidate) never cleared it, so a
  transient dev-loop failure stayed in plugin status until the next
  source change. Both load-path builds (buildPluginApp in
  loadAppBundleCandidate, buildPluginHost in loadHostArtifactCandidate)
  now clear their own target's problem on success; the dev-loop callers
  already cleared on success and now do so per target.

The unit test constructs the plugin runtime directly (in-memory SQLite,
stub hub) and covers per-target labeling, independent clearing, and the
problem surviving later status updates until cleared. End-to-end
coverage of the enable-path clear would require real host bundle builds
in the test, so that path is exercised only through the existing
builtin dev-loop tests.

Fixes #1725

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SlopCop review nit on #1729: buildDiscoveredModel inlined the same
spread-map the relocated helper encodes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ymichael
ymichael merged commit 155a53a into main Aug 17, 2026
10 of 11 checks passed
@ymichael
ymichael deleted the provider-bridge-surface-repatriation branch August 17, 2026 22:52
ymichael added a commit that referenced this pull request Aug 18, 2026
…registry, repatriate single-consumer helpers (#1742)

De-overfits `bridge-kit` following a two-reviewer adversarial audit of
every module and export, calibrated on one ruling: **GOOD** = code
encoding bb-side invariants (canonical event/item semantics, wire
contracts both sides validate); **BAD** = a frame hosting per-provider
knowledge injected through generics, callbacks, or config objects. ~80%
of the kit survived the audit as genuine invariants (notably
`turn-state`, whose suspect generic-plus-hooks shape is driven
identically by all three consumers); this PR removes the part that
didn't. One commit per finding group:

1. **Unwind `buildToolUseItem`** — the router was an if-chain each
bridge could write itself, inverted into the kit via name-sets + parser
callbacks + an escape hatch supplied by exactly one provider. The
invariant constructors stay (`buildFileChangeItem`, new
`buildGenericToolCallItem` fallback); claude-code and pi own explicit
switches, preserving null-parse→generic fallback and parent-id
threading.
2. **Split `bridge-session-registry`** — only 2 of 4 bridges used it,
and over half its option surface existed for one consumer each
(`nextToolCallRequestId`, `resolveAdditionalPendingWork`, `stopSession`
claude-code-only; `TCloseResult` pi-only). The genuinely shared kernel
survives as `createPendingToolCallTracker` (flat requestId→resolver map
— also removes the per-response all-sessions scan); session
orchestration inlined into the two bridges. **Reviewer note:**
claude-code's interactive requests previously shared the tool-call id
counter; they now use string-prefixed ids (`interaction-N`), keeping the
id spaces collision-free. Wire-compatible: JSON-RPC ids are `string |
number` and both ends treat them opaquely.
3. **One decoder for canonical tool-call requests** —
`decodeNativeProviderToolCallRequest` had zero consumers anywhere
(deleted); `bridge-protocol-adapter` reimplemented
`decodeNormalizedProviderToolCallRequest` inline (now delegates);
`providerToolCallResponseSchema` privatized.
4. **Repatriations** — `buildShellEnvironmentPolicyConfig` →
provider-codex (its `shell_environment_policy.set.*` namespace is
codex-native config); claude-code stops round-tripping env vars through
codex-style keys and carries a plain map under its own bag key (both
ends verified inside the plugin — nothing crosses the daemon wire
schema). `diffCumulativeText` → pi, its only consumer.
5. **Dead surface + trims** — `finishOpenProviderTurn` (only caller was
a test) deleted; two per-provider policy booleans removed from the good
constructors (`completeWebItems`, `preserveUndefinedToolCallFields`);
the universally-identical `drainAcceptedUserMessages` call folded into
the turn-state core; `CounterScopedItemIdState`'s lying `reasoning*`
field names renamed (compaction ids flow through them too);
`contentWrapperSchema` and dead arg interfaces un-exported. Includes the
`docs/api_to_audit.md` record and regenerated bundled types.

## Numbers

- Published surface: 196 → 192 names (−7 removed, +3 added: the two kept
constructors and the tracker).
- 35 files, +972/−908 (+825/−738 excluding regenerated bundled types).
Insertions exceed deletions by design: the audit trades kit generics and
single-consumer options for deliberate, explicit per-consumer code, plus
~200 lines of new tests (tracker + moved diff tests).

## Verification

- Typecheck green via turbo: provider-bridge-protocol, plugin-sdk,
agent-runtime, provider-claude-code, provider-codex, provider-acp,
@bb/server.
- Tests green via turbo (post-rebase onto the merged #1729): 74 + 98 +
316 + 260 + 164 + 144 + 1722 across those packages.
- No wire-shape changes, no protocol or SDK version bumps, pi's
daemon-bundled path untouched.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

> AGENT GENERATED: by Claude Fable 5

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant