brain_kernel 0.2.2
brain_kernel: ^0.2.2 copied to clipboard
Headless system kernel for knowledge-grounded multi-agent systems. Bundles project / canonical / patch / validate / build / MCP / chat / RAG over mcp_bundle and flowbrain_core. Products (builder / ind [...]
0.2.2 - 2026-09-14 #
Added #
AccountKbRecordStoreandKbAccountRecords— a bundle'skbrecords in account storage (app/<appId>, platform spec 20 §2) with this device's copy underneath. Writes are conditioned on the account version last seen; while the account is unreachable they wait on the device and go up in order when it answers, and one whose base moved meanwhile is kept forconflicts()instead of being forced. A refusal from the account (KB_QUOTA_EXCEEDED,KB_VALUE_TOO_LARGE, a key or scope it does not accept) reaches the bundle rather than waiting, and one met in the queue does not hold back the writes behind it. Keys are stored askb/<key>with every UTF-8 byte outsideA-Z a-z 0-9 . _ / -written as:and two hex digits (platform spec 20 §2.1.2) —accountKeyOf/kbKeyOf— and a key whose stored form is longer thanaccountKeyLimitis refused withKB_INVALID_KEYbefore it is read, written or queued.clearDeviceCopydrops this device's copy and queue, never the account's records.BundleKbStore— a bundle'shost.kbstate as one implementation every host forwards to.get·list(prefix)(ascending, string prefix) ·put·delete·conflicts·query. Each key is a versioned record: a write is made on the version the store last saw, and when the record moved since, nothing is written and{ok: false, conflict: {value}}returns the current value for the bundle to merge;forceoverwrites deliberately. Keys are refused (KB_INVALID_KEY) when empty, starting with/, containing\or NUL, or holding an empty,.or..segment; values JSON cannot carry are refused (KB_INVALID_VALUE);querywithout a knowledge engine is refused (KB_QUERY_UNAVAILABLE).KbError.unavailable(KB_UNAVAILABLE) names a store that will not take the app's state. State is keyed by app identity (listing:<id>/bundle:<manifest.id>).KbRecordStoreandKvKbRecordStore— records in the kernelKvStoragePortunderapp/<appId>/kb/<key>, each segment percent-encoded so any app id or key is a valid file name on every platform. A delete keeps a tombstone so versions keep counting up.importDomainStorageNamespace— moves a host's formerDomainStoragestate intokbonce, never overwriting and never deleting the source.
Fixed #
KvStoragePortAdapterrefuses a key with a.or..segment. A key is a path under the root, soa/../../xwrote outside it anda/x/../bgave one file a second name.KvStoragePortAdapter.keys(prefix)walks only the directory the prefix's last/names instead of the whole store. The keys returned are the same.
Deprecated #
DomainStorageandJsonFileDomainStorage— a second store beside the kernel's, with no versions. UseBundleKbStore.
Changed #
- Internal dependencies raised to the latest published:
mcp_bundle ^0.4.10,mcp_server ^2.2.3,flowbrain_core ^0.1.8.
0.2.1 - 2026-08-13 #
Added #
- The kernel runs where there is no filesystem. Storage is behind two ports:
CanonicalStoragePortfor the canonical bundle andSidecarStoreforprefs,undo,historyandchat. Neither port names a platform library, so a host can implement one without being handeddart:io. OpfsSidecarStore— a browser store over the origin-private file system, exported frombrain_kernel_web.dart. It is not on the main barrel:dart:js_interophas no implementation off the web compilers, so a VM build that reached it would not compile.forAccount(accountKey)is the only constructor — OPFS is keyed by origin, not by person, so two people sharing a browser would otherwise share their records.
Changed #
- The sidecars take an optional store (
Prefs.load(path, store: …),ChatLog.attach(path, store: …), and the same forHistoryLog/UndoLog). Omitting it keeps the previous behaviour — the filesystem, where there is one. Where there is none, the call refuses with aStateErrornaming the missing decision rather than failing later inside a read.Canonical.openAtbehaves the same way with itsstorage. ManifestOnlyCanonicalStoragemoved to its own library so that naming the port does not import the filesystem implementation. It is still exported from the barrel.- Floor:
mcp_client ^2.2.1. New dependencyweb ^1.1.0, reached only through the web branch of a conditional import.
Fixed #
McpClientKernelHost.connectis bounded (15 s default,options.connectTimeoutMsto change it) and reports a timeout as an error. Building a transport does not touch the endpoint, so an unreachable target first shows up in the handshake, and a caller that never gets an answer cannot report one.- The barrel exports
SidecarStoreanddefaultSidecarStore(). Every sidecar constructor requires a store, so without them the sidecars could not be called from outside this package at all.
0.2.0 - 2026-07-28 #
Changed #
- Internal dependency floors moved to the current releases:
mcp_client ^2.1.0,mcp_server ^2.1.1. The server floor matters beyond hygiene — 2.1.1 fixes in-flight requests being keyed by the bare JSON-RPC id, which let two sessions using the same id (the first id a client hands out is2) overwrite each other's pending response. Leaving the floor at^2.0.0would resolve against a release that still loses responses under concurrent sessions.
Added #
SharedResourceSubscriptions— reference-countedresources/subscribeover a client several consumers share. A device subscription belongs to the LINK: the server knows only "subscribed" or not. Once one connection per device is shared, a device's own screen and a composed tile naming the same device land on one subscription, and the first to release it stopped the other's stream — a tile that streamed until the device's own screen was visited and closed, then froze and moved one step per manual Subscribe. The wire call now happens on 0 → 1 and on the return to 0; a failed subscribe leaves no count behind.ExtensionTransportConnect.adoptClient({id, client})— register a client the HOST already holds under an id, instead of dialling the device a second time. One device, one connection: many embedded boards serve a single peer, so a host that opened a device for its own screens and then named it as a composition origin got the second dial refused, and the user saw a device that "sometimes will not open". Even where a second link is allowed it splits subscriptions and health tracking across two links to the same device. An adopted connection does NOT own the client — closing it deregisters only, because ending a device connection is the user's explicit action, not a side effect of leaving a screen.mcp.subscribe_resource/mcp.unsubscribe_resource, and theKernelClientConnection.subscribeResource/unsubscribeResource/resourceUpdatesthey drive. The client surface could read a resource once but not track it, so a UI showing a live device value had no way to get one — it rendered the reading's label and never a number, which looks like a layout bug rather than a missing capability. First consumer: MCP UI DSL v1.4 composition, where one screen watches several devices at once.resourceUpdatesis a broadcast stream. Several views may watch the same device, and a single-subscription stream would hand updates to whichever listened first and leave the rest empty.
Breaking #
KernelClientConnectiongains three abstract members. Implementors outside this package must add them; the reference implementation and the in-repo fakes are updated. Additive for callers.
0.1.8 - 2026-07-14 #
Fixed #
McpClientKernelHoststreamableHttp/sse connect now sendsoptions.accessTokenasAuthorization: Bearer(+options.headerspassthrough) — the token was dropped, failing authenticated service connects.
0.1.7 - 2026-07-12 - ExtensionTransportConnect seam capability (additive) #
Added #
ExtensionTransportConnectcapability interface +connectExtensionhelper (package:brain_kernel/mcp_host.dart). Codifies the extension-transport injection seam standard. The seamconnectWith({ id, transport })— how a host opens an outbound MCP connection over a transport it built itself (serial / usb / ble / tcp / ws viamcp_bridge, or the hub relay ws viagateway_node'sHubConsumerTransport) — previously lived only on the concreteMcpClientKernelHost. The abstractKernelClientHost(the typeKernelApp.clientHostexposes) surfaces onlyconnect({ transport: KernelTransportKind })for the kernel-buildable stdio / Streamable HTTP / SSE transports, so a host had to hold a concrete client-host reference to reach the seam.McpClientKernelHostnow alsoimplements ExtensionTransportConnect, and hosts reach the seam off the abstract client host via the canonical helperconnectExtension(clientHost, { id, transport })— it probesExtensionTransportConnect, does the explicit cast (the interface is unrelated toKernelClientHost?, soisdoes not promote the variable — a footgun sealed in one place), injects, or throws aStateError. Both exported from themcp_host.dartsub-barrel (they referencemcp_client'sClientTransport, so they stay out of the library-agnostic main barrel).KernelClientHostitself is unchanged (cascade 0). Test:client_tools_test.dart(probe off the abstract type; non-capable / null host throws). The host-facing surface (themcp.connect_extensiontool) lives in therecipes/extension_transport/recipe, not the kernel (it carries an mcp_bridge FFI dependency). 227 PASS.
Backward compatibility #
- Fully additive.
KernelClientHostis unchanged — existing implementers are untouched (no new abstract member to satisfy). The new capability is a separate interface a client host opts into. Floors unchanged.
0.1.6 - 2026-07-02 - bk.philosophy provenance discipline + bk.agent.update #
Added #
bk.agent.updatestandard tool (48 tools). In-place mutation of a persistent agent —agentIdplus any ofdisplayName/role/model/systemPrompt/tags. Closes the CRUD asymmetry in thebk.agent.*surface (create/delete existed, update did not), so changing an agent's orchestration role or model through the kernel tool surface no longer requires delete→recreate — which destroys the individual's owned axis forks and history, contradicting the persistent-roster principle. An unknownrolevalue is rejected (not silently defaulted). Requiresflowbrain_core ^0.1.7(therole-accepting update seam) — floor bumped. Test:standard_tools_test.dart(in-place promote persists · untouched fields kept · unknown role rejected). 223 PASS.bk.philosophy.put/bk.philosophy.activateenforce a provenance lifecycle. An ethos payload may now carry an optionalprovenanceblock —payload['provenance'] = { 'kind': 'anchor'|'derived'|'workaround', 'serves': <principle id>, 'validWhile': <condition> }. Aderivedorworkaroundethos is a transient judgment, not an original principle: it must declare the principle itserves, and it is forced inactive onput— it becomes the active principle only through an explicitactivate(the confirm step), mirroring the fact candidate→confirm lifecycle. This keeps a derived judgment from silently being stored or activated as if it were a defining principle. Rides the existingEthosStorePortcontract (payload preserved as-is) — no core type change inmcp_bundle. Tests:philosophy_authoring_test.dart(anchor unconstrained · derived-without-serves rejected · derived forced inactive + provenance round-trip · workaround confirmed via activate). 222 PASS.
Backward compatibility #
- Fully additive.
kinddefaults toanchorwhen absent, so pre-existing ethos records and the stock seed (which carry noprovenance) are unconstrained and behave exactly as before. Floors unchanged.
0.1.5 - 2026-06-30 - KvStoragePortAdapter.keys(prefix:) string-prefix contract fix #
Fixed #
KvStoragePortAdapter.keys(prefix:)violated the string-prefix contract. It treatedprefixas a directory path (<rootDir>/<prefix>/), so flat colon-namespaced keys (e.g.philosophy.ethos:<id>, stored as a single<key>.jsonfile) were never listed:keys(prefix: 'philosophy.ethos:')returned[]even thoughget/setworked andkeys()(no prefix) listed them. This surfaced asbk.philosophy.listreturning an empty array whileput/getsucceeded. The method now walks the full store, reconstructs each key, and filters bykey.startsWith(prefix)— matching the in-memory referenceKvStoragePort. Hierarchical slash-namespaced prefixes (e.g.ws/A/) still match (keys use/separators) and partial-segment prefixes now match correctly too. Regression tests added (kv_storage_port_adapter_test.dart). 218 PASS.
0.1.4 - 2026-06-24 - BundleActivation tool-dispatch via injected callTool closure (additive) #
Added #
BundleActivationoptionalcallToolclosure — an alternative to a fullKernelServerHost bootfor wiring flow / behavior tool-action dispatch. A host whose endpoint is a registry (e.g. aBuiltinToolRegistrythat exposescallToolwithout ever surfacing a rawKernelServerHost) can now inject just the dispatch closure:BundleActivation(system: ..., bundleId: ..., callTool: server.callTool).registerBehavior/registerFlowroute tool steps throughcallTool ?? boot?.callTool. Mirrors the skill-executorcallToolbinding pattern already used across hosts. Tests:bundle_activation_behavior_test.dart(closure dispatch withboot == null· unwired-throws). 214 PASS.
Fixed #
- Registry-host topologies could not dispatch tool-action behavior / flow steps. When a host endpoint is a
BuiltinToolRegistry(not a rawKernelServerHost),bootis necessarily null and there was no other way to supply dispatch, so everykind: toolbehavior / flow step threwtool dispatch not wired (<ref>)at run time (the live-registered philosophy-gate path was latently affected too). ThecallToolseam closes that gap; the same diagnostic now fires only when neithercallToolnorbootis provided.
Backward compatibility #
- Fully additive. The
bootpath and thetool dispatch not wireddiagnostic are unchanged.BundleActivationcallers that don't passcallToolsee no behavior change.
0.1.3 - 2026-06-23 - FlowBrain orchestration tools (route/review) + destructive-action gate #
Added #
- Orchestration tools —
bk.agent.route+bk.agent.reviewstandard tools (agent_tools: 11 → 13) — expose the AgentFacade's manager-routing + reviewer-verdict as MCP tools so workflows / agents can drive rule-based agent→agent handoff.route{managerId, request, candidateAgentIds?}→{targetAgentId, confidence, reason};review{reviewerId, targetAgentId, content}→{verdict, severity, comments}. standardTools map: 45 → 47. - Destructive-action gate —
HostToolRegistry:registerExposed(destructive: true)+ optionalconfirmDestructivehost callback (ctor). Destructive tools (git push / mail / settlement / external publish) are gated through the callback before running — blocked when the human declines or no callback is wired (deny-by-default).destructivedefaults false → existing tools unaffected. The confirm UI is host-supplied (core has no UI). 209 PASS.
Fixed #
bk.philosophy.putaccepts a raw Ethos and never silently drops the body. PreviouslyputcalledEthosRecord.fromJson(input)directly, so an author / LLM passing a raw Ethos (nopayloadenvelope key) storedpayload: {}— the body was lost and every latergetEthos/intervene/checkProhibitionsoperated on an empty ethos (or crashed inEthos.fromJson).putnow detects the shape: an envelope (payloadpresent) is stored as before; a raw Ethos is wrapped into anEthosRecordwithpayload: <ethos>,id/name/versionderived from the ethos (version frommetadata.version). The body is validated viaEthos.fromJsonbefore storage, returning a clearinvalid ethos: <field-named message>(mcp_bundle 0.4.4) instead of storing garbage. Integration test:test/system/philosophy_authoring_test.dart(raw round-trip preserves body · envelope back-compat · malformed → clear error) over a realKvEthosStoreAdapter. 212 PASS.
Changed (dependency floor) #
flowbrain_core^0.1.4→^0.1.5— track the latest published cascade release (flowbrain_core 0.1.5 wires the orchestration cascade). The kernel's route/review tools wrap the existingAgentFacade.route/review(present since 0.1.x), so this is an internal-latest constraint bump, not a symbol requirement.mcp_bundle^0.4.1→^0.4.4— thebk.philosophy.putfix above relies on the Ethos graphfromJsonthrowing field-namedFormatExceptions (mcp_bundle 0.4.4) for the clear-error guarantee; floored to guarantee it.
Backward compatibility #
- Fully additive. No existing
HostToolRegistry,BundleActivation,standardTools, or host-abstract surface changed. Tools registered withoutdestructive: trueand hosts that don't passconfirmDestructivesee no behavior change.
0.1.2 - 2026-06-10 - Extension transport seam + clientTools export (additive) #
Added #
McpClientKernelHost.connectWith({id, transport})— new public method on the referenceKernelClientHostimplementation. Accepts a host-suppliedmcp_client.ClientTransport(e.g.TcpClientTransportorWebSocketClientTransportfrommcp_bridge) and opens aKernelClientConnectionover it. The kernel itself carries no FFI or platform dependency for the transport — the calling host owns those by design (injection seam). The abstractKernelClientHostis unchanged.clientToolsfunction exported from the main barrel (lib/brain_kernel.dart). Returns thebk.mcp.*in-process tool map so hosts (e.g.appplayer_core) can register it alongsidestandardToolswithout reaching intosrc/.
Backward compatibility #
- Fully additive. No existing
KernelApp,BundleActivation,standardTools, or host-abstract surface changed. Hosts that do not use extension transports see no behavior change.
0.1.1 - 2026-06-01 - Behavior definition engine bridge + MCP serving (additive) #
Added #
bk.philosophy.checkstandard tool — wrapsPhilosophyFacade.checkProhibitions, evaluating a proposedaction/outputagainst active ethos and returning{hasHardViolation, violations}. The read-side ofbk.philosophy.*(the existing put/get/activate go to the ethos store); lets a behavior step gate onhasHardViolation.BundleActivation.registerBehavior(BehaviorDefinition)— maps a bundle'sbehavior.definitions[]entry to anOpsRuntime.behaviorRegistryfactory. Called automatically inside theactivateloop whenbundle.behavioris present; result carriesresult.behaviorscount andregisteredBehaviorslist.ownsBehavior(id)predicate and teardown unregistration included. The action dispatcher surfaces a step's tool/skill output into run state — a tool's JSON result (or a skill'sMapresult) is merged so a later step'swhenguard can read its keys (e.g. gate onhasHardViolationfrombk.philosophy.check).bk.behavior.run,bk.behavior.resume, andbk.behavior.liststandard tools registered inops_tools.dart, under thebk.behavior.*namespace alongsidebk.workflow.*/bk.pipeline.*/bk.runbook.*. Execution routes through the ops facade (app.system.ops.runBehavior/resumeBehavior/listBehaviors, added in mcp_knowledge 0.2.4) — the same layer the workflow/runbook tools use — so the kernel and tools layer hold no directmcp_knowledge_opsdependency for behavior execution.bk.behavior.resumeaccepts an optionalstatePatch(e.g.{"approved": true}) merged into the run state before re-evaluation, so an approval unblocks a waiting guard.BundleActivationoptionalbehaviorStorefield (StateStore?) — injected durable store for suspend/resume across restarts; defaults to per-behaviorEphemeralStateStorewhen absent.- MCP serving (MCP Serving 1.0) —
KernelEndpoint.activateexposes the activated bundle as the well-knownbundle://manifest.jsonresource (the bundle document: manifest metadata + sections) so a remote AppPlayer-class client canresources/readit, reconstruct theMcpBundle, and run it identically to a local bundle.KernelServerHostgains aresourceUrisintrospection getter (parity withtoolDefinitions/promptDefinitions), implemented byInProcessKernelServerHostandServerBootstrap. - New regression tests included in the system test suite.
Changed (dependency floors) #
The kernel uses symbols introduced in this round's lower releases, so the constraint floors are raised to guarantee them, not merely resolve to them (the prior ^0.2.1-style floors were satisfiable by versions lacking the symbols):
mcp_bundle^0.4.0→^0.4.1—BehaviorSection/BehaviorDefinition(bundle.behavior) consumed byBundleActivation.mcp_knowledge_ops^0.2.1→^0.2.2—BehaviorEngine/BehaviorRunnable/StateStore/OpsRuntime.behaviorRegistryconstructed byBundleActivation.flowbrain_core^0.1.2→^0.1.3— its re-exportedOpsFacademust carryrunBehavior/resumeBehavior/listBehaviors(flowbrain_core 0.1.3 raises its ownmcp_knowledgefloor to^0.2.4).
Backward compatibility #
- Fully additive. No existing
BundleActivation,KernelApp, or tool API changed. Hosts that do not setbundle.behaviorsee no behavior change.
0.1.0 - 2026-05-23 - Initial release #
First public release of brain_kernel. Headless system kernel that
wraps mcp_bundle and flowbrain_core with the project / canonical /
patch / validate / build / MCP / chat / RAG pieces every host needs, and
exposes the BundleActivation standard API that hosts (AppPlayer Core,
vibe_studio, future hosts) use to manage per-bundle catalog lifecycle.
Added #
- Core layer — project, canonical store, patch pipeline, asset validator, undo/redo stack, prefs / chat-log / history-log / undo-log sidecars.
- Feature layer — BM25 index, gold-question runner, asset extractor
- reviewer queue, asset-touch observer.
- Infra layer — bundle reader / knowledge writer / mcpb packager, embedding runner, BM25 query engine + bundle registry, domain storage, FlowBrain wiring (KvStoragePort adapter, runtime probe, LLM port adapter, FlowDefinitionWorkflow), MCP server bootstrap (tool scope + transport picker + server bootstrap), agent LLM sessions, agent chat controller + system-prompt composer.
- System layer —
BundleActivation+BundleActivationRegistry: the canonical asset-registration standard. Per-bundle catalog via<bundleId>.<asset.id>prefixing; idempotent registration; one registry handles N concurrent activations. - Re-exports —
flowbrain_core,mcp_bundle,mcp_server, and a selected slice ofmcp_clientare re-exported so products can stay on the kernel as the single MCP surface (FR-CMP-002).
Dependencies #
mcp_bundle: ^0.4.0flowbrain_core: ^0.1.2mcp_llm: ^2.1.1mcp_knowledge_ops: ^0.2.1mcp_server: ^2.0.0,mcp_client: ^2.0.0