Architecture
The backbone of MeshWeaver: message-based communication, the actor model, partitioned persistence, access control, and UI streaming. Start here to understand how the platform works under the hood.
MeshWeaver is a distributed platform for building data-driven applications with AI capabilities. A handful of principles hold the whole system together:
| Principle | What it means |
|---|---|
| Data locality | Process and render where the data lives — no unnecessary round-trips. |
| Message-driven | Every operation is a typed message routed through the hub; no direct object calls across boundaries. |
| Type as data | Node types live in the mesh, not only in compiled code — they can be authored, versioned, and released at runtime. |
| Agent-ready | AI agents reach everything through the same unified APIs as users — no special back-channels. |
| Security-first | Access control is validated at every read and write, not bolted on after the fact. |
Platform overview
Core concepts
Message-based communication
Message hubs manage concurrency through the actor model and route messages across the mesh.
User interface
UI is generated where data lives, serialized to JSON, and streamed to the browser with two-way binding.
Agentic AI
AI agents are first-class citizens that query the mesh for context and collaborate through messages.
Mesh graph
Hierarchical namespaces where data types attach at any level, with built-in semantic versioning.
Access control
Hierarchical, dimensional, and operation-specific permissions enforced on every read and write.
Deployment
Run as a single-process monolith or an Orleans-based distributed mesh orchestrated by .NET Aspire.
Topic map
Each theme starts with its introductory page, followed by related architecture topics.
Reactive core
- Start here: Asynchronous Calls — the no-
awaitrulebook - Actor Model
- Turn-Loop Arrival Order — a hub has TWO queues and a delivery moves between them at turn time, so a turn can be in neither when the last gate opens; the permutation names which message straddled the window, never which defect is live
- Controlled I/O Pooling
- Subscription Ownership — a pending timer is a GC root
- Silent Completion — an empty completion is invisible to every timeout
- AsyncLocal Across Scheduler Hops
- Initialization Gates
- What the DataContext Init Time-Box Bounds — the 120 s box is nested three deep (data source → stream → type-source leg), a per-node hub's initialization is in practice ONE unbounded storage read, and the timeout now names the leg instead of guessing "a stuck NodeType compile", which cannot reach it
- Retiring an Activation — a transient init fault retires instead of latching; the gate is failed BEFORE the dispose, because two drains cannot be ordered by a comment
- Stale State Until a Recycle — an activation serves what it bound and never re-reads it, so merged, sealed, rolled and restarted do not make a fix live at an address that is already up; what a
DisposeRequestchanges and what it provably does not - Aggregating Providers
- Hub Disposal Model
- Transient Node Probes — a probe hub's own address is not a node
- Executive Assistant Credential Reads — a turn that waits for a mesh read holds the queue that read's reply must travel through, and the timeout was rendered as "you never connected"
- Bounds Must Be Ordered
- Message-Based Communication
- A Request a Hub Sends to Itself — node CRUD is issued on the hub that executes it, so routing and the reply leg cannot lose it; what that leaves, and why an empty queue at the timeout proves nothing when the handler answers from a detached observable
- Router Traffic Detection — the detector has two sites; the receiver names the two addresses, the origin names the call site, and a ratchet per tree keeps the seams adopted
- No Static State
- Observable Hub Pipeline (migration design)
- Per-Hub TaskScheduler — Actor Isolation Across the Mesh
- Removing Hand-Woven Concurrency Gates
- Removing Observable-to-Task Bridges
- JSON Serialization
Reading & writing nodes
- Start here: CQRS — Queries vs. Content Access
- An Answer Nobody Gave Is Not Cached — a synced chain replays its FIRST frame for the life of the process, and a provider that completes without an Initial is counted as an empty one, so a cold moment used to become a permanent false "absent"; the frame now names who never answered and an unanswered frame is delivered but not kept
- MeshNode Stream Cache
- Update Queue Ownership — one published queue per path, retained until accepted work settles
- Request via Stream Update
- Expressing a Write — the four shapes a mutation can take (C# lambda, JSON Patch + text splice, full entity, other), which context may use which, and the lowering that keeps the fold owner-side
- Data Access Patterns
- Node Identity and Path Keying —
(namespace, id)is the key andpathis derived, so splitting a path positionally leaves the path identical while re-keying the node into a second row - Workspace References
- Content Chunk Navigation
- Moving Nodes — a move relocates the node and everything that belongs to it, or it refuses
- Copy Completeness — a copy asserts a set equality it never established; the two readings that turn a short enumeration from a silence into a number, and why the failure stops instead of rolling back
- Moved-Node Redirects — keeping links alive after a move
- MainNode and Rebasing — a
with { Namespace = … }copy un-lists a node with nothing logged - Write Verdict Totality — a write whose base read ends empty answers nobody, and arms no deadline either
- Reading a Base-State Timeout — "no initial state arrived within 30s" has two causes with two different fixes; the census that says which, and how to read one off a running deployment
- The Phantom Base After Owner Disposal — the owner echoes a merge BEFORE it flushes it, so a "never applied" NACK's re-attempt can find its own unpersisted write in the mirror, diff to nothing and report success
- Conditional Writes Across Hubs — on a node you do not own the lambda runs on YOUR mirror and ships a diff, so a field it decided not to write is absent from the patch and a concurrent write to it survives
- Live Mirrors and the Change Feed — a write must not end its own streams
- Stream Liveness and the Hub Reference — a stream outlived the hub it held, and the contract said it could not
- The sync/ Hub Population — a
sync/hub is one field of a stream and a subscription makes two of them; the only reaper of a Started one is an idle sweep the traffic keeps re-arming - A Hub That Pins Its Own Cache Entry — on Orleans every activated hub held the cache's live view of its own path for life, so the entry never released, its heartbeat kept the grain alive, and the loop closed; the one-shot own-node source that opens it
- The Evicted-Stream Retention — a change-feed eviction parks a remote stream and
ReclaimIfUnheldrefuses to dispose one that carries no lease entry, so every unleased call site retains one stream, and twosync/hubs, per change event - The Read Path Minted a Hub Per Read — a live in-process census decomposed a replica's
sync/hubs into their holders and pinned the growth on the read path: a constant configuration tookGetDataRequestout of the stream cache, so every read left a permanent hub behind (six reads, six hubs, measured on the running portal) - A Reference That Cannot Be a Key — the same defect through the other door: a record whose member is a collection is compared BY REFERENCE, so the reference can never hit the stream cache at all; every one of a replica's 311
sync/hubs attributed to its minting stream, and the duplicates split into "cache bypassed" and "key unhittable" by comparing the reference objects on the heap. Carries the census script, because the last two were lost - A Release Refused at the Source — the other direction: why the population never DRAINS. An
UnsubscribeRequestis the only thing that ends an owner-sidesync/hub, and on the hub-teardown route the subscribing hub is inDisposeHostedHubsby construction when it is posted, so the teardown guard refused it at the source and the owner was never told; theIReleasesRemoteStatemarker and the one-hop parent carrier - The Recursive-Delete Drain — the plan is a snapshot the removals may exceed, the completion check must include the ROOT, and the stage bound measures progress, not duration
- Deleting What Is Already Gone — an absent node already satisfies the delete's postcondition, so the delete succeeds and reports that it removed nothing; why checking existence first cannot close the race, and which absences are still failures
- Business Rules & Calculations
- Data Versioning Strategies
- Mesh Graph Architecture
- MeshNode Versioning
- Query Provider Parity
- Search Coverage and Refusal — the
searchtool answered an unanchored query with a clean 0 for nodes it returned when anchored; it now refuses a query that names no partition and declares no fan-out, and every envelope carriescoverage.partitions— the denominator a zero is read against - Query Result Scoring
- Reading a Write Verdict
- Satellite Entity Patterns
- Satellite Node Patterns
- Repairing a Stale MainNode — When the Broken Field Guards Itself
- Synced Mesh Node Queries
- Update Validators See Typed Content
- Content Is Validated Against Its Declared Shape On Write — content that cannot bind to its NodeType's declared content type was stored verbatim and then read as absent everywhere; the two shapes the write boundary refuses, the narrow rule that keeps legitimate writers landing, and the wire-boundary residue it does not close
- The /api/mesh REST Contract — a 200 carries the verb's JSON document and nothing else; a sentinel answer is a non-2xx JSON envelope naming the sentence and its kind
Storage & partitions
- Start here: Postgres Schema Architecture
- Partition Storage Routing
- Partition Teardown — deleting a partition ROOT drops its backing store; keyed on the node's SHAPE, never its NodeType
- Partition Storage Hubs
- Partitioned Persistence
- Storage Adapter Implementation
- Change-Feed Isolation — one throwing subscriber must never starve the others
- In-Memory Child Index Consistency — a listing taken while the in-memory store re-indexed came back short, a synced query cached it for good, and one NodeType's compile then failed on files that were there; the three rules that keep a reader from ever seeing a half-built index, and how it composes with the mid-install judgement race (#4280)
- A Container Registry in Memex — the fleet's own registry at cr.meshweaver.cloud (a separate distribution + docker_auth service), the bootstrap circularity that keeps the hosting instance's boot image off it, and the in-portal mirror that was built, never wired, and deleted (#4066)
- Static Repo Import
- The Prune Requires a Complete Listing — an import prunes on "absent from the source ⇒ deleted"; a truncated GitHub tree arrives as HTTP 200 and turns every unread file into a deletion
- Import Write Ordering — a NodeType lands before the instances that name it
- Import-Side Content Degradation — a typed file whose own parser is absent on the importing host lands as Markdown with its configuration discarded, and the read-side degradation instrument is blind to it by construction, because the content it wrote types perfectly (#4319)
- Vector Search
- Durable But Unreadable — a write that is acknowledged, versioned and invisible
- Instance-Key Resolution — the registry reads an instance key through live mirrors, never a per-request point read
- Cross-Schema Fan-Out Elimination — an unanchored query is a lock bomb; the census and the per-caller plan
- Addressed Notifications — plan 1 worked out: deliver a notification to its addressee so the bell reads two schemas, not 199
- Content Indexing Activation
- Cross-Instance Mirror
- Data Synchronization and CRDT
- Setting Up Data Sync
- DatabaseBackups
- Declarative export and import
- Syncing a Space with GitHub
- What a Green Build Costs a Synced Space — one field decided whether a delivery was free or a full clone, and it is deliberately frozen while an import does not converge; the second, weaker pointer that makes a settled source free again, and why the skip needs the verdict to be FINAL and not merely recorded
- When a Publication Seal Stops Advancing — a Space converges on a green build only while the publication sealed for THIS instance's framework identity keeps reaching the built commit; when the instance's identity and the lane that publishes for it drift apart that condition stops being satisfiable, and until the hold was recorded on the node a held source was byte-identical to a settled one
- The Import Marker Records Convergence
- A Content Verdict Is Per Node — one unstorable byte in one file earned a partition-wide "these bytes cannot import" verdict and took every instance action offline for an evening; where the refusal is remembered now, and what an import must name when it loses a node
- A Parked Type Names the Import — a NodeType failing on
CS0246for a symbol whose file is plainly in git is an IMPORT state, not a code one; how the compile failure is joined to the import that lost the file, why the join is scoped to the types that actually reference it, and the three answers it keeps apart so an import is never accused of a deletion it did not make - Instance Sync — bi-directional space replication between MeshWeaver instances
- Managing Partition Sync (Admin Guide)
- Static Node Providers
Security
- Start here: Access Control
- Granting Access
- AccessContext Propagation
- Query Identity — an unstamped read answers as Anonymous, which reads as absence
- Owner Injection
- Permission API
- Invitation-Only Onboarding
- Logon Actions — per-user work at logon, run as the user
- Unanchored Security Reads — why the permission fold reads mesh-wide, and why pinning it to the viewer's partition is a silent revocation-fails-open bug
- A Denial Is an Answer — a check on a hub with no evaluator grants Permission.All, and a refusal the mesh decided is rendered, never raised
- PublicRead and Denies — a Public/Anonymous deny under a
PublicReadpolicy is honoured by the SQL read path and ignored by the C# evaluator; what that split exposes, and what each remedy costs - Who Owns a Partition's Access Shape
- Partition Ownership Resolution — the four create-path checks that ask whether a NodeType owns its partition, what one resolution costs for a type declared in mesh content, which of them share ONE view and which deliberately keeps its own, and how a nested instance of such a type is refused from the definition's durable row without activating the type's hub
- Protected Segments on a Public Partition — a partition that is public except for one inbox cannot be expressed with
PublicRead: the C# evaluator and the SQL projection resolve a deeper deny under it differently, so the segment reads by exact path and is absent from every listing. The grant shape both folds agree on, why a read cap is a blackout rather than a gate, and why the boot heal may never retire a deny it could not have written - OWASP ZAP Scan — 3.0.0 (6 September 2026)
- OWASP ZAP Scan — Every Release
Threads, activities & AI
- Start here: Thread Operations
- Thread Supervision — a round ends stamped, whatever failed; the one death the hub cannot cover is its own, and the supervisor, dispatch pool and
Admin/Threadsqueue page that cover it - Agent Task Collaboration — launch shared work only through
start_collaboration; participant effort, harness, and model are creation-time settings, not follow-up-message overrides - Thread Execution Streaming
- Activity Control Plane
- Activity Mirror Release Lifetime
- Activity Operations
- Notifications
- Notification Retention — the platform's first data-retention pass, and why it is a logon action
- Agentic AI
- Script Execution
- Agent Framework Stores — mesh nodes behind Microsoft's abstractions
- Centralized speech — Whisper Swiss German as a container
- Email Ingestion, Channels and Notifications
- Event Subscriptions — the durable 'when THIS fires, run THAT' engine
- Foreign-Language Bridge (Python, Bun/Node) over gRPC
- Foreign-Language & Cross-Platform Integration
- Model Providers and BYO Credentials
- On-device voice — Whisper + Swiss German
- Voice model distribution — where a 547 MB CC BY-NC model may live
- Python Code Nodes
- Script Execution — Try It
- Sending Email
UI
- Start here: User Interface
- Blazor Data Binding
- Editor Field Keys — the node-content editor binds by JSON key, so a rename behind
[JsonPropertyName]or a value the serializer drops discards what an admin set, silently and permanently - Per-Tab Session State — a node is shared by every tab of one account, so "which page is this viewer on" and "navigate ME there" can never live on one
- Blazor Async
- Available Controls
- Node Page Provenance — the landing page carries "who wrote this, and when" by default; declining it is a sentence, not an absence
- Menus as Data — re-word a menu without a build
- The Menu Contribution Boundary — what may be data, what stays compiled
- Markdown Fence Extensions — the platform emits a marker, the clients hydrate it; a new fence is always a two-repo change
- Localization — the viewer's language, resolved explicitly, never from ambient culture
- Chrome and Content Language — ownership decides the language, and in-flow chrome minimises words
- Localized Refusals — a
*Response.Erroris a wire field and stays English; the activity transcript is the surface a viewer reads - The Supplied Navigation Rail — a module supplies its own left-hand index, and core renders it in the order the module gave
- The Apps Home
- Content Favicon Rasterization
- Controls That Cannot Fail
- Catalog Action Identity — a retained click keeps its package when the catalog refreshes
- Link Previews
- Public Web Presence — one public host, a body in the first response, a sitemap that descends to every page a stranger may open
- A Zero-Root Sitemap Is an Assertion — the sitemap projected the tri-state anonymous gate onto a bool because omitting ONE undecidable page states nothing; omitting every root produces a 200 that says the deployment publishes nothing, so an empty surface nothing decided is now 503 and a partial one is still published
- Local-First Client & Bootstrap
- PDF Export — one browser, two fidelities
- UI Extensibility
Node types
- Start here: Adding a New Node Type
- Creatable Types — what may be created under a node: the one provider the Create form asks, what a parent NodeType restricts, what it extends, and why a parent that declares nothing must never narrow the menu
- Retiring a NodeType — the prune keeps the definition and deletes its sources
- Dangling NodeTypes — a node whose type resolves to nothing, and the two write paths that allowed it
- Node Type Compilation
- Who Owns a NodeType Member — the repo owns the definition, the mesh owns the compile state, and the mask that encodes it was pinned in ONE direction: four runtime-state members were missing from it, one spelled outside the naming convention meant to catch them. The three guards, and why a member the mesh writes may still have to stay unmasked
- Compile Cache Input Freshness — verify the captured input before reusing a DLL that finished after a source edit
- Execute-Time Interlock — a build proven stale is never armed
- Emit Reference Capture — bounded, opt-in CI evidence for runtime compiler failures
- Graph / Compiler Layering — the four assemblies, the cycle, and the full-MVID size rule
- Toolchain Re-evaluation Lane — why a toolchain change stopped rebaking the world
- The Dependency Record Floor — a record's module entry says "I need at least X", not "I need exactly this build"; the MVID pin that could not converge because Roslyn hashes absolute source paths, the two-replica recompile ping-pong it produced, and the four things the floor deliberately does not relax
- Reading a Module's Stamp — reading ONE assembly-level attribute through reflection resolves the type of ALL of them, so a module with a private dependency killed the version read with a nine-frame reflection stack naming nothing; the metadata read that fixes it, and the measurement (23 of 24 declared modules carry a module attribute —
MeshWeaver.Mapscarries none) that says module-ness is a deployment fact, not a property of the bytes - An Unloadable Build Is Never A Silent Default — a recorded build that does not LOAD in this process used to bind the mesh default configuration for the grain's whole life; the always-activated Hosting/PlatformBuilds hub that ran twenty hours without its inbox, fleet watch and build queue while its record read Ok, and the two hypotheses (a missing module, "a restart activates it") the measurements refuted
- Producer Determinism of the Dependency Record — the same content must stamp the same record however the producer reached its bytes; the disk-cache hit that shipped a weaker guard, and why the digest is persisted beside the bytes rather than recomputed
- Rebake Waves — why a roll rebakes the world anyway, and what one rebake writes
- Source-Set Establishment — a resolved source set of ZERO is ambiguous, and only the type's own persisted snapshot tells "owns no Code" from "the discovery pass came back short"; the boot that resolved 91 fewer Code nodes than its neighbours and held a portal out of rotation for the startup probe's full three hours
- Missing Declared Sources — emptiness measured on the UNION is invisible for any type that also draws on a shared library; the NodeType whose own Source subtree was gone, reported itself as broken C#, and had the identical doomed compile taken again on every boot for four days
- Compiled Against A Platform The Instance Does Not Run — the source compile gate ran and PASSED: it compiles against the platform CI is about to ship, while the receiving instance is still on an older image. Six NodeTypes on memex-cloud stopped compiling forty minutes after that satellite merge; why the prebuilt was declined and Roslyn ran, and why the
CS1061localizes the fault to the platform surface without saying which side moved - Install-Time Prebuilt Adoption — the only lane that serves a package installed AFTER boot, and the four answers its zero must keep apart because a silent non-adoption reads exactly like a successful one
- Adoption and the Sweep Count Different Things — the cold boot that adopted 78 prebuilt assemblies and then reported 5, with nothing wrong on the share: what each instrument counts, why the sweep could not see its own process's writes, and the node-version ordering that keeps the fix from becoming a stale serve
- A Census That Counts Must Name — the one past-RLS census counted a permanently-broken NodeType and dropped its path one call before publication, so its output read as clean; where the identity was lost, what a PUBLIC census may name (the partition, never the node title), and how to tell a fix that is merged from a fix that is running
- Import Write Ordering — type before instance, and what a foreign type does
- Language Services
- Extensible Defaults
- Build coordination — the Build node protocol
- Build Identity Admission
- The Build Process — compile and test as a dependency cascade
- What a Pull Request Rebuilds
- The Build Server
- The Compile Program — State of Record
- Content-Type Registration
- Import-Side Content Degradation — the OTHER half: content degraded at IMPORT rather than at read. The
/healthcontent-typescensus cannot see it, because an import-degraded node holds a plainMarkdownContentwhose$typeresolves perfectly on every replica - NodeType Catalogs (shipping instances of a NodeType)
- NodeType Release Redesign
Plugins & content delivery
- Start here: Plugins — node repos from git, no NuGet
- Plugin Manual — author · publish · install · own registry
- Plugin Registry — memex re-serves plugins over REST
- Webhook Inbox — external services deliver into /_Inbox
- Plugin Packaging — bundles, the framework identity, and the
Releasenode that links a release to its assemblies per architecture - Install Readability — the two doors an install can open, and the cover-grant deadlock detector
- A Module's Static Web Assets — a module's CSS/JS ride the bundle in their own folder and must land MODULE-RELATIVE beside the entry assembly; anything that copies only the closure loads perfectly and 404s every asset behind one Debug line
- Static Repo Import
- Adopt Then Sync, Per NodeType — the seal is a REPOSITORY fact and adoption is a per-NodeType one, so landing a Space on the sealed commit is not enough: an adopted type's sources wait for the bundle built from them, the rest of the Space imports, and a partially-held Space keeps the commit it genuinely holds
- The Sync-Ref Contract — an import of a repository whose bundles this instance runs lands on the commit they were baked from, whoever asked — a person's Update included since 2026-09-17; every other repository reads a commit CI proved, or a branch tip a person asked for; resolving the ref twice put sources no build had compiled onto two production portals for five hours
- Node Type Compilation
- The Platform Image's Closure — the image IS the reference set every satellite's modules compile against; the two invariants, and why every consumer used to discover them by failing to compile
- Compiled Against A Platform The Instance Does Not Run — the link gate measures a module's bytes against the platform ACTUALLY RUNNING; the source lane measures Code nodes against the platform it is about to ship, and
judge-against-baseline— the arm that reads what the fleet runs today — is wired into core's promote, not into the satellite PR where the content half lands first - Sealed Publication Reads — a publication is unreadable for ~90s per target per publish and the
pluginsprefix has two writers; the three answers (404/503/412), the generation that pins one instance, and the mix no reader can detect - Sealed Publication Generations — the layout that makes that mix UNREPRESENTABLE (a directory per publication plus a pointer swapped last), the reader contract, the retention rule, and the ordered migration that avoids a new-writer/old-writer half-state
- Install Completeness — what an install RECORD declares landed, compared against what is actually in the mesh; the comparison nothing made until #3485, and why only one of its five verdicts is a pass
- Declared Is Not Landed — the three exits an install can take and the one that never looked at the mesh: an UPDATE fetched the manifest diff alone, so a node lost after a previous install survived every subsequent update, each reporting success. The measured case, the batched presence read that fixes it, and the sweep hazard that made the damage read smaller than it was
- One Partition, One Bookkeeping — a partition written by BOTH a GitSync source and the registry installer keeps two independent records of one mesh; the seal reconcile rewrites the content and the next registry delta is computed against a record that stopped describing it, so
Storeon memex became a mix of 1.10.3 and 1.11.1 andStore/Catalogparked onCS1061. The invariant, why resetting the record or diffing the mesh both produce a ping-pong, and the two gates - CI Content Bake
- The In-Mesh Warning Standard — in-mesh C# is the only C# no
-warnaserrorbuild ever sees, and the bake was discarding its warnings too; the two shrink-only ratchets (real warnings, and CS1591 on its own), why the RUNTIME compile must stay lenient — a parked NodeType refuses readiness and stalls a rollout — the three codes the platform itself was emitting into content it does not own (850 raw occurrences → 375), and the observe-only default that lets a repo adopt without going red - A Gate Must Compile the Same Program — the pre-push NodeType gate compiled each source file on its own while the mesh concatenates them into one unit, so a nullable-context directive in the first file (in force in the last) reached nothing and the gate was blind to diagnostics the bake then filed under the NodeType's name with no file and no line; what the unit boundary decides, the culture-sensitive
StartsWiththat a naive reproduction gets wrong, and the parity test that caught it - Bundle Delivery Stages — the four independent stages between a merge and a portal serving prebuilt bytes (write · compose · select · deliver), which of #3461 / #3732 / #3768 / #3583 owns each, the instrument that answers for each — and why a reading taken at one stage is not evidence about another
- Framework Identity Churn — the identity moves on every core COMMIT, not on every content change (43 merges, 5 touching the full-MVID set, ≥18 identities in 24h); the commit sha compiled into
AssemblyInformationalVersionis why, the falsification test that refuted the local fix (0 of 22 control, 22 of 22 and 21 of 21), and the four costed options with every runner-hour labelled as arithmetic - Prebuilt Bundle Retention — the sweep that prunes what CI bakes: where it is registered (and why "zero callers" was measured twice and wrong both times), the deletion default that is
truein code andfalsein the chart, the report that names its denominator, and the pinned satellite gate the protected set cannot see - Deploying a plugin change — merging is not shipping
- Module Activation Head Ownership — which generation a deployment runs is a decision every replica writes to ONE shared file and replaces unconditionally; why the same-content case is already benign, why the regression propagates into the proposed module set rather than being bounded by it, why routing the write to an owning hub is a cycle (boot reads the record before the mesh exists), and what deriving the head costs measured rather than estimated
- Module Adoption Policy
- Publishing A File On A Shared Volume — a name readers watch must appear holding the whole file or not appear at all, and
File.Move(…, overwrite: false)does not promise that: on a volume without hard links (Azure Files) its failed rename COPIES into the final name, which is then incomplete and exclusively locked for the length of the copy (measured: 21,573 sharing violations, 52,619 incomplete reads, ZERO "absent"). The primitive that replaces it, what it refuses rather than copies, and what is still not atomic - Module Build Architecture
- Module Closure Accounting
- The Module Identity Anchor
- Two Identity Schemes, One Comparison — a bundle states a
g<sha>commit identity and a portal resolves ans<hash>surface identity, so the #4161 discriminator answered "different" for every pair in the fleet: measured on memex.systemorph.com, eight modules declined on every boot and reported as "a restart activates them" across a restart that could not clear one of them - Module-Owned Siblings Ride
- The Module Platform Link Gate
- Rolling-Update Build Tolerance — why a rolling platform update recompiled Store/Plugin ten times in four minutes and blanked every instance behind "build did not settle within 30s" (two generations, one record, one framework identity per record), and the rules that let an instance render on the last build its process can load instead
- The Module Publication Gate — a bundle used to reach the live registry from inside its own pack leg, before the sibling suites, the portal-host shards, the compile-check and the Tests-area gate had reported; the hand-over moved downstream of the full source verdict, and what it refuses (failed, skipped, cancelled, missing, foreign-lane, substituted)
- Module Generation Substitution —
Assembly.LoadFromdoes not promise to load the path it is handed: a byte-identical copy the load context already holds is returned instead, silently, so the loader recorded the generation it ASKED for while the process ran another; the three answers that replace two - Module Set Convergence
- Module Versioning
- Modules
- Required Module Authority —
Modules:Requiredis an array and configuration merges arrays BY INDEX, so a record's list is an overlay and not a statement: a shorter list leaves the image's tail required and an EMPTY list requires MORE; the scalar claim that lets a record say "these and only these", why it is opt-in, and the two instruments that make the gap visible - Package Mark Inheritance
- Pin-Boundary Contracts
- Platform and content — two layers, two cadences
- Platform Build Identity
- The Platform-Shipped Witness
- The Plugin Build Contract
- Plugin Bundles in the Registry
- The Registry Listing Cache — GET /api/plugins re-read the whole repository per request and blew its 30 s budget ~60×/day; what is cached is the SOURCE snapshot, never the response, which is what keeps the fix from becoming a disclosure — and the read itself now transfers only the manifests it parses (47.8 MB / 13 s becomes 1.3 MB / 3.3 s) instead of the whole repository
- The Bundle Transfer Budget — a module adopt's 120 s attempt used to cover the whole archive download, so the budget measured size ÷ throughput instead of whether the registry was answering; 18 adopts failed at exactly the outer 3-minute bound recording neither bytes nor elapsed time, which is why they could not be explained
- Plugin Publication Provenance — the signed publication callback names the CONTENT commit that was built and the platform version read from the selected portal image, never the calling workflow's commit or event; core CD building Plugins used to announce a core sha as a Plugins commit
- Plugin Update on Green Build
Reliability & wedges
- Start here: Error Propagation & Wedges — drive wedges to 0
- Which Kind of Silence — a quiet log has four causes with four owners; the liveness heartbeat that separates them, and the CPU sample and page snapshot that agreed with the wrong one
- Action-Block Wedge Prevention
- Riding Out a ShuttingDown Address — the one transient NACK, and the two axes a ride-out must bound separately
- Hub Initialization Failure
- Orleans Stream Pub-Sub Durability — a publish with no subscriber succeeds, so a cross-silo reply can vanish with nothing logged
- Durable Streams Are Mesh Nodes — the design that retires the memory stream without a provider
- The Pod-Hub Claim Must Be Re-Asserted — a claim asserted once into a directory that is re-partitioned on every membership change is lost silently, and forever
- Oversized Delivery Refusal — a message too large for its transport destroys the connection carrying it; refuse at the producer, never raise the limit
- Content Sync Visibility — a Space whose assets the transport refuses says so, on the Space itself, naming the file, its size and the limit
- Out-of-Band Content Transfer — a content file too large for one delivery travels through the content store behind a content-addressed handle, never on the message
- An Unreachable Store Is Not a Refusal — one classification, three consumers; reporting an availability failure as a verdict is how a retried create becomes a duplicate
- A Name That Does Not Resolve Is Not Transient — the default pipeline retried a hostname that does not exist three times and logged each attempt at Error, so a URL in somebody's data manufactured a platform incident; the one socket error that is permanent, why the breaker must not count it either, and the control that keeps a nameserver hiccup retryable
- A Departed Silo Is Not a Delivery Defect — two incidents (191 and 3,959 occurrences) read as two defects for four weeks and are ONE root; which predicate sees which of the four rejection shapes, why the cure is the classifier and never a retry, and why an incident fingerprinted on a dependency's logger counts attempts rather than verdicts
- A Timed-Out Delivery Is Still Held by the Callee — a response timeout is a caller-side give-up timer, so the six-retry ladder sized for an instant rejection re-sent seven copies of every slow delivery and held a dispatch slot for 3 m 40 s; the three-predicate ladder that separates "is this transient" from "may we send it again", and the one caller that keeps the wider answer because it is idempotent
- A Bulk Create Compensates Per Node — every row is durable before any post-creation handler runs, so one critical failure left the failed node AND every node after it, whose handlers never ran and which nothing can tell apart from a success; what the rollback removes, why it walks backwards, and the measured reason the stop is a fault and not a
Take(1) - Undetermined Is Not No — a read that did not answer is a THIRD state; the second door that shared the first door's failure domain, and the rule for what a gate does with "I could not determine"
- Reading a Silo Eviction — a heartbeat newer than the suspect votes is not proof the silo was healthy; the control arm that tells a correct eviction from a false positive
- Dead-Circuit Fan-Out Storm — a closed tab's owner pushed to the corpse for 46 minutes because the only verdict the eviction acts on could not be said; the release tombstone that says it
- Bake Seal — NodeOps Saturation — the mesh's ONE node-CRUD hub stops draining under a bulk burst, and every consumer then reports its own bound
- The /api/content 503 — three causes with different fixes, why the third wears the first's signature, and the black-box discriminator that needs no log line
- Refused Replies During Teardown — every failure route answers the SENDER, which for a reply is the responder; the answer the caller is parked on is dropped with nobody told
- Refusing a Lost User Action — a click whose stream is gone is refused out loud instead of dropped as churn; why "deliver it anyway" is not implementable as stated
- Guards and Unknown States
- Mesh Admission
- Mesh Lifecycle — Build Up & Tear Down
- Pod-Hub Delivery — the Transport Swap and its Roll Plan
- The Portal Heap Is Hubs
- SignalR Mesh Participant — joining the mesh over a WebSocket
- Teardown Layers — work finishes, nothing is forced
- Teardown Verdicts Are Causal, Not Timed
Testing & debugging
- Start here: Writing Tests
- Negative Controls — a pin is only a pin if it fails against the defect
- Reactive Test Assertions
- Test State Isolation
- Disposable-mesh e2e
- Debugging Message Flow
- Debugging Disposal & Leaks
- Departed Platform Assemblies — an assembly that leaves the platform for a module breaks every OTHER module that binds it, at LOAD time and invisibly to every compile gate; why "those are the platform" is one answer per host
- Detached Response Continuations — why a
hub.Observe(...)continuation runs on the RESPONDING hub's action block, what that cost on the mesh's one node-CRUD hub, and the six invariants that make the hop an opt-in rather than the default - Reading a Disposal Stall Verdict — what each field of the disposal snapshot actually measures, the three that were read as evidence while measuring nothing, and the verdict hole that sent 47 reports to children that were not the problem
- A Failure Report Answers Its Own Instruction — a report that says "find why this hub disposed" while holding the answer, and an outstanding-work field that rendered "not measured" identically to "none"
- Ambient Test-Host Hangs — what decides whether a killed test host can be diagnosed at all, and the readings of it already falsified
- In-Mesh Tests and the Seal — a Tests area no required context executes is a latent trunk red the seal detonates fleet-wide; how to measure a gate before requiring it
- Cancel and Join Are Two Questions — a deadline that asks work to stop and a deadline that waits for it to have stopped must not share one clock
- Collection-Scoped Test Fixtures
- Debugging Native Crashes (core dumps)
- Peer Death Is Dated by Its Exception Class — a frozen silo and a dead silo raise different Orleans exceptions, so the changeover between them timestamps the crash; how one pod's SIGSEGV became three issues, and how to get a dead pod's own account out of Loki
- Reading the Memory Watchdog — a step with no mesh class active is a plain test class, a ramp across mesh classes is retention; the guard states what it measured, never a cause
- Debugging Postgres in Prod / Test
- Decentralised Tests
- Gate Content Assets
- In-Mesh Build and Test
- Orleans Test Routing Pattern
- Reading CI Signals
- The Canonical Node-Test Harness —
run-node-tests.pyhas one home and the satellites launch it; how three vendored copies broke silently and differently the day the compile model changed, and why the one-line revert is measurably not the fix - Which Attempt an Artefact Belongs To — a run holds every attempt's artefacts and the API names no attempt; how the required check consolidated attempt 1 over attempt 2's green and could not be re-run to green
- Workflow Permission Pairing — a job-level
permissions:in a shared lane is a requirement on every caller; an unpaired one isstartup_failurewith zero jobs
Deployment & ops
- Start here: Deployment (the router)
- AKS
- Database Migration Procedure — the schema moves before the image, every roll; the 2026-09-03 wedge behind a 200, the recovery, and why a migration deadlocks under load
- Container Apps
- In-cluster databases — each instance's PostgreSQL as its own Helm release: a CloudNativePG Cluster on a dedicated
dbnode pool, primary and standby in two zones; why neither the chart's bundled Postgres nor the shared Flexible Server serves a client instance - Local Dev Workflow
- Onboarding a New Environment
- Unclaimed Control-Plane Requests — an InstanceAction at version 1 with an empty log means "queued", "nobody is listening" and "the operator died holding it" in the same bytes; the 2026-09-10 measurement, the
Ops/Statusstaleness that DOES discriminate, and the acceptance signal that does not exist - Release & Self-Update Strategy
- Release Channels — a channel is a named, moving pointer to an immutable release;
latestis derived and onlystableis promoted, and a channel names what to SELECT while the selection always resolves to an immutable id that is what gets pinned, recorded and run - Release Support Policy
- Released Artifact Retention — retain artifacts for at least 30 days, supported releases for their support lifetime, and every artifact still needed by a published set or consumer
- Self-Update Target Selection — candidates are ranked by the CD run number, not the version string; a mislabelled line outranked every sealed set for ever, and an install on a withdrawn tag could never see anything newer
- The Self-Update Registry Credential — which plugin-registry key may be presented to a container registry: a DECLARED pairing, never host equality or name resemblance; an absent declaration refuses
- Self-Update on the Control Lane — detection stays on the instance, the apply is one signed event to the control instance, the chart's one declaration binds the self-patch Role to the poller's intent; no portal holds a credential that changes the cluster
- The Continuous Delivery Contract — all-or-nothing publication; verify the image, never the tick
- Why the Fleet Stopped Rolling Itself — the September 2026 measurement: a frozen
heldReasonis history, not a hold; a policy record that lost its own policy; "waiting for an approval" is not a freeze; and the seal that a cross-repo pair skipped - Reading a Bake Publication Receipt — the four target outcomes and what each licenses; the one that had no word rendered "already everywhere" as "reached nothing", and two readers acted on it
- CD Reconciles the Plugins Seal — a set seals on its trio alone, so it can seal with no
pluginspublication for its framework identity; why the reconciler REPAIRS that rather than the seal forbidding it, and the three probe answers of which only one licenses a re-attempt - The Self-Update Schema Wall — every schema-bumping release is un-takeable by self-update, the stall is invisible, and a promoted tag is not a deployable tag
- Bake Identity Mismatch — why a green CD can publish a bake no portal adopts, and the one rule that keeps two images of one commit on one address
- Release Availability Gates — one predicate; never roll or build into a release a package cannot survive
- Adding a Data Sync Needs a Global Admin — a sync is a standing grant, not a one-off action: it keeps moving data indefinitely under an identity nobody re-examines, so the review at creation is the only one there will be. The trigger list, what is explicitly NOT covered, why a credential request instead of a proposal is the anti-pattern, and the one finding that blocks rather than being filed
- Policy Not Prose — never hard-code a decision's date or author into source, a comment, an XML doc comment or doc prose; a policy is a record with a value and an in-force date and everything else cites its id. The register, what counts as evidence rather than a policy marker (and so stays), the review finding, and why it is forward-only with no backward migration
- Issue Taxonomy and the Release Readiness Gate — four axes on every issue, and the one that is a gate:
sev:Bandsev:Hmust both be zero to cut a release; why only bugs carry a severity, why a zero is only trustworthy when its query's coverage is, and why the ledger stays in GitHub rather than being mirrored - Combo Gate Wiring — the roll consults the combo verdict; Red refuses, and "could not find out" is neither
- Roll Selection — completeness as a SELECTION criterion: pick the latest release that ships all of an environment's plugins, refuse an empty denominator, and never roll backwards
- Release Process
- NuGet Package Retirement — two packages survive (the Aspire integration and the
dotnet newtemplate) and the other forty-three are unlisted; what unlisting does and does not break, the derived retirement sweep, and the ground rule that startup dependencies become Aspire options rather than new packages - Repository Dependency Direction — the platform never depends on a plugin repo; the inventory of every edge that still does
- The Cross-Repo Pair Gate — a removal here reds a plugin repo's trunk hours later; the deleting half lands LAST
- Platform Script Resolution — a repo runs the platform's gate scripts, never a copy; the local runner must resolve the ref the LANE resolves, which is per-script, so a loader copied from another repo refuses on every call (one repo demands one lane sha, another pins four and the pin gate calls that consistent)
- A Stale Run Listing Is Not a Broken Main — GitHub serves the platform resolver a weeks-old page of workflow runs, per call and with no error (three measured); why only one of the two listings can be checked, why neither retries, and the refusal wording that sent two readers at a
mainthat was fine - Keeping the Platform Source Pin Current — a satellite pins WHICH core commit its
src/compiles against, the image set had a mover and the source ref had none, and a bump PR opened withGITHUB_TOKENis a PR no CI ever runs - Transitional Allow Entries — an allow entry is written for ONE merge and expires with it by mechanism; the instruction that was ignored once cost every C#-touching PR in the fleet ~40 minutes of red
- Pinned Image Retention — registry retention deletes what CI pins, and republishing frequency is what destroys a pin rather than what protects it; the guard that names a dead pin, and the retention design that stops the deletion
- Artifact Retention Interlock — the one mechanism behind the four retention issues: cleanup may delete only what a COMPLETE and FRESH consumer inventory shows to be unreferenced. Three axes (the third asks each installation what it is RUNNING, because a committed pin is a proxy that drifts), the denominator every run must state, the TAG lock a manifest lock does not provide, and the instrument control that replaced an assertion about the fleet
- CI Artifact Storage — where CI's big build outputs live: the measured $260/month GitHub Actions storage bill and the org budget that decides whether a private repo can upload at all, the ONE artifact family that is read across runs (and why most of its bytes are duplicates of themselves), the 66.8 GB uploaded for a reader that was never built — and the stale checkout that made "nothing reads this" wrong, why an EXPIRED artifact is still billed and still deletable, the object-store seam and the degrade rule that keeps the public repo working, and the grants and the one variable the migration still needs
- PR Artifacts on Our Infrastructure — moving PR compute to our runners did not move its artifact BYTES: the named-artifact transport (
store:on the shared upload/download actions, a declared store that cannot be used being an error and never a quiet fall back to GitHub), the partial-rerun selection rule, and the four rollout gates that separate "the transport exists" from "a private PR uses it" — including why queue admission is not a native build worker - Fleet Registry Retention — the same question asked of
cr.meshweaver.cloud, the fleet's OWN registry and the default for new instances: what deletes today (nothing — enumerated, with the one row that is a maintainer read), and why a registry with NO LOCK needs a stricter rule than the ACR rather than the same one, because there the derivation IS the whole safety margin - The Image Tag Contract — which image tags the promotion actually publishes, why the portal has no
latest, and the two-writer history of the one that had no producer at all: retired lane, then retention, and every check green throughout - Pin Set Consistency — every pinned digest EXISTING is not every pinned digest naming the same BUILD; the invariants that red a half-moved set, three written deliberately weaker than the obvious version, and the falsification that found the vacuity trap inside the gate itself
- Duplicate Keys in Workflow YAML — a duplicate mapping key is accepted silently and the LAST one wins, so a pin can move in the diff and not in the job; the near-miss, why every existing gate was blind, and the guard that names the file, the key and both lines at the first job
- Image Pair Skew — a promoted image pairs a core commit with a Plugins head resolved hours later; each half green, the pair never run (the 2026-09-03 sign-in outage)
- The CD Ledger Records a Failure, Not a Cadence — 109 of 109
incomplete image setalarms recorded a delivery that had not failed: the pair tag that cannot be satisfied because Plugins merges faster than a publish takes, the minutes before a publisher even exists, the registry fingerprint that separates an attempt from an absence — and the rebuild-cadence decision this deliberately leaves open - The Merge Queue — one entry built at a time so nothing churns, and a steward that re-queues an ejected PR on evidence and never re-runs
- Review Findings Answered — a pull request reads red until the automatic review has landed and each thread it opened has a person's reply; the reviewer's two logins, the quota refusal posted as a review, and the maintainer-only waiver
- Carving Projects Out Of Core — what a SOURCE move costs and what it does not
- Red-Log Watching & Ticketing — every
fail:/crit:becomes exactly one triaged issue - Log Entries Are a Query Result, Not a Feed —
Hosting/LogEntryis the output of oneLogsaction, so an absence in it is evidence of nothing; the denominator printed on every row, the level that lives on a different node, and how to ask for a line that carries an answer - Verifying Chart Values — a key can be set, reach the render, and still not be read; why the obvious gate was vacuous for the one component it existed to guard, and the binary check that closes it (the drain that erased every namespace's log history)
- Measuring a Live Portal Read-Only —
/healthfirst (public, past RLS, a different replica each call), the incident store, the four break-glass instruments, and why an absence needs a coverage fact before it counts as evidence - Chart Ownership and the Runner Pool — why the chart's gate is here, what a relocation must carry, and why path-filtering it is unsafe
- Sharding the Node-Repo Gate — a cap cut reports as
cancelled, so the fan-out that removes it, and the fold that keeps ONE required context and ONE gate log - Applying Is Not Rolling Out — helm applies, the caller observes; the fixed fifteen-minute
--atomic --waitthat reverted a correct upgrade mid-startup-gate, and why a bigger timeout only moves the cliff - Probe Semantics — readiness, liveness and startup ask three different questions with three different remedies; why they get three paths and three tags
- A Probe Must Answer Inside Its Own Timeout —
/healthreached 8-10 s against the 5 s the startup probe waits, so a healthy replica could never leave startup and was killed at its 3 h budget; why a startup timeout is the unrecoverable one, why a HEALTHY slow check is the one nothing could name, and the timing line the endpoint now publishes - What a Synthetic Probe May Assert — a probe naming one deployment's installed content is broken by construction; the platform floor, the negative control that tells "absent" from "down", and reading the target's own declaration
- Why a GC-Bound Pod Stays in Rotation — the GC's hard limit sits below the container limit, so a portal short of memory is defended rather than restarted
- Self-hosted CI runners on AKS — ARC beside the portals on one pool; three brakes, a negative priority class, and the reserve arithmetic that decides the cap
- Candidate Release Protocol
- Chart Drift — what a deploy actually does
- Rendering a chart you are not allowed to fully configure — 39 runs, 39 failures, zero verdicts: the check may hold two of the deploy's three value sources and the chart correctly refuses that subset; the placeholder that unblocks the render, the two-render proof that no compared object depends on it, and the bake gate that was off on both production namespaces the moment a verdict finally appeared
- Configuring an instance from Aspire
- The Dependabot Secret Store
- GitHub App Credentials —
meshweaver-cloudwrites to its own repo; every cross-repo READ mints from the read-onlyfleet-reader - Deployment env layers — what a record must be able to hold
- DeploymentInventory
- Deployment Options (AKS)
- Environment Composition
- Feature Flags
- First-Run Setup
- First-run setup on a PROVISIONED instance — a fleet-provisioned instance boots configured and unadministerable; the wizard keys on "no storage" and the onboarding gate on "no admin grant", so neither fires
- Image Cleanup
- Instance Identity and Setup
- Instance Lifecycle — State of Record
- Instances
- Local memex on Colima k3s (Mac)
- Mac local stack — on-device AI + local observability (M-series)
- Memex Cloud Deployment
- Merge Queue Mechanics
- The fleet's ONE CI process — the mechanism lives here as a lane or a shared script; a satellite carries a thin caller (verdict adoption, the lock resolver, the cancellation rule)
- Operating from the portal, not the cluster
- The Payment Provider Contract
- Pre-Boot Service Substitution
- Project Templates
- Reading a Recurrence Reopen — a bot reopen asserts two things and both fail independently; the 2026-09-17 wave measured, and the honest triple behind core's count
- Reopening on Image Provenance — the third reopen predicate: an occurrence counts only if it came from an image whose commit contains the fix, and why a staleness window would close live defects
- Registry-key rotation — two phases, at the registry that holds the instance
- The Release Event Bus
- Release Failure Classes — one log line carried four unrelated defects, so its issue could never be closed; what an incident's identity is really computed from (including the second line that never reaches it) and the rule that puts the failure CLASS in the template
- The Release Gate's Denominator
- Release to Production — the whole path
- Renaming a Required Status Check
- Repository Topology
- The Release Wave — one emitter, and who resolves the digest
Contributing docs
- Start here: Authoring Documentation
- Docs Follow The Functionality — which repo a page belongs in, and what pins the rest here
- Specifying Software
- Glossary
- Developing from within MeshWeaver
- Shared Rule Blocks
- Incidental Findings — the defect you did not come for: the three tests that decide, what a filed issue owes, and why turning aside costs twice
- Governed Autonomy — do, file, govern or ask: the four responses to an instruction, and why the test is reversibility rather than importance
Licensing
- Start here: Dependency Licensing — Apache-2.0/MIT compatible only; the CI gate that enforces it
- Dependency Major Upgrades — the five things a green
-warnaserrorbuild cannot see at a major boundary (in-mesh source, authored content, the satellites that import this repo's package list, behaviour behind an unchanged signature, and rules an analyzer would have enforced had the build actually loaded it), the differential method that replaces them, and the ledger of boundaries actually crossed
Getting started
New to the platform? Read Specifying Software to learn how to write iterative specifications closely aligned with implementation, skim the Glossary for the vocabulary, then explore the full catalog of architecture topics above.