Reaktor Graph — Data-oriented Substrate and Typed Maps

Design proposal · 8 September 2026 · ecosystem update: 9 September 2026 · implementation status: proposed. Evolve Reaktor's existing heterogeneous port graph into a small, immutable semantic kernel with compact storage, typed capability tables, compiled execution plans and a familiar Kotlin authoring surface. Keep the expressive node/port model; separate its data from live behavior, resource ownership and authorization.

One graph means one identity, contract and composition model across the ecosystem. It supports many owned partitions, runtime instances, physical stores and execution engines. Every module can describe its part of the system using the same substrate. A phone does not load every server's graph, and a service call does not consult a central graph server before executing.

This document refines the unified system graph, stable foundations and formal-methods program into a graph-specific architecture. The Living Graph atlas remains the product/design contract. The living UI/UX audit remains the implementation ledger. Nothing here closes an operational workflow merely by specifying an interface.

Ecosystem integration update: Section 22 maps all 34 framework module/build directories, all 13 desktop mode values and all 74 authored subpanes onto this substrate. It specifies module contributions, runtime hooks, observation feeds, shared Workbench context, ownership and integration acceptance. This is the required adoption contract for the complete framework and desktop, including the parts that do not currently import reaktor-graph.

Wire form: GraphPatch, ChangeProtocol and the revision model below are carried across a process boundary by Reaktor Graph Protocol — the substrate defines the values, the protocol defines how a workbench, an agent or a peer runtime reads and commits them.

1. Decisions that hold the design together

DecisionConsequence
Nodes, ports and edges are data; capabilities are typed data facetsA bare entity owns no coroutine, lifecycle machine, DI scope, socket or database connection.
Runtime behavior is registered separatelyA route, screen or actor remains convenient to author; its runtime resources exist only when its host activates them.
Stable semantic IDs and schema IDs cross boundariesLabels, Kotlin class names, source paths, canvas coordinates and dense array indices are never durable identity.
Maps select and derive facts over the same skeletonAuth, navigation, telemetry, analytics and IDE tools can be composed without copying the application's structure into competing graphs.
A connection points from consumer to providerPreserve existing dependency/invocation semantics. Value delivery and traversal direction are specified separately.
Traversals are bounded strategies; visitors return findings, values or patchesNavigation setup, wiring, authorization analysis and agent work share inspectable passes. Effects execute through runtime capabilities or the control plane.
Services carry an interface plus an execution profileLocal, remote, native, streaming and durable delivery have explicit failure, ownership and completion contracts.
Async uses channels and subscriptions as ordinary graph entitiesPubsub, queues, mailboxes and durable workflows remain distinguishable and inspectable.
Kotlin authors typed IR; portable behavior has explicit semanticsExcellent native DX and a code-pushable language can coexist without promising arbitrary Kotlin hot replacement.
Definition changes and operational commands are differentAtomic local graph publication is achievable. A deployment, database migration or distributed cutover needs an execution/reconciliation protocol.
Verification and benchmarks are first-class evidenceCorrectness, portability, memory and speed claims attach to exact artifacts and targets.

The design deliberately keeps the core vocabulary small. Screens, routes, actors, topics, tests, services and database tables are module-defined node capabilities. Navigation, dependency, authorization, ownership and delivery relations are module-defined edge capabilities. The kernel does not acquire a growing enum containing every Reaktor product concept.

2. What the current system gives us

Review scope and source status

The review inventoried the entire local ReaktorWeb Markdown corpus: 101 documents, approximately 69,000 lines, including archived/private material. It also scanned 3,455 source files in the sibling workspace for graph/portgraph references and found 290 matching files across Reaktor, BestBuds, GymBuddy, Manna and shibasis.dev. These are corpus and dependency inventories, not a claim that every line, provider implementation or application path has been exhaustively verified. The architecture below uses targeted reads of the primary implementations, their consumers and the relevant foundation/module/design documents.

Source baseline for this proposal: Reaktor 57e8385642df3bc0c01552ca2e8b2beec8c5e7d6; BestBuds 727054b0fa8687c402b8ceda93f75ee975cb1571. Research was checked on 8 September 2026. Historical audit findings are treated as leads; the current source determines current behavior.

Evidence in current sourcePreserveArchitectural pressure
reaktor-graph/.../core/Graph.kt, node/Node.kt, BasicNode.ktNested graph composition and concise creation helpersEven a basic node inherits lifecycle/concurrency machinery. Graph construction also creates DI and navigation state. Definition inspection can require runtime construction.
reaktor-graph-port/.../graph/PortGraph.kt, port/Port.ktTyped keyed ports and practical lookup APIsConcurrent object maps, repeatedly flattened collections, and Type identity involving strings/KClass are unsuitable as the universal wire/storage model.
.../edge/Edge.kt, graph/connect.ktConsumer-to-provider binding and direct typed callsConstructing an edge mutates endpoints. Bulk wiring can mutate earlier connections before a later failure. Semantic changes need batch validation and atomic publication.
Both graph visitor implementationsSelectors and reusable passesDFS is recursive; BFS ignores the exit closure that DFS invokes. A visitor relying on a push/pop hierarchy stack is not valid under both. Traversal event contracts must be explicit.
RouteNode.kt, NavigationEdge.kt, ActorNode.ktTyped route payloads, navigation bindings, bounded actor mailboxes, convenient state and message APIsRuntime identity, binding objects and jobs are mixed with topology. An in-memory mailbox is not automatically a durable queue.
reaktor-service/.../Service.kt, ServiceTransport.ktExisting graph-neutral request/response service APIA transport enum containing PUBSUB/QUEUE/WORKFLOW does not implement their semantics. Operation contracts and adapter guarantees need validation.
reaktor-auth/.../AuthNode.kt, SecuredPort.ktGraph-neutral auth kernel plus optional context/policy portsConnection checks are useful but do not by themselves establish authorization for every later invocation, revocation or remote caller.
reaktor-telemetry/.../GraphTelemetry.ktLifecycle, navigation and port instrumentation seamsRuntime observation needs stable definition/activation links and incremental attachment; telemetry volume must not become graph definition churn.
reaktor-ffi/.../Invokable.kt, switch/Switch.ktExisting byte-oriented cross-language seamRaw buffer/handle results need explicit schema, lifetime, cancellation, failure and ownership contracts.
reaktor-flow/.../document/GraphDocument.ktExisting serializable editor document and additive wire compatibilityDocument kind, node metadata, scope paths and optional edge ports are an editor contract, not the new canonical semantic IR. Keep a versioned adapter.
reaktor-compiler/.../ReaktorProcessor.ktCompiler tooling seamprocess() currently returns immediately. It is not an existing portable graph compiler. Other processors must be evaluated independently.

BestBuds already proves why the current graph is worth evolving. BestBuds.kt composes nested feature graphs, repositories/interactors, routes, bindings and actors. ChatActor.kt consumes session, operations, timeline, analytics, socket and typing contracts while exposing useful ordinary Kotlin methods. MessagingService.kt defines concrete typed HTTP operations such as message reads, sends, reactions and read cursors. PubSubHello.kt separately declares topics and subscriptions. NotificationDispatchGateway.kt addresses named Durable Objects. FeatureFlags.kt hydrates configuration before graph initialization. These are related semantics currently spread across source and runtimes; the redesign must connect them without forcing all their internals into visual nodes.

GymBuddy's TodayGraph and CalendarGraph demonstrate a second requirement: repeated instances of similar interactors with different ownership and route contexts. Manna's minimal Graph plus Compose entry point establishes a small-app adoption case. The import census also found shibasis.dev; its full application behavior was not qualified in this review.

Reconcile the existing documents

Existing design familyBinding input to this proposal
Framework overview, essays, kernel analysis, refinement, visitorsSmall composable vocabulary, ordinary code inside durable primitives, typed composition outside. This proposal clarifies purity and traversal semantics where earlier sketches conflate data and behavior.
Stable foundations, verified foundations, formal methodsImmutable IR, transactional patches, explicit effects, bounded claims and evidence. Existing audits remain traceable; their proposed APIs are not automatically shipped contracts.
Unified graph, graph sources, hierarchical UI, atlasOwned runtime islands, source authority, one context, semantic zoom, exact port selection and truthful coverage.
Core, capability, lifecycle, actors, distributed actorsSeparate data capability, executable behavior, authority and host/resource lifetime. Preserve graph-neutral library APIs.
Service, bus mesh, work, FFI, FlexBuffersTyped contracts, transport-specific guarantees, durable work and versioned encoding. A shared envelope must not erase provider differences.
Auth, multitenancy, data, server, telemetry/analyticsTenant-aware authority and data ownership; physical stores and telemetry remain authoritative for their domain.
Agentic tooling, Conductor, UI/UX auditHumans and agents use the same query/proposal/plan/execute/receipt path. A workbench feature is accepted through a real developer journey.

These are design inputs, not proposed dependency purchases or claims of feature parity.

System / primary referenceUseful ideaReaktor decision
Unreal Blueprint pins, functions, debuggerTyped data pins, explicit execution flow, reusable code primitives, breakpoints and pin-value watchesDistinguish contract bindings, value flow and control flow. Preserve source maps and execution identity so a displayed value names the run that produced it.
Unreal MassEntityData-only fragments/entities, batch processors, chunk storage and deferred composition changesUse compact data and batched passes; do not make every capability combination a mandatory archetype. Reaktor's sparse heterogeneous relations need their own measured layout.
n8n queue modeTrigger reception, execution IDs, workers and persistent execution results are separate concernsExpose trigger, placement, queue, execution and result as connected entities. A visual workflow is incomplete without a real runner and inspectable failures.
Temporal execution/replayWorkflow definitions differ from executions; replay checks emitted commands against recorded historyDurable work requires deterministic decisions, recorded effect outcomes, pinned program versions and explicit migration. A suspend function alone does not supply durability.
Google Maps Data layer, Pixxel bandsCommon spatial reference, selectable measurements, feature-based styling and derived visualizationsUse a common semantic reference system with typed overlays. Preserve the difference between measured data, a derived result and a color/style.
Kotlin builders, KSPReceiver-based builders and generated declarations improve DXBuilders emit typed IR. @DslMarker controls receiver scope, not purity. KSP is not a general body-expression compiler.
WebAssembly WITInterface contracts, typed values and explicit resource ownership across languagesGenerate compatible service/FFI facades from schema. Evaluate Wasm as one execution target; it does not replace Reaktor's graph or prove Kotlin/Native portability.
Alloy specification, TLA+Relational constraints and state-machine reasoning solve different classes of problemsUse a verification portfolio with precise scopes and assumptions, tied back to executable kernel laws.

The hyperspectral analogy is especially useful when taken literally enough: an auth band answers a different question from a latency band, and each has its own units, coverage, resolution and freshness. Combining them should compute a declared result, such as “reachable operations denied for this principal and observed above this latency threshold.” It should not merely stack decorative colors. The analogy does not imply that software has one natural two-dimensional geographic embedding; layout is a projection.

4. HLD: one semantic model, several execution planes

Proposed Reaktor architecture: typed authoring and adapters feed canonical graph data; queries produce maps and evidence; owned runtimes execute compiled plans through explicit boundaries.

The pipeline is:

  1. Author or extract. Kotlin DSL, supported visual edits, manifests and provider adapters produce typed definitions or provenance-bearing observations. A legacy runtime adapter can expose existing graphs during migration.
  2. Normalize and validate. Resolve stable IDs, schemas, capability requirements, ownership, port contracts and source authority. Produce a deterministic canonical representation and a revision digest.
  3. Publish locally. The semantic store atomically publishes immutable revisions of an owned partition. Snapshot readers retain a stable view. Runtime plans are derived artifacts keyed by revision and target profile.
  4. Query and compose maps. Indexed query plans select entities, join observations and produce typed derived claims with coverage and lineage. Workbench, IDEs, MCP and tests use this same service.
  5. Activate and execute. Runtime islands bind installed implementations, allocate resources required by capabilities and execute validated plans. Effects are authorized at their boundaries.
  6. Observe and reconcile. Execution events, traces, measurements, test results and command receipts join back through semantic IDs and activation references. Observations do not silently rewrite desired definitions.

Module placement

LayerResponsibilityForbidden dependency
Proposed pure reaktor-kernelIDs, schemas, graph records, patch algebra, invariant contracts, deterministic normalizationCompose, DI, databases, clocks, networking, default jobs
Evolved reaktor-graph-portTyped graph facade, contract compatibility, indexed traversal APIs and legacy adaptersApp shell or provider-specific operational logic
Evolved reaktor-graph runtimeActivation, installed behavior, routing/actor integration and execution plansWorkbench layout or app-owned policy
Compiler/toolingDSL lowering, schema/stub generation, source maps, validation and evidenceProduction runtime required merely to inspect source
Auth/DB/service/bus/work/telemetry modulesGraph-neutral domain kernels and optional graph installation/projectionMandatory graph adoption for plain library callers
reaktor-flowReaktor scene adaptation, measurement, layout, maps and editor adaptersProduct shell chrome
compose-flowGeneric canvas, camera, rendering, generic edges and hit testingReaktor semantics
BestBuds engine / desktop / MCPProduct workflows, adapters, tools, inspector, context and orchestrationDuplicated graph semantics or authority rules

These are target responsibilities, not an instruction to create all these packages at once. The first migration can place the pure kernel behind existing APIs and extract a module once dependency tests demonstrate the boundary.

The complete module and desktop integration matrix expands this HLD: every subsystem contributes definitions, operations, observations, maps, runtime hooks or presentation adapters through an explicit contract. Graph-neutral APIs remain usable independently, while Reaktor hosts install the shared projection and execution bindings.

5. Semantic model

Graph, node, port and edge

At a revision, a graph contains finite sets of nodes N, ports P and edges E, a port-owner function owner: P → N, typed capability relations, and a schema catalog. Every edge names exact source and destination ports. A node can have zero ports and zero capabilities. A graph partition has a stable identity and a declared owner/authority; publication produces a new revision.

A basic node is an identity plus data. A basic port is an identity, owner, consumer/provider role, contract reference and cardinality declaration. A basic edge is an identity, two endpoint references and a relation/interface reference. Constructors do not connect, invoke, emit events or allocate runtime resources.

A port contract and an edge contract answer different questions. A port contract defines the interface a node requires or offers: operations, typed values or a structural relation. An edge contract defines a legal relationship between endpoints, including allowed endpoint shapes, direction, multiplicity and composition rules. An invocation edge additionally records the negotiated service contract and binding profile. Matching string names is never sufficient.

Default callable binding is consumer → provider, preserving current Reaktor semantics. A consumer requiring Messaging.send binds to a provider offering that operation. A response returns in the other direction. For a stream, values can also flow provider → consumer. For navigation, the originating route's consumer references the destination's navigation provider. UI arrows must distinguish “requires/invokes,” “delivers values,” and “next control step.”

Edges for structural relations also attach to ports. Modules can generate compact implicit ports such as Ownership.child and Ownership.parent; these implement relation contracts and are not callable services. The normal inspector hides these ports until structural detail is requested. A relation with unusual role rules must declare them in its schema; it cannot bypass endpoint validation.

