Per-repo skill for the Peat mesh networking layer — pluggable transport, peer discovery, topology, routing, optional Automerge/Iroh CRDT sync, optional HTTP/WS broker.
Resources
16Install
npx skillscat add defenseunicorns/peat-mesh Install via the SkillsCat registry.
peat-mesh SKILL
peat-mesh is the mesh networking layer of the Peat ecosystem. It provides a pluggable Transport abstraction (BLE via peat-btle, lightweight bridge via peat-lite, IP), peer discovery (mDNS, Kubernetes CRD), topology and partition management, routing, an optional Automerge + Iroh + redb CRDT storage backend, and an optional HTTP/WS service broker. It's a Rust library (edition 2021) with an optional peat-mesh-node binary; other peat-* repos depend on it as a building block — peat-mesh does not depend on its consumers.
When this skill applies
- Editing any file under
src/transport/,src/discovery/,src/topology/,src/routing/,src/storage/,src/broker/ - Authoring or reviewing tests under
tests/ - Touching the feature-flag matrix in
Cargo.toml - Working on an active slice of any local ADR (4-digit padded
ADR-0001throughADR-0011indocs/adr/) or any ecosystem ADR that lands here. Recent ecosystem slices touching this repo:ADR-032(BLE transport),ADR-035(peat-lite bridge),ADR-042(transport security),ADR-049(security primitives),ADR-059(translator) — these live in the siblingpeat/docs/adr/, not in this repo.
If you're editing a peat-* sibling repo and only consume peat-mesh as a dependency, this skill probably isn't the one you want.
Scope
In scope:
- Mesh transport implementations and the
Transporttrait surface - Peer discovery (mDNS, Kubernetes CRD)
- Topology manager state and partition healing
- Routing logic
- Storage backends (Automerge + redb + Iroh sync, blob store)
- Service broker (HTTP/WS, Axum-based, feature-gated)
- Feature-flag wiring in
Cargo.toml
Out of scope (route elsewhere):
- BLE transport implementation details →
peat-btle/SKILL.md - Lightweight runtime →
peat-lite/SKILL.md - Edge-hardware node integration →
peat-node/SKILL.md - ATAK / Android FFI →
peat-atak-plugin/SKILL.md - Top-level shared types/traits — consider whether the change belongs in
peat/(the ecosystem core crate) instead
Workflow
Numbered steps. Skipping a step requires explicit user instruction.
- Orient. Read
peat/SKILL.md(ecosystem) if accessible. Read this file. ReadCONTRIBUTING.mdfor the build matrix.git status,git log -10. - Locate the spec. Confirm the task has a GitHub issue with Context / Scope / Acceptance / Constraints / Dependencies. If not, stop and ask the user.
- Plan. Produce a 1–5 step plan. Cross-check against ecosystem hard invariants (transport agnosticism, no cross-repo direct deps, peat-mesh has no consumers as deps) and the scope guards below. If the change is architectural, reference an existing ADR (
docs/adr/) or propose a new one. - Implement. Branch from
mainper the trunk-based convention. Vertical slices, one concern per commit. Match existing module boundaries — don't bleed transport logic into discovery, etc. - Verify. Run every command in the verification checklist below. Capture output.
- Hand off. Open PR against
mainreferencing the issue. Single concern per PR — peat-mesh squash-merges, so the PR title becomes the merge commit subject.
Verification (exit criteria)
A session in this repo is not done until each of these produces evidence:
-
cargo fmt --checkexits 0 -
cargo clippy -- -D warningsexits 0 -
cargo testexits 0 - If the change touches code under any feature flag, also:
cargo test --features <flag>for each affected feature (automerge-backend,broker,kubernetes,bluetooth,lite-bridge). Build-only (cargo build --features <flag>) is not sufficient — feature-gated test paths only execute undercargo test --features, and recent ADR-049 / ADR-059 work lives entirely under feature gates. - If the change spans multiple features:
cargo test --features nodeexercises the combined feature set used by the binary. - If the change is functional: a behavioral test or example demonstrates the new behavior — not just unit-coverage padding
- The pre-commit hook installed by
./scripts/install-hooks.shruns clean (it gatescargo fmt --checkandcargo clippy -- -D warningson every commit)
"Seems right" or "the diff looks correct" is never sufficient.
Anti-rationalization
| Excuse | Rebuttal |
|---|---|
| "This change is too small to need a test." | If it's worth changing, it's worth one assertion. Add the test. |
| "I'll fix the clippy warning later." | The CI gate is -D warnings. There is no later. Fix it before commit. |
| "This refactor is right next door — I'll just clean it up." | Out of scope. Open a separate issue if it matters. Squash-merge ≠ kitchen-sink PR. |
| "I only changed library code; the feature builds will pass." | Feature flags interact non-obviously with optional dependencies (especially iroh / ed25519 pinning). Run the affected feature builds locally. |
"I'll just import directly from peat-btle to avoid the Transport trait detour." |
peat-mesh depends optionally on peat-btle (gated by bluetooth); the trait abstraction is the whole point. Cross-direction or non-trait imports break the abstraction and the dependency direction. |
| "The transport-level retry can live in the topology manager — same crate." | Transport-specific retry (link-level send/recv, framing) belongs in the transport adapter — topology must not assume any specific transport's retry semantics. Higher-layer retries — partition healing, route re-discovery — legitimately live above the transport seam (see ADR-0003) and are a different concern; do not collapse them into the same row of reasoning. |
| "I'll skip GPG signing this once — it's just a docs change." | Signing is a repo-policy gate, not a quality gate. Don't bypass. Fix the signing config instead. |
"I'll bump iroh to drop the pre-release ed25519/pkcs8 pins — it's cleaner." |
Those pins exist because iroh 0.97/0.98 ship pre-release transitives that don't survive their own dep ranges under rustc ≥1.95. Remove only after verifying upstream actually fixed it (see the comment in Cargo.toml). |
Scope guards
- Touch only files the issue/user asked you to touch.
- Do not edit other peat-* repos. Cross-repo work goes in a separate PR in that repo, linked through a tracking issue.
- Do not bleed transport-specific logic into
discovery,topology,routing, orstoragemodules. TheTransporttrait is the seam. - Do not add a hard dependency on a feature-gated crate without gating it behind the matching feature.
- Do not add
peat-meshconsumers (peat-node, peat-btle, peat-lite, etc.) aspeat-meshdependencies. The dependency direction is one-way. - Do not configure git to bypass GPG signing or use
--no-verifyto skip the pre-commit hook.
Gotchas
Add an entry each time a session produces output that needed correction. One line per gotcha plus a Why: line.
AutomergeStore::putis wholesale-byte-replace at the doc-key level; any get→modify→put sequence on the same key must holdstore.lock_doc(&key)across the whole sequence.
Why: two concurrent load-modify-write cycles for the same key silently drop one writer (lastputwins) regardless of typed-field structure inside the doc — surfaced as 6/8 lost writes in a concurrent-spawn test during the peat#868 substrate fix.- The auto-sync push task (
AutomergeBackend::start_sync) silently swallows the per-peer error fromsync_document_with_all_peers(let _ = e); anything that returnsErrfrominitiate_syncis dropped with no retry.
Why: returningFlowControlError::CooldownActivethere meant back-to-back local writes within the 100ms cooldown never reached peers — the root of peat#864's missing-frame symptom. Defer (sleep the remaining cooldown) instead of erroring on that path. FlowController.sync_cooldownis defer-not-drop on the auto-sync path as of rc.10; don't "simplify"initiate_syncback to fast-fail on cooldown.
Why: the regression test pins both the timing (≥80ms wait) and error-shape (noCooldownActivesurfaced); a revert silently re-opens peat#864.
References (read on demand, not by default)
- Ecosystem invariants:
peat/SKILL.md(sibling repo) - Build matrix and feature flags:
CONTRIBUTING.md - Local ADR index:
docs/adr/— repo-local ADRs use 4-digit padded form (ADR-0001throughADR-0011) - Ecosystem ADR index:
peat/docs/adr/(sibling repo) — ecosystem ADRs use 3-digit form (ADR-032,ADR-049, etc.); these are the IDs cited in this repo'sCargo.tomlcomments and recent commits iroh/ed25519/pkcs8pin rationale: comment block inCargo.tomlaround theautomerge-backenddeps- Codex-specific orientation:
AGENTS.md(do not duplicate skill content there) - Repo: https://github.com/defenseunicorns/peat-mesh
Last updated: 2026-05-05
Maintained by: Kit Plummer, VP Data and Autonomy, Defense Unicorns