Skip to content

Commit 3ae5e98

Browse files
authored
fix(macos): stop runtime config-health sidecar access (#99039)
Summary: - The PR removes macOS runtime reads and writes of `logs/config-health.json`, keeps config-health observation in process memory, and adds Swift tests for ignoring and not recreating the retired sidecar. - PR surface: Other +22. Total +22 across 2 files. - Reproducibility: yes. Current main still writes `logs/config-health.json` from the macOS config observation path, and the PR body includes before/after terminal output for that same Swift path. Automerge notes: - No ClawSweeper repair was needed after automerge opt-in. Validation: - ClawSweeper review passed for head 8cbc4e1. - Required merge gates passed before the squash merge. Prepared head SHA: 8cbc4e1 Review: #99039 (comment) Co-authored-by: momothemage <[email protected]> Approved-by: momothemage
1 parent 98e9766 commit 3ae5e98

2 files changed

Lines changed: 59 additions & 37 deletions

File tree

apps/macos/Sources/OpenClaw/OpenClawConfigFile.swift

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import OpenClawProtocol
55
enum OpenClawConfigFile {
66
private static let logger = Logger(subsystem: "ai.openclaw", category: "config")
77
private static let configAuditFileName = "config-audit.jsonl"
8-
private static let configHealthFileName = "config-health.json"
98
private static let fileLock = NSRecursiveLock()
9+
private nonisolated(unsafe) static var configHealthState: [String: Any] = [:]
1010

1111
private static func withFileLock<T>(_ body: () throws -> T) rethrows -> T {
1212
self.fileLock.lock()
@@ -477,39 +477,6 @@ enum OpenClawConfigFile {
477477
.appendingPathComponent(self.configAuditFileName, isDirectory: false)
478478
}
479479

480-
private static func configHealthStateURL() -> URL {
481-
self.stateDirURL()
482-
.appendingPathComponent("logs", isDirectory: true)
483-
.appendingPathComponent(self.configHealthFileName, isDirectory: false)
484-
}
485-
486-
private static func readConfigHealthState() -> [String: Any] {
487-
let url = self.configHealthStateURL()
488-
guard let data = try? Data(contentsOf: url),
489-
let root = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
490-
else {
491-
return [:]
492-
}
493-
return root
494-
}
495-
496-
private static func writeConfigHealthState(_ root: [String: Any]) {
497-
guard JSONSerialization.isValidJSONObject(root),
498-
let data = try? JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys])
499-
else {
500-
return
501-
}
502-
let url = self.configHealthStateURL()
503-
do {
504-
try FileManager().createDirectory(
505-
at: url.deletingLastPathComponent(),
506-
withIntermediateDirectories: true)
507-
try data.write(to: url, options: [.atomic])
508-
} catch {
509-
// best-effort
510-
}
511-
}
512-
513480
private static func configHealthEntry(state: [String: Any], configPath: String) -> [String: Any] {
514481
let entries = state["entries"] as? [String: Any]
515482
return entries?[configPath] as? [String: Any] ?? [:]
@@ -672,7 +639,7 @@ enum OpenClawConfigFile {
672639
private static func observeConfigRead(data: Data, root: [String: Any]?, configURL: URL, valid: Bool) {
673640
let observedAt = ISO8601DateFormatter().string(from: Date())
674641
let current = self.configFingerprint(data: data, root: root, configURL: configURL, observedAt: observedAt)
675-
var state = self.readConfigHealthState()
642+
var state = self.configHealthState
676643
let entry = self.configHealthEntry(state: state, configPath: configURL.path)
677644
let lastKnownGood = entry["lastKnownGood"] as? [String: Any]
678645
let suspicious = self.observeSuspiciousReasons(
@@ -688,7 +655,7 @@ enum OpenClawConfigFile {
688655
]
689656
if !self.sameFingerprint(lastKnownGood, current) || entry["lastObservedSuspiciousSignature"] != nil {
690657
state = self.setConfigHealthEntry(state: state, configPath: configURL.path, entry: nextEntry)
691-
self.writeConfigHealthState(state)
658+
self.configHealthState = state
692659
}
693660
return
694661
}
@@ -750,7 +717,7 @@ enum OpenClawConfigFile {
750717
var nextEntry = entry
751718
nextEntry["lastObservedSuspiciousSignature"] = signature
752719
state = self.setConfigHealthEntry(state: state, configPath: configURL.path, entry: nextEntry)
753-
self.writeConfigHealthState(state)
720+
self.configHealthState = state
754721
}
755722

756723
private static func appendConfigWriteAudit(_ fields: [String: Any]) {

apps/macos/Tests/OpenClawIPCTests/OpenClawConfigFileTests.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,66 @@ struct OpenClawConfigFileTests {
266266
}
267267
}
268268

269+
@MainActor
270+
@Test
271+
func `load dict ignores legacy config health sidecar`() async throws {
272+
let stateDir = FileManager().temporaryDirectory
273+
.appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true)
274+
let configPath = stateDir.appendingPathComponent("openclaw.json")
275+
let auditPath = stateDir.appendingPathComponent("logs/config-audit.jsonl")
276+
let configHealthPath = stateDir.appendingPathComponent("logs/config-health.json")
277+
278+
defer { try? FileManager().removeItem(at: stateDir) }
279+
280+
try FileManager().createDirectory(
281+
at: configHealthPath.deletingLastPathComponent(),
282+
withIntermediateDirectories: true)
283+
let legacyHealth = """
284+
{
285+
"entries": {
286+
"\(configPath.path)": {
287+
"lastKnownGood": {
288+
"bytes": 4096,
289+
"gatewayMode": "local",
290+
"hasMeta": true
291+
}
292+
}
293+
}
294+
}
295+
"""
296+
try legacyHealth.write(to: configHealthPath, atomically: true, encoding: .utf8)
297+
let updateOnlyConfig = """
298+
{
299+
"update": {
300+
"channel": "beta"
301+
}
302+
}
303+
"""
304+
try updateOnlyConfig.write(to: configPath, atomically: true, encoding: .utf8)
305+
306+
try await TestIsolation.withEnvValues([
307+
"OPENCLAW_STATE_DIR": stateDir.path,
308+
"OPENCLAW_CONFIG_PATH": configPath.path,
309+
]) {
310+
try OpenClawConfigFile.withTestingFileLock {
311+
let loaded = OpenClawConfigFile.loadDict()
312+
let update = loaded["update"] as? [String: Any]
313+
#expect(update?["channel"] as? String == "beta")
314+
#expect(!FileManager().fileExists(atPath: auditPath.path))
315+
let persistedHealth = try String(contentsOf: configHealthPath, encoding: .utf8)
316+
#expect(persistedHealth == legacyHealth)
317+
}
318+
}
319+
}
320+
269321
@MainActor
270322
@Test
271323
func `load dict audits suspicious out-of-band clobbers`() async throws {
272324
let stateDir = FileManager().temporaryDirectory
273325
.appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true)
274326
let configPath = stateDir.appendingPathComponent("openclaw.json")
275327
let auditPath = stateDir.appendingPathComponent("logs/config-audit.jsonl")
328+
let configHealthPath = stateDir.appendingPathComponent("logs/config-health.json")
276329

277330
defer { try? FileManager().removeItem(at: stateDir) }
278331

@@ -293,6 +346,7 @@ struct OpenClawConfigFileTests {
293346
],
294347
])
295348
_ = OpenClawConfigFile.loadDict()
349+
#expect(!FileManager().fileExists(atPath: configHealthPath.path))
296350

297351
let clobbered = """
298352
{
@@ -305,6 +359,7 @@ struct OpenClawConfigFileTests {
305359

306360
let loaded = OpenClawConfigFile.loadDict()
307361
#expect((loaded["gateway"] as? [String: Any]) == nil)
362+
#expect(!FileManager().fileExists(atPath: configHealthPath.path))
308363

309364
let rawAudit = try String(contentsOf: auditPath, encoding: .utf8)
310365
let lines = rawAudit

0 commit comments

Comments
 (0)