Multiple edges between the same nodes are valid. A consumer's cardinality may be one, optional, many or a module-defined constrained multiplicity. A single consumer with two candidates is an ambiguity error unless an explicit resolver/aggregate capability defines selection. Requiredness can depend on an activation profile, but the condition must be a typed predicate rather than an arbitrary callback evaluated secretly during wiring.

Capabilities

A capability is a versioned typed data facet on a node, port or edge. Examples include Screen, Container, Route, Actor, Weighted, AuthRequirement, DeliveryPolicy, StateSchema, SourceLocation, TelemetryLink and TestDefinition. Empty marker capabilities can be stored as membership bitsets.

A module registers the facet's schema, valid entity kinds, dependencies/exclusions, invariants, available operations, inspector metadata and optional compiler/runtime handlers. Capability values describe behavior requirements; the implementation registry supplies executable code. Installed handlers are identified by schema/ABI and artifact digest, never serialized as lambdas inside graph data.

Four concepts stay distinct:

ConceptQuestion
Data capabilityWhat does this entity describe or support?
Runtime implementationWhich installed code fulfills the declared behavior?
AuthorityWho may read or act on which resources under which conditions?
EffectWhat external state or sensitive information can this operation touch?

Unknown capabilities can round-trip losslessly and render generically if their encoding is understood. A runtime cannot activate an unknown required behavior or effect. An optional presentation facet may be ignored. This is an explicit compatibility classification, not ignoreUnknownKeys applied indiscriminately to executable contracts.

Fractal composition

A graph can be packaged as a component and instantiated within another graph through boundary ports. Containment is an acyclic ownership relation; dependency, navigation and message relations may contain cycles. Internal entities retain identity under visual expansion/collapse. An exported boundary port forwards to an internal endpoint through an explicit binding, preserving source and runtime provenance.

A definition is reusable. Two feature instances do not share runtime state merely because they use the same definition. Instance identity, ownership and configuration distinguish GymBuddy's current workout from its calendar workout, and one user's chat actor from another's. Detaching a visual scope never destroys those runtime instances; an explicit lifecycle operation does.

Identity, revision and time

IdentityMeaning
Graph/partition IDStable namespace and ownership boundary
Entity IDStable semantic identity of a node, port or edge within that namespace
Definition revisionContent-addressed normalized definition, schema lock and program/artifact references
Instance IDA particular realization of a reusable definition in an owned runtime
Activation epochFencing generation for a runtime activation/cutover
Operation/run/event IDOne command, workflow run, test run, invocation or observation
Local handleDense slot plus generation, valid only under the relevant store/lease

Use explicit or generated persisted IDs for authored entities. Source rename/move preserves identity through compiler metadata and migration aliases. Paths are locators. Instance identity is not definition identity. Dense slots never escape over FFI, persistence, deep links or federation.

Revision hashing needs a specified canonical order, stable schema IDs, canonical scalar encoding, explicit defaults and deterministic unknown-field retention. Signatures bind the resulting artifact digest plus target/profile constraints. Floating-point edge cases, map ordering and Unicode normalization require conformance vectors; “hash the JSON” is not a protocol specification.

6. Data-oriented storage with a pleasant API

The public model is typed records and views. The hot representation is not a heap containing one polymorphic object with several maps per entity.

DataProposed representationWhy
Entity identity/kind and port ownershipDense primitive columns plus stable-ID-to-slot indexFast scans and compact references; stable external identity remains available.
Edge endpoints and relation kindsParallel endpoint/relation columnsBatch filtering and adjacency construction without following object pointers.
AdjacencyCompact base ranges plus indexed versioned deltas; periodic compactionEfficient reads without rebuilding a whole CSR-like structure on each edit.
Capability membershipBitsets or sparse sets per facetEfficient intersections; avoid an archetype for every overlay combination.
Capability payloadsTyped columns for hot facets; schema-coded blocks for cold/variable dataKeep runtime queries cache-friendly without making heterogeneous data inexpressible.
Labels, source locations and schemasInterned tables and cold blocksKeep strings and reflection out of repeated traversal.
Mutable runtime stateActivation-owned state stores and resource handlesNo jobs, closures or sockets in immutable definition storage.
Telemetry, payloads and test artifactsExternal event/time-series/blob stores with graph referencesObservation volume does not multiply the resident definition graph.

Use chunked copy-on-write publication or an equivalent immutable segment scheme. Readers pin snapshots; writers validate a patch against its base and atomically publish a new root. Platform-specific reclamation must prove that a retired segment is not reclaimed while readers or FFI borrows still use it. Do not assume a JVM technique automatically works on Kotlin/Native, JS or Wasm.

For small graphs, a flat compact implementation may be cheaper than elaborate indexing. Build indexes lazily or when declared workloads justify them. Specialized dense capability tables are an optimization behind one logical API, not a second semantic model. Use generics/reified helpers and generated typed facades for DX; use primitive cursors or batches for hot loops to avoid per-element wrappers and boxing.

Published collections must be truly immutable by ownership or persistent storage. Kotlin's read-only List/Map interfaces alone do not prevent the caller from retaining a mutable backing collection. The reference Kotlin types later in this document describe values, not permission to retain mutable input arrays.

Incrementality and scheduling

Each map, validator and compiled plan records its schema/entity/relation dependencies. A patch invalidates the affected dependency closure. Unknown dependencies trigger a conservative wider revalidation. Worker threads compile layouts, indexes and plans; publication uses revision checks so a stale background result cannot replace a newer one.

The local runtime compiles bindings into direct dispatch tables. Calling a hot provider should not scan the graph, allocate a traversal or serialize a payload merely because a remote implementation is also possible. Required authorization/effect checks remain at the generated dispatch boundary and may use safely scoped caches. Revocation and policy changes invalidate those caches.

High-volume telemetry uses sampling/aggregation and bounded queues. Structural deltas, policy changes and observations have separate revision streams. No actor state update or trace span should force full graph re-layout.

Performance acceptance, not invented speedups

The following are initial engineering budgets to validate, not measured results or unconditional promises. Record hardware, OS, target, build mode, graph distribution, schema/capability density, warm/cold status and profiler artifacts in reaktor-performance.

WorkloadFirst qualification target
Current BestBuds/GymBuddy graphsNo material startup or interaction regression against the current baseline; compare p50/p95, allocations and retained memory.
10k nodes, 50k ports, 100k edges, mixed capabilitiesWarm indexed one-hop query p95 below 5 ms; a bounded local map update below 50 ms, excluding provider/network latency.
1k changed entities in that graphIncremental normalization/validation/publication p95 below 50 ms, with full validation correctness cross-checks.
Large offline inventory: 1m nodes / 5m edgesBounded paged inspection within a declared memory budget; initial target below 1 GiB for base topology/indexes, excluding retained payloads and historical snapshots. Measure actual capability density separately.
Main MacBook and Dell U4025QW, normal/wide/ultrawide and portrait canvasVisible interaction meets a 16.7 ms frame budget at 60 Hz; qualify higher-refresh targets separately. Expanded scene work must be culled and asynchronous.
Hot local typed service callNo graph traversal or payload codec on the steady-state direct path; compare checked dispatch overhead and allocation count with today's typed port call.
Repeated snapshot/expand/close and remote detach cyclesBounded retained memory after reclamation; no growing listener/job/handle count.

Use chain, star, balanced tree, high-degree hub, dense SCC, sparse overlays and churn-heavy graphs. A benchmark containing only a tidy tree cannot qualify the graph. Compare the simple reference model with the optimized store and preserve identical results. Performance and DX are both release gates; neither compensates for failure of the other.

7. Maps: a common skeleton with typed overlays

A map is a versioned selection/derivation over a graph context. It includes selected nodes, ports and edges, chosen capability views, derived claims, coverage and provenance. The complete graph is the identity map over the declared scope and schema catalog. “Complete” never silently means every remote entity is loaded or every principal can see everything.

There are three related artifacts:

  1. Map definition: a typed query plan and declared dependencies. For example, select route-capable nodes, navigation edges and authorization requirements.
  2. Map result: a snapshot-scoped subgraph plus typed derived facts and a coverage/frontier report.
  3. Presentation profile: styling, layout, visible labels, thresholds and semantic zoom rules for that result.

A fourth use, an executable policy/selection artifact, is deliberately explicit: a compiled route table, rollout selection or authorization policy may be derived from a map, but changing the displayed overlay does not activate it. Activation follows the modification protocol.

Map algebra

Provide typed select, projectCapabilities, union, intersect, difference, joinFacts, derive, reachable, group and aggregate. Set operators preserve entity identity; they do not clone nodes. A map's edge set is endpoint-closed: include its endpoint ports/owners or include explicit boundary references explaining why details are unavailable.

Derived relations carry a producer ID, producer version, input revision/fact-cut digest and witness references. Their stable identity derives from the producer and semantic input keys, not from canvas positions. They cannot masquerade as declared canonical edges. A derived entity can be inspected through the same APIs, but mutation redirects to its authoritative source or is rejected with a reason.

Set union can be commutative; transformations, policy composition and rollout precedence often are not. Publish the algebra for each operator. Conflicting facts remain a conflict or resolve through an explicit policy with retained alternatives. Never make overlay order silently override authorization or executable configuration.

Cache keys include the definition revision vector, schemas, map version, environment, tenant/principal/visibility policy, query parameters, time/fact cut and relevant run/activation. A cached result for one principal must not leak into another's view.

Useful maps, with actual questions

MapExample questionRequired input / result
NavigationWhich screens can this role reach from this deep link under these flags?Route contracts, roots, conditions, policy context; witnessed routes and unresolved conditions.
AuthWhy was this operation denied, and which grants could permit it?Principal/session/token metadata, policies, resource/tenant context and recorded decisions; explanations tied to policy revision.
RuntimeWhich implementation is serving this logical provider now?Definition-to-instance bindings, placement, deployment digest and fresh activation observations.
TelemetryWhere did this request spend time across phone, Worker, server and DB?Correlated spans/events and boundary links; sampled/missing segments visible.
AnalyticsWhich eligible user journeys stop after opening chat?Versioned event taxonomy, cohort/consent context and aggregates; observation gaps remain distinct from unreachable routes.
DataWhich tables/collections/graph labels does this operation read or mutate?Declared effects, schema adapters and observed query evidence, with engine-specific details.
IDEWhat source change affects this route, contract or native export?Symbol/source maps, generated artifact provenance, dependency edges and build target.
DeliveryWhich activations use this revision and which are waiting for cutover?Release plan, artifact digest, target profiles, epochs and receipts.
Test / assuranceWhat proves this patch, and what has not been tested?Test definitions, affected closure, run artifacts, budgets, assumptions and stale evidence.

Flow selection differs from map selection

A map selects a subgraph. A flow selection identifies a declared program path, a candidate route, or an observed causal execution through that subgraph. It can include repeated visits, branches, fan-out/fan-in and concurrent partial order. Store its ordered/causal steps and exact port/edge references. A highlighted simple path is not enough to represent a distributed workflow.

Selection carries graph revision, map, entity/port, source, activation/run and time context across IDE, database, auth, devices and MCP. Overlay switching preserves that semantic selection even if the entity becomes hidden; show why and offer reveal. It does not silently choose a different node.

8. Traversals and visitors

A traversal is a strategy over a pinned map result from explicit starting references. Its request declares relation types, direction, deterministic ordering, cycle policy, maximum visits/edges/depth, deadline/cancellation, remote boundary policy and result budget. DFS uses an explicit stack. BFS uses a queue. Topological traversal rejects cycles or returns SCCs; weighted algorithms validate weight assumptions. These are different contracts rather than one callback with surprising behavior.

The basic visitor is a pure fold over discovery events: it receives a view and accumulator and returns the next accumulator plus Continue, Prune or Stop. Its result can contain diagnostics, route-table entries, test selections or typed patch proposals. A separate structured DFS event stream supplies enter/leave guarantees for scope-sensitive passes. BFS never pretends to supply a nesting stack. Pruning, duplicate visits and cancellation behavior are specified and tested for each strategy.

Results include visited counts, termination reason, unresolved frontier, coverage, and witness paths when requested. “No denied path found in this bounded result” is not “all users are authorized.” A remote boundary may be opaque, use a pinned cached export, or be expanded by an authorized async query before a new local pass. Pure traversal itself does not secretly call the network.

Visitors still do useful tasks:

TaskVisitor outputEffectful consumer
Navigation setupValidated route/binding tableRuntime installs table for an activation.
WiringDeterministic binding proposal with ambiguity diagnosticsKernel validates and publishes atomic patch.
Auth analysisPolicy obligations, decisions under explicit inputs and witnessesRuntime enforces at invocation; tools display explanations.
Agent refactoringFindings, typed patch and affected-test selectionShared change planner executes authorized plan.
Telemetry installationInstrumentation plan and required event hooksRuntime attaches bounded observers.
Dead-screen finderReachability classification and evidenceWorkbench opens source/tests or offers a proposed removal.

Kotlin interfaces alone cannot enforce purity: a trusted Kotlin plugin can still read a global or perform I/O. Untrusted/portable visitors must execute in the restricted program runtime with only declared read imports and budgets. Trusted native passes require review, dependency constraints and conformance tests; their assurance label reflects that distinction.

Dead-screen analysis must be honest

Roots include normal launch, deep links, notification actions, platform entry points, role/tenant variants, experiments and dynamic configuration. Classify screens as reachable with a witness, unreachable within a stated closed model, unobserved in a time/cohort window, or unknown because inputs/edges are missing. Conditional reachability may require a solver or bounded scenario enumeration. Lack of telemetry is never sufficient proof of dead code.

9. Services and FFI

A service is an interface-bearing capability whose operations can cross a machine, process or language boundary. Keep existing graph-neutral Service callers working. Generated Kotlin, C++ and TypeScript bindings share stable operation IDs, request/response/error schemas, version negotiation and source maps.

Each bound operation declares:

  • Interaction shape: unary call, stream, publish/accept, subscription or durable job handle.
  • Effects, principal propagation, resource/tenant scope and authority requirements.
  • Locality and placement: direct, thread/process, native ABI or remote transport.
  • Completion: returned value, accepted message, committed mutation or completed workflow.
  • Deadline, cancellation propagation, retry eligibility and idempotency scope.
  • Buffer/resource ownership, maximum sizes and serialization/ABI profile.

Local and remote calls can have the same typed interface while exposing different failure capabilities. A timeout after sending a mutation may have unknown outcome; it must not be converted to “nothing happened.” Retry only under an operation contract that makes it valid. Cancellation acknowledgement is distinct from requesting cancellation, and neither necessarily reverses committed effects.

FFI invocation uses validated envelopes containing operation/contract IDs, request/run context, buffer bounds and ownership mode. Generated direct fast paths can elide serialization when safe. A borrowed buffer has a lease; a returned owned handle has explicit release and generation checks. Async calls retain needed buffers until completion/cancel acknowledgement and specify callback thread/dispatcher and reentrancy. A raw Long is not a portable lifetime protocol. WIT's separation of contracts, values and owned/borrowed resources is a useful reference, not a requirement to rewrite the existing codec. WIT reference.

