Merge nucleic/fuzzy-maple-koala-87xd into dev
This commit is contained in:
@@ -196,7 +196,7 @@ final class HostConnection {
|
|||||||
private var reconnectAttempts = 0
|
private var reconnectAttempts = 0
|
||||||
private var seenSeq: Set<UInt64> = []
|
private var seenSeq: Set<UInt64> = []
|
||||||
|
|
||||||
// Covalence direct (SYNC §3.3): when the current attempt is over the relay, its channel is
|
// Hydrangea direct (SYNC §3.3): when the current attempt is over the relay, its channel is
|
||||||
// wrapped in a `MultipathFrameChannel` so a background hole punch can migrate the session
|
// wrapped in a `MultipathFrameChannel` so a background hole punch can migrate the session
|
||||||
// off the relay. `directBox` routes the host's `directAnswer`/`directGo`/`directDecline`
|
// off the relay. `directBox` routes the host's `directAnswer`/`directGo`/`directDecline`
|
||||||
// replies to the driver; `directTask` is the background upgrade attempt.
|
// replies to the driver; `directTask` is the background upgrade attempt.
|
||||||
@@ -218,7 +218,7 @@ final class HostConnection {
|
|||||||
private enum TransportAttempt {
|
private enum TransportAttempt {
|
||||||
case lan(NWEndpoint)
|
case lan(NWEndpoint)
|
||||||
case tailnet(host: String, port: UInt16)
|
case tailnet(host: String, port: UInt16)
|
||||||
/// Covalence Relay (mesh P2) — the immediate baseline whenever admission is available.
|
/// Hydrangea Relay (mesh P2) — the immediate baseline whenever admission is available.
|
||||||
case relay(base: URL, membershipToken: String)
|
case relay(base: URL, membershipToken: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,7 +542,7 @@ final class HostConnection {
|
|||||||
releaseChannel: BuildInfo.current.channel.releaseChannel,
|
releaseChannel: BuildInfo.current.channel.releaseChannel,
|
||||||
// Mesh "join": advertise roster gossip so a host pushes its group view — the phone
|
// Mesh "join": advertise roster gossip so a host pushes its group view — the phone
|
||||||
// then auto-learns and connects to every Mac in the mesh, not just the one it scanned.
|
// then auto-learns and connects to every Mac in the mesh, not just the one it scanned.
|
||||||
// Also offer this phone as a low-tier AFM executor (COVALENCE_RUNNER §5) when the
|
// Also offer this phone as a low-tier AFM executor (HYDRANGEA_RUNNER §5) when the
|
||||||
// OS has Foundation Models — a runner host's mesh queue may place background work
|
// OS has Foundation Models — a runner host's mesh queue may place background work
|
||||||
// here; the interactive tiers stay on desktop-class devices by the queue's rules.
|
// here; the interactive tiers stay on desktop-class devices by the queue's rules.
|
||||||
clientCaps: WireClientCapabilities(
|
clientCaps: WireClientCapabilities(
|
||||||
@@ -551,7 +551,7 @@ final class HostConnection {
|
|||||||
intelligenceProfile: PhoneIntelligenceExecutor.profile,
|
intelligenceProfile: PhoneIntelligenceExecutor.profile,
|
||||||
// Mesh casting: receive the activity feed / messages / runner presence.
|
// Mesh casting: receive the activity feed / messages / runner presence.
|
||||||
canCast: true,
|
canCast: true,
|
||||||
// Covalence direct (SYNC §3.3): this phone runs the relay→direct upgrade.
|
// Hydrangea direct (SYNC §3.3): this phone runs the relay→direct upgrade.
|
||||||
canDirectConnect: directEnabled))
|
canDirectConnect: directEnabled))
|
||||||
self.client = client
|
self.client = client
|
||||||
consume(client, pairingPayload: pairingPayload)
|
consume(client, pairingPayload: pairingPayload)
|
||||||
@@ -812,15 +812,15 @@ final class HostConnection {
|
|||||||
// Collapsed Bash summary lines the owner pushes to peer *Macs* (mesh session sync).
|
// Collapsed Bash summary lines the owner pushes to peer *Macs* (mesh session sync).
|
||||||
// The phone renders its own deterministic command summaries, so it ignores these.
|
// The phone renders its own deterministic command summaries, so it ignores these.
|
||||||
break
|
break
|
||||||
case .carbonHeads, .carbonHeadAdvanced, .carbonManifestData, .carbonManifestUnavailable,
|
case .hydrangeaHeads, .hydrangeaHeadAdvanced, .hydrangeaManifestData, .hydrangeaManifestUnavailable,
|
||||||
.carbonShardData, .carbonShardUnavailable:
|
.hydrangeaShardData, .hydrangeaShardUnavailable:
|
||||||
// Carbon shard replication (docs/CARBON_SHARDING.md §8.6, D13): phones hold no
|
// Hydrangea shard replication (docs/HYDRANGEA_SHARDING.md §8.6, D13): phones hold no
|
||||||
// Carbon store, no key custody, and never mirror — every case is inert here. The
|
// Hydrangea store, no key custody, and never mirror — every case is inert here. The
|
||||||
// phone never sends the fetch verbs (it doesn't advertise `canMirrorCarbon`), so
|
// phone never sends the fetch verbs (it doesn't advertise `canMirrorHydrangea`), so
|
||||||
// these arrive only if a future host misroutes; ignoring them is the contract.
|
// these arrive only if a future host misroutes; ignoring them is the contract.
|
||||||
break
|
break
|
||||||
case .carbonLockDecision, .carbonLockLedgerAdvanced:
|
case .hydrangeaLockDecision, .hydrangeaLockLedgerAdvanced:
|
||||||
// Carbon lock verbs (CARBON_SHARDING §17.5): phones never acquire and hold no
|
// Hydrangea lock verbs (HYDRANGEA_SHARDING §17.5): phones never acquire and hold no
|
||||||
// ledger fold — the lock viewer rides the sync-protocol snapshots. Inert (D13).
|
// ledger fold — the lock viewer rides the sync-protocol snapshots. Inert (D13).
|
||||||
break
|
break
|
||||||
case .transcriptReverted(let reverted):
|
case .transcriptReverted(let reverted):
|
||||||
@@ -874,7 +874,7 @@ final class HostConnection {
|
|||||||
// resolves (success or failure). Correlation by requestID happens in RemoteStore.
|
// resolves (success or failure). Correlation by requestID happens in RemoteStore.
|
||||||
callbacks.projectCreated(outcome)
|
callbacks.projectCreated(outcome)
|
||||||
case .intelligenceRequest(let request):
|
case .intelligenceRequest(let request):
|
||||||
// A runner host delegated one AFM job here (docs/COVALENCE_RUNNER.md §5) — it only
|
// A runner host delegated one AFM job here (docs/HYDRANGEA_RUNNER.md §5) — it only
|
||||||
// ever sends these after this app advertised `canProvideIntelligence`. Generate off
|
// ever sends these after this app advertised `canProvideIntelligence`. Generate off
|
||||||
// the event stream (a model call takes seconds) and answer with the same id.
|
// the event stream (a model call takes seconds) and answer with the same id.
|
||||||
Task { [weak self] in
|
Task { [weak self] in
|
||||||
@@ -1004,7 +1004,7 @@ final class HostConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Covalence direct upgrade (SYNC §3.3)
|
// MARK: - Hydrangea direct upgrade (SYNC §3.3)
|
||||||
|
|
||||||
/// Once a relay session is live, arm its mux and start the background hole-punch upgrade.
|
/// Once a relay session is live, arm its mux and start the background hole-punch upgrade.
|
||||||
/// The relay stays the session's spine; a successful punch just moves the frames off it.
|
/// The relay stays the session's spine; a successful punch just moves the frames off it.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ struct PairedHost: Codable, Equatable {
|
|||||||
var transport: String?
|
var transport: String?
|
||||||
var tailnetHost: String?
|
var tailnetHost: String?
|
||||||
var tailnetPort: UInt16?
|
var tailnetPort: UInt16?
|
||||||
/// Covalence Relay bootstrap (mesh P2): the host's room, this device's membership
|
/// Hydrangea Relay bootstrap (mesh P2): the host's room, this device's membership
|
||||||
/// token, and an optional base-URL override. Set from the pairing QR and refreshed by
|
/// token, and an optional base-URL override. Set from the pairing QR and refreshed by
|
||||||
/// the host's `relayMembership` push on every connect; nil while the host has the relay
|
/// the host's `relayMembership` push on every connect; nil while the host has the relay
|
||||||
/// method off (records predating the relay decode them as nil).
|
/// method off (records predating the relay decode them as nil).
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import NucleicProtocol
|
|||||||
import FoundationModels
|
import FoundationModels
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// The phone-side executor for delegated intelligence work (docs/COVALENCE_RUNNER.md §5,
|
/// The phone-side executor for delegated intelligence work (docs/HYDRANGEA_RUNNER.md §5,
|
||||||
/// item 6): a runner host pushes `HostMsg.intelligenceRequest` at this device — the mesh AFM
|
/// item 6): a runner host pushes `HostMsg.intelligenceRequest` at this device — the mesh AFM
|
||||||
/// queue only ever sends it the lower tiers (`completion`/`background`), which don't need
|
/// queue only ever sends it the lower tiers (`completion`/`background`), which don't need
|
||||||
/// desktop tok/s — and this renders the shared `IntelligenceDelegate` template on the local
|
/// desktop tok/s — and this renders the shared `IntelligenceDelegate` template on the local
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ final class RemoteStore: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The mesh's runner-presence cards (Macs / cloud runners advertising capacity), sorted by
|
/// The mesh's runner-presence cards (Macs / cloud runners advertising capacity), sorted by
|
||||||
/// host name — the phone's window into the Covalence dispatch candidate pool. Keyed by the full
|
/// host name — the phone's window into the Hydrangea dispatch candidate pool. Keyed by the full
|
||||||
/// `deviceID` (distinct from `PairedHost.fingerprint`), so it's presented as its own section
|
/// `deviceID` (distinct from `PairedHost.fingerprint`), so it's presented as its own section
|
||||||
/// rather than cross-matched against the directly-paired Macs.
|
/// rather than cross-matched against the directly-paired Macs.
|
||||||
var meshRunnerCards: [(hostID: String, presence: RunnerPresence)] {
|
var meshRunnerCards: [(hostID: String, presence: RunnerPresence)] {
|
||||||
@@ -338,11 +338,11 @@ final class RemoteStore: ObservableObject {
|
|||||||
return (descriptor, candidates)
|
return (descriptor, candidates)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dispatch a new chat to the abstract **Covalence** destination from the phone: rank eligible
|
/// Dispatch a new chat to the abstract **Hydrangea** destination from the phone: rank eligible
|
||||||
/// hosts by the shared scorer and try them in order, one at a time with a correlated,
|
/// hosts by the shared scorer and try them in order, one at a time with a correlated,
|
||||||
/// idempotent ack (a timeout retries the same candidate once before moving on). On success
|
/// idempotent ack (a timeout retries the same candidate once before moving on). On success
|
||||||
/// routes to the landed session. Mirrors `AppStore.dispatchChatToMesh`. The phone stamps
|
/// routes to the landed session. Mirrors `AppStore.dispatchChatToMesh`. The phone stamps
|
||||||
/// itself as the Covalence origin, so the landed session is Covalence-managed (its owner keeps it
|
/// itself as the Hydrangea origin, so the landed session is Hydrangea-managed (its owner keeps it
|
||||||
/// on the optimal host between turns); the phone can't own sessions, so the origin exclusion
|
/// on the optimal host between turns); the phone can't own sessions, so the origin exclusion
|
||||||
/// is naturally satisfied by every candidate.
|
/// is naturally satisfied by every candidate.
|
||||||
/// `intelligence` rides along exactly as it does for a direct start — and matters more here:
|
/// `intelligence` rides along exactly as it does for a direct start — and matters more here:
|
||||||
@@ -365,8 +365,8 @@ final class RemoteStore: ObservableObject {
|
|||||||
backend: nil, excluding: excluded).first
|
backend: nil, excluding: excluded).first
|
||||||
else {
|
else {
|
||||||
showError(tried == 0
|
showError(tried == 0
|
||||||
? "No Covalence host can take this chat right now."
|
? "No Hydrangea host can take this chat right now."
|
||||||
: "No Covalence host could take this chat (\(tried) tried).", sessionID: nil)
|
: "No Hydrangea host could take this chat (\(tried) tried).", sessionID: nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tried += 1
|
tried += 1
|
||||||
@@ -379,7 +379,7 @@ final class RemoteStore: ObservableObject {
|
|||||||
let request = StartChatRequest(
|
let request = StartChatRequest(
|
||||||
projectID: targetProjectID, message: text, model: model, effort: effort,
|
projectID: targetProjectID, message: text, model: model, effort: effort,
|
||||||
auto: auto, requestID: requestID,
|
auto: auto, requestID: requestID,
|
||||||
covalenceOriginDeviceID: IdentityStore.deviceID(),
|
hydrangeaOriginDeviceID: IdentityStore.deviceID(),
|
||||||
intelligence: intelligence)
|
intelligence: intelligence)
|
||||||
var outcome = await sendDispatch(request, on: conn, timeout: .seconds(10))
|
var outcome = await sendDispatch(request, on: conn, timeout: .seconds(10))
|
||||||
if outcome == nil {
|
if outcome == nil {
|
||||||
@@ -679,7 +679,7 @@ final class RemoteStore: ObservableObject {
|
|||||||
|
|
||||||
/// "Add a project" (Projects tab): the phone asks a connected host advertising
|
/// "Add a project" (Projects tab): the phone asks a connected host advertising
|
||||||
/// `canCreateProjects` to clone a git URL and register it (CLOUD_RUNTIME §4.3) — how a
|
/// `canCreateProjects` to clone a git URL and register it (CLOUD_RUNTIME §4.3) — how a
|
||||||
/// fresh Covalence runner gets its first project. The outcome arrives asynchronously as
|
/// fresh Hydrangea runner gets its first project. The outcome arrives asynchronously as
|
||||||
/// `HostMsg.projectCreated`, correlated by the request id below; the project row itself
|
/// `HostMsg.projectCreated`, correlated by the request id below; the project row itself
|
||||||
/// rides the dashboard push.
|
/// rides the dashboard push.
|
||||||
enum AddProjectState: Equatable {
|
enum AddProjectState: Equatable {
|
||||||
@@ -2945,13 +2945,13 @@ final class RemoteStore: ObservableObject {
|
|||||||
// Session-owning intents → the Mac that has this session.
|
// Session-owning intents → the Mac that has this session.
|
||||||
case .subscribe(let s):
|
case .subscribe(let s):
|
||||||
connection(owningSession: s.sessionID)?.send(msg)
|
connection(owningSession: s.sessionID)?.send(msg)
|
||||||
case .fetchCarbonHeads, .fetchCarbonManifests, .fetchCarbonShards, .carbonShardAck:
|
case .fetchHydrangeaHeads, .fetchHydrangeaManifests, .fetchHydrangeaShards, .hydrangeaShardAck:
|
||||||
// Carbon shard replication (docs/CARBON_SHARDING.md §8.6, D13): phones never
|
// Hydrangea shard replication (docs/HYDRANGEA_SHARDING.md §8.6, D13): phones never
|
||||||
// mirror — no Carbon store, no key custody — so these verbs are never issued from
|
// mirror — no Hydrangea store, no key custody — so these verbs are never issued from
|
||||||
// iOS. Inert by contract.
|
// iOS. Inert by contract.
|
||||||
break
|
break
|
||||||
case .carbonLockAcquire, .carbonLockRelease:
|
case .hydrangeaLockAcquire, .hydrangeaLockRelease:
|
||||||
// Carbon lock verbs (CARBON_SHARDING §17.5): phones never acquire (D13) — the
|
// Hydrangea lock verbs (HYDRANGEA_SHARDING §17.5): phones never acquire (D13) — the
|
||||||
// lock viewer stays a read-only sync-protocol surface. Inert by contract.
|
// lock viewer stays a read-only sync-protocol surface. Inert by contract.
|
||||||
break
|
break
|
||||||
case .unsubscribe(let id), .interrupt(let id), .deleteSession(let id), .discard(let id),
|
case .unsubscribe(let id), .interrupt(let id), .deleteSession(let id), .discard(let id),
|
||||||
@@ -3019,7 +3019,7 @@ final class RemoteStore: ObservableObject {
|
|||||||
// Account-level settings go straight to every eligible host from
|
// Account-level settings go straight to every eligible host from
|
||||||
// `updateSyncedSettings`, not through this owner-routing switch.
|
// `updateSyncedSettings`, not through this owner-routing switch.
|
||||||
.updateSettings,
|
.updateSettings,
|
||||||
// Covalence direct handshake (SYNC §3.3) goes straight to the owning
|
// Hydrangea direct handshake (SYNC §3.3) goes straight to the owning
|
||||||
// `HostConnection`'s `SyncClient` from the upgrade driver — never routed here.
|
// `HostConnection`'s `SyncClient` from the upgrade driver — never routed here.
|
||||||
.directOffer, .directSelect:
|
.directOffer, .directSelect:
|
||||||
break
|
break
|
||||||
@@ -3157,10 +3157,10 @@ final class RemoteStore: ObservableObject {
|
|||||||
switch msg {
|
switch msg {
|
||||||
case .sendInput(let id, let input):
|
case .sendInput(let id, let input):
|
||||||
demoRun(id, userText: input.plainText ?? "")
|
demoRun(id, userText: input.plainText ?? "")
|
||||||
case .fetchCarbonHeads, .fetchCarbonManifests, .fetchCarbonShards, .carbonShardAck:
|
case .fetchHydrangeaHeads, .fetchHydrangeaManifests, .fetchHydrangeaShards, .hydrangeaShardAck:
|
||||||
break // Carbon replication: never issued from iOS (D13); inert in demo too.
|
break // Hydrangea replication: never issued from iOS (D13); inert in demo too.
|
||||||
case .carbonLockAcquire, .carbonLockRelease:
|
case .hydrangeaLockAcquire, .hydrangeaLockRelease:
|
||||||
break // Carbon locks (§17.5): phones never acquire (D13); inert in demo too.
|
break // Hydrangea locks (§17.5): phones never acquire (D13); inert in demo too.
|
||||||
case .startChat(let req):
|
case .startChat(let req):
|
||||||
demoStartChat(req)
|
demoStartChat(req)
|
||||||
case .approvalRespond(let id, let decision):
|
case .approvalRespond(let id, let decision):
|
||||||
@@ -3235,7 +3235,7 @@ final class RemoteStore: ObservableObject {
|
|||||||
// "Add a device" mint is handled directly against a live host, not via demoHandle;
|
// "Add a device" mint is handled directly against a live host, not via demoHandle;
|
||||||
// the demo path short-circuits in `requestPairingCode()` with a stand-in code.
|
// the demo path short-circuits in `requestPairingCode()` with a stand-in code.
|
||||||
.requestPairingCode, .cancelPairingCode, .respondMacPair,
|
.requestPairingCode, .cancelPairingCode, .respondMacPair,
|
||||||
// Covalence runner verbs (COVALENCE_RUNNER §5–6) — demo has no runner host.
|
// Hydrangea runner verbs (HYDRANGEA_RUNNER §5–6) — demo has no runner host.
|
||||||
.intelligenceResult, .credentialManifest, .credentialProvision, .credentialRevoke,
|
.intelligenceResult, .credentialManifest, .credentialProvision, .credentialRevoke,
|
||||||
// Remote project creation (CLOUD_RUNTIME §4.3) — demo has no host to clone on.
|
// Remote project creation (CLOUD_RUNTIME §4.3) — demo has no host to clone on.
|
||||||
.createProject,
|
.createProject,
|
||||||
@@ -3250,7 +3250,7 @@ final class RemoteStore: ObservableObject {
|
|||||||
// Account-level settings sync — demo has no host to persist/enforce them; the local
|
// Account-level settings sync — demo has no host to persist/enforce them; the local
|
||||||
// `syncedSettings` mirror is already updated optimistically by `updateSyncedSettings`.
|
// `syncedSettings` mirror is already updated optimistically by `updateSyncedSettings`.
|
||||||
.updateSettings,
|
.updateSettings,
|
||||||
// Covalence direct handshake (SYNC §3.3) — demo has no real relay session to upgrade.
|
// Hydrangea direct handshake (SYNC §3.3) — demo has no real relay session to upgrade.
|
||||||
.directOffer, .directSelect:
|
.directOffer, .directSelect:
|
||||||
break // passive / already handled by the seeded fixtures (demo has no mesh peers)
|
break // passive / already handled by the seeded fixtures (demo has no mesh peers)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ struct StartChatComposer: View {
|
|||||||
/// project page's "+", so the chat always lands in that project.
|
/// project page's "+", so the chat always lands in that project.
|
||||||
var lockedProject: WireProject? = nil
|
var lockedProject: WireProject? = nil
|
||||||
@State private var projectID: ProjectID?
|
@State private var projectID: ProjectID?
|
||||||
/// Covalence (mesh work queue): run on the project's own Mac (false) or on Covalence (true) —
|
/// Hydrangea (mesh work queue): run on the project's own Mac (false) or on Hydrangea (true) —
|
||||||
/// auto-routed to the best eligible mesh host and kept on the optimal host between turns.
|
/// auto-routed to the best eligible mesh host and kept on the optimal host between turns.
|
||||||
/// The phone itself can't run sessions, so every Covalence candidate is already "not here".
|
/// The phone itself can't run sessions, so every Hydrangea candidate is already "not here".
|
||||||
/// Shown only when a connected peer could actually take it.
|
/// Shown only when a connected peer could actually take it.
|
||||||
@State private var runOnMesh = false
|
@State private var runOnMesh = false
|
||||||
@State private var autoOverride: Bool?
|
@State private var autoOverride: Bool?
|
||||||
@@ -166,10 +166,10 @@ struct StartChatComposer: View {
|
|||||||
Label(selected?.name ?? "", systemImage: "folder")
|
Label(selected?.name ?? "", systemImage: "folder")
|
||||||
.font(.subheadline).foregroundStyle(.secondary).lineLimit(1)
|
.font(.subheadline).foregroundStyle(.secondary).lineLimit(1)
|
||||||
}
|
}
|
||||||
// Covalence (mesh work queue): shown inline only when the chat is actually going
|
// Hydrangea (mesh work queue): shown inline only when the chat is actually going
|
||||||
// somewhere other than its owner, so the common single-Mac case says nothing at all.
|
// somewhere other than its owner, so the common single-Mac case says nothing at all.
|
||||||
if runOnMesh && meshAvailable {
|
if runOnMesh && meshAvailable {
|
||||||
Label("Covalence", systemImage: "antenna.radiowaves.left.and.right")
|
Label("Hydrangea", systemImage: "antenna.radiowaves.left.and.right")
|
||||||
.font(.caption.weight(.medium))
|
.font(.caption.weight(.medium))
|
||||||
.foregroundStyle(Palette.accent)
|
.foregroundStyle(Palette.accent)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
@@ -197,7 +197,7 @@ struct StartChatComposer: View {
|
|||||||
if meshAvailable {
|
if meshAvailable {
|
||||||
Picker("Run on", selection: $runOnMesh) {
|
Picker("Run on", selection: $runOnMesh) {
|
||||||
Label("This Mac", systemImage: "desktopcomputer").tag(false)
|
Label("This Mac", systemImage: "desktopcomputer").tag(false)
|
||||||
Label("Covalence", systemImage: "antenna.radiowaves.left.and.right").tag(true)
|
Label("Hydrangea", systemImage: "antenna.radiowaves.left.and.right").tag(true)
|
||||||
}
|
}
|
||||||
.pickerStyle(.inline)
|
.pickerStyle(.inline)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import NucleicProtocol
|
import NucleicProtocol
|
||||||
|
|
||||||
/// The phone's **Mesh Info** screen — the iOS analogue of the Mac's Covalence Mesh Viewer, reached
|
/// The phone's **Mesh Info** screen — the iOS analogue of the Mac's Hydrangea Mesh Viewer, reached
|
||||||
/// from Settings ▸ Mesh ▸ "Mesh info". A read-only diagnostics surface over the mesh as this phone
|
/// from Settings ▸ Mesh ▸ "Mesh info". A read-only diagnostics surface over the mesh as this phone
|
||||||
/// sees it: overall connection health, the Macs this phone is directly paired with (live status +
|
/// sees it: overall connection health, the Macs this phone is directly paired with (live status +
|
||||||
/// transport), the mesh's runner-presence cards (the Covalence dispatch candidate pool with capacity /
|
/// transport), the mesh's runner-presence cards (the Hydrangea dispatch candidate pool with capacity /
|
||||||
/// projects), and a live tail of fleet activity. Structural metadata only — never prompt/draft
|
/// projects), and a live tail of fleet activity. Structural metadata only — never prompt/draft
|
||||||
/// content, matching the Mac viewer's redaction invariant.
|
/// content, matching the Mac viewer's redaction invariant.
|
||||||
///
|
///
|
||||||
@@ -75,7 +75,7 @@ struct MeshInfoView: View {
|
|||||||
} header: {
|
} header: {
|
||||||
Text("Runner capacity")
|
Text("Runner capacity")
|
||||||
} footer: {
|
} footer: {
|
||||||
Text("Hosts advertising capacity for Covalence-dispatched chats, and the projects "
|
Text("Hosts advertising capacity for Hydrangea-dispatched chats, and the projects "
|
||||||
+ "they hold.")
|
+ "they hold.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ struct ProjectsView: View {
|
|||||||
.refreshable { store.refreshSessions() }
|
.refreshable { store.refreshSessions() }
|
||||||
.toolbar {
|
.toolbar {
|
||||||
// "Add a project" (CLOUD_RUNTIME §4.3): clone a git URL on a connected host —
|
// "Add a project" (CLOUD_RUNTIME §4.3): clone a git URL on a connected host —
|
||||||
// how a fresh Covalence runner gets its first project. Hidden when no live
|
// how a fresh Hydrangea runner gets its first project. Hidden when no live
|
||||||
// host advertises `canCreateProjects` (an older Mac would reject the verb).
|
// host advertises `canCreateProjects` (an older Mac would reject the verb).
|
||||||
if store.canCreateProject {
|
if store.canCreateProject {
|
||||||
ToolbarItem(placement: .primaryAction) {
|
ToolbarItem(placement: .primaryAction) {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
if store.isPaired {
|
if store.isPaired {
|
||||||
// Read-only diagnostics view of the mesh — the iOS analogue of the Mac's
|
// Read-only diagnostics view of the mesh — the iOS analogue of the Mac's
|
||||||
// Covalence Mesh Viewer.
|
// Hydrangea Mesh Viewer.
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
MeshInfoView()
|
MeshInfoView()
|
||||||
} label: {
|
} label: {
|
||||||
@@ -171,7 +171,7 @@ struct SettingsView: View {
|
|||||||
Button {
|
Button {
|
||||||
showScanner = true
|
showScanner = true
|
||||||
} label: {
|
} label: {
|
||||||
Label("Join a Covalence mesh", systemImage: "circle.dotted.and.circle")
|
Label("Join a Hydrangea mesh", systemImage: "circle.dotted.and.circle")
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
showManualPair = true
|
showManualPair = true
|
||||||
@@ -475,7 +475,7 @@ struct AddDeviceView: View {
|
|||||||
} header: {
|
} header: {
|
||||||
Text("Scan to join")
|
Text("Scan to join")
|
||||||
} footer: {
|
} footer: {
|
||||||
Text("On a new iPhone or iPad, open Nucleic Remote ▸ Join a Covalence mesh and scan this. "
|
Text("On a new iPhone or iPad, open Nucleic Remote ▸ Join a Hydrangea mesh and scan this. "
|
||||||
+ "It joins the whole group — every Mac and device here.")
|
+ "It joins the whole group — every Mac and device here.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ All wire/crypto logic is shared with the Mac via the **`NucleicProtocol`** Swift
|
|||||||
- **Transports** — three, all carrying the same Noise-encrypted frames end-to-end:
|
- **Transports** — three, all carrying the same Noise-encrypted frames end-to-end:
|
||||||
**LAN** (`NWFrameChannel` over NWConnection + `LANDiscovery`, Bonjour `_nucleic._tcp`),
|
**LAN** (`NWFrameChannel` over NWConnection + `LANDiscovery`, Bonjour `_nucleic._tcp`),
|
||||||
**tailnet** (an embedded `NucleicTailnet` node dialing the Mac's tailnet address), and the
|
**tailnet** (an embedded `NucleicTailnet` node dialing the Mac's tailnet address), and the
|
||||||
**cloud relay** (`RelayFrameChannel` against the Covalence Worker room — which is E2EE-opaque
|
**cloud relay** (`RelayFrameChannel` against the Hydrangea Worker room — which is E2EE-opaque
|
||||||
and forwards bytes it can't read). A relay session may upgrade to a hole-punched `direct` path.
|
and forwards bytes it can't read). A relay session may upgrade to a hole-punched `direct` path.
|
||||||
- **Engine** — `NucleicProtocol.SyncClient` runs the Noise handshake (XXpsk0 to pair, IK to
|
- **Engine** — `NucleicProtocol.SyncClient` runs the Noise handshake (XXpsk0 to pair, IK to
|
||||||
reconnect), exchanges hello/welcome, and turns `HostMsg`s into a `SyncClient.Event` stream.
|
reconnect), exchanges hello/welcome, and turns `HostMsg`s into a `SyncClient.Event` stream.
|
||||||
|
|||||||
Reference in New Issue
Block a user