1.0 archive. This section describes the previous 1.0 API. The current model is the 2.0 design.
Appendix A. As-built deviations that change plugin code (D1–D20)
From next/docs/stage-2/04-kernel-as-built.md §1. "Built wins" means: write code against the built column. "Flippable" means a README request exists; plan for both.
| # | Package | Topic | Built behavior (one line) |
|---|---|---|---|
| D1 | kernel-core | Registration conflicts | provide/define/register conflicts are recorded as activation problems (degraded) with a no-op disposer; invalid_facts, invalid_contract, unknown_command, scope_disposed still reject. A registration is visible once its promise settles. |
| D2 | kernel-core | Nouns, multi contracts, actors | Noun ownership is composition order (ties by plugin id); RESERVED_NOUNS = kernel composition plugin host preference secret; a multi contract may not carry a mutation; every MethodDef carries actors and destructive. |
| D3 | kernel-core | Interceptor order and budget | Priority desc → exact before wildcard → composition order → registration order; the budget covers only the interceptor's own work before next(); an overrun skips it and cannot veto. |
| D4 | kernel-contract | method() / defineService shape |
Inputs must be z.strictObject; no kind means "query"; defineService fills command, cli.name, tool.name. |
| D5 | kernel-contract | Actors, exposure gates, host target | Anonymous loopback callers are human:local via: "anonymous"; expose.cli is not enforced over HTTP; target: "host" is 503 service_unavailable in core today. |
| D6 | cli | CLI tree, --json, exit codes |
--json prints the bare result; {ok:false,error} on error; exits usage 2, no runtime 4, declined confirm 1, SIGINT 130, --timeout 5; a word collision drops the later claimant with a warning. |
| D7 | kernel-loader | Placement | Bundled and path: plugins run in-process; marketplace installs in a worker; worker gaps: declared .default()/.transform() do not reach the handler; kind: custom in a worker is refused. |
| D8 | kernel-loader | Plan-time problems and boot | Collisions and config problems are degraded + detail, not failed loads; boot is sequential in topological order; the composition file is not watched. |
| D9 | kernel-loader | Build outputs are checked | contributes.slots is cross-checked at build; a browser registration absent from app.contributions.json fails the load with contributions_mismatch; kernel/plugins.install has no CLI positional yet. |
| D10 | kernel-loader | Background services | A non-empty contributes.background starts a separate worker; no schedules table; fork --detach disables the original. |
| D11 | kernel-store | Kinds and reducers | Core kinds are snake_case; row kinds turn, interaction, notice are reducer-synthesized and refused as event kinds; $.progress is a legal delta path on every item kind. |
| D12 | kernel-store | Entity events | kernel/<entity>.changed for thread project environment host thread-head interaction thread-annotation, plus kernel/thread.purged, kernel/store.appended, derived kernel/store.rows and kernel/store.changed. |
| D13 | kernel-store | SQL handle and CAS | Rows are SqlResultRow; plugin tables live in plugins/data/<id>/data.db via ctx.storage.openDatabase(migrations); kernel/preferences.set takes expectedUpdatedAt and returns {updatedAt}. |
| D14 | kernel-host | Roles and the host entry | HostRoleName = provider-bridge environment-provider skill-discovery terminal-backend ai-service rpc; defineHostEntry derives commands from the rpc rows; RoleContext.watch is a no-op, openLane is absent. |
| D15 | kernel-host | Env handles and the relay | RootRef.source carries path; turn.completed {status: "interrupted"} is the settlement on exit; core → role rpc from a server tier is not wired yet (service_unavailable). |
| D16 | kernel-ui | Slots, routes, arbitration | A priori slots: root, diff.renderer, source.renderer; every other slot is declared by an occupant's children; arbitration replaces → pin → priority → sorted plugin id, committed in sorted-id waves. (changed at e1efe72a3: a pane kind's children are declarations too, live while the kind's plugin wins it — slot-tree.ts kindReg; the instance key ends in the registration id; declares in app.contributions.json also carries pane:<kind> owners and inject-thunk registrations; back/forward reports pop.) |
| D17 | kernel-ui | Services and commands | useService resolves local kernel-ui/* → local container → core scope over one WebSocket; a lost socket is a reload plus a toast; ServiceUnavailable is thrown from the hook. (changed at e1efe72a3: the client bus has a caller face, useCommands(): ClientCommands (§4.6), and a server-side sender, ctx.hub.command over the hub's command lane (§3.5); a keydown inside an IME composition never dispatches a chord.) |
| D18 | kernel-ui | Data hooks and CSS | defineRowStore gates on {seq, op}; defineQuery(...).useHandle() is a hook; authored CSS roots every selector at [data-bb-plugin-effect="<id>"]; zod is bundled into every tier. (changed at e1efe72a3: RowState.exhausted is required and apply receives { threadId } (§4.8); the authored sheet now loads — core keys cssUrl on meta.digests["app.css"], core/src/app.ts (§4.12); contracts.mjs carries no Node ESM banner.) |
| D19 | plugin-sdk | Facade rules | definePlugin({config?, activate}); ctx.agents.configure is watch-held over the _pending copy of threads/agent-config; ctx.realtime.declare + publish is the only channel API. |
| D20 | plugin-sdk | Test harness rules | Four helpers; createAppHarness requires a synchronous setup and root-scoped children; happy-dom is installed by hand; every suite calls expectDerivedSurfaces. |
Superseded at dc07292bf: D15's "not wired yet" — core now passes createHostClients(...).clientFor to the loader (packages/core/src/core.ts). D9's install positional and the dotted-noun grammar moved with the Stage 2 integration (see §0.7).
Changed at e1efe72a3: D16, D17 and D18 carry inline notes above; the full list is §0.8. D7's worker gaps gain one: ctx.hub.command answers service_unavailable in a worker placement (§3.2).
Appendix B. Known gaps to plan around (H1–H8)
See next/docs/stage-2/04-kernel-as-built.md §6. The ones that touch plugin code: a lost browser socket reloads the page (H1); ctx.hostClient from a server tier is unwired (H5-adjacent, D15); target: "host" methods answer 503 (D5); the cli tier (defineOfflineHandlers) is not built. (D9's missing install positional is closed at dc07292bf: bb plugin install <source> parses, kernel-loader/src/service.ts.)
Added 2026-08-26. H9: app module exports (bb.appExports, contributes.appImports, @get-bb/plugin-<id>/app, importAppModule) are design only — no loader or builder support exists; the design is §4.16 and Guide 18. Components do already travel by value (slot registration objects, the @bb/ui/domain facades, and browser-local services over the Symbol.for("bb.ui-shell.services") window table — §4.16 first row); the SDK gap behind that table is app.services.provide, which every UI plugin's copied app-services.ts stands in for. Also design, not built: the slot-catalog generator and dump (bb sdk types --slots, bb plugin slots, §4.14); the type-distribution step (bb sdk types materializing installed artifacts' dist/types/ behind a generated paths block, §4.14, Guide 16 step 4); and the typed browser-local services (AppServices merge registry, app.services.provide, the keyed useService overload, §4.16). The SlotMap machinery itself is built. The cross-plugin slot contract (§4.15) is as built except the two named edges: a realized inject thunk is not re-validated when the declaration changes under it, and a parked declaration's registrations remain reachable through Original chains. Note: several of this appendix's "not built" rows are stale against f97fbe617 — the cli tier now builds and loads (defineCliEntry, dist/cli.mjs), and the composition file is watched (D8) — see gap-analysis-2026-08-26.md at the repo root for the verified list.
Added 2026-08-26 (kernel-domain tier). The architecture adds a tier between kernel and plugins (§0.9): threads, projects, environments, files, terminals, and the provider framework become first-class core-provided services, SDK-versioned and always present; provider drivers and environment providers remain plugins behind them. Sections written before this decision describe the domain as plugins (threads, projects, environments rows in §5 and the guides); their contract shapes carry over unchanged — only the provider of those contracts and its guarantee move into core.