Interface compatibility checks include operation availability, required/optional fields, wire representation, nullability, error variants, size limits, streaming semantics and effects. An additive field with a default may be compatible; removing an operation or adding a newly required effect is not automatically compatible. Kotlin generic type safety at one call site does not establish cross-version or cross-language compatibility.

10. Async: channels, subscriptions and durable work

Adopt channels as the organizing concept. A channel is a node with publish/consume/inspect capabilities and a message schema. A topic is a channel with fan-out subscriptions. A queue is a channel with a competing-consumer delivery policy. A subscription is an ordinary node with its own filter, delivery policy, progress and destination. An actor mailbox can expose the same protocol family with an explicitly in-memory, activation-scoped profile.

No new kernel entity kind is required. The async module introduces vocabulary and execution contracts. This is seamless composition at the type level while keeping delivery behavior inspectable.

Async topology: producer publishes to a channel; subscriptions select fan-out destinations; a competing-consumer subscription uses a worker group; receipts distinguish acceptance from processing.

Canonical bindings still point consumer → provider. A producer requires a channel's publish service. A delivery adapter requires a handler's consume service. A subscription links its source channel through a structural/source contract. The delivery map renders message movement producer → channel → subscription → handler and identifies that as value flow, not the raw orientation of every binding edge.

Delivery policy must be data

DimensionRequired semantics
DurabilityVolatile, persisted before acceptance, or transactionally enqueued with a named store boundary.
RoutingFan-out per subscription, competing consumers per group, partition/key affinity and explicit filters.
OrderingNone, per key, per partition or a provider-qualified stronger order; retries/replays state their effect on order.
AcknowledgementAccepted, delivered, handler-completed or transaction-committed; broker ack point is explicit.
RetryEligible errors, delay/backoff/jitter, maximum attempts/age, and retry authority.
DeduplicationKey, scope, storage, retention and the transaction covering the business effect.
BackpressureMessage/byte capacity, in-flight limit, producer wait/reject/drop policy and fairness.
FailureDead-letter target, poison-message reason, redrive policy, cancellation and expired leases.
VisibilityLag, attempts, handler duration, last progress, oldest age and coverage/freshness of observations.

Provider adapters publish a guarantee profile. Validation rejects an unsupported requested policy rather than silently weakening it. For example, Cloudflare Queues documents at-least-once delivery; consumers must handle possible duplicates. A Reaktor wrapper cannot upgrade that to general end-to-end exactly-once processing by renaming an enum. Cloudflare delivery guarantees.

For a database mutation that emits an event, use a transactional outbox where the provider supports that boundary: commit the business row and outbox record together; publish later; deduplicate at the consuming effect boundary. The publisher can crash after sending but before marking the record sent, so replay can publish twice. A broker-specific exactly-once acknowledgement feature does not make arbitrary downstream effects exactly once.

A durable workflow is a stateful program capability with an input schema, pinned program revision, durable history/checkpoint policy, timers, child runs, effect IDs and compensation rules. Deterministic decision logic is separated from external activities. Replaying history reuses recorded results; it must not repeat a payment, notification or database mutation merely because code was re-executed. Workflow upgrades pin old runs, use explicit version branches or apply a tested state/history migration. Temporal replay model.

11. Distributed stitching and runtime ownership

Federation joins exports from owned partitions using stable endpoint and contract IDs. A runtime export identifies its source revision, instance/epoch, schema catalog, offered endpoints, placement and observation cursor. Authentication of the exporter and authorization of the reader are separate from matching an ID.

The global query result contains a revision vector and coverage, not an invented single instantaneous snapshot. Each owner can provide a consistent local cut. A causally consistent cross-owner cut requires an explicit supported protocol; otherwise the result is a declared combination of observations from different times. Partial, stale, unavailable and inaccessible boundaries remain visible without leaking unauthorized details or counts.

Definition state has an authoritative writer or explicit multi-writer protocol per partition. Initial implementation should use optimistic concurrency against a base revision, not silently merge every edit with a CRDT. Concurrent nonoverlapping edits may be merged only after normalization and invariant checks. Concurrent edits to ownership, required bindings, schemas or policy often require a conflict decision.

Runtime placement is a map over instances: Android/iOS processes, browser tabs, desktop JVMs, Workers, Durable Objects, servers, Kubernetes workloads and native modules. Logical service identity survives a pod replacement; activation epoch and artifact digest expose that replacement. Device-offline state does not delete the corresponding definition. Expired discovery records do not prove a service was intentionally removed.

Distributed invocation carries causal/run context through service, queue and FFI boundaries, with appropriate attenuation of authority. Trace context is correlation metadata, never a credential. Telemetry links reference recorded causality; they cannot infer that two events with similar timestamps are definitely the same operation.

For BestBuds, D1, Postgres, ClickHouse, Memgraph, SQLite, Durable Object storage and object stores remain physical systems of record. The semantic graph catalogs schemas, ownership, operations, deployments and selected records through adapters. It is not automatically a replacement storage engine for all product data, nor should millions of messages become eagerly resident workbench nodes. Query result graphs are bounded maps with their own result identity and provenance.

12. Kotlin authoring, portable logic and Turing completeness

Two stages in one language experience

Stage A — authoring. An ordinary Kotlin builder produces graph/program IR. It may use functions, loops and reusable components to generate definitions. Its output is normalized, schema-checked and reproducible under declared inputs. The builder's Kotlin execution happens during build/authoring; its arbitrary closures are not the artifact sent to clients.

Stage B — portable execution. A typed logic DSL constructs explicit expressions, branches, state transitions, loops and calls to declared effects. A compiler plugin can later lower a supported Kotlin subset into the same program IR. Unsupported constructs fail with source diagnostics; they never fall back silently to unrestricted runtime evaluation. KSP can generate declarations and registries, but does not supply arbitrary expression/body analysis. Kotlin builders, KSP scope.

The compact program representation may use typed registers/blocks rather than reifying every arithmetic operation as a globally indexed entity. The graph contains the program definition and imports; an on-demand code map expands its internal IR using stable instruction/source references. Native Kotlin/C++ algorithms remain ordinary code behind declared contracts. Blueprint authoring composes these primitives and can edit supported portable logic with source round trips.

What Turing completeness does and does not mean

A static port graph is a data structure. Cycles alone do not make it a universal programming language. Turing completeness belongs to an execution semantics capable of expressing general computation, with unbounded resources in the mathematical model. The target portable language can include conditional branching, general loops/recursion and suitable memory; a machine-simulation/conformance example should establish the claim instead of using the phrase as marketing.

General computation means there is no algorithm that decides termination for every possible program. Purity does not imply termination. Therefore Reaktor cannot promise arbitrary Turing-complete logic, automatic proof of every behavior and guaranteed unbounded execution all at once. It can offer a total/bounded subset for policies and queries, a general portable subset with explicit resource limits, and trusted native implementations with declared assurance. The underlying computability limit is grounded in Turing's original paper.

Practical execution uses fuel/instruction budgets, memory limits, deadlines, cancellation, bounded output and effect quotas. Exhaustion is a typed result, not a hung UI or implicit success. For durable work, a budgeted slice checkpoints or yields according to its profile. Determinism requires explicit inputs for time, randomness, environment and effect outcomes. Numeric overflow, floating-point behavior, map iteration, exceptions and concurrency ordering must be specified across targets.

Code push classification

Proposed changeEligible mechanismRequired evidence
Presentation map or saved viewVersioned user/workspace dataSchema compatibility and rendering tests; does not change executable policy.
Dynamic config or flow/overlay selection affecting behaviorSigned configuration revision with typed conditionsTarget compatibility, policy checks, scenario tests, rollout/cutover receipt.
Rewiring installed compatible providersSemantic graph patch plus compiled plan activationContract/effect/lifecycle validation, impacted tests, state/resource transition plan.
Portable program change within installed importsSigned program artifactIR validation, supported target profile, budgets, effect authority, migration and replay evidence.
New native implementation, ABI or unavailable importBuild and distribute a new host artifactPlatform build, conformance and deployment qualification.
Persistent state/schema changeExplicit migration planCompatibility window, backup/recovery where applicable, data checks and reconciliation.

An artifact is code-pushable only relative to a target's installed runtime, allowed imports, policy and distribution constraints. Kotlin purity or a data encoding is not a universal mobile distribution exemption. Apple's current guideline 2.5.2 restricts downloaded code that changes app functionality, with specified exceptions; target release profiles need review against the applicable distribution rules. Apple App Review Guidelines. Default to the ordinary release path where eligibility has not been established.

Runtime replacement protocol

Prepare and verify artifact → stage under new epoch → check state compatibility → drain/fence or migrate affected instances → publish activation binding → observe/reconcile → retain receipt. Definition publication can succeed while activation fails; report both. An old writer fenced by a new epoch cannot continue mutating the new state. A rollback may need a reverse migration or compensation; switching a pointer back is insufficient after irreversible external effects.

13. Important Kotlin interfaces

These are proposed, compilable contract declarations, not shipped APIs. The complete Kotlin specimen is kept outside runtime source sets. The declarations express the main boundaries; codecs, constructors with validation, wire formats, platform storage and runtime implementations remain implementation work. Published values require immutable backing storage. All external input is validated against the schema catalog.

Identity, pure graph data and authoring

The builder is an authoring interface. Its output is data; registering a provider here declares a contract, not a live implementation. Generated module helpers return named port bundles so ordinary product code rarely handles schema digests directly.

data class GraphId(val value: String)
data class EntityId(val graph: GraphId, val value: String)
data class Digest(val value: String)
data class SchemaRef(val id: String, val version: Int, val digest: Digest)
data class BlobRef(val schema: SchemaRef, val digest: Digest, val byteLength: Long)
data class Revision(val graph: GraphId, val digest: Digest)
data class RevisionSet(val entries: List<Revision>, val digest: Digest)
data class SnapshotRef(val definitions: RevisionSet, val factCut: Digest)
data class ActivationRef(
    val instance: String,
    val epoch: Long,
    val definitions: RevisionSet,
)
data class LocalHandle(val slot: Int, val generation: Int)

enum class EntityKind { Node, Port, Edge }
enum class PortRole { Consumer, Provider }
data class Cardinality(val minimum: Int, val maximum: Int?)
data class ContractRef(val schema: SchemaRef)
data class CapabilityKey<T : Any>(val schema: SchemaRef)
data class CapabilityValue(val entity: EntityId, val value: BlobRef)

data class NodeRecord(val id: EntityId)
data class PortRecord(
    val id: EntityId,
    val owner: EntityId,
    val role: PortRole,
    val contract: ContractRef,
    val cardinality: Cardinality,
)
data class EdgeRecord(
    val id: EntityId,
    val from: EntityId,
    val to: EntityId,
    val relation: SchemaRef,
    val bindingContract: ContractRef?,
)
data class GraphDefinition(
    val revision: Revision,
    val nodes: List<NodeRecord>,
    val ports: List<PortRecord>,
    val edges: List<EdgeRecord>,
    val capabilities: List<CapabilityValue>,
)

interface Graph {
    val snapshot: SnapshotRef
    fun node(id: EntityId): NodeRecord?
    fun port(id: EntityId): PortRecord?
    fun edge(id: EntityId): EdgeRecord?
    fun <T : Any> capability(id: EntityId, key: CapabilityKey<T>): T?
}

interface SnapshotLease : AutoCloseable {
    val graph: Graph
    override fun close()
}

interface GraphStore {
    fun acquire(revisions: RevisionSet): SnapshotLease
    fun validate(patch: GraphPatch): ValidationReport
    fun commit(patch: GraphPatch): CommitResult
}

data class Contract<C : Any>(val ref: ContractRef)
data class Consumer<C : Any>(val id: EntityId, val contract: Contract<C>)
data class Provider<C : Any>(val id: EntityId, val contract: Contract<C>)
data class NodeRef<P>(val id: EntityId, val ports: P)

@DslMarker
annotation class GraphDsl

@GraphDsl
interface NodeBuilder {
    val id: EntityId
    fun <T : Any> capability(key: CapabilityKey<T>, value: T)
    fun <C : Any> consumes(key: String, contract: Contract<C>): Consumer<C>
    fun <C : Any> provides(key: String, contract: Contract<C>): Provider<C>
}

@GraphDsl
interface GraphBuilder {
    fun <P> node(key: String, configure: NodeBuilder.() -> P): NodeRef<P>
    fun <C : Any> connect(
        key: String,
        consumer: Consumer<C>,
        provider: Provider<C>,
        relation: SchemaRef,
    ): EntityId
    fun build(): GraphDefinition
}

Maps, traversal and visitors

This is the minimal query algebra and discovery-visitor contract. Typed joins, predicates, weighted algorithms, structured DFS events, pagination and remote export sessions extend these contracts through versioned modules. They must preserve the coverage and budget laws described above.

sealed interface Selection {
    data object All : Selection
    data class Ids(val ids: List<EntityId>) : Selection
    data class HasCapability(val schema: SchemaRef) : Selection
    data class Union(val inputs: List<Selection>) : Selection
    data class Intersection(val inputs: List<Selection>) : Selection
    data class Difference(val left: Selection, val right: Selection) : Selection
}

data class ReadContext(
    val workspace: String,
    val environment: String,
    val principalRef: String,
    val tenantRef: String?,
    val visibilityPolicy: Digest,
    val snapshot: SnapshotRef,
)

data class MapDefinition(
    val id: EntityId,
    val version: Digest,
    val selection: Selection,
    val projectedCapabilities: List<SchemaRef>,
    val derivations: List<ProgramRef>,
)

enum class BoundaryReason { Unloaded, Inaccessible, Unavailable, Unknown }
data class Frontier(val ref: EntityId?, val reason: BoundaryReason)
data class Coverage(
    val completeWithinDeclaredScope: Boolean,
    val frontier: List<Frontier>,
    val staleEvidence: List<Digest>,
)

data class MapResult(
    val definition: MapDefinition,
    val context: ReadContext,
    val graph: Graph,
    val coverage: Coverage,
    val lineage: List<Digest>,
)

interface MapEngine {
    suspend fun evaluate(definition: MapDefinition, context: ReadContext): MapResult
}

enum class Direction { Outgoing, Incoming, Both }
enum class TraversalOrder { BreadthFirst, DepthFirst, Topological, StrongComponents }
data class TraversalBudget(val maxEntities: Int, val maxEdges: Int, val maxDepth: Int)
data class TraversalSpec(
    val starts: List<EntityId>,
    val relations: List<SchemaRef>,
    val direction: Direction,
    val order: TraversalOrder,
    val budget: TraversalBudget,
)

interface Cancellation {
    fun isRequested(): Boolean
}

enum class VisitAction { Continue, Prune, Stop }
data class Visit(val entity: EntityId, val viaEdge: EntityId?, val depth: Int)
data class VisitStep<A>(val accumulator: A, val action: VisitAction)

