# HearthNet Phase 3 — Implementation Reference
**Spec set:** v3.0 — *experimental*
**Status:** Research-shaped. Names and contracts may shift before promotion to stable.
This document is the symbol index and quick-reference for everything introduced in Phase 3. It mirrors the structure of Phase 1's and Phase 2's `IMPLEMENTATION_REFERENCE.md`, so a maintainer can find the relevant spec section, file, class, capability, event, or constant by name.
Read this with the Phase 1 + Phase 2 references already in hand. Phase 3 is purely additive; it does not redefine anything from earlier phases.
---
## 1. Module index
| ID | Name | Status | Spec file |
|----|------|--------|-----------|
| M26 | Distributed Inference (layer sharding) | experimental | [phase-3/modules/M26-distributed-inference.md](modules/M26-distributed-inference.md) |
| M27 | MoE Expert Routing | experimental | [phase-3/modules/M27-moe-routing.md](modules/M27-moe-routing.md) |
| M28 | Federated Learning (LoRA aggregation) | experimental | [phase-3/modules/M28-fedlearn.md](modules/M28-fedlearn.md) |
| M29 | LoRa Hardware Beacons | experimental | [phase-3/modules/M29-lora-beacons.md](modules/M29-lora-beacons.md) |
| M30 | Evidence Graph & EBKH Integration | experimental | [phase-3/modules/M30-evidence-ebkh.md](modules/M30-evidence-ebkh.md) |
| M31 | Civil Defense (NRW Bevölkerungsschutz) | experimental | [phase-3/modules/M31-civil-defense.md](modules/M31-civil-defense.md) |
| M32 | Protocol Standardisation & Conformance | provisional | [phase-3/modules/M32-protocol-standard.md](modules/M32-protocol-standard.md) |
| X08 | Tensor Transport | experimental | [phase-3/cross-cutting/X08-tensor-transport.md](cross-cutting/X08-tensor-transport.md) |
| X09 | Conformance Suite | provisional | [phase-3/cross-cutting/X09-conformance-suite.md](cross-cutting/X09-conformance-suite.md) |
All `experimental` modules are gated by per-module feature flags in `hearthnet/config.py` and default to `False`.
---
## 2. Capability index
All Phase 3 capabilities (except `protocol.*`) live in the `experimental.*` namespace. The bus refuses to register them unless the corresponding feature flag is on.
### 2.1 Distributed Inference (M26)
| Capability | Module | Notes |
|------------|--------|-------|
| `experimental.distributed_llm.shard.list` | M26 | Local advertisement of shards we host |
| `experimental.distributed_llm.shard.connect` | M26 | Negotiate an X08 tensor session |
| `experimental.distributed_llm.shard.forward` | M26 | Run forward through a hosted shard |
| `experimental.distributed_llm.pipeline.plan` | M26 | Construct a layer pipeline for a model |
| `experimental.distributed_llm.pipeline.run` | M26 | Execute a planned pipeline |
| `experimental.distributed_llm.pipeline.status` | M26 | Pipeline state and stats |
### 2.2 MoE Routing (M27)
| Capability | Module | Notes |
|------------|--------|-------|
| `experimental.moe.expert.register` | M27 | Register self as an expert for some topics |
| `experimental.moe.expert.list` | M27 | List registered experts |
| `experimental.moe.expert.unregister` | M27 | Withdraw expert registration |
| `experimental.moe.route.query` | M27 | Get top-K experts for a query |
| `experimental.moe.route.handoff` | M27 | Initiate human-in-the-loop handoff |
| `experimental.moe.feedback.record` | M27 | Record outcome for scorer training |
### 2.3 Federated Learning (M28)
| Capability | Module | Notes |
|------------|--------|-------|
| `experimental.fedlearn.round.announce` | M28 | Coordinator announces a round |
| `experimental.fedlearn.round.list` | M28 | List open rounds |
| `experimental.fedlearn.round.join` | M28 | Participant joins a round |
| `experimental.fedlearn.round.submit` | M28 | Submit gradient delta |
| `experimental.fedlearn.round.status` | M28 | Get round state |
| `experimental.fedlearn.round.finalize` | M28 | Coordinator finalises and aggregates |
| `experimental.fedlearn.adapter.fetch` | M28 | Fetch an aggregated adapter by SHA |
| `experimental.fedlearn.adapter.apply` | M28 | Apply adapter to session or node |
### 2.4 LoRa Beacons (M29)
| Capability | Module | Notes |
|------------|--------|-------|
| `experimental.lora.status` | M29 | Hardware and link status |
| `experimental.lora.beacon.send` | M29 | Send a normal beacon |
| `experimental.lora.panic.send` | M29 | Send a panic burst |
| `experimental.lora.peer.list` | M29 | Known LoRa peers |
| `experimental.lora.peer.verify` | M29 | TOFU-confirm a peer's NodeID binding |
| `experimental.lora.recent_beacons` | M29 | Recent RX'd beacons |
| `experimental.lora.duty_cycle` | M29 | Current duty-cycle budget status |
### 2.5 Evidence Graph (M30)
| Capability | Module | Notes |
|------------|--------|-------|
| `experimental.evidence.claim.assert` | M30 | Assert a new claim |
| `experimental.evidence.claim.dispute` | M30 | Dispute an existing claim |
| `experimental.evidence.claim.attest` | M30 | Attest to an existing claim |
| `experimental.evidence.claim.get` | M30 | Fetch a single claim by ID |
| `experimental.evidence.claim.query` | M30 | Query claims by triple |
| `experimental.evidence.provenance.trace` | M30 | Walk the derivation graph |
| `experimental.evidence.subject.summary` | M30 | Multi-claim summary for a subject |
| `experimental.evidence.ebkh.sync` | M30 | Sync with external EBKH endpoint |
### 2.6 Civil Defense (M31)
| Capability | Module | Notes |
|------------|--------|-------|
| `experimental.civdef.alert.publish` | M31 | Role-cert-gated alert publication |
| `experimental.civdef.alert.cancel` | M31 | Cancel an active alert |
| `experimental.civdef.alert.list` | M31 | List active alerts (filtered) |
| `experimental.civdef.alert.get` | M31 | Fetch an alert envelope |
| `experimental.civdef.alert.subscribe` | M31 | Subscribe to alerts matching a filter |
| `experimental.civdef.alert.ack` | M31 | Acknowledge an alert |
| `experimental.civdef.alert.acks` | M31 | List acks for an alert |
| `experimental.civdef.role.register` | M31 | Register a role certificate |
| `experimental.civdef.role.list` | M31 | List registered certificates |
| `experimental.civdef.role.revoke` | M31 | Revoke a certificate |
| `experimental.civdef.audit.export` | M31 | Export tamper-evident audit chain |
### 2.7 Protocol (M32) — stable
| Capability | Module | Notes |
|------------|--------|-------|
| `protocol.version.list` | M32 | Versions supported |
| `protocol.self.describe` | M32 | Implementation descriptor |
| `protocol.conformance.report` | M32 | Run / fetch conformance report |
| `protocol.registry.list` | M32 | Known implementations |
| `protocol.registry.announce` | M32 | Announce self to registry |
---
## 3. Event types
All Phase 3 event types follow the convention `..` and are recorded in the X02 event log.
### 3.1 Distributed inference
```
distributed_llm.shard.advertised
distributed_llm.shard.withdrawn
distributed_llm.pipeline.planned
distributed_llm.pipeline.started
distributed_llm.pipeline.shard_failed
distributed_llm.pipeline.failover
distributed_llm.pipeline.completed
distributed_llm.pipeline.cancelled
```
### 3.2 MoE
```
moe.expert.registered
moe.expert.unregistered
moe.route.computed
moe.handoff.initiated
moe.handoff.accepted
moe.handoff.declined
moe.handoff.timed_out
moe.feedback.recorded
```
### 3.3 Federated learning
```
fedlearn.round.announced
fedlearn.round.joined
fedlearn.round.consent.granted
fedlearn.round.submitted
fedlearn.round.aggregated
fedlearn.round.completed
fedlearn.round.aborted
fedlearn.round.takeover
fedlearn.adapter.published
fedlearn.adapter.applied
```
### 3.4 LoRa
```
lora.beacon.sent
lora.beacon.received
lora.panic.sent
lora.panic.received
lora.peer.unknown
lora.peer.verified
lora.peer.conflict
lora.duty_cycle.exhausted
lora.duty_cycle.overridden
lora.rx.dropped
```
### 3.5 Evidence
```
evidence.claim.asserted
evidence.claim.attested
evidence.dispute.opened
evidence.dispute.retracted
evidence.ebkh.synced
evidence.ebkh.sync_partial
```
### 3.6 Civil defense
```
civdef.alert.published
civdef.alert.forwarded
civdef.alert.acked
civdef.alert.cancelled
civdef.alert.dropped.revoked
civdef.alert.foreign_role
civdef.role.registered
civdef.role.revoked
civdef.audit.checkpointed
civdef.audit.broken
```
### 3.7 Protocol
```
protocol.descriptor.announced
protocol.registry.updated
protocol.conformance.ran
```
---
## 4. Type aliases (added to `hearthnet/types.py`)
```python
ShardID = NewType("ShardID", str) # "model:layer_range[:tier]"
ExpertID = NewType("ExpertID", str) # "human:..." | "model:..." | "service:..." | "external:..."
ExpertKind = Literal["human","model","service","external"]
ClaimID = NewType("ClaimID", str) # base32 of SHA-256 canonical claim
SourceID = NewType("SourceID", str)
EvidenceLevel = Literal["unverified","cited","cross_referenced","attested","disputed"]
RoundID = NewType("RoundID", str) # ULID
LoraBeaconID = NewType("LoraBeaconID", str)
LoraDeviceID = NewType("LoraDeviceID", str)
AlertID = NewType("AlertID", str) # ULID
AlertSeverity = Literal["info","advisory","warning","emergency","extreme"]
AckStatus = Literal["received","acting","need_help","standing_down","mistaken"]
@dataclass(frozen=True)
class ProtocolVersion: major: int; minor: int; patch: int; suffix: str = ""
# Reused from earlier phases but referenced here for completeness:
NodeID # M01
EventID # X02
AuthToken # M16
Bbox # M07 spatial extensions
Tensor # local LLM tensor type, dtype-tagged
```
---
## 5. Centralised constants (`hearthnet/constants.py`, Phase 3 additions)
```python
# --- Distributed inference (M26) ---
DISTRIBUTED_LLM_MAX_SHARDS_PER_PIPELINE = 16
DISTRIBUTED_LLM_SHARD_HEARTBEAT_SECONDS = 5
DISTRIBUTED_LLM_FAILOVER_TIMEOUT_SECONDS = 10
DISTRIBUTED_LLM_MAX_PIPELINE_LATENCY_TOKENS_PER_S = 2.0 # advisory floor
DISTRIBUTED_LLM_DEFAULT_DTYPE = "fp16"
# --- MoE routing (M27) ---
MOE_TOP_K_DEFAULT = 3
MOE_LEARNED_SCORER_MIN_FEEDBACK_SAMPLES = 200
MOE_HUMAN_HANDOFF_DEFAULT_TIMEOUT_HOURS = 24
MOE_HUMAN_HANDOFF_COOLDOWN_HOURS = 2
MOE_HUMAN_RATE_LIMIT_PER_DAY = 5
# --- Federated learning (M28) ---
FEDLEARN_MAX_LORA_RANK = 64
FEDLEARN_MAX_LORA_TARGET_MODULES = 8
FEDLEARN_MAX_TRAIN_STEPS = 1000
FEDLEARN_MAX_PARTICIPANTS = 32
FEDLEARN_MIN_PARTICIPANTS = 3
FEDLEARN_DP_NOISE_SCALE_DEFAULT = 0.0 # off
FEDLEARN_CLIP_NORM_DEFAULT = 1.0
FEDLEARN_SUBMISSION_MAX_BYTES = 64 * 1024 * 1024
# --- LoRa beacons (M29) ---
LORA_BEACON_PERIOD_SECONDS_DEFAULT = 600 # 10 min
LORA_BEACON_MAX_PAYLOAD_BYTES = 32
LORA_RX_QUEUE_MAX = 256
LORA_PEER_RX_MAX_PER_MINUTE = 20
LORA_PANIC_BURST_COUNT = 3
LORA_PANIC_BURST_GAP_MS = 800
# --- Evidence (M30) ---
EVIDENCE_CLAIM_TTL_DAYS_DEFAULT = 365
EVIDENCE_DISPUTE_MIN_TRUST = 0.3
EVIDENCE_MAX_PROVENANCE_DEPTH = 8
# --- Civil defense (M31) ---
CIVDEF_AUDIT_RETENTION_YEARS = 10 # operator must validate against current law
CIVDEF_ACK_MAX_PER_MINUTE_PER_NODE = 5
CIVDEF_ALERT_TITLE_MAX_CHARS = 80
CIVDEF_ALERT_BODY_MAX_CHARS = 1000
# --- Tensor transport (X08) ---
TENSOR_CHUNK_BYTES = 1 * 1024 * 1024 # 1 MiB
TENSOR_FLOW_CONTROL_WINDOW = 16
TENSOR_COMPRESSION_THRESHOLD_BYTES = 64 * 1024
TENSOR_KEEPALIVE_SECONDS = 30
TENSOR_MAX_SESSION_LIFETIME_SECONDS = 3600
# --- Conformance suite (X09) ---
CONFORMANCE_DEFAULT_SEED = 0xC0FFEE
CONFORMANCE_DEFAULT_OUTPUT_DIR = "./conformance-report"
```
---
## 6. Error codes (Phase 3 additions)
| Code | Module | When |
|------|--------|------|
| `experimental_disabled` | shared | Capability called with the feature flag off |
| `shard_unavailable` | M26 | No replica for the required layer range |
| `shard_unreachable` | M26 | All replicas connectivity-failed |
| `pipeline_failed` | M26 | Aggregate failure of an in-flight pipeline |
| `pipeline_cancelled` | M26 | Pipeline cancelled by caller |
| `tensor_too_large` | X08 | Tensor exceeds rx_buffer_bytes_max |
| `unknown_frame_type` | X08 | Frame type outside the defined set |
| `expert_unknown` | M27 | Referenced expert is not registered |
| `expert_unavailable` | M27 | Expert known but currently outside availability window |
| `human_handoff_declined` | M27 | Human expert explicitly declined |
| `human_handoff_timed_out` | M27 | Handoff exceeded timeout without ack |
| `consent_required` | M28 | join() without explicit operator consent |
| `base_model_mismatch` | M28 | Local base model SHA differs from manifest |
| `insufficient_resources` | M28 | Estimated VRAM/disk exceeds budget |
| `delta_invalid` | M28 | Submitted state-dict fails structural validation |
| `fedlearn_aggregation_failed` | M28 | Aggregation produced NaN/Inf |
| `fedlearn_min_participants_unmet` | M28 | Round closed below quorum |
| `fedlearn_aggregator_unreachable` | M28 | Finalize attempted while coordinator offline |
| `adapter_not_found` | M28 | Fetch for unknown adapter SHA |
| `lora_hardware_unavailable` | M29 | No stick present |
| `lora_hardware_unsupported` | M29 | Adapter init failed |
| `lora_duty_cycle_exhausted` | M29 | Non-panic send with empty budget |
| `lora_peer_unknown` | M29 | Verify against unseen sender_hash |
| `lora_peer_conflict` | M29 | Verify would create conflicting binding |
| `lora_frame_malformed` | M29 | RX frame structurally invalid |
| `claim_not_found` | M30 | Reference to unknown ClaimID |
| `claim_signature_invalid` | M30 | Signature doesn't verify |
| `evidence_cycle_detected` | M30 | Derivation chain forms a cycle |
| `evidence_contradiction` | M30 | (advisory) conflicting claims on same triple |
| `ebkh_unavailable` | M30 | EBKH endpoint unreachable |
| `civdef_cert_not_owned` | M31 | Cert holder ≠ caller identity |
| `civdef_cert_invalid` | M31 | Cert expired, revoked, or signature broken |
| `civdef_cert_unrecognised` | M31 | Issuer chain doesn't reach a trust root |
| `civdef_cert_out_of_scope` | M31 | Cert lacks the requested role/region |
| `civdef_alert_not_found` | M31 | Operation on unknown AlertID |
| `civdef_alert_target_invalid` | M31 | Malformed target or outside scope |
| `civdef_audit_chain_broken` | M31 | Audit chain hash/signature mismatch |
| `civdef_role_revoked` | M31 | Op with revoked cert |
| `civdef_region_unsupported` | M31 | No region adapter loaded |
| `civdef_ack_rate_limited` | M31 | Ack rate exceeded |
| `protocol_version_unknown` | M32 | Reference to unknown protocol version |
| `protocol_suite_not_installed` | M32 | Conformance report requested without X09 |
| `protocol_descriptor_invalid` | M32 | Malformed descriptor announcement |
| `protocol_unsupported_capability` | M32 | Federation negotiates no compatible major |
---
## 7. File map (top-level)
```
hearthnet/
├── distributed_inference/ # M26
│ ├── shard.py
│ ├── orchestrator.py
│ ├── router.py
│ ├── plan.py
│ └── failover.py
├── moe/ # M27
│ ├── router.py
│ ├── scorer.py
│ ├── expert_registry.py
│ ├── human_in_the_loop.py
│ └── feedback.py
├── fedlearn/ # M28
│ ├── coordinator.py
│ ├── participant.py
│ ├── trainer.py
│ ├── aggregator.py
│ ├── delta.py
│ ├── privacy.py
│ └── manifest.py
├── lora/ # M29
│ ├── service.py
│ ├── serial_bridge.py
│ ├── frame.py
│ ├── duty_cycle.py
│ ├── peer_map.py
│ └── adapters/{meshtastic,rfm95w,sx126x}.py
├── evidence/ # M30
│ ├── service.py
│ ├── claim.py
│ ├── store.py
│ ├── query.py
│ ├── extractor.py
│ ├── ebkh_adapter.py
│ └── trust.py
├── civdef/ # M31
│ ├── service.py
│ ├── alert.py
│ ├── role.py
│ ├── audit.py
│ ├── target.py
│ ├── ack.py
│ └── regions/nrw.py
├── protocol/ # M32 runtime
│ ├── service.py
│ ├── registry.py
│ └── report.py
└── transport/
└── tensor/ # X08
├── session.py
├── frame.py
├── flow.py
└── compress.py
protocol/ # M32 spec artefacts (repo root)
├── VERSION
├── README.md
├── CHANGELOG.md
├── governance.md
├── versioning.md
├── reference-implementations.md
├── core/...
└── experimental/...
conformance/ # X09 suite (repo root)
├── VERSION
├── runner.py
├── report.py
├── harness/...
├── suites/...
└── vectors/...
```
---
## 8. Configuration index
Each module defines its own `*Config` dataclass; all are surfaced through the global `HearthnetConfig` and read from `~/.config/hearthnet/config.toml`. Phase 3 additions:
```python
@dataclass(frozen=True)
class HearthnetConfig:
# ... (Phase 1, Phase 2 fields) ...
distributed_llm: DistributedLlmConfig
moe: MoeConfig
fedlearn: FedLearnConfig
lora: LoraConfig
evidence: EvidenceConfig
civdef: CivDefConfig
tensor_transport: TensorTransportConfig
protocol: ProtocolConfig
```
Every Phase 3 config has `enabled: bool = False` except `protocol` (default `True`). The bus dispatcher refuses to register Phase 3 capabilities when their module's enabled flag is False.
---
## 9. Build order (recap from `00-OVERVIEW.md`)
Phase 3 has eight independent tracks A-H that can be parallelised:
```
Track A: X09 conformance suite scaffolding → M32 protocol service
Track B: M30 evidence + EBKH adapter
Track C: M27 MoE machine experts (router, registry, scorer)
Track D: M27 human-in-the-loop coordinator (depends on Track C base)
Track E: M28 federated LoRA aggregation
Track F: X08 tensor transport → M26 distributed inference
Track G: M29 LoRa beacons (hardware-gated)
Track H: M31 civil defense (depends on M30 evidence)
```
Tracks A and F unlock the most downstream work (M32 needs X09; M26 needs X08). Tracks G and H are most easily deferred if Phase 3 needs to ship a minimal cut.
---
## 10. Open-question summary
Each module spec has its own §10 with detailed open questions. The recurring themes across Phase 3:
1. **Real-world identity binding** (M28 sybil defence, M31 institutional keys, M30 EBKH trust roots, M27 human verification) — the cryptographic story is solid; the social/institutional story is the work.
2. **Adversarial robustness** (M26 byzantine shards, M28 poisoning, M30 disputed claims, M31 forged certs) — all have stub defences and known harder problems.
3. **Second implementation** (M32) — until a non-reference impl exists, conformance is performative. This is the single most important next step.
4. **Cross-Land / cross-border generalisation** (M31 regional adapter, M30 EBKH OSINT scope, M29 regulatory regions) — designed for NRW first; structures admit other regions but they're unbuilt.
5. **Resource tiers** (M26 phone-class participants, M28 hardware fairness) — heterogeneous hardware aggregation is largely unsolved.
6. **Privacy / DP calibration** (M28 noise scale, M30 sensitive claims, M29 sender hash) — defaults are conservative; tuning is operator-by-operator.
Each module also lists module-specific items. Read them.
---
*Last updated: spec set v3.0. Phase 3 specs were authored with the intent that any of M26–M31 could be cut from a shipping release without affecting Phase 1 + Phase 2 functionality. M32 + X09 are the long-term durability investment and should ship even when other Phase 3 modules don't.*