| name | peat-mesh |
| description | Per-repo skill for the Peat mesh networking layer — pluggable transport, peer discovery, topology, routing, optional Automerge/Iroh CRDT sync, optional HTTP/WS broker. |
| when_to_use | Editing files under peat-mesh/, reviewing peat-mesh PRs, debugging peer/discovery/topology/routing/storage/broker issues, or working on ADR slices that touch mesh. |
| verifies_with | cargo fmt --check, cargo clippy -- -D warnings, cargo test, plus feature-flagged builds for any feature whose code paths the change touches. |
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-0001 through ADR-0011 in docs/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 sibling peat/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
Transport trait 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. Read CONTRIBUTING.md for 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
main per 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
main referencing 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:
"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, or storage modules. The Transport trait 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-mesh consumers (peat-node, peat-btle, peat-lite, etc.) as peat-mesh dependencies. The dependency direction is one-way.
- Do not configure git to bypass GPG signing or use
--no-verify to 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::put is wholesale-byte-replace at the doc-key level; any get→modify→put sequence on the same key must hold store.lock_doc(&key) across the whole sequence.
Why: two concurrent load-modify-write cycles for the same key silently drop one writer (last put wins) 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 from sync_document_with_all_peers (let _ = e); anything that returns Err from initiate_sync is dropped with no retry.
Why: returning FlowControlError::CooldownActive there 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_cooldown is defer-not-drop on the auto-sync path as of rc.10; don't "simplify" initiate_sync back to fast-fail on cooldown.
Why: the regression test pins both the timing (≥80ms wait) and error-shape (no CooldownActive surfaced); a revert silently re-opens peat#864.
- Jobs that share a physical self-hosted runner pool (e.g. the
peat-arm64-linux-gb10-mesh host) must serialize with a static, repo-wide concurrency group named peat-{repo}-{job}-self-hosted (no ${{ github.ref }} in the key) and cancel-in-progress: false. peat-mesh's P2P Functional Tests pairs with peat-node's peat-cli-e2e on the same pool.
Why: a ref-scoped group (${{ github.workflow }}-${{ github.ref }}) lets two refs (push-to-main vs. a release tag) land the same job on one runner concurrently and contend for CPU + loopback multicast — the #222 P2P flake. A new repo sharing the pool is easy to miss; follow this naming so the cross-repo contract is discoverable.
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-0001 through ADR-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's Cargo.toml comments and recent commits
iroh / ed25519 / pkcs8 pin rationale: comment block in Cargo.toml around the automerge-backend deps
- 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