fun interface Visitor<A> {
    fun visit(graph: Graph, at: Visit, accumulator: A): VisitStep<A>
}

enum class StopReason { Exhausted, VisitorStopped, BudgetExceeded, Cancelled, InvalidStrategy }
data class TraversalResult<A>(
    val value: A,
    val reason: StopReason,
    val coverage: Coverage,
    val visitedEntities: Int,
    val examinedEdges: Int,
)

interface Traversal {
    fun <A> run(
        map: MapResult,
        spec: TraversalSpec,
        initial: A,
        cancellation: Cancellation,
        visitor: Visitor<A>,
    ): TraversalResult<A>
}

Services and async capabilities

The call facade illustrates unary invocation; interaction-shape validation rejects using it as an implicit stream or durable queue. Streaming adapters expose separate typed sessions with explicit demand, close and cancellation. Authority references are broker-validated references, never self-authorizing strings. Delivery profiles require provider conformance.

data class EffectRequirement(val operation: SchemaRef, val resourceSelector: BlobRef)
enum class Interaction { Unary, Stream, Publish, Subscribe, DurableJob }
data class Operation<C : Any, I : Any, O : Any>(
    val id: String,
    val contract: Contract<C>,
    val input: SchemaRef,
    val output: SchemaRef,
    val errors: SchemaRef,
    val interaction: Interaction,
    val effects: List<EffectRequirement>,
)

data class InvocationContext(
    val operationId: String,
    val activation: ActivationRef,
    val authorityRef: String,
    val remainingBudgetMillis: Long,
    val idempotencyKey: String?,
    val causationRef: String?,
)

enum class EffectOutcome { NotStarted, Applied, PartiallyApplied, Unknown }
data class CallFailure(val code: String, val outcome: EffectOutcome, val evidence: Digest?)
sealed interface CallResult<out T> {
    data class Success<T>(val value: T, val receipt: Digest) : CallResult<T>
    data class Failure(val failure: CallFailure) : CallResult<Nothing>
}

interface BoundService<C : Any> {
    suspend fun <I : Any, O : Any> call(
        operation: Operation<C, I, O>,
        input: I,
        context: InvocationContext,
    ): CallResult<O>
}

interface RuntimeIsland {
    val activation: ActivationRef
    fun <C : Any> bind(consumer: Consumer<C>): BoundService<C>
}

enum class Durability { Volatile, PersistedBeforeAcceptance, TransactionalOutbox }
enum class Routing { FanOut, CompetingConsumers, KeyAffinity }
enum class Ordering { Unordered, PerKey, PerPartition }
enum class Overflow { Wait, Reject, DropOldest, DropNewest }
enum class AckPoint { Accepted, HandlerCompleted, TransactionCommitted }
data class DeliveryPolicy(
    val durability: Durability,
    val routing: Routing,
    val ordering: Ordering,
    val ackPoint: AckPoint,
    val maxInFlight: Int,
    val maxBufferedBytes: Long,
    val overflow: Overflow,
    val retryProfile: BlobRef,
    val deduplicationProfile: BlobRef?,
    val deadLetter: EntityId?,
)
data class ChannelDefinition(val entity: EntityId, val message: SchemaRef)
data class SubscriptionDefinition(
    val entity: EntityId,
    val channel: EntityId,
    val handlerPort: EntityId,
    val filter: ProgramRef?,
    val delivery: DeliveryPolicy,
)
data class PublishReceipt(val messageId: String, val durability: Durability, val evidence: Digest)
interface Publisher<T : Any> {
    suspend fun publish(message: T, context: InvocationContext): CallResult<PublishReceipt>
}

Portable program shape

This compact register/block representation illustrates the separation from graph storage. The profile defines register assignment/initialization, intrinsic semantics, typed failures, loop semantics, memory and yielding. The initial implementation must reject profiles or instructions it cannot validate. This specimen is not a finished VM specification or a proof of Turing completeness.

data class ProgramRef(val digest: Digest, val profile: SchemaRef)
data class Register(val index: Int, val schema: SchemaRef)
data class BlockId(val index: Int)
sealed interface Instruction {
    data class Constant(val target: Register, val value: BlobRef) : Instruction
    data class Compute(
        val target: Register,
        val intrinsic: SchemaRef,
        val arguments: List<Register>,
    ) : Instruction
    data class Invoke(
        val target: Register,
        val operation: SchemaRef,
        val input: Register,
    ) : Instruction
}
sealed interface Terminator {
    data class Branch(val condition: Register, val yes: BlockId, val no: BlockId) : Terminator
    data class Jump(val target: BlockId) : Terminator
    data class Return(val value: Register) : Terminator
}
data class ProgramBlock(val id: BlockId, val instructions: List<Instruction>, val end: Terminator)
data class ProgramDefinition(
    val ref: ProgramRef,
    val entry: BlockId,
    val input: Register,
    val result: SchemaRef,
    val blocks: List<ProgramBlock>,
    val imports: List<SchemaRef>,
    val effects: List<EffectRequirement>,
    val sourceMap: BlobRef,
)
data class ExecutionBudget(val fuel: Long, val memoryBytes: Long, val effectCalls: Int)

Patches and execution plans

A GraphPatch is limited to one owning partition. Cross-partition changes become a Plan containing locally atomic steps. expectedDigest = null means the entity must be absent. Explicit removal operations must account for dependent edges and facets. commit rechecks validation and concurrency; a prior accepted report is not a bypass token.

data class EntityPrecondition(val entity: EntityId, val expectedDigest: Digest?)
sealed interface PatchOp {
    data class PutNode(val value: NodeRecord) : PatchOp
    data class PutPort(val value: PortRecord) : PatchOp
    data class PutEdge(val value: EdgeRecord) : PatchOp
    data class PutCapability(val value: CapabilityValue) : PatchOp
    data class RemoveCapability(val entity: EntityId, val schema: SchemaRef) : PatchOp
    data class RemoveEntity(val entity: EntityId) : PatchOp
}
data class GraphPatch(
    val id: String,
    val base: Revision,
    val preconditions: List<EntityPrecondition>,
    val operations: List<PatchOp>,
    val sourceAuthorityRef: String,
)
data class Finding(val rule: String, val subjects: List<EntityId>, val evidence: Digest?)
data class ValidationReport(val patchDigest: Digest, val accepted: Boolean, val findings: List<Finding>)
sealed interface CommitResult {
    data class Committed(val revision: Revision, val receipt: Digest) : CommitResult
    data class Rejected(val report: ValidationReport) : CommitResult
    data class Conflict(val current: Revision) : CommitResult
}
data class CommandRequest(val operation: SchemaRef, val input: BlobRef, val context: ReadContext)
data class PlanRef(val digest: Digest)
data class Plan(
    val ref: PlanRef,
    val inputs: SnapshotRef,
    val patches: List<GraphPatch>,
    val commands: List<CommandRequest>,
    val requiredEffects: List<EffectRequirement>,
    val requiredEvidence: List<EntityId>,
    val expiresAtEpochMillis: Long,
)
data class ExecutionReceipt(val plan: PlanRef, val outcome: EffectOutcome, val evidence: List<Digest>)
interface ChangeProtocol {
    suspend fun prepare(patches: List<GraphPatch>, commands: List<CommandRequest>): Plan
    suspend fun execute(plan: PlanRef, authorityRef: String): ExecutionReceipt
    suspend fun reconcile(plan: PlanRef, authorityRef: String): ExecutionReceipt
}

Tests and assurance evidence

Definitions, executions and evidence have separate identities. The target profile names runtime/compiler/hardware and provider conditions. Existing Reaktor truth/provenance types should back the implementation; these fields describe the minimum evidence boundary, not a replacement truth taxonomy.

enum class TestKind { Unit, Contract, Property, Integration, Scenario, Performance, Memory, Model }
data class TestDefinition(
    val entity: EntityId,
    val kind: TestKind,
    val subject: Selection,
    val program: ProgramRef,
    val fixture: BlobRef,
    val requiredEffects: List<EffectRequirement>,
    val acceptance: BlobRef,
)
enum class Assurance { Observed, Tested, BoundedChecked, ProvenUnderAssumptions }
data class EvidenceRecord(
    val test: EntityId,
    val testRevision: Digest,
    val runId: String,
    val inputs: SnapshotRef,
    val artifacts: List<Digest>,
    val targetProfile: BlobRef,
    val seed: Long?,
    val assumptions: BlobRef,
    val assurance: Assurance,
    val result: BlobRef,
)
interface GraphVerifier {
    fun selectTests(patch: GraphPatch, graph: Graph): List<EntityId>
    suspend fun verify(plan: PlanRef, authorityRef: String): List<EvidenceRecord>
}

14. Modification protocol for developers and agents

The graph should help an agent answer four questions before editing: what owns this behavior, what else depends on it, which changes are permitted here, and what evidence would establish the result? Expose those answers as typed queries and findings, with source/target links. Do not require an agent to reconstruct them from a screenshot or infer authority from chat text.

The shared protocol is:

StepConcrete artifact / invariant
ReadAuthorized snapshot and source/observation context, with coverage and a revision vector.
ProposeIntent, typed graph patch and/or operational command; stable target IDs; declared expected outcome.
NormalizeCanonical ordered operations, explicit removals/rebindings, resolved schema and source ownership. No side effects.
ValidateStructural/type/capability invariants, base revision, policy/effects, target compatibility and source round-trip consistency.
PlanFingerprint of exact inputs, artifacts, commands, target instances, preconditions, policy, required tests, budgets and recovery steps.
Establish authorityBroker-issued scoped authority or policy-required approval bound to that plan and expiry. Sensitive reads are included.
ExecuteRevalidate authority, expiry and preconditions at each effect boundary; publish local patches atomically; execute target-specific operations with idempotency keys.
ReconcileCompare desired result with authoritative observed state; expose partial, failed and unknown outcomes.
Retain receiptExact plan, artifacts, affected revisions/epochs, results, evidence, omissions and any outstanding recovery.

This is not a mandatory human click for every action. Policy can authorize low-impact work automatically. The essential requirement is explicit scope and a reproducible plan; neither a UI button nor an agent identity grants ambient production access.

Atomic patches and source ownership

Validate the complete candidate revision before publication. Required bindings, endpoint existence, containment, schemas and capability compatibility must hold at the new root. Readers see the old or new revision, never the first half of a bulk connection. A failed patch publishes nothing and emits a rejection finding rather than a misleading successful port event.

Source-derived definitions remain owned by source. A visual semantic edit produces a supported source change, re-extracts and compares the normalized result. Reject edits that cannot round-trip without losing comments, identity or unsupported constructs; offer a source edit with diagnostics. Graph-native documents can be directly authoritative within their declared scope. Provider-observed facts cannot be edited as if they were desired configuration.

Control-plane writes go through this protocol. Routine application effects, such as sending a message, use the already validated runtime plan and checked operation boundary; they do not need a new human change plan for every call. Those calls still retain operation identity, effect scope and outcome semantics. This separation keeps governance off unnecessary hot paths.

Distributed changes

A plan spanning two owners is a coordinated transition with explicit intermediate states. Use prepared artifacts, compatibility windows, fencing and ordered activation where supported. Otherwise use a saga with reconciliation and compensation. Do not expose a global commit() that implies atomic rollback of HTTP calls, databases and devices.

Revocation or policy changes after planning require execution-time reauthorization. A changed schema, instance epoch, source revision or migration fingerprint invalidates relevant preconditions. An inverse graph patch is a new validated change; it is not proof that an external effect can be undone.

Agent and MCP interface

Expose query, explain, resolveSource, compare, propose, validate, plan, execute, cancel, reconcile and readEvidence as typed operations over the same model. A tool response includes stable references, coverage, pagination and a bounded result. Tool availability is filtered by authority; the execution broker checks authority again. User-supplied source/doc/telemetry text remains data, not instructions to the agent or executor.

15. Tests as graph entities

Tests should be discoverable and composable in the same graph without running merely because the graph was opened. A test definition declares its subject map, fixtures, generator/seed, runner, effects, platform/provider profile and assertions or performance budget. A test run is an activation/execution with a distinct ID. Evidence is immutable and tied to the exact test, code, schema, graph, policy and environment revisions.

Test familyFirst-class capability / result
Unit and contractPure logic assertions, port/schema compatibility, generated local/remote/FFI contract vectors.
Property and model-basedGraph/patch generators, reference-model equivalence, shrinking and a replayable counterexample.
IntegrationReal provider fixture, declared credentials/effects, setup/teardown, result and cleanup receipt.
Application scenarioRoute/role/flag/device starting context, actions, expected UI and downstream effects.
Performance and memoryWorkload distribution, warm-up, sample policy, p50/p95/p99, allocations, peak/retained bytes and profiling artifacts.
Concurrency and failureInterleavings, cancellation, retry, restart, disconnect, lease expiry and partition schedules.
Formal checkModel artifact, property, bounds/assumptions, solver/tool version and counterexample/proof reference.

Affected-test selection walks declared dependency and effect relationships, including source imports, schema consumers and runtime adapters. Dynamic or unmodeled boundaries broaden the selection and lower confidence; they never justify skipping tests silently. A cached result is reusable only when the relevant input closure and acceptance profile match.

An agent can propose a patch and receive the smallest justified test plan plus the reason each test was selected. Failed evidence becomes a source-linked finding or a replayable scenario. A UI test cannot replace an authorization test, and a successful model check cannot replace provider qualification. Keep all these evidence classes visible.

The initial acceptance harness must include real BestBuds and GymBuddy source/build scenarios, plus synthetic scale/failure fixtures. Tests that merely serialize the new data classes do not establish the redesign's value.

16. Formal methods with useful, limited claims

Start with invariants that prevent actual failures in the current architecture. The formal-methods design gives the broader program; this proposal selects the first kernel obligations.

LawExecutable check / verification approach
Every port has one existing owner; every edge has valid endpointsDeterministic validation plus generated malformed graphs.
Endpoint roles, contracts and cardinality satisfy the edge relationType/schema checker, compatibility vectors, Alloy relation models.
Ownership is acyclic; explicit dependency cycles remain legalIncremental ownership check cross-checked with a simple full traversal.
Rejected patches do not change the published revision or emit success effectsReference-model property tests; model publication as a state transition.
Concurrent publication respects base revisionsLinearizability/interleaving tests and a small TLA+ state model.
A local handle cannot refer to a different entity after slot reuseGeneration checks, stale-handle tests and FFI lifetime tests.
A map cannot elevate visibility or invent missing coveragePolicy model tests, cross-principal cache tests and noninterference checks within a stated model.
Effect execution requires current authority for the target and operationBroker contract tests, revocation/TOCTOU schedules and runtime monitors.
An activation's stale epoch cannot write after cutoverFencing model plus crash/restart/partition integration tests.
Replay does not reissue a committed effect as a new effectDurable-run state model, history conformance and duplicate-delivery fault tests.
Optimized storage/query results equal the simple modelProperty-based differential tests after randomized patches and compaction.
Portable instructions obey their type/effect/resource profileIR verifier, interpreter/native lowering conformance and adversarial artifact tests.

