Compose the CM0 fullscreen application and standard Debian package, align the Cardputer Zero shell, and share protocol, configuration, audio and storage services with embedded targets through existing platform seams. Add the paginated on-device TMAP creator using Center's published producer, private workspace recovery and direct keyboard shortcuts. Preserve unfinished management work behind its existing opt-in capability. Include native, ARM and shared-core regression fixtures, integration records, packaging helpers and dependency/license updates. Keep local build trees, device credentials, produced packages and validation logs outside version control. Validation before integration: ESP stack hygiene, Reticulum scope guard, staged whitespace checks and GitNexus scope audit. Prior device/build evidence and remaining hardware/package boundaries are recorded in the acceptance documents.
3.8 KiB
Native peer directory ownership
Shared data, native concurrency
LinuxPeerDirectory implements the existing IMeshPeerDirectory port around
one MeshPeerDirectoryCore. Its format, protocol partitions, identity keys,
fact-merging rules and local flags remain owned by that core. Native callers
serialize memory operations through a short recursive mutex; no blob I/O runs
under that mutex. Read-only visitor reentry is allowed, while mutation or flush
from a visitor returns Busy instead of invalidating its scan or deadlocking.
One storage thread loads the existing blob, encodes persistence snapshots and
saves them. Startup begin() waits for initial loading. Runtime record()
acknowledges admission to the in-memory owner and schedules persistence; it
does not assert a durable observation. Administrative mutations retain an
explicit persistence barrier before returning, and flush() waits for a fresh
attempt covering its target revision. These administrative/startup barriers
can wait for storage and are not frame-loop query operations.
The storage thread allocates its encoded byte buffer outside the mutex, copies a coherent core revision under the mutex and performs the physical write after unlocking. It acknowledges a revision only after the port accepts that write. Concurrent newer observations stay dirty and are encoded again. Save failure retains dirty memory and retries with a bounded pause; a later explicit barrier does not reuse an earlier failed attempt as its result. Shutdown rejects new mutations and attempts the newest admitted snapshot, including updates that arrived during an older in-flight write. A failed volume cannot create an endless shutdown retry loop.
Core policy mutations apply in memory before persistence. An I/O error is reported by the barrier; it does not roll back that in-memory user decision. Callers must distinguish accepted policy from durable storage rather than assuming an error restores an older policy. This preserves the existing core merge model without introducing another policy table or optimistic UI owner.
File effects
The native composition still supplies the existing resolved storage path and
logical mesh/peers.bin file.
The resolved path is pinned before its storage thread starts, so shutdown I/O
does not depend on the lifetime of a global path-configuration object.
Linux publication uses an exclusively created,
descriptor-relative temporary file, synchronizes file contents, atomically
renames it over the target and synchronizes the containing directory. It does
not unlink the previous book before publication. Failures retain the previous
target whenever publication has not occurred. A rename followed by failed
directory synchronization reports uncertainty as failure and leaves the core
dirty for retry.
Corrupt and truncated existing snapshots refuse loading and do not accept ordinary mutations. Missing storage is distinct from a valid loaded book; the core's canonical codec still validates record shape and CRC. This is not a new peer-file format or an automatic repair/migration policy.
Verification
The native regression blocks the actual persistence port while reading and admitting a newer observation, checks that the newer revision is eventually saved, verifies explicit barriers, retries a failed revision, preserves local flags/aliases on runtime updates and rejects visitor mutation. It also stops with an older snapshot blocked and confirms that the later accepted update is drained. Reopen and corrupt-blob retention are covered. Source/core units run with ASan, UBSan and leak checks on native Linux.
Reticulum ingress now uses this port from its protocol worker. The UI contact service reads the same protected memory owner through its existing contract; node events do not introduce a second directory or perform background writes against an unprotected UI-owned core.