Repository navigation
Epic: a third-party backend or tool renderer can do what the first-party ones do using supported API #1345
Description
Outcome
The agent-backend and tool-renderer seams, both on the sanctioned seam list, are expressible by an implementation outside this repo: no closed union names the first-party backends, no backend-specific helper sits in a public entry, and first-party renderers use the same ToolCallView contract a third party gets.
Why now
Found by the 2026-10-09 code-quality review of main @ 0c69e0cb. The backend toolkit ruling (docs/decisions/backend-authoring-toolkit.md, #535) and the export boundary (docs/decisions/public-export-boundary.md, #534) settled what is public and what is first-party sharing. Three things still contradict the seam promise:
BridgeToolAdapter/ToolAdapter = "claude" | "pi"is a closed union in a public entry (packages/ui-sdk/src/tool-contracts/contract.ts:23), consumed by ui-react (packages/ui-react/src/lib/tool-names.ts).- Backend-specific helpers still live in the SDK and reach backends through
/internal. The mask-file naming helpers (claudeMaskFilename,piMaskFilenameand their reported-path pairs,packages/ui-sdk/src/server/bridge-tools/mask.ts:408-442) are no longer in a public entry — onlypackages/ui-sdk/src/internal.ts:12exports them — but the host and each backend import them, so their home is a host-plus-one-backend question (ui-sdk: classify the SDK helpers that only the host and one backend import #2772), not a public-removal task. - Built-in renderers cast
ToolCallViewback to an internal type (packages/ui-react/src/components/chat/renderers/claude-tools.tsx:45,pi-tools.tsx:27,generic.tsx:20) and forward toswitch (tool.name)blocks (packages/ui-react/src/components/chat/tool-views.tsx:129,:182,:237,:421).
Shared context
- Seams lose
@experimentalat 1.0 (Epic: 1.0.0 — the stability bar #56); this epic is part of making that freeze honest. - The shared conformance suite (
runBackendContract,packages/ui-sdk/src/testing/index.ts:189-634) is the proof vehicle for backend changes. - Ruled 2026-10-09 (see the decision comment): extension packages (
module-*,ui-backend-*) import public entries only;./internalis for packages that are one product split for packaging. What both backends import becomes public toolkit (ui-sdk: promote the helpers both backends import into the public backend toolkit #1399), single-backend helpers move into their backend (backends: move the Claude-only SDK helpers bashCommand and loadedSdkIdentity into the Claude backend #1372), unused internal entries are deleted (packages: delete internal entry points that no other package uses #1401), and a lint gate holds the rule (ci: extension packages may import only public entry points #1400).
Constraints and non-goals
- No new seam; the wire protocol stays non-pluggable.
- Changing a public type is a
contractchange and, if it removes a name,breakingwith a maintainer ruling first.
Breakdown
Native children retain their own implementation and proof boundaries. The original third-backend id, renderer-contract, single-backend ownership and internal-import gate tasks remain. Already delivered #1397/#1399 supply the module/toolkit foundations.
The later repository review attached #2489 (shared worker-host API), #2490 (bridge availability), #2491 (application policy), #2492 (shared configuration/state-room rules) and #2538 (third-id parent-effect authority). Each directly advances the external-backend/toolkit outcome; their current briefs, actual dependencies and recorded reproductions govern delivery. These are already native children, not new attachments in this pass.
#1374 split, 2026-10-24: #1374 keeps pi web-search ownership; its other ruled families are #2770 (geo alias removal, breaking) and #2771 (SDK→render-template link policy, dropping SDK→ui-kit). The host-plus-one-backend helpers that decision 3 left "internal pending #1374" are classified by the 2026-10-24 ruling on #2772: public experimental SDK spawn/timeout helpers and backend-owned public mask helpers consumed through the loaded backend module (A/A/B); implementation remains open. #1372 now moves only the Claude-only bashCommand and loadedSdkIdentity.
Coordinated maintainer amendment, 2026-10-22: #2489 selects supported experimental APIs for all 41 shared worker-host helpers in the server-only runtime package extracted by #2528 under #2541 (working name @schlessera/brain-ui-worker). This amends the owning package for that set; existing public SDK toolkit APIs remain supported. Both first-party and third-party authors use the same supported runtime primitives, with no internal exception, duplicate SDK aliases or SDK-to-worker reverse dependency. #2489 consumes #2528 after #2530; no reverse implementation blocker or reparenting is selected. Durable toolkit/export-boundary amendments remain implementation deliverables.
The October 9 ruling above remains historical context for the earlier SDK toolkit set. A recorded choice is not delivered API or conformance proof. Keep this epic without agent-ready.
Definition of done
A test-only third backend id and a test-only renderer compile and pass conformance using only public entry points.
2026-10-24: corrected the baseline claim that the mask helpers ship in public /server (they are internal-only and a host-plus-one-backend question, #2772), recorded #1374's split into #2770, #2771 and #2772, and moved the dated triage notes to a comment.
2026-10-24 triage at main af6300478a07379178bd30221a31c0b917df2283: Refreshed moved current-source pointers by inspecting their named anchors. Historical receipts retain their source identities; scope, rulings, priorities and outstanding prerequisites are preserved. No runtime result or readiness is inferred from this navigation repair.
2026-10-24 maintainer reconciliation: #1400 now permits exported brain-common/internal/* as shared infrastructure without a compatibility promise; extensions still use public APIs of every other package. #2772 selects A/A/B as above. These amend the earlier pending boundaries; they do not claim implementation or epic completion.
Activity
6 remaining items
CONTRACT: feat(ui-sdk): promote the helpers both backends import into…
schlessera commentedon Oct 13, 2026
2026-10-13 triage: refreshed the current source pointers against
857ab01d1; preserved immutable historical evidence and all existing prerequisites. No completed outcome is inferred from moved code.schlessera commentedon Oct 22, 2026
2026-10-22 triage at main aa8c896: folded the later native children and coordinated #2489/#2528 owning-package rulings into the active breakdown. Verified the current closed ToolAdapter union, adapter-specific mask helpers and renderer casts still exist. Existing public toolkit guarantees, child dependencies, priorities and no epic readiness remain; no package extraction, public API delivery or third-party runtime conformance is claimed.
schlessera commentedon Oct 22, 2026
2026-10-22 triage at
0332f1f093d6d3fdc8fe83465eb762d6e90c3650: verifiedclaudeMaskFilenameandpiMaskFilenameand corrected its moved source anchor after #2619. Preserved the brief, labels, native parent, assignment, release attribution and all original proof limits; no new runtime result.schlessera commentedon Oct 24, 2026
Dated notes removed from the epic body on 2026-10-24, kept here verbatim as history:
2026-10-09: folded in the maintainer rulings on
/internaland the shared-file copies.2026-10-10 triage at main
7e398dc207f2c4725f6c364331c3cd5d3112954d: 1397 supported module entry is delivered by1466/a4120ed2, and1399 public backend toolkit by1461/02fd0b94. Current source exports those supported entry/toolkit surfaces;1396 common helpers were delivered separately. Remaining single-backend ownership, internal-import gate/removal and third-party renderer/conformance outcomes retain their native tasks. New public exports do not prove the entire third-party outcome. This triage inspected landed source/ancestry and current issue receipts, not a fresh test suite or independent automatic-main CI audit. Native child lists retain progress; epic readiness remains absent.2026-10-10 triage at main
0fff240b6167390276e141ff9aaf06e927289ea2: Refreshed runBackendContract to its actual named complete suite; no conformance criterion is removed.2026-10-13 source reconciliation at main
857ab01d1f9cb591f928755f5be516ab7f73338e: refreshed named current-source anchors after governed-flow integration. Historical receipts, scope and remaining prerequisites are unchanged; source inspection supplies no new runtime proof.2026-10-20 triage at main
af0547c2d4d197ed3766f2817cf56eb5f0486ab4: refreshed the four activeswitch (tool.name)pointers after verifying the renderer casts and current switch anchors. The public toolkit/extension rulings, native children and complete third-party conformance outcome are unchanged. No new runtime proof or epic completion is claimed.2026-10-22 triage at main aa8c896: folded the later native children and coordinated #2489/#2528 owning-package rulings into the active breakdown. Verified the current closed ToolAdapter union, adapter-specific mask helpers and renderer casts still exist. Existing public toolkit guarantees, child dependencies, priorities and no epic readiness remain; no package extraction, public API delivery or third-party runtime conformance is claimed.
2026-10-22 source navigation at main
0332f1f093d6d3fdc8fe83465eb762d6e90c3650: refreshed the moved citation forclaudeMaskFilenameandpiMaskFilenameafter #2619. Scope, unresolved prerequisites and original runtime evidence are unchanged; source inspection is not a reproduction or repair.2026-10-24 correction: the body's baseline said
claudeMaskFilenameandpiMaskFilenameship in public/server. They do not: onlypackages/ui-sdk/src/internal.ts:12exports them, andpackages/ui-sdk/tests/backend-toolkit.test.ts:22-28asserts the ordinary entries exclude them. The host imports both (packages/ui-server/src/brain/mask-application.ts:6), so their home is the host-plus-one-backend question decision 3 left pending; that is now #2772. #1374 was split into #1374 (web-search), #2770 (geo), #2771 (link policy) and #2772.schlessera commentedon Oct 24, 2026
2026-10-24 triage at main
af6300478a07379178bd30221a31c0b917df2283: Refreshed moved current-source pointers by inspecting their named anchors. Historical receipts retain their source identities; scope, rulings, priorities and outstanding prerequisites are preserved. No runtime result or readiness is inferred from this navigation repair.