For a single owner, let S be the current immutable definition and p a patch. The initial transition law is:

candidate = applyToPrivateCandidate(S, p)
eligible  = p.base == revision(S)
            AND sourceAuthorityAllows(p)
            AND wellFormed(candidate)
            AND preservesRequiredContracts(S, candidate)

if eligible AND compareAndPublish(revision(S), candidate):
    published' = candidate
    receipt'   = committed(p.digest, revision(candidate))
else:
    this transition publishes no graph change
    receipt'   = conflict-or-rejection(p.digest, reasons)

Other writers may publish concurrently; “no graph change” means this rejected transition made none, not that the whole world froze. External effects are absent from applyToPrivateCandidate. Runtime activation is a subsequent protocol. This is a specification sketch, not a model-checking result.

Use Alloy for bounded structural/relational exploration and relevant temporal models, TLA+ for publication/leases/retries/cutover, and SMT-backed checks for a restricted predicate language. A small proof-oriented kernel can later use Lean or another proof assistant where the maintenance cost is justified. Avoid coupling initial adoption to proving all application code. Alloy language specification, TLA+ overview.

Every assurance statement records the model, property, bounds, assumptions, tool/version, target and artifact digest. “No counterexample within these scopes” is distinct from a proof under assumptions. Liveness claims require fairness and failure assumptions. Native adapters, compiler lowering and external providers are part of the trusted boundary until checked; modeling them as perfect functions would erase the failures we need to study.

17. BestBuds worked example: send a message and diagnose failure

This is the target connected flow, grounded in existing chat actors, service operations, pubsub and notification code. The complete join, transactional guarantees and distributed debugger are not established as implemented by this document.

StepGraph representationDeveloper/agent value
Open a chat from a normal route or notificationScreen/route capability with typed payload, entry-point relation and active flag/policy contextSee exactly which route and role led to the screen.
User sends a messageChat actor instance, consumed messaging operation and operation/run IDInspect actor state/mailbox and jump to the ordinary Kotlin method.
Client invokes messagingLogical service contract bound to a concrete client/server transport and active deploymentFollow the exact request schema and endpoint across the boundary.
Server authorizes and moderatesAuth decision and moderation operations joined to policy revision, tenant/resource and traceExplain denial or moderation failure without guessing from a red edge.
Store the message and schedule downstream workDeclared Postgres mutation and outbox transaction, if implemented for this operationInspect the actual schema/query/transaction evidence and pending event.
Deliver downstream eventsChannel, subscriptions, adapter placement, attempts and deduplication scopeIdentify lag, duplicate handling, dead letters and which consumer group owns progress.
Update connected clients / notificationsSocket or notification delivery operations, including Durable Object placement where usedDistinguish accepted notification from confirmed device delivery.
Render updated stateClient actor/state update, device activation and screen observationLink the visible problem to the producing operation and target build.

Suppose the operator sees “message pending” on iOS. The workbench should retain the selected client activation and message operation while moving through actor → service → auth → storage → delivery → device. It can explain one of several materially different outcomes: request not sent; authorization denied; server outcome unknown after timeout; message committed but outbox pending; event delivered twice but deduplicated; handler failed; device offline; client update received but view state stale. Each explanation needs evidence and an unresolved frontier where evidence stops.

The agent then proposes a specific change, such as a retry-policy correction or a missing consumer binding. The plan shows whether that is config, a graph patch, portable logic or a native release; the authority and schema requirements; affected clients/servers; contract/scenario tests; and recovery. Execution produces a retained receipt and observed reconciliation. This closes a developer workflow instead of adding another graph decoration.

Preserve the Kotlin DX

At the kernel-facing level, wiring can remain this small. The following function uses the proposed contract declarations and is included in the downloadable specimen. Domain helpers add actor/service capabilities and return named port bundles; product developers should not need to manually build schema records for each use.

fun <C : Any> messagingBindings(
    graph: GraphBuilder,
    messaging: Contract<C>,
    bindingRelation: SchemaRef,
): GraphDefinition = with(graph) {
    val chat = node("chat") { consumes("messaging", messaging) }
    val endpoint = node("messaging") { provides("api", messaging) }
    connect("chat.messaging", chat.ports, endpoint.ports, bindingRelation)
    build()
}

These nodes are pure definitions. A separate runtime registry binds the service implementation and actor factory using their declared capability/contract IDs. Existing ChatActor.open, sendMessage, retry and reaction methods remain ordinary typed methods; the redesign does not require drawing every list transform or repository algorithm. State ownership, required ports, effects and source locations become inspectable contracts around that code.

Auth and database detail must remain useful

The auth map must link principals, organizations/tenants, tiered roles, memberships, grants, resources, sessions and token metadata. Access, refresh, service and PAT credentials differ in purpose, audience, scope, expiry, issuer, subject and revocation lifecycle. Show who issued/uses a credential and recorded enforcement decisions. Raw secrets are not canonical graph properties or ordinary telemetry; a narrowly authorized credential operation may issue or reveal a permitted value through a dedicated sensitive result path. Do not claim every access token can be enumerated if the identity provider does not maintain such a registry.

The data map must retain engine-specific capabilities: Postgres tables/indexes/plans, ClickHouse statistics and query behavior, Memgraph labels/relationships/Cypher, D1/SQLite schema and results, Durable Object instance/storage context, and device object-store schemas/files. A generic graph representation joins them to operations and owners; specialized query and editing interfaces retain the details developers need. Query permissions, schema modification and record mutation are separate effect contracts.

18. Workbench and design implications

The graph redesign supplies the semantics behind the Pencil design. It does not replace reaktor.pen, and this documentation change does not edit its authored boards or claim new runtime screens. Update the atlas/Pencil implementation handoff when an accepted kernel contract changes the user flow.

SurfaceRequired behavior from this substrate
Graph canvasSame selected entity and exact ports across map switches, semantic zoom, expansion and partial loading. Geometry never changes graph identity.
Adaptive expansionUse measured canvas dimensions after docks/toolbars: expand right in landscape/square and below in portrait. Preserve anchors and camera intent; maintain stable layout where possible.
Collapsed groupsShow boundary portals and accurate edge bundles; selection can reveal the exact internal endpoint without inventing a connection.
Large graphIndexed neighborhood queries, viewport culling, level of detail, bounded expansion, cancellable background layout and incremental scene publication.
InspectorTyped node/port/edge/capability details, source authority, revision/activation, connected endpoints, map derivation and evidence.
ComputeLogical worker/server topology joined to observed routes, Kubernetes workloads, bindings, database connections, versions, health and deployment receipts.
DatabaseReal schema/result/statistics/plan adapters and reviewed data/schema operations, with a stable link to the owning service and environment.
AuthPrincipal/session/credential metadata and policy decisions joined to actual operation boundaries; issuance/revocation are governed operations.
DevToolsDevice/app/view identity joined to graph activation, route and source; adb/idb operations, deployment, file/data inspection and performance evidence use explicit targets.
IDE / MCPSame query/selection/diagnostic/plan contracts with source navigation and bounded authoritative operations.

The adaptive layout work already recorded in the UI/UX audit is an implementation input. This redesign adds requirements for identity, incremental invalidation and large-scale queries; it does not retroactively qualify million-node rendering or all physical devices.

19. Migration: preserve the graph, replace its load-bearing internals

Use one vertical slice and explicit compatibility adapters. Avoid a fleet-wide rewrite before the new kernel proves better behavior and acceptable performance.

PhaseConcrete deliverableExit gate
G0 — laws and baselinesStable schema/identity proposal, simple immutable reference model, canonical encoding vectors; current graph/DX/performance baselinesReproduce current BestBuds and GymBuddy wiring/navigation semantics; record existing differences and scale costs.
G1 — pure definitions and atomic patchesData records, snapshot store, contract registry, validation and all-or-nothing local publicationRandomized patch/reference equivalence; failed bulk wiring leaves no partial edges; concurrent readers observe stable snapshots.
G2 — adapters and typed DXExisting node/port DSL adapter, source IDs, generated contract keys; GraphDocument semantic-reference adapterCurrent apps and editor documents still load; identity survives rename/round trip; graph inspection no longer requires unrelated effects.
G3 — maps and traversalTyped maps, coverage, bounded iterative traversal, pure visitors and incremental indexesAuth/navigation/source maps agree on entity IDs; BFS/DFS semantics and cycle/budget tests pass; scale and memory budgets measured.
G4 — runtime capability separationInstalled behavior registry, activation-owned resources, compiled dispatch and route/actor integrationBestBuds chat and GymBuddy route instances retain behavior; cancellation/close/rebind tests pass; local call performance meets baseline.
G5 — one distributed BestBuds flowMessaging service contract, auth enforcement, store effects, one channel/subscription adapter, runtime exports and trace joinsDiagnose and recover one real client-to-server-to-delivery failure with exact revisions, outcomes and coverage.
G6 — safe modification and testsShared planner/broker/receipts, affected-test selection, source edit round trip and provider-qualified operationsA developer and agent independently complete the same change → test → execute → reconcile workflow.
G7 — portable logic and formal expansionRestricted typed interpreter, signed artifacts, budgets, target conformance; then compiler lowering and deeper modelsOne eligible config/logic update activates safely on supported targets; incompatible or unauthorized artifacts fail with useful diagnostics.

G5 does not wait for every possible VM target or proof assistant. Real provider flows are required early enough to shape the abstractions. G7's restrictions can be introduced during G1–G4 for predicates/queries; general portable behavior follows a stable kernel and effect model.

Compatibility rules

  • Preserve consumer/provider direction, route payload semantics and the existing graph-neutral module APIs.
  • Keep a legacy object-graph projection while moving definitions and runtime state apart. Label legacy-only identity and coverage limits; do not hash unstable runtime UUIDs into fake durable source identity.
  • Preserve the additive GraphDocument wire contract. Add semantic references and sidecar projection state through an explicit adapter/version path; do not rename existing fields or use scope paths as new kernel IDs.
  • Maintain old and new readers for a declared compatibility window, with export/import vectors and unknown-field retention tests.
  • Migrate one ownership scope at a time. Never let both old and new runtimes own the same actor/mailbox/effect without an explicit bridge and fencing.
  • Retire old paths only after product behavior, source round trips, runtime lifecycle and performance evidence pass. Keep the simple reference store for differential verification even after optimized storage ships.

20. Requirement-to-acceptance matrix

Each requested ecosystem concern has a home and an observable exit condition. These are design coverage entries, not a completion checklist marked done.

RequirementCore mechanismAcceptance evidence
Heterogeneous graph and capability compositionTyped records, relation contracts, facet registryNew module composes without editing a central node-kind enum or adding runtime cost to bare nodes.
Navigation and fractal architectureRoute/state capabilities, ownership, boundary ports, typed rootsNested routes, repeated instances, deep links and back navigation preserve state/identity across targets.
Workflows and flow selectionProgram definitions, causal selections, runs/historyBranches, loops, fan-out, cancellation and replay remain inspectable with exact step identity.
Maps and overlay selectionQuery/derivation algebra plus presentation profileAuth + telemetry + source compose with stable selection, lineage and correct policy/time-scoped caches.
Auth and tiered RBACRequirements, operation effects, authority broker and decision factsConnect, invoke, token expiry/revocation and cross-tenant denial tested at real execution boundaries.
Telemetry and analyticsStable definition/activation/run links and external observationsTrace and aggregate joins identify source/revision; missing samples and cohort limits remain explicit.
Dead-screen finderConditional reachability plus observation mapDeep-link/notification/flag roots included; unreachable and unobserved produce distinct evidence.
Services and FFI invocationSchema/operation registry, generated stubs, boundary profilesKotlin/C++/TS contract vectors, buffer lifetime/cancellation tests and remote unknown-outcome handling.
Pubsub, queues and actorsChannels, subscriptions, delivery profiles and activation ownershipDuplicate, retry, pressure, crash, dead-letter and ordering behavior matches the selected adapter.
Distributed system graphExport contracts, ownership, revision vectors and federation coveragePhone/Worker/server/device fragments stitch by contract identity without a central per-call dependency.
Versioning and code pushCanonical revisions, program artifacts, activation epochs and target eligibilityCompatible update can stage/activate/reconcile; incompatible state/import/platform changes fail before activation.
Tests and automationTest definitions, effect-scoped runners, immutable run evidenceAgent-selected tests explain impact and return reproducible failures; performance/memory regressions block release.
Formal methodsKernel laws, models, bounded checks, proof/evidence metadataCounterexamples map to source/patch; claims accurately state scope, assumptions and trusted adapters.
IDEs and MCPShared queries, diagnostics, source maps and change protocolSame entity/operation opens the correct source and retains authority/context across tools.
Compute and databasesRuntime placement and provider-specific schema/operation projectionsReal worker/Kubernetes/storage queries and reviewed modifications retain target, result and reconciliation.
DevTools and adaptive UXDevice/activation/view links plus scalable map sceneReal adb/idb workflows and graph navigation work across qualified viewports without losing exact selection.
Performance and excellent DXCompiled typed facade over compact indexed storageProduct code stays concise; measured latency/memory/frame budgets pass on declared workloads and targets.

21. Decisions still requiring experiments

The semantic direction above is concrete enough to implement. These implementation choices remain open because evidence should decide them:

ChoiceRecommended first experimentDecision criterion
Storage layoutSimple immutable reference store plus one columnar/chunked candidateSame results under randomized patches; better measured scans/memory without unacceptable small-graph or edit cost.
Schema encodingReuse existing schema/codec work where conformance permits; define canonical hashing separatelyCross-language evolution and malformed-input vectors pass; no accidental dependence on runtime class names.
Source identityExplicit persisted IDs plus generated symbol metadata and rename supportStable identity through source moves, repeated instances and visual/source round trips.
Portable execution targetA small typed reference interpreter first; compare native lowering and Wasm for qualified profilesDebuggability, budgets, conformance, size/startup and target distribution eligibility.
Federated cut semanticsOwner-consistent snapshots with explicit revision vector and partial coverageUseful queries under disconnect/restart without pretending to supply unsupported global consistency.
Channel providerOne existing BestBuds pubsub/queue path and an in-memory test adapterMeasurable duplicate/failure/pressure behavior and a real developer debugging journey.
Formal toolingStructural model plus publication/fencing transition modelCounterexamples reproduce in executable tests; models remain small enough to maintain.

Do not postpone the kernel laws while debating tools. Conversely, do not lock in a storage engine or universal VM based on a diagram. The first deliverable after this proposal is G0/G1 plus a preserved BestBuds slice, not a new collection of empty modules.

22. Complete framework and desktop integration

The graph is the composition, inspection and modification substrate of the entire Reaktor ecosystem. Integration is not restricted to modules that happen to inherit Node today. Every framework module and desktop feature must declare its graph-facing contracts, relevant effects, evidence and ownership. Almost everything contributes a map, provides runtime behavior, emits observations, exposes operations or consumes those facilities. A subsystem can play several of these roles.

The semantic kernel stays small by moving vocabulary and handlers into module registrations. A camera frame, database row, compiler instruction, UI pixel or telemetry sample need not become an eagerly resident canonical node. Its stream/schema/resource/operation and relevant provenance must be addressable, with bounded detail maps when useful. This is how the design combines complete integration with data-oriented performance.

22.1 Expanded review scope and current seams

The follow-up audit enumerated 34 framework module/build directories and 658 non-test source files under their src trees: 31 included root Gradle modules, the included dependeasy build, the standalone reaktor-cli build and the paused reaktor-react module. It extracted declarations across those trees and inspected selected domain interfaces, adapters and implementation boundaries. Native wrappers, CMake/build entry points and generated bridges were inventoried separately by path/surface; vendored C++ and generated distribution bundles were not treated as hundreds of separate Reaktor integration modules. reaktor-tactile has no source in this census. A source file count is not a working-provider count.

Desktop coverage comes from WorkbenchModes.kt, WorkbenchPaneCatalog.kt, WorkbenchModePanes.kt, the common WorkbenchGraph/pane subgraphs, operational models/control plane, the architecture overlay, source/device/database adapters, StudioDesignCatalog.kt, and the desktop MCP entry point. The mode enum has 13 values; visibleReaktorModes() lists 12, with App/UI preview mounted separately in the native rail. The authored catalog has 9 families and 74 subpanes; additional graph, auth-directory, compute, database and device controls are covered below rather than discarded because they are outside that catalog.

The running native application was inspected through its accessibility surface at the verification snapshot. It showed the BestBuds graph, relation-layer filters, exact port inspectors, source/runtime/evidence context, all mode labels and the Runs/Logs/Traces/Network/Tests/Build/Diagnostics drawer. This establishes the current surface and context seams; it is not a fresh qualification of every button, provider or authored board. The UI/UX audit retains behavioral qualification and remaining gaps.

The machine-readable integration inventory records module source paths, declaration names, revisions, mode values and exact authored tab labels. It is a dated review artifact. New modules or surfaces must extend the matrix and conformance contract rather than being assumed covered by the word “everything.”

Current seam found in codeRequired redesign integration
Feature / CreateSlot and platform Adapter registrationsExport owned provider identities, required contracts and availability through a host adapter. Preserve plain-library callers; progressively replace ambient cross-module calls with explicit runtime bindings. A legacy opaque call remains a declared coverage gap.
Common WorkbenchShellGraph and pane graphs already contain actors, routes and interactorsPreserve them as real host-runtime composition. Connect their document, selection and operation references to the inspected graph through typed relations. The desktop is itself a Reaktor application.
ToolingCatalog, CloudResource/CloudRun, OperationalSnapshot and editor GraphDocument have distinct modelsAdapt them to shared entity/run references and typed contracts. Keep provider-specific detail and existing wire compatibility. Do not create another unconnected catalog with another set of IDs.
OperationalArchitectureOverlay already projects providers, targets, resources, tasks and runsEvolve this projection into a registered map with source-owned identities and typed relation endpoints. Preserve provenance while replacing open attribute bags in semantic hot paths.
Cloud inventory can recover a provider failure as an empty listCarry a source availability/coverage record alongside results. A failed provider must not look like a successfully observed empty estate.
OperationalControlPlane already fingerprints plans, tracks runs and delegates to toolingReuse and extend this seam for shared graph/command plans and receipts. Keep existing effect/sensitive-output protections during migration.
Desktop MCP installs the active graph and exposes graph, architecture and control-plane readsPreserve active-session identity and the current consistency qualifier. Evolve through the same query/operation registry as the UI and CLI; do not bypass authority by exposing a raw graph mutator.
Conductor owns protocols, agent sessions and a causal thread documentProject thread/protocol/run identities, context inputs and tool effects. Preserve the independent Conductor API and distinguish an agent's proposal from an executed system change.
The UI/AI modes have distinct state and do not all map into an operational domain todayRegister their maps, actions, selection context and execution ownership explicitly. A pane label or capability declaration is insufficient integration evidence.

22.2 Six ways a module connects to the substrate

ContributionWhat is registeredOwnership and execution rule
Definition vocabularyNode/port/edge capabilities, contracts, schemas, relations, source extractorsPure versioned data; source or graph-document owner controls changes.
Runtime behavior and hooksImplementations, lifecycle/resource bindings, invocation guards/transforms and delivery handlersInstalled code owned by a runtime activation; contracts and effect checks apply at the boundary.
Observation sourceRuntime state, provider inventory, measurements, traces, artifacts and cursor-based updatesSource owns truth and freshness; readers receive scoped coverage and lineage.
Map and analysisQueries, joins, derived relations, traversals, visitors and invariantsPure/bounded computation over declared inputs; derived facts retain input revision and witness references.
OperationTyped reads, writes, build/test/device/cloud actions, cancellation and reconciliationShared planner/executor/authority path; provider-specific outcomes and limits remain explicit.
PresentationInspector sections, editors, graph styles, diagnostics, commands and source linksReads the same maps and action descriptors; UI state does not silently mutate application behavior.

An integration manifest describes these contributions. It contains data and implementation references, not serialized Kotlin closures. Runtime installation binds those references to trusted native handlers or supported portable programs. Plugins cannot register handlers for another owner's namespace or replace security-critical hooks merely because their manifest loads.

Default developer experience: install the module normally; a Reaktor host discovers its opt-in graph integration and installs it once for the relevant scope. Generated typed helpers hide registry boilerplate. The plain-library API continues to work without graph construction. Explicit registry/batch APIs remain available for unusual use cases and performance-sensitive code.

22.3 Every framework module and build

The following table names every module in the census. The “contribution” column is required target behavior, not a claim that the module already has that integration. Availability must be qualified per platform and adapter.

Module / current source seamGraph contribution and useful mapsOwned execution / integration acceptance
reaktor-core — Feature, Adapter, Component, permissions, FactModule/provider identity, host/platform capabilities, component lifecycle, availability and provenance.Platform lifecycle/permission adapters retain ownership; graph inspection does not allocate every feature. Plain use and graph use agree on availability.
reaktor-graph-port — port graph, bindings, selectorsCanonical typed endpoint/relation facade, contract compatibility and efficient neighborhood access.Atomic validated wiring, stable IDs and bounded traversal replace incidental object mutation.
reaktor-graph — routes, containers, actors, ServiceNodeApplication structure, route/payload contracts, actor state/mailbox definitions, service bindings and ownership maps.Runtime capabilities own jobs/resources/state; typed route and actor APIs retain current DX.
reaktor-flow — graph document/session, architecture overlays, layoutGraph/editor adapters, selected maps, scene detail, source links, exact ports and projection lineage.Layout/camera/pins stay presentation state; edits to semantics produce source-aware patches.
compose-flow — viewport, generic nodes/edges/handlesGeneric rendering/hit-testing contract consumed through reaktor-flow. Performance evidence can reference the graph scene.Remains graph-neutral and does not import Reaktor semantics; viewport work is bounded and culled.
reaktor-ui — component specs, design tokens, Machine Signal, adaptive layoutsComponent/design-system definitions, variants, renderer links, accessibility/preview/test maps and token provenance.Tokens retain one owner. Composition/recomposition and geometry use UI runtime state; no canonical patch per pixel/frame.
reaktor-react — paused module; JSI, Promise, FlowHandle, module invokersReserved integration boundary for JS/native module and operation contracts, renderer/host attachment and handle/stream ownership.It is excluded from the root build; this proposal does not reactivate it. Any future revival must qualify cancellation, lifetime and error propagation with graph-neutral APIs.
reaktor-web — platform WebView seamsWebView instance, document/origin, navigation and bridge contracts; browser/debug attachment maps where supported.Host owns WebView/security/lifecycle. Do not advertise unsupported browser/network inspection based on a wrapper class.
reaktor-io — files, share/compression, HTTP/WebSocket/PartySocketFile/resource schemas, network endpoints, connection/reconnect state, stream and transfer operations.Files/sockets stay provider resources; byte streams use bounded buffers and explicit read/write authority.
reaktor-media — camera/gallery, caches, media services/uploader, speechCapture/pick/transform/upload pipeline, media artifact/codec/cache references, speech operation contracts and progress.Camera/microphone sessions, frames and large blobs stay outside the resident graph. Permission, cancellation and supported-platform evidence are required.
reaktor-location — location and map adaptersLocation-source capability, coordinate system, accuracy/time metadata and geography overlay links.Device owns permission and acquisition. Software topology layout is independent of physical geography; precise locations are scoped sensitive observations.
reaktor-sensors — step counter, baseline/rebasingSensor/device/session capability, measurement schema, time/reset/baseline provenance and availability.High-rate data is streamed/aggregated. Unsupported or denied readings never become zero-valued healthy measurements.
reaktor-health — health availability, permissions, steps and sessionsHealth-store/read/write contracts, consent scope, session/aggregate result maps and provenance.HealthKit/Health Connect adapters retain platform constraints. Register graph-neutral APIs and explicitly scoped sensitive reads/writes.
reaktor-notification — client, node, scheduler, events and dev harnessCategories/actions, permission, endpoint metadata, schedule/delivery/tap flow, route targets and test harness.Join scheduled → accepted → received → response with evidence; device delivery and user action are distinct. Listener/scheduler cleanup belongs to the host.
reaktor-auth — auth kernel, providers, graph ports and directoriesPrincipal/tenant/role/grant/session/credential metadata, requirements, enforcement points and decision/simulation maps.Invocation-time authority remains enforced when an auth overlay is hidden. Issuance/revocation and sensitive reads use governed operations.
reaktor-security — device credentials, MLS conversations/envelopes, secret boxCrypto-device/group identity, membership, protocol/key epoch metadata, native implementation and security evidence.Private keys, decrypted content and sealed state stay in authorized crypto/storage boundaries. MLS epoch is a separate typed domain from graph activation epoch.
reaktor-secrets — secret refs/versions/store adaptersSecret reference/version metadata, consumers, rotation dependencies and access/audit operations.Values travel only through scoped secret capabilities; no raw secrets in snapshots, maps, logs or general agent context.
reaktor-db — SQL/object-store/cache/sync and Memgraph inspectionEngine/schema/table/collection/relationship catalogs, object ownership, query/result/plan, cache/sync and migration maps.Data stays with stores; results are bounded maps. Read, mutation, schema migration, sync and retention have separate contracts.
reaktor-service — typed handlers, chain/interceptors, endpoint transportService/operation schemas, routes, bindings, effects, guards and cross-language/source mappings.Compile required interceptors into dispatch. Same contract can use qualified transports without erasing their failure/completion semantics.
reaktor-google — PubSub topic/subscription/message/ack APIsTopic/subscription/channel bindings, messages/delivery summaries, ack/retry/lag and credential-provider metadata.Provider guarantee profiles qualify publish/pull/push/ack behavior; broker delivery and business completion are separate.
reaktor-cloudflare — Worker/DO context, bindings, storage, AIWorker/DO instance/namespace contracts, service routes, D1/R2/KV/Hyperdrive/vector/AI bindings and placement/effect maps.Worker/DO runtime owns invocation and storage. Bindings describe deployment facts; observed versions and requests need independent evidence.
reaktor-cloud — inventory/tool providers, Kubernetes, Wrangler, Dagger/Pulumi adaptersProvider/resource/operation/deployment topology, observed health/drift, logs and cost dimensions.Use existing provider/planning interfaces; preserve failures and partial coverage. Mutations bind exact target, input, authority and receipt.
reaktor-work — task manager and background workersSchedule/task definitions, constraints, payload schemas, run/status, retry/reschedule and cancellation maps.The platform scheduler owns actual background execution. OS-deferred work is distinct from a graph-runner failure or immediate execution promise.
reaktor-telemetry — graph instrumentation, analytics sinks, crash adaptersInstrumentation schema, trace/event/metric/crash sources and definition/activation/run correlation.Observers attach/detach incrementally. Payloads remain in telemetry stores; sampling, redaction, freshness and missing coverage are visible.
reaktor-performance — collectors, harnesses, budgets, reportsPerformance/memory/build-size budgets, benchmark workloads, profiles and regression evidence.Measurements carry target/build/workload identity; instrumentation overhead is measured and bounded.
reaktor-flexbuffer — codecs, views, pools, schema tooling, native bridgeWire/schema/codec profile, artifact compatibility, ownership and codec performance/conformance evidence.Compact storage may reuse the codec after validation; buffers are not entities per byte. Canonical hashing remains separately specified.
reaktor-ffi — Switch, Invokable and native transportsExported operation registry, ABI/contract profile, target/handle/lifetime and FFI invocation evidence.Generated typed dispatch validates buffers, leases, errors and cancellation; opaque native operations are labeled as such.
reaktor-compiler — processors and generatorsSymbol/schema/source maps, portable-program lowering, generated artifact provenance and diagnostics.Build-time transformations produce deterministic artifacts and reject unsupported semantics; they are not runtime node constructors.
dependeasy — Gradle plugins, platform/native/bootstrap configurationModule/dependency/target/toolchain graph, native inputs, build tasks and artifact lineage.Gradle/CMake own builds; extracted definitions preserve source authority. Dependency changes drive impact/test/build selection.
reaktor-tooling — discovery, catalog, planner, executor, devices/source indexWorkspace/target/resource/task/run/artifact identities, source symbols, device operations and run ledger.Reuse its planning/execution ports and process supervision; unify references with cloud/desktop/MCP rather than duplicate authority logic.
reaktor-cli — command tree and discovered script familiesTerminal projection of registered queries, task/operation descriptors, diagnostics and plans.A command and its desktop/MCP equivalent resolve to the same operation and target; raw scripts remain explicit opaque actions until qualified.
reaktor-mcp — read server/client and protocol descriptorsTools/resources/session attachment, schemas, authority-filtered discovery and query provenance.Current read surfaces remain qualified as reads; future execution delegates to the shared broker. Tool descriptions are not executable authority.
reaktor-conductor — agents, protocols, context compiler and thread eventsAgent/thread/protocol/task DAG, context lineage, model/session/budget, proposed patch and run/evaluation maps.Agent harnesses execute within declared tool/effect budgets. Store conversation/artifacts appropriately and link them; private context does not become ambient graph visibility.
reaktor-tactile — build/README placeholder, no sourceReserved future haptic/tactile capability vocabulary only when real APIs are designed.Keep status unavailable; no claim of an installed handler, working haptic operation or completed graph integration.

Non-Gradle surfaces are also part of the system: CMake/cinterop and native vendor dependencies contribute build/ABI/artifact facts through tooling; experiments contributes explicitly experimental evidence; framework docs/website and product ReaktorWeb contribute source/docs/knowledge-map artifacts. Standalone design-system files, generated TypeScript/native outputs and bootstrap tools link back to their owning module/build inputs. A directory or vendored library does not become a second authority for runtime semantics.

22.4 Every desktop mode and authored family

The kernel does not own a Pane enum. The workbench registers mode, editor, inspector and action contributions against the shared semantic/context contracts. Specialized tools retain their own UI; switching mode changes the projection and available operations while preserving the selected system identity.

Desktop mode / surfaceComplete authored family or additional controlsGraph integration requirement
GraphApplication explorer; relation layers; System/Container/Component/Code detail; exact ports; Inspect/Ports/Runtime/Source/Telemetry/A11y; source/diff/preview linksOne map/selection model with coverage, source authority, runtime binding and evidence. Expansion/layout changes presentation; edits produce explicit semantic/source proposals.
App / UI previewSeparate preview mode and native rail entry; mobile/tablet/desktop targets, theme/network context and element inspectionPreview session and view-tree instance link to definition, activation, build, route and source. Simulated device/network state is labeled and cannot masquerade as observed hardware.
DevToolsPreview, Devices, Testing, Pipeline, Releases, Recorder, Traces, Logs, Source; additional Mobile/Workers/Servers/Workspace domain tabsDevice/app/process/view/recording/run/source references join to the application graph. adb/idb, install/delete, file/database inspection, breakpoints and replay are typed target-scoped operations.
UICanvas, Workbench, Design System, Flow, Responsive, A11y, Visual Tests, Source DiffDesign/component/token/variant identities connect to implementation, viewports, navigation and visual/accessibility evidence. References and authored examples remain distinct from active application instances.
DatabaseQuery, Schema, Data, Relationships, Query Plan, History, Migrations; connection/catalog/statistics and engine-specific graph/object inspectionQuery session, engine schema, parameters, result page, execution plan and migration plan retain environment, authority, source and affected-service links. Data grids remain specialized projections, not screenshots of the graph.
AuthProviders, Roles & Permissions, Sessions, Audit, Security, Simulator; principals, memberships, refresh tokens, PATs, service accounts, grants, issuance and signing-key lifecycleJoin selected identity/resource to requirements and actual enforcement points. Simulated policy decisions and observed decisions are separate evidence. Session/token lifecycle operations share the broker.
CloudResources, Operations, Deploy, Pipeline, Runs, Cost; Worker/server routes, Kubernetes objects, bindings, database connections and driftLogical service → deployable artifact → placement → observed instance → operation/run. Provider/source coverage is retained across topology, tables, logs and cost views.
DeployTarget/environment selection, build/package/release, promotions, distribution, rollout and recoveryShared artifact/plan/approval/activation/receipt graph. Releasing mobile, desktop, web, Workers and servers uses qualified target adapters and explicit compatibility/cutover windows.
TestingUnit/contract/property/integration/model/performance/memory plus Maestro, Playwright and desktop/device harnessesTest definition → affected map → fixture/profile → run → results/artifacts/counterexample. A declared harness is distinct from an executed qualifying test.
Insights / TelemetrySpans, Metrics, Logs, Profiles, eBPF, Crashes, Pipelines, Alerts, SourcesSource/collector configuration, signal schema, resource/activation/run context, sample windows and event lineage. eBPF and crash panes require actual qualified collectors; presence in the catalog is not evidence of attachment.
AnalyticsPerformance, Errors, Funnels, Cohorts, Retention, Experiments, Costs, ReportsVersioned event taxonomy, consent/cohort/time scope, experiment assignment and user journey join to routes/programs/releases. Business outcomes and runtime metrics retain their distinct units and evidence.
AgentChat, Kanban, Tasks DAG, Agents, Pipeline, MCP, Memory, Runbooks, AuditConductor thread/protocol/task/run/context lineage with typed findings/proposals/patches. Kanban status alone cannot establish that an operation ran; audit/receipt references do.
AIPlayground, Notebooks, Models, Chain Builder, Prompts, RAG, Tools, Evals, Guardrails, Routing & Cost, AI Traces, ReleasesModel/provider/prompt/program/dataset/index/tool contracts; chain execution, retrieval lineage, eval evidence, routing/budget policy and artifact releases. Inputs/outputs may be sensitive; caches and datasets are separately owned.

The exact 74 authored subpane labels are retained in the inventory. The table also covers top-level Graph, App, Testing and Deploy surfaces outside those nine families. Additional mounted controls must be registered rather than silently dropped to match an older design catalog.

Cross-cutting desktop facilities have the same requirement:

FacilitySemantic hook and ownership
File/Edit/View/Navigate/Code/Graph/Run/Tools/Window/Help menus and command paletteCommands resolve through action descriptors with current target/context and availability reasons. Menus, shortcuts and agent tools invoke the same domain operation.
Explorer, search, bookmarks, favorites, history and source/definition navigationStable entity/symbol/document references plus user-owned workspace state; missing or renamed targets resolve through identity/alias rules.
Open documents, source diff, editor undo, graph documents and saved mapsDocument owner and revision are explicit. Undoing a camera move is local presentation undo; undoing a committed semantic change is a new validated patch.
Runs, Logs, Traces, Network, Tests, Build and Diagnostics drawerOne run/artifact/evidence index joins to operations and selected entities. Counts state their scope and coverage; a network inventory count is not automatically a captured request count.
Status bar, environment/target selection, run/debug/stop and pending plansDisplay the exact selected context and actual execution target. Changing a filter does not retarget a prepared operation; stale plan preconditions invalidate it.
Browser, terminals, JVM/native/device debugger and detached preview windowsAttachment capability with session/host identity, source map, authority, availability and disposal. An opaque external tool retains an explicit boundary and deep link.
Design studio, authored board chooser, Pencil references and component previewsDesign/source reference map linked to target semantics and qualification evidence. The authored design remains a specification, never the runtime body of an operational pane.
Split panes, tabs, docks, cameras, selection and adaptive viewportsLocal/persisted workspace state keyed by graph/map identity. Geometry and hover changes are not replicated as application definition revisions.
Workspace opening, discovery, indexing, caches and background refreshSource/attachment tasks with progress, diagnostics, cancellation and coverage. A slow provider cannot indefinitely block unrelated local graph work.

22.5 One graph also describes Reaktor itself

There are several namespaces/ownership scopes in one semantic model: framework definitions, product definitions, deployed/runtime instances, workspace/authoring artifacts, operations/evidence and external provider resources. These are not competing graph kernels. A Workbench actor can own a preview session that inspects a BestBuds activation, renders a selected map and invokes a tooling operation through typed boundary relations.

Keep the inspected application's authority and lifetime separate from the inspector's. Closing the preview releases its view/resource attachment; it does not delete the application definition or revoke a user's session. Installing an inspector cannot grant access to its target. The graph must also support a self-inspection boundary: operational telemetry from inspecting the graph does not recursively trigger infinite inspection events or unbounded graph growth.

The shared Workbench context includes workspace, revision/fact cut, environment, principal/tenant/visibility policy, selected map(s), exact entity/port, activation, selected causal flow, mission and run. A live-follow mode must explicitly move the pinned context to newer observations; a saved historical result remains historical. Agents and UI receive appropriately scoped projections of this same context.

22.6 Hooks are contracted boundaries, not arbitrary callbacks everywhere

A module registers a versioned hook boundary and declares transform, enforce or observe purpose, input/output schema, handler reference, effect requirements, dependencies/order, failure policy and resource budget. Runtime implementations are bound separately. The first implementation should support a small set of useful boundaries and extend them through schema-qualified modules.

Boundary familyExamples and required semantics
Author/extract/validate/compileSource extraction, schema registration, invariant checking, route/dispatch compilation and source maps. Pure passes return outputs/findings; they do not perform runtime effects.
Activate/deactivate/disposeResolve providers, allocate actor/camera/socket resources, restore supported state, attach observers, drain and close. Every registration has an owner and removal path.
Bind/invoke/return/fail/cancelContract negotiation, auth/tenant checks, input transformation, telemetry, retry eligibility and cancellation propagation. Auth cannot be disabled by hiding a map or bypassing an inspector.
Enqueue/deliver/ack/checkpointAdmission/backpressure, subscription filtering, message identity, effect deduplication, retry/dead-letter and durable history. Completion and replay rules stay provider-qualified.
Commit/change/reconcileValidate an immutable candidate, publish, invalidate queries, compile/activate and record receipts. Observers see committed changes; they cannot mutate the collection currently being traversed.
Observe/project/renderSource cursors, stale/partial availability, map invalidation, bounded aggregation, source-to-view correlation and scene update. Presentation does not become an effectful policy hook.

Order is a validated dependency DAG with deterministic tie-breaking. Cyclic or ambiguous security-sensitive ordering fails registration. Enforcement failures/timeouts fail the protected operation closed. Optional telemetry failure normally reports lost observation without changing business outcome, subject to the declared policy. A transformation cannot remove required authorization or enlarge authority. Hook reentrancy, cancellation, asynchronous completion and which thread/runtime owns the callback must be defined by its boundary contract.

Compile hook chains at activation/revision change and cache checked dispatch plans. Avoid reflective registry scans, string-map lookups, arbitrary async suspension or graph traversal on every frame, sensor sample or local call. Batch high-rate observations and retain loss/drop counts. A hook descriptor is not permission to put a global event bus into the pure kernel.

22.7 Observation and projection protocol

Every source—device inventory, Kubernetes, database schema, auth directory, trace collector, source index, model provider or test runner—needs the same outer protocol while keeping its own typed payload and guarantees:

  1. Identify source/owner, schema, target, authority, source revision or activation generation, and collection scope.
  2. Read an initial bounded snapshot/page with coverage, capture/freshness metadata and a resumable cursor where supported.
  3. Apply ordered deltas only within that source/generation. Duplicate pages are idempotent; gaps or generation changes request resynchronization. There is no assumed global total order.
  4. Distinguish entity deletion/tombstone from temporary absence, permission loss, stale cache, unsupported capability and provider failure.
  5. Track dependency invalidation and observation cut separately from definition revisions. Maps carry lineage and explicit partial results while updates are pending.
  6. Enforce byte/entity/time quotas, cancellation, retention/redaction and attachment cleanup. Large rows/blobs/events stay behind bounded result handles or external references.

Use the existing Fact/truth/provenance semantics for observation envelopes. Do not collapse assurance, source, freshness and availability into one Live boolean. Sensitive data may be visible only through a purpose-specific session/result capability; graph visibility does not imply permission to export it to a model, file or remote peer.

22.8 Kotlin integration contracts

The following declarations extend the same compiled proposal specimen. They specify data boundaries; the registry, source adapters and handler implementations are still proposed. A BlobRef below names a schema-validated batch of definition candidates or provenance-bearing observation records, including tombstones where appropriate. It is not an untyped permission to overwrite arbitrary graph state. The host validates schema, namespace, source authority and cursor generation before materialization.

data class CapabilityDescriptor(
    val schema: SchemaRef,
    val validOn: Set<EntityKind>,
    val requires: List<SchemaRef>,
    val excludes: List<SchemaRef>,
    val requiredBehavior: SchemaRef?,
)
enum class HookPurpose { Transform, Enforce, Observe }
data class HookDescriptor(
    val id: SchemaRef,
    val boundary: SchemaRef,
    val input: SchemaRef,
    val output: SchemaRef,
    val purpose: HookPurpose,
    val handler: SchemaRef,
    val before: List<SchemaRef>,
    val after: List<SchemaRef>,
    val effects: List<EffectRequirement>,
    val budget: ExecutionBudget,
    val failurePolicy: SchemaRef,
)
data class QueryDependency(
    val entities: Selection,
    val readsSchemas: List<SchemaRef>,
)
data class ProjectionDescriptor(
    val id: EntityId,
    val sourceContract: SchemaRef,
    val outputSchemas: List<SchemaRef>,
    val dependencies: List<QueryDependency>,
    val effects: List<EffectRequirement>,
    val retentionProfile: SchemaRef,
)
data class InspectorDescriptor(
    val id: SchemaRef,
    val subjects: Selection,
    val maps: List<EntityId>,
    val actions: List<SchemaRef>,
    val rendererContract: SchemaRef,
)
data class GraphIntegrationManifest(
    val module: SchemaRef,
    val requiresModules: List<SchemaRef>,
    val capabilities: List<CapabilityDescriptor>,
    val contracts: List<ContractRef>,
    val projections: List<ProjectionDescriptor>,
    val maps: List<MapDefinition>,
    val operations: List<SchemaRef>,
    val hooks: List<HookDescriptor>,
    val inspectors: List<InspectorDescriptor>,
    val conformanceTests: List<EntityId>,
)
data class ProjectionCursor(val source: EntityId, val generation: String, val position: String)
data class ProjectionBudget(val maxEntities: Int, val maxBytes: Long, val remainingMillis: Long)
data class ProjectionRequest(
    val projection: EntityId,
    val context: ReadContext,
    val authorityRef: String,
    val after: ProjectionCursor?,
    val budget: ProjectionBudget,
)
enum class SourceAvailability { Available, Unavailable, Unsupported, Unknown }
data class ProjectionPage(
    val source: EntityId,
    val sourceRevision: Digest?,
    val records: BlobRef,
    val next: ProjectionCursor?,
    val resetRequired: Boolean,
    val availability: SourceAvailability,
    val coverage: Coverage,
)
interface GraphProjectionSource {
    suspend fun read(request: ProjectionRequest): ProjectionPage
}
interface InstalledGraphIntegration : AutoCloseable {
    val manifest: GraphIntegrationManifest
    fun source(id: EntityId): GraphProjectionSource?
    override fun close()
}
data class SemanticFocus(
    val entity: EntityId,
    val map: EntityId?,
    val activation: ActivationRef?,
    val evidence: Digest?,
)
data class FlowStep(
    val id: String,
    val focus: SemanticFocus,
    val viaEdge: EntityId?,
    val causedBy: List<String>,
)
data class FlowSelection(val id: String, val steps: List<FlowStep>, val lineage: List<Digest>)
data class WorkbenchContext(
    val read: ReadContext,
    val maps: List<EntityId>,
    val focus: SemanticFocus?,
    val flow: FlowSelection?,
    val missionId: String?,
    val runId: String?,
)

Installed integrations resolve native/portable implementation references through the host's trusted registry. Discovery of a manifest does not load untrusted code automatically. The binding/authority contract applies equally to built-in modules and third-party plugins. Manifest uninstall/upgrade drains owned work, releases attachments and invalidates contributions without deleting another source's entities.

22.9 Integration release gates

“Hooks into the graph” is accepted only when the following are demonstrated for the exact module/provider/target:

  • Coverage: every module, pane, operation and source appears in the integration catalog with an owner, status and implementation/evidence reference. Unsupported and opaque boundaries are explicit.
  • Identity: source → definition → activation → operation → observation/test/artifact joins work across UI, CLI and MCP. Rename, reconnect, restart and repeated instances do not silently change identity.
  • Dual surface: equivalent plain-library and graph-bound calls produce equivalent domain behavior; graph-disabled use does not initialize the whole Workbench or require a graph store.
  • Authority: hidden overlays, cached sessions, agent tools and local fast paths cannot bypass enforcement. OS permissions, tenant authority and secret/crypto ownership retain their distinct checks.
  • Lifecycle: install/refresh/reconnect/upgrade/uninstall cycles do not leak jobs, listeners, buffers, handles or stale cache entries. Pending cancellation and unknown outcomes remain inspectable.
  • Projection: cursor gaps, duplicate updates, stale/missing sources and revoked visibility produce truthful coverage and invalidate affected maps without recreating the entire graph.
  • Performance: the same workload passes with observers disabled and enabled under an explicit overhead budget; high-rate producers do not generate unbounded graph mutations or layout work.
  • Developer workflow: a real task starts from any relevant pane, reaches source and runtime/data evidence, makes a supported change, tests it, executes/reconciles it and returns a retained result with the original context intact.

Add these gates to G0–G6 incrementally, beginning with source/tooling/workspace integration, then the existing BestBuds chat/auth/data/compute/device slice. Also qualify one peripheral path early—such as permission → camera/media upload → background task → notification → route—to ensure the core was not accidentally designed only for server requests and navigation. Health/sensors/location and secure-device/secret lifecycles need their own target-specific evidence before being called fully integrated.

Validation of this document

This change supplies the architecture proposal, two HLD/topology diagrams, the Kotlin contract specimen, the complete framework/desktop integration matrix and links from the living implementation/design documents. The complete specimen, including the wiring example and integration contracts, compiled successfully with Kotlin 2.3.0; all eight Kotlin blocks in this document match that specimen. That checks declaration/type consistency, not a runtime implementation. The module and authored-subpane coverage was checked against the inventory. The diagrams were rendered for visual inspection. Documentation navigation, site build and published-route checks are recorded with the delivery of this revision. No performance measurements, provider qualification, formal proofs or new runtime feature completion are claimed by publishing it.

23. Independent review (Claude)

Independent review · Claude (Opus 5) · 9 September 2026 · advisory; not an accepted change to the proposal above. This section reviews §1–§22 against the source they cite. It was written after reading the full proposal, the complete Kotlin specimen, and targeted reads of the implementations named in §2. It decides nothing and supersedes nothing. It records defects, internal contradictions and one scope risk that should be resolved before G1 opens. Findings are ordered by the cost of leaving them unfixed.

23.1 Summary judgment

The diagnosis is accurate. Every claim in §2 that could be checked against source was checked and holds (§23.6). The direction — pure definition data, typed capability facets, runtime resources owned by activations, maps over one skeleton, coverage as a first-class result rather than an afterthought — is right and should proceed.

Two things are not yet true of the artifact as delivered.

The specimen delivers neither half of its title. It is not data-oriented: there is no cursor, batch or column API anywhere in its 483 lines, and the only read path allocates per entity. It is not typed where typing carries weight: capability and contract type parameters are phantoms, cross-cutting identity is String, and the payload of nearly every record is a BlobRef that nothing in the file can resolve.

§19 and §22 pull in opposite directions. §19 correctly prescribes one vertical slice with adapters. §22 declares a 34-module, 74-subpane adoption contract with eight per-module release gates, in the same normative voice. Against the project's actual capacity the second will either be ignored or stall the first.

Neither is fatal. The first is a specimen revision measured in a few hundred lines. The second is an editorial decision about what §22 is.

23.2 Defects in the contract specimen

#DefectClassBlocks
C1No blob resolution path; BlobRef carries the payload of most records and nothing can open itIncomplete contractG1
C2CapabilityKey and Contract type parameters are phantoms; equal keys, different static typesUnsound typingG1
C3Interaction names Stream/Subscribe/DurableJob with no interface — the defect §2 charges to ServiceTransportContradictionG4
C4Coverage.completeWithinDeclaredScope: Boolean collapses what §22.7 forbids collapsingContradictionG3
C5Coverage.frontier enumerates inaccessible boundaries, leaking counts §11 forbids leakingCorrectness / policyG3
C6Authority, principal, tenant, run and cursor identity are bare String, against decision #2 and §13's own proseUnsound typingG1
C7EntityId carries no kind, so §16's first two laws cannot be expressed in typesWeak typingG1
C8GraphPatch.base is one Revision while reads are a RevisionSet; cross-partition read-set is unfencedCorrectnessG1
C9No cursor, batch or column read API; the data-oriented half has no contractMissing contractG1
C10Traversal.run consumes a MapResult whose coverage must therefore precede discoveryDesign inversionG3
C11The structured DFS enter/leave stream is promised in §8 and absent from the specimen, while G3 gates on itMissing contractG3
C12Redaction boundary between principal-scoped MapResult and unscoped Graph is unspecifiedCorrectness / policyG3

C1 — the specimen has no data plane. BlobRef is (schema, digest, byteLength): a reference, not bytes. It then carries nearly all real payload — CapabilityValue.value, ProjectionPage.records, EffectRequirement.resourceSelector, CommandRequest.input, TestDefinition.fixture and acceptance, EvidenceRecord.assumptions, result and targetProfile. There is no blob store, no resolve, and no codec interface in the file; CapabilityDescriptor does not carry one either. Consequently Graph.capability(id, key): T? cannot be implemented from the declarations given — nothing maps a SchemaRef to a decoder. A second consequence lands on the hot path: because EffectRequirement.resourceSelector is a blob, no authority check can name its target resource without decoding, yet §6 requires that check to sit in generated dispatch. Fix: add the schema/codec registry and a blob-resolution capability to the specimen, and make EffectRequirement name its resource in typed fields.

C2 — phantom type parameters. data class CapabilityKey<T : Any>(val schema: SchemaRef) binds T to no constructor parameter and carries no witness, so capability() can only cast. Because the key is a data class over schema alone, CapabilityKey instances for two different T with the same schema compare equal; a registry keyed on them resolves the wrong type silently. Contract<C> has the identical shape, which makes RuntimeIsland.bind(consumer: Consumer<C>): BoundService<C> an unchecked cast as well. Fix: give the key a decoder (CapabilityKey<T>(schema, Codec<T>)), or drop the parameter and return the encoded value honestly.

C3 — the interaction enum repeats the diagnosed defect. §2 charges ServiceTransport with naming PUBSUB, QUEUE and WORKFLOW without implementing their semantics; the charge is correct. The specimen then ships Interaction { Unary, Stream, Publish, Subscribe, DurableJob } while defining only BoundService.call and Publisher.publish. Stream, Subscribe and DurableJob have no session type, no demand signal, no close and no cancellation. §13's prose acknowledges this and defers the sessions, which is the right call — but then the enum should not name them yet. An enum value is a promise the type system will be read as having kept. Fix: reduce Interaction to the shapes that have interfaces, and reintroduce values alongside their sessions.

C4 — coverage collapses availability. §22.7 says, correctly, not to collapse assurance, source, freshness and availability into one Live boolean. ProjectionPage honours this with SourceAvailability. Coverage — the kernel's own type, and the one every map and traversal returns — reduces the same question to completeWithinDeclaredScope: Boolean. The rule should apply first to the kernel that states it. Fix: give Coverage per-frontier availability and freshness, and drop the boolean or derive it.

C5 — the frontier leaks counts. §11 requires partial, stale, unavailable and inaccessible boundaries to remain visible "without leaking unauthorized details or counts", and §16 carries the law that a map cannot elevate visibility. Coverage.frontier: List<Frontier> is a count, and Frontier.ref: EntityId? may name the entities. Unloaded and Unavailable are safe to enumerate; Inaccessible is not, and the type does not distinguish them. Fix: aggregate the inaccessible case into a single redacted marker, and keep enumeration for the other reasons.

C6 — identity is stringly typed. InvocationContext.authorityRef, ReadContext.principalRef and tenantRef, WorkbenchContext.missionId and runId, InvocationContext.causationRef and idempotencyKey, ActivationRef.instance, ProjectionCursor.generation and position are all String, as are the authorityRef parameters of ChangeProtocol.execute, GraphVerifier.verify and ProjectionRequest. §13's own preamble says authority references are "broker-validated references, never self-authorizing strings", and decision #2 rules that labels and class names are never durable identity. §2 then charges the current Port.Type with exactly this. The charge is if anything understated — Port.kt falls back to anonymous_${counter} for anonymous classes, so present identity is not even stable within a run. Value classes cost nothing at runtime and prevent the whole class of mix-ups. Fix: one value class per identity kind in the kernel, before any of them reaches a wire format.

C7 — EntityId carries no kind. EdgeRecord.from and to are EntityId, though §5 requires edges to name exact ports; nothing prevents a node id. PortRecord.owner could name an edge. §16's first law — every port has one existing owner, every edge has valid endpoints — is therefore a runtime check in a design whose stated pitch is typed records. NodeId, PortId and EdgeId make both violations unrepresentable and cost one line each. This pairs naturally with C6.

C8 — the patch fences only what it writes. Reads return SnapshotRef(definitions: RevisionSet, …); GraphPatch.base is a single Revision. A patch on partition B that was decided by reading partition A cannot express that read, so a concurrent publication to A permits a stale-derived patch to commit to B. This is write-skew, and §16's law "concurrent publication respects base revisions" is stated over the write set only, so the law as written does not catch it. Fix: carry the read-set (RevisionSet plus cross-partition entity preconditions) in the patch, and restate the law over the read-set.

C9 — nothing in the specimen is data-oriented. §6 mandates dense primitive columns, interned tables, primitive cursors and batches "to avoid per-element wrappers and boxing", and makes allocation count a release gate. The specimen's only read API is Graph.node(id): NodeRecord?, which allocates a record per lookup and hashes an EntityId holding a GraphId holding a String. There is no cursor, no batch, no column view, and LocalHandle(slot, generation) is declared and then referenced by no interface in the file. So the storage half of the title has no contract, and G1's exit gate exercises only the reference model. Experience says the pleasant API ships and the compact one does not, unless both are specified together. Fix: put the cursor/batch surface in the specimen before G1, and make G1's differential test run over both.

C10 — traversal inverts the large-graph case. Traversal.run(map: MapResult, …) consumes an evaluated map, and coverage is a field of MapResult, so the frontier must be known before traversal starts. In the 1m-node paged-inspection workload of §6 the frontier is discovered by the traversal. The two requirements cannot both hold as typed. Fix: make coverage a traversal output as well as a map field, or give bounded inspection its own entry point that does not require a materialised map.

C11 — the enter/leave contract is diagnosed but never written. §2's claim is exactly right and was verified: DepthFirstTraverser invokes the returned ExitScope, BreadthFirstTraverser discards it, and HierarchyVisitor's mapStack push/pop is therefore unsound under BFS today. §8 promises "a separate structured DFS event stream" with enter/leave guarantees. It is not in the specimen, while G3's exit gate is "BFS/DFS semantics and cycle/budget tests pass". A contract that is not written cannot be tested. This is roughly twenty lines and it is the one place the redesign fixes a bug that exists now.

C12 — the redaction boundary is unstated. MapResult is principal-scoped because it embeds ReadContext, but Traversal.run operates on map.graph: Graph, and Graph has no principal. If that is the raw snapshot view, a traversal reads unfiltered data and §16's noninterference law fails at the type level rather than at runtime. Fix: state whether filtering is materialised at map evaluation or applied at Graph access, and make the type say which.

23.3 Programme risk: §19 against §22

§19 is the right plan. One vertical slice, explicit compatibility adapters, retire nothing until evidence passes.

§22 then declares itself "the required adoption contract for the complete framework and desktop", and §22.9 requires, per module and provider and target, evidence across coverage, identity, dual surface, authority, lifecycle, projection, performance and developer workflow. Multiplied across 34 module/build directories and 74 subpanes, that is not an adoption contract; it is a second programme an order of magnitude larger than G0–G7, written in the same imperative voice and with no owner, sequence or budget attached.

Set against what exists — no continuous integration, a large majority of modules without a test harness, roughly 30 of 74 panes actually wired, and BestBuds as the only real consumer — the predictable outcome is that §22 is read as aspirational and then ignored, which costs the document its credibility, or read as binding and then blocks G1.

The content of §22 is worth keeping; it is the most complete map of the system anyone has written. The framing is the problem. Recommendation: demote §22 from contract to a target-state register — a per-module row with owner, status and evidence link, explicitly not a gate. Keep exactly one integration gate, G5's BestBuds slice. Let a module earn its row by adopting, rather than being pre-assigned a debt it has no plan to pay.

23.4 The missing artifact: a kernel v0

The document runs to roughly 1,300 lines and states on the order of 150 normative requirements. It does not contain a section that says: these are the types, laws and tests G1 ships, and this is what G1 explicitly does not do. §19's G1 row is one sentence, and §21 correctly refuses to pre-decide storage — but between them there is no buildable unit.

For a proposal intended to be implemented by agents as well as people, that is the highest-leverage omission. Forty lines would close it: the G1 type list, the four invariants it enforces, the differential test against the reference store, the acceptance numbers already given in §6, and the non-goals. Everything needed is present in the document; it has not been gathered.

23.5 What should survive unchanged

The honesty calibration is better than most production architecture writing and is the document's most transferable property. Specifically: the Apple 2.5.2 constraint on code push, the Cloudflare at-least-once note and the refusal to launder it into exactly-once, "hash the JSON is not a protocol specification", "a suspend function alone does not supply durability", the §6 performance table labelled as budgets to validate rather than results, the treatment of a timeout as an unknown outcome rather than a failure, and the "Validation of this document" paragraph that states precisely what was and was not checked. Also worth preserving: the consumer→provider preservation rule, the map/flow-selection distinction, and the four-way separation of data capability, runtime implementation, authority and effect.

Whatever survives redrafting, these should survive verbatim.

23.6 Verification log

Claims in §2, §21 and §22.1 that could be checked against source on 9 September 2026, at the working-tree state of the sibling workspace:

ClaimResult
DFS is recursive; BFS ignores the exit closure DFS invokesConfirmed. DepthFirstTraverser calls onExit(); BreadthFirstTraverser discards the returned ExitScope. HierarchyVisitor is unsound under BFS as described.
Type identity involves strings/KClassConfirmed, and stronger than stated: KClass.name() falls back to anonymous_${sequence}, so identity is unstable within a single run.
ServiceTransport names PUBSUB/QUEUE/WORKFLOW without their semanticsConfirmed; ServiceEndpoint.portType also formats transport identity as a string.
ReaktorProcessor.process() returns immediatelyConfirmed; the body is guarded by an unconditional early return.
13 mode values; visibleReaktorModes() lists 12; App mounted separatelyConfirmed exactly.
reaktor-tactile has no source in this censusConfirmed; the src tree exists and is empty.
34 framework module/build directories = 31 included root modules + dependeasy + standalone reaktor-cli + paused reaktor-reactConfirmed. settings.gradle.kts has 31 include( lines, includeBuild("dependeasy"), and //include(":reaktor-react") // will fix later. reaktor-cli carries its own settings file. This breakdown is precise; an earlier reviewer count of 33 was wrong.
All eight Kotlin blocks in this document match the specimenConfirmed by extraction and comparison: 8 fenced blocks, 433 non-blank lines, zero divergence in either direction.
Diagrams, inventory JSON and specimen exist and are reachable; document is registered in the nav manifestConfirmed.
Specimen compiles under Kotlin 2.3.0Not re-verified in this review. No finding above depends on it; unused type parameters (C2) compile without error.

Not checked: performance claims of any kind, provider behaviour, the accessibility-surface inspection reported in §22.1, and the 101-document/3,455-file corpus counts